Skip to content

Commit c1f0166

Browse files
committed
Add docstrings
1 parent 05bd347 commit c1f0166

File tree

5 files changed

+50
-35
lines changed

5 files changed

+50
-35
lines changed

sqliteondbf/__main__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from executor import SQLiteExecutor as _SQLiteExecutor, connect, convert, export, view, dump
2525

2626
def execute(script, logger=logging.getLogger("sqliteondbf")):
27+
"""execute a sqlite3 script on a DBF base"""
2728
_SQLiteExecutor(script, logger).execute()
2829

2930
def _get_args():
@@ -38,6 +39,7 @@ def _get_args():
3839
return parser.parse_args()
3940

4041
def main():
42+
"""sqliteondbf main function"""
4143
args = _get_args()
4244
if args.quiet:
4345
logging.basicConfig(level=logging.ERROR)

sqliteondbf/converter.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,13 @@
2424
import dbfread
2525

2626
class SQLiteConverter():
27+
"""A converter from dbf to sqlite3"""
2728
def __init__(self, connection = sqlite3.connect(":memory:"), logger=logging.getLogger("sqliteondbf")):
2829
self.__connection = connection
2930
self.__logger = logger
3031

3132
def import_dbf(self, dbf_path, lowernames=True, encoding="cp850", char_decode_errors="strict"):
33+
"""Import a dbf database to the current sqlite connection"""
3234
cursor = self.__connection.cursor()
3335

3436
for fpath in self.__dbf_files(dbf_path):
@@ -46,6 +48,7 @@ def __dbf_files(self, dbf_path):
4648
yield os.path.join(root, name)
4749

4850
class SQLiteConverterWorker():
51+
"""The worker: converts a dbf table and add the table to the current connection"""
4952
__typemap = {
5053
'F': 'FLOAT',
5154
'L': 'BOOLEAN',
@@ -64,6 +67,7 @@ def __init__(self, logger, cursor, dbf_table):
6467
self.__dbf_table = dbf_table
6568

6669
def import_dbf_file(self):
70+
"""Import the file"""
6771
try:
6872
self.__add_sqlite_table()
6973
except UnicodeDecodeError as err:

sqliteondbf/executor.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@
2323
import csv
2424
import sys
2525

26-
from splitter import SemicolonSplitter as _SemicolonSplitter
26+
from splitter import Splitter as _Splitter
2727
from converter import SQLiteConverter as _SQLiteConverter
2828

2929
class SQLiteExecutor():
30+
"""A script executor: executes a sqlite script on a dbf database"""
3031
def __init__(self, script, logger):
3132
if type(script) == str:
3233
self.__script = script
@@ -45,7 +46,8 @@ def __init__(self, script, logger):
4546
}
4647

4748
def execute(self):
48-
for e in _SemicolonSplitter().split(self.__script):
49+
"""Execute the script"""
50+
for e in _Splitter().split(self.__script):
4951
e = e.strip()
5052
if not e:
5153
continue
@@ -146,15 +148,18 @@ def __get_args(self, e):
146148
return shlex.split(e)
147149

148150
def connect(dbf_path, logger=logging.getLogger("sqliteondbf"), lowernames=True, encoding="cp850", char_decode_errors="strict"):
151+
"""take a dBase (= set of dbf files) directory and return a SQLite connection over the database"""
149152
return convert(dbf_path, ":memory:", logger=logger, lowernames=lowernames, encoding=encoding, char_decode_errors=char_decode_errors)
150153

151154
def convert(dbf_path, sqlite_path, logger=logging.getLogger("sqliteondbf"), lowernames=True, encoding="cp850", char_decode_errors="strict"):
155+
"""convert a dBase (= set of dbf files) directory to a SQLite file and return a SQLite connection over the database"""
152156
logger.info("import {} to {}".format(dbf_path, sqlite_path))
153157
connection = sqlite3.connect(sqlite_path)
154158
_SQLiteConverter(connection, logger).import_dbf(dbf_path, encoding=encoding, lowernames=lowernames, char_decode_errors=char_decode_errors)
155159
return connection
156160

