Skip to content

Commit fe37ee5

Browse files
committed
Added contrib tools with conversion to networkx, this is useful for visualising schema - like in the README
1 parent ca86e1c commit fe37ee5

9 files changed

+119
-1
lines changed

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,7 @@ schemas common in OLAP. For example when the same table is the target of
7070
multiple foreign keys the basic functionality of SQLAlchemy breaks down.
7171
Also since you might have sub-queries or CTEs which you might want to
7272
attach to your schema it's not always possible to use foreign keys.
73+
74+
TODO: standard schema diagram, explain difference
75+
76+
![star schema](doc/sales_schema.png "example star schema")

doc/sales_schema.png

15.5 KB
Loading

poetry.lock

+41-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ sqlalchemy-stubs = "^0.3"
1717
pycodestyle = "^2.6.0"
1818
mistletoe = "^0.7.2"
1919
beautifulsoup4 = "^4.9.3"
20+
networkx = "^2.5"
2021

2122
[build-system]
2223
requires = ["poetry>=0.12"]

setup.cfg

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
[mypy]
22
plugins = sqlmypy
33

4+
[mypy-networkx.*]
5+
ignore_missing_imports = True
6+
47
[pycodestyle]
58
max-line-length = 100

star_alchemy/contrib/__init__.py

Whitespace-only changes.

star_alchemy/contrib/networkx.py

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import networkx as nx
2+
3+
from star_alchemy import StarSchema
4+
5+
6+
def to_nx(star_schema: StarSchema):
7+
"""
8+
9+
:param star_schema:
10+
11+
:return:
12+
"""
13+
G = nx.DiGraph()
14+
15+
for s in star_schema:
16+
G.add_node(s.name, name=str(s.name))
17+
if s.parent is not None:
18+
G.add_edge(s.parent.name, s.name)
19+
20+
return G

tests/test_contrib_networkx.py

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import difflib
2+
import json
3+
from unittest import TestCase
4+
5+
import networkx as nx
6+
7+
from examples.sales import schema
8+
from star_alchemy.contrib.networkx import to_nx
9+
10+
11+
class ToNxTestCase(TestCase):
12+
13+
def test_to_nx(self):
14+
G = to_nx(schema)
15+
actual = json.dumps(nx.tree_data(G, schema.name), indent=4)
16+
expected = json.dumps(indent=4, obj={
17+
'name': 'sale',
18+
'id': 'sale',
19+
'children': [
20+
{
21+
'name': 'product',
22+
'id': 'product',
23+
'children': [
24+
{'name': 'category', 'id': 'category'}
25+
]
26+
},
27+
{
28+
'name': 'employee',
29+
'id': 'employee',
30+
'children': [
31+
{'name': 'department', 'id': 'department'},
32+
{'name': 'employee_location', 'id': 'employee_location'}
33+
]
34+
},
35+
{
36+
'name': 'customer',
37+
'id': 'customer',
38+
'children': [
39+
{'name': 'customer_location', 'id': 'customer_location'}
40+
]
41+
}
42+
]
43+
})
44+
if actual != expected:
45+
actual_lines = actual.split('\n')
46+
expected_lines = expected.split('\n')
47+
diff = difflib.unified_diff(actual_lines, expected_lines)
48+
self.fail('\n'.join(diff))

tests/test_star_schema.py

+2
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,8 @@ class DocStringTestCase(TestCase, DocTestMixin(_star_alchemy)):
211211
212212
Most docstring checking focus on the format, which is less important
213213
for me.
214+
215+
TODO: Make this more generic with auto-discovery
214216
"""
215217

216218
@property

0 commit comments

Comments
 (0)