Skip to content

Commit 3e99bc9

Browse files
committed
First working implementation of dump command
1 parent b2a1394 commit 3e99bc9

5 files changed

Lines changed: 83 additions & 4 deletions

File tree

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,8 @@
66

77
Tools for dumping/loading a SQLite database to diffable directory structure
88

9-
Work in progress.
9+
Usage:
10+
11+
$ sqlite-diffable dump fixtures.db out/ facetable
12+
13+
This dumps the table called "facetable" from fixtures.db into the out/ directory.

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def get_long_description():
2626
extras_require={"test": ["pytest", "black"]},
2727
entry_points="""
2828
[console_scripts]
29-
sqlite-diffadble=sqlite_diffable.cli:cli
29+
sqlite-diffable=sqlite_diffable.cli:cli
3030
""",
3131
tests_require=["sqlite-diffable[test]"],
3232
url="https://github.com/simonw/sqlite-diffable",

sqlite_diffable/cli.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,44 @@
11
import click
2+
import json
3+
import pathlib
4+
import sqlite_utils
25

36

47
@click.group()
58
@click.version_option()
69
def cli():
710
"Tools for dumping/loading a SQLite database to diffable directory structure"
811
pass
12+
13+
14+
@cli.command()
15+
@click.argument(
16+
"path", type=click.Path(exists=True, file_okay=True, dir_okay=False), required=True
17+
)
18+
@click.argument(
19+
"output", type=click.Path(file_okay=False, dir_okay=True), required=True
20+
)
21+
@click.argument("tables", nargs=-1, required=True)
22+
def dump(path, output, tables):
23+
output = pathlib.Path(output)
24+
output.mkdir(exist_ok=True)
25+
conn = sqlite_utils.Database(path)
26+
for table in tables:
27+
filepath = output / "{}.ndjson".format(table)
28+
metapath = output / "{}.metadata.json".format(table)
29+
# Dump rows to filepath
30+
with filepath.open("w") as fp:
31+
for row in conn[table].rows:
32+
fp.write(json.dumps(list(row.values())) + "\n")
33+
fp.close()
34+
# Dump out metadata
35+
metapath.open("w").write(
36+
json.dumps(
37+
{
38+
"name": table,
39+
"columns": [c.name for c in conn[table].columns],
40+
"schema": conn[table].schema,
41+
},
42+
indent=4,
43+
)
44+
)

tests/conftest.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import pytest
2+
import sqlite_utils
3+
4+
5+
@pytest.fixture
6+
def one_table_db(tmpdir):
7+
path = str(tmpdir / "one_table.db")
8+
db = sqlite_utils.Database(path)
9+
db["one_table"].insert_all(
10+
[
11+
{"id": 1, "name": "Stacey"},
12+
{"id": 2, "name": "Tilda"},
13+
{"id": 3, "name": "Bartek"},
14+
],
15+
pk="id",
16+
)
17+
return path

tests/test_dump.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,24 @@
1-
def test_dump():
2-
assert False
1+
from click.testing import CliRunner
2+
from sqlite_diffable import cli
3+
import json
4+
5+
6+
def test_dump(one_table_db, tmpdir):
7+
output_dir = tmpdir / "out"
8+
result = CliRunner().invoke(
9+
cli.cli, ["dump", one_table_db, str(output_dir), "one_table"]
10+
)
11+
assert 0 == result.exit_code, result.output
12+
# out/ should now have a single file in it
13+
ndjson = output_dir / "one_table.ndjson"
14+
metadata = output_dir / "one_table.metadata.json"
15+
assert ndjson.exists()
16+
assert metadata.exists()
17+
assert [[1, "Stacey"], [2, "Tilda"], [3, "Bartek"]] == [
18+
json.loads(line) for line in ndjson.open()
19+
]
20+
assert {
21+
"name": "one_table",
22+
"columns": ["id", "name"],
23+
"schema": "CREATE TABLE [one_table] (\n [id] INTEGER PRIMARY KEY,\n [name] TEXT\n)",
24+
} == json.load(metadata)

0 commit comments

Comments
 (0)