157161
def export(cursor, csv_path, logger=logging.getLogger("sqliteondbf")):
162+
"""export the result of the last query to a csv file"""
158163
logger.info("export data to {}".format(csv_path))
159164
with open(csv_path, 'w', newline='', encoding='utf-8') as dest:
160165
writer = csv.writer(dest)
@@ -163,6 +168,7 @@ def export(cursor, csv_path, logger=logging.getLogger("sqliteondbf")):
163168
writer.writerow(row)
164169

165170
def view(cursor, limit, logger=logging.getLogger("sqliteondbf"), file=sys.stdout):
171+
"""print the result of the last query"""
166172
logger.debug("display data on terminal")
167173
column_names = [description[0] for description in cursor.description]
168174
if limit >= 0:
@@ -175,7 +181,8 @@ def view(cursor, limit, logger=logging.getLogger("sqliteondbf"), file=sys.stdout
175181
if cursor.fetchone():
176182
print ("...", file=file)
177183

178-
def dump(dest, connection):
179-
with open(dest, 'w', encoding="utf-8", newline="\n") as f:
184+
def dump(sqlite_path, connection):
185+
"""dump the database to a SQLite file"""
186+
with open(sqlite_path, 'w', encoding="utf-8", newline="\n") as f:
180187
for line in connection.iterdump():
181188
f.write(line+"\n")

sqliteondbf/splitter.py

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
along with this program. If not, see <http://www.gnu.org/licenses/>.
1515
"""
1616

17-
class SemicolonSplitter():
17+
class Splitter():
18+
"""A splitter: splits a script into separate chunks. By default, the
19+
separator is the semicolon. Ignores separators in comments or strings"""
1820
__NONE = 0
1921

2022
__OPEN_BLOCK_COMMENT_C1 = 10
@@ -38,60 +40,60 @@ def __init__(self, block_comment=("/*", "*/"), line_comment="--", splitter=";"):
3840

3941
def split(self, script):
4042
cur_chunk = []
41-
state = SemicolonSplitter.__NONE
43+
state = Splitter.__NONE
4244
for c in script:
43-
if state == SemicolonSplitter.__NONE:
45+
if state == Splitter.__NONE:
4446
if c == self.__block_comment[0][0]:
45-
state = SemicolonSplitter.__OPEN_BLOCK_COMMENT_C1
47+
state = Splitter.__OPEN_BLOCK_COMMENT_C1
4648
elif c == self.__line_comment[0]:
47-
state = SemicolonSplitter.__OPEN_LINE_COMMENT_C1
49+
state = Splitter.__OPEN_LINE_COMMENT_C1
4850
elif c == "\"":
49-
state = SemicolonSplitter.__DOUBLE_QUOTED
51+
state = Splitter.__DOUBLE_QUOTED
5052
elif c == "'":
51-
state = SemicolonSplitter.__SINGLE_QUOTED
53+
state = Splitter.__SINGLE_QUOTED
5254
elif c == self.__splitter:
5355
chunk = "".join(cur_chunk).strip()
5456
if chunk:
5557
yield chunk
5658
cur_chunk = []
5759
continue
58-
elif state == SemicolonSplitter.__OPEN_BLOCK_COMMENT_C1:
60+
elif state == Splitter.__OPEN_BLOCK_COMMENT_C1:
5961
if c == self.__block_comment[0][1]:
60-
state = SemicolonSplitter.__BLOCK_COMMENT_OPENED
62+
state = Splitter.__BLOCK_COMMENT_OPENED
6163
else:
62-
state = SemicolonSplitter.__NONE
63-
elif state == SemicolonSplitter.__BLOCK_COMMENT_OPENED:
64+
state = Splitter.__NONE
65+
elif state == Splitter.__BLOCK_COMMENT_OPENED:
6466
if c == self.__block_comment[1][0]:
65-
state = SemicolonSplitter.__BLOCK_COMMENT_OPENED_CLOSE_BLOCK_COMMENT_C1
66-
elif state == SemicolonSplitter.__BLOCK_COMMENT_OPENED_CLOSE_BLOCK_COMMENT_C1:
67+
state = Splitter.__BLOCK_COMMENT_OPENED_CLOSE_BLOCK_COMMENT_C1
68+
elif state == Splitter.__BLOCK_COMMENT_OPENED_CLOSE_BLOCK_COMMENT_C1:
6769
if c == self.__block_comment[1][1]:
6870
cur_chunk = []
69-
state = SemicolonSplitter.__NONE
71+
state = Splitter.__NONE
7072
continue
71-
elif state == SemicolonSplitter.__OPEN_LINE_COMMENT_C1:
73+
elif state == Splitter.__OPEN_LINE_COMMENT_C1:
7274
if c == self.__line_comment[1]:
73-
state = SemicolonSplitter.__LINE_COMMENT_OPENED
75+
state = Splitter.__LINE_COMMENT_OPENED
7476
else:
75-
state = SemicolonSplitter.__NONE
76-
elif state == SemicolonSplitter.__LINE_COMMENT_OPENED:
77+
state = Splitter.__NONE
78+
elif state == Splitter.__LINE_COMMENT_OPENED:
7779
if c == "\n":
7880
cur_chunk = []
79-
state = SemicolonSplitter.__NONE
81+
state = Splitter.__NONE
8082
continue
81-
elif state == SemicolonSplitter.__DOUBLE_QUOTED:
83+
elif state == Splitter.__DOUBLE_QUOTED:
8284
if c == "\\":
83-
state = SemicolonSplitter.__DOUBLE_QUOTED_ESCAPE
85+
state = Splitter.__DOUBLE_QUOTED_ESCAPE
8486
if c == "\"":
85-
state = SemicolonSplitter.__NONE
86-
elif state == SemicolonSplitter.__DOUBLE_QUOTED_ESCAPE:
87-
state = SemicolonSplitter.__DOUBLE_QUOTED;
88-
elif state == SemicolonSplitter.__SINGLE_QUOTED:
87+
state = Splitter.__NONE
88+
elif state == Splitter.__DOUBLE_QUOTED_ESCAPE:
89+
state = Splitter.__DOUBLE_QUOTED;
90+
elif state == Splitter.__SINGLE_QUOTED:
8991
if c == "\\":
90-
state = SemicolonSplitter.__SINGLE_QUOTED_ESCAPE
92+
state = Splitter.__SINGLE_QUOTED_ESCAPE
9193
if c == "'":
92-
state = SemicolonSplitter.__NONE
93-
elif state == SemicolonSplitter.__SINGLE_QUOTED_ESCAPE:
94-
state = SemicolonSplitter.__SINGLE_QUOTED;
94+
state = Splitter.__NONE
95+
elif state == Splitter.__SINGLE_QUOTED_ESCAPE:
96+
state = Splitter.__SINGLE_QUOTED;
9597

9698
cur_chunk.append(c)
9799

test/splitter_test.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import sqliteondbf.splitter as sp
1919
import unittest
2020

21-
class SemicolonSplitterTest(unittest.TestCase):
21+
class SplitterTest(unittest.TestCase):
2222
def test(self):
2323
text="""
2424
a semicolon "in a double quoted (\\") string;" is not a separation
@@ -32,7 +32,7 @@ def test(self):
3232
this is one;
3333
"""
3434

35-
l = list(sp.SemicolonSplitter().split(text))
35+
l = list(sp.Splitter().split(text))
3636
self.assertEquals(
3737
['a semicolon "in a double quoted (\\") string;" is not a separation\n this is one',
3838
"a semicolon 'in a single quoted (\\') string;' is not a separation\n this is one",

0 commit comments

Comments
 (0)