sqlite-sh 0.1.0__tar.gz → 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sqlite_sh-0.1.0/sqlite_sh.egg-info → sqlite_sh-0.1.1}/PKG-INFO +17 -1
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/README.md +16 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/pyproject.toml +2 -1
- sqlite_sh-0.1.1/sqlite_sh/USAGE.md +95 -0
- sqlite_sh-0.1.1/sqlite_sh/__init__.py +1 -0
- sqlite_sh-0.1.1/sqlite_sh/diagram.py +197 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1/sqlite_sh.egg-info}/PKG-INFO +17 -1
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh.egg-info/SOURCES.txt +1 -0
- sqlite_sh-0.1.0/sqlite_sh/__init__.py +0 -1
- sqlite_sh-0.1.0/sqlite_sh/diagram.py +0 -37
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/LICENSE +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/setup.cfg +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/__main__.py +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/algorithm_flowchart_gost.pdf +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/1.jpg +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/10.jpg +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/2.jpg +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/3.jpg +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/4.jpg +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/5.jpg +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/6.jpg +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/7.jpg +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/8.jpg +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/9.jpg +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/Icon.JPG +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/Icon.ico +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/Icon.png +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/__init__.py +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/picture.png +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/bootstrap.py +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/config.py +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/data/__init__.py +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/data/shop.db +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/database.sql +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/db_uml_diagram.pdf +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/gui.py +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/storage.py +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh.egg-info/dependency_links.txt +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh.egg-info/entry_points.txt +0 -0
- {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlite-sh
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: SQLite-backed Tkinter shoe shop demo application
|
|
5
5
|
Author-email: adwedelf <adwedelf@users.noreply.github.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -37,6 +37,8 @@ pip install sqlite-sh
|
|
|
37
37
|
shop
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
+
Detailed usage is also installed inside the package as `sqlite_sh/USAGE.md`.
|
|
41
|
+
|
|
40
42
|
On first import/run, the packaged seed database is copied to:
|
|
41
43
|
|
|
42
44
|
```text
|
|
@@ -93,3 +95,17 @@ PyPI:
|
|
|
93
95
|
```bash
|
|
94
96
|
python -m twine upload dist/*
|
|
95
97
|
```
|
|
98
|
+
|
|
99
|
+
## Easy DB diagram
|
|
100
|
+
|
|
101
|
+
Create a browser-ready HTML/SVG database diagram without extra tools:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
sqlite-sh-diagram
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
This writes `db_diagram.html`, which can be opened directly in Edge or any modern browser. Mermaid output is still available:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
sqlite-sh-diagram --format mermaid -o db_diagram.mmd
|
|
111
|
+
```
|
|
@@ -15,6 +15,8 @@ pip install sqlite-sh
|
|
|
15
15
|
shop
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
+
Detailed usage is also installed inside the package as `sqlite_sh/USAGE.md`.
|
|
19
|
+
|
|
18
20
|
On first import/run, the packaged seed database is copied to:
|
|
19
21
|
|
|
20
22
|
```text
|
|
@@ -71,3 +73,17 @@ PyPI:
|
|
|
71
73
|
```bash
|
|
72
74
|
python -m twine upload dist/*
|
|
73
75
|
```
|
|
76
|
+
|
|
77
|
+
## Easy DB diagram
|
|
78
|
+
|
|
79
|
+
Create a browser-ready HTML/SVG database diagram without extra tools:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
sqlite-sh-diagram
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
This writes `db_diagram.html`, which can be opened directly in Edge or any modern browser. Mermaid output is still available:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
sqlite-sh-diagram --format mermaid -o db_diagram.mmd
|
|
89
|
+
```
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "sqlite-sh"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.1"
|
|
8
8
|
description = "SQLite-backed Tkinter shoe shop demo application"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -41,6 +41,7 @@ include-package-data = true
|
|
|
41
41
|
[tool.setuptools.package-data]
|
|
42
42
|
sqlite_sh = [
|
|
43
43
|
"database.sql",
|
|
44
|
+
"USAGE.md",
|
|
44
45
|
"algorithm_flowchart_gost.pdf",
|
|
45
46
|
"db_uml_diagram.pdf",
|
|
46
47
|
"assets/*",
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# sqlite-sh usage
|
|
2
|
+
|
|
3
|
+
This file is installed inside the Python package, so it remains available after:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
pip install sqlite-sh
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Find the installed package folder:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
python -c "import sqlite_sh, pathlib; print(pathlib.Path(sqlite_sh.__file__).parent)"
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Run the application
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
shop
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
On first run the seed database is copied from the installed package to:
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
~/.sqlite_sh/shop.db
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Use another writable database folder:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
SQLITE_SH_HOME=/path/to/folder shop
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Admin credentials
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
Login: 94d5ous@gmail.com
|
|
37
|
+
Password: uzWC67
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Build a Windows exe after pip install
|
|
41
|
+
|
|
42
|
+
```bat
|
|
43
|
+
python -m venv .venv
|
|
44
|
+
.venv\Scripts\activate
|
|
45
|
+
pip install sqlite-sh pyinstaller
|
|
46
|
+
pyinstaller --noconfirm --windowed --name shop --collect-all sqlite_sh --icon .venv\Lib\site-packages\sqlite_sh\assets\Icon.ico -m sqlite_sh
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Result:
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
dist\shop\shop.exe
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
One-file variant:
|
|
56
|
+
|
|
57
|
+
```bat
|
|
58
|
+
pyinstaller --noconfirm --onefile --windowed --name shop --collect-all sqlite_sh --icon .venv\Lib\site-packages\sqlite_sh\assets\Icon.ico -m sqlite_sh
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Rebuild database from Excel files
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
sqlite-sh-bootstrap
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The importer expects the original exam Excel files in the known import folder. If your files are elsewhere, edit `sqlite_sh/bootstrap.py` or place the import folder near the project before running the command.
|
|
68
|
+
|
|
69
|
+
## Generate database diagram easily
|
|
70
|
+
|
|
71
|
+
Browser-ready HTML/SVG file, no Mermaid extension required:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
sqlite-sh-diagram
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
This creates:
|
|
78
|
+
|
|
79
|
+
```text
|
|
80
|
+
db_diagram.html
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Open it in Edge, Chrome, Firefox, or any modern browser.
|
|
84
|
+
|
|
85
|
+
Mermaid source is still available:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
sqlite-sh-diagram --format mermaid -o db_diagram.mmd
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Print Mermaid to the console:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
sqlite-sh-diagram --format mermaid -o -
|
|
95
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.1"
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import html
|
|
3
|
+
import sqlite3
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from sqlite_sh.config import DB_FILE
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
DEFAULT_HTML = "db_diagram.html"
|
|
10
|
+
DEFAULT_MERMAID = "db_diagram.mmd"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def load_schema():
|
|
14
|
+
if not DB_FILE.exists():
|
|
15
|
+
raise SystemExit("База данных не найдена. Сначала выполните: sqlite-sh-bootstrap")
|
|
16
|
+
with sqlite3.connect(DB_FILE) as conn:
|
|
17
|
+
conn.row_factory = sqlite3.Row
|
|
18
|
+
tables = [
|
|
19
|
+
row["name"]
|
|
20
|
+
for row in conn.execute(
|
|
21
|
+
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name"
|
|
22
|
+
)
|
|
23
|
+
]
|
|
24
|
+
columns = {table: list(conn.execute(f"PRAGMA table_info({table})")) for table in tables}
|
|
25
|
+
foreign_keys = {table: list(conn.execute(f"PRAGMA foreign_key_list({table})")) for table in tables}
|
|
26
|
+
return tables, columns, foreign_keys
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def render_mermaid(tables, columns, foreign_keys):
|
|
30
|
+
lines = ["erDiagram"]
|
|
31
|
+
for table in tables:
|
|
32
|
+
lines.append(f" {table} {{")
|
|
33
|
+
for col in columns[table]:
|
|
34
|
+
name = col["name"]
|
|
35
|
+
type_name = col["type"] or "TEXT"
|
|
36
|
+
pk = " PK" if col["pk"] else ""
|
|
37
|
+
lines.append(f" {type_name} {name}{pk}")
|
|
38
|
+
lines.append(" }")
|
|
39
|
+
for table in tables:
|
|
40
|
+
for fk in foreign_keys[table]:
|
|
41
|
+
ref_table = fk["table"]
|
|
42
|
+
from_col = fk["from"]
|
|
43
|
+
to_col = fk["to"]
|
|
44
|
+
lines.append(f" {ref_table} ||--o{{ {table} : \"{to_col} to {from_col}\"")
|
|
45
|
+
return "\n".join(lines) + "\n"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def table_height(columns_count):
|
|
49
|
+
return 46 + max(columns_count, 1) * 24 + 12
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def svg_text(x, y, text, size=14, weight="normal"):
|
|
53
|
+
return (
|
|
54
|
+
f'<text x="{x}" y="{y}" font-family="Arial, sans-serif" '
|
|
55
|
+
f'font-size="{size}" font-weight="{weight}">{html.escape(str(text))}</text>'
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def render_html(tables, columns, foreign_keys):
|
|
60
|
+
layout = {
|
|
61
|
+
"roles": (60, 100),
|
|
62
|
+
"users": (60, 360),
|
|
63
|
+
"categories": (60, 650),
|
|
64
|
+
"manufacturers": (60, 870),
|
|
65
|
+
"suppliers": (60, 1090),
|
|
66
|
+
"units": (520, 1090),
|
|
67
|
+
"products": (520, 360),
|
|
68
|
+
"order_items": (1010, 360),
|
|
69
|
+
"orders": (1430, 360),
|
|
70
|
+
"pickup_points": (1430, 720),
|
|
71
|
+
}
|
|
72
|
+
default_positions = {}
|
|
73
|
+
for idx, table in enumerate(tables):
|
|
74
|
+
default_positions[table] = (60 + (idx % 4) * 430, 100 + (idx // 4) * 310)
|
|
75
|
+
positions = {table: layout.get(table, default_positions[table]) for table in tables}
|
|
76
|
+
widths = {
|
|
77
|
+
"products": 390,
|
|
78
|
+
"orders": 330,
|
|
79
|
+
"order_items": 310,
|
|
80
|
+
"users": 330,
|
|
81
|
+
"pickup_points": 330,
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
def box(table):
|
|
85
|
+
x, y = positions[table]
|
|
86
|
+
w = widths.get(table, 300)
|
|
87
|
+
h = table_height(len(columns[table]))
|
|
88
|
+
return x, y, w, h
|
|
89
|
+
|
|
90
|
+
svg = []
|
|
91
|
+
svg.append('<svg xmlns="http://www.w3.org/2000/svg" width="1850" height="1320" viewBox="0 0 1850 1320">')
|
|
92
|
+
svg.append('<defs><marker id="arrow" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto" markerUnits="strokeWidth"><path d="M0,0 L0,6 L9,3 z" fill="black" /></marker></defs>')
|
|
93
|
+
svg.append('<rect x="0" y="0" width="1850" height="1320" fill="white"/>')
|
|
94
|
+
svg.append(svg_text(50, 45, "ER/UML диаграмма SQLite", 28, "bold"))
|
|
95
|
+
svg.append(svg_text(50, 76, "Таблицы, поля, первичные и внешние ключи", 15))
|
|
96
|
+
svg.append('<line x1="50" y1="90" x2="1800" y2="90" stroke="black" stroke-width="2"/>')
|
|
97
|
+
|
|
98
|
+
def anchor(table, side):
|
|
99
|
+
x, y, w, h = box(table)
|
|
100
|
+
if side == "left":
|
|
101
|
+
return x, y + h / 2
|
|
102
|
+
if side == "right":
|
|
103
|
+
return x + w, y + h / 2
|
|
104
|
+
if side == "top":
|
|
105
|
+
return x + w / 2, y
|
|
106
|
+
return x + w / 2, y + h
|
|
107
|
+
|
|
108
|
+
lanes = {
|
|
109
|
+
("roles", "users"): ["bottom", "top"],
|
|
110
|
+
("products", "order_items"): ["right", "left"],
|
|
111
|
+
("orders", "order_items"): ["left", "right"],
|
|
112
|
+
("pickup_points", "orders"): ["top", "bottom"],
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
for table in tables:
|
|
116
|
+
for fk in foreign_keys[table]:
|
|
117
|
+
ref = fk["table"]
|
|
118
|
+
start_side, end_side = lanes.get((ref, table), ["right", "left"])
|
|
119
|
+
sx, sy = anchor(ref, start_side)
|
|
120
|
+
ex, ey = anchor(table, end_side)
|
|
121
|
+
mx = (sx + ex) / 2
|
|
122
|
+
path = f"M {sx:.0f} {sy:.0f} L {mx:.0f} {sy:.0f} L {mx:.0f} {ey:.0f} L {ex:.0f} {ey:.0f}"
|
|
123
|
+
svg.append(f'<path d="{path}" fill="none" stroke="black" stroke-width="2" marker-end="url(#arrow)"/>')
|
|
124
|
+
svg.append(svg_text(mx + 6, (sy + ey) / 2 - 4, "1:N", 13, "bold"))
|
|
125
|
+
|
|
126
|
+
for table in tables:
|
|
127
|
+
x, y, w, h = box(table)
|
|
128
|
+
svg.append(f'<rect x="{x}" y="{y}" width="{w}" height="{h}" fill="white" stroke="black" stroke-width="2"/>')
|
|
129
|
+
svg.append(f'<rect x="{x}" y="{y}" width="{w}" height="36" fill="white" stroke="black" stroke-width="2"/>')
|
|
130
|
+
svg.append(svg_text(x + 12, y + 24, table, 16, "bold"))
|
|
131
|
+
cy = y + 60
|
|
132
|
+
fk_columns = {fk["from"] for fk in foreign_keys[table]}
|
|
133
|
+
for col in columns[table]:
|
|
134
|
+
marks = []
|
|
135
|
+
if col["pk"]:
|
|
136
|
+
marks.append("PK")
|
|
137
|
+
if col["name"] in fk_columns:
|
|
138
|
+
marks.append("FK")
|
|
139
|
+
suffix = f" [{' '.join(marks)}]" if marks else ""
|
|
140
|
+
svg.append(svg_text(x + 12, cy, f"{col['name']}: {col['type'] or 'TEXT'}{suffix}", 13))
|
|
141
|
+
cy += 24
|
|
142
|
+
svg.append("</svg>")
|
|
143
|
+
|
|
144
|
+
return """<!doctype html>
|
|
145
|
+
<html lang="ru">
|
|
146
|
+
<head>
|
|
147
|
+
<meta charset="utf-8">
|
|
148
|
+
<title>SQLite DB Diagram</title>
|
|
149
|
+
<style>
|
|
150
|
+
body { margin: 0; padding: 24px; background: white; color: black; font-family: Arial, sans-serif; }
|
|
151
|
+
.hint { margin: 0 0 16px; font-size: 14px; }
|
|
152
|
+
svg { max-width: 100%%; height: auto; border: 1px solid #ddd; }
|
|
153
|
+
</style>
|
|
154
|
+
</head>
|
|
155
|
+
<body>
|
|
156
|
+
<p class="hint">Откройте этот файл в браузере. Дополнительные расширения и интернет не нужны.</p>
|
|
157
|
+
%s
|
|
158
|
+
</body>
|
|
159
|
+
</html>
|
|
160
|
+
""" % "\n ".join(svg)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def write_output(content, output):
|
|
164
|
+
if output == "-":
|
|
165
|
+
print(content, end="")
|
|
166
|
+
return None
|
|
167
|
+
path = Path(output)
|
|
168
|
+
path.write_text(content, encoding="utf-8")
|
|
169
|
+
return path
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def main(argv=None):
|
|
173
|
+
parser = argparse.ArgumentParser(description="Generate a database diagram for sqlite-sh.")
|
|
174
|
+
parser.add_argument(
|
|
175
|
+
"--format",
|
|
176
|
+
choices=("html", "mermaid"),
|
|
177
|
+
default="html",
|
|
178
|
+
help="Output format. html opens directly in a browser; mermaid writes .mmd text.",
|
|
179
|
+
)
|
|
180
|
+
parser.add_argument("-o", "--output", help="Output file. Use '-' for stdout.")
|
|
181
|
+
args = parser.parse_args(argv)
|
|
182
|
+
|
|
183
|
+
tables, columns, foreign_keys = load_schema()
|
|
184
|
+
if args.format == "mermaid":
|
|
185
|
+
content = render_mermaid(tables, columns, foreign_keys)
|
|
186
|
+
output = args.output or DEFAULT_MERMAID
|
|
187
|
+
else:
|
|
188
|
+
content = render_html(tables, columns, foreign_keys)
|
|
189
|
+
output = args.output or DEFAULT_HTML
|
|
190
|
+
|
|
191
|
+
path = write_output(content, output)
|
|
192
|
+
if path:
|
|
193
|
+
print(f"Диаграмма сохранена: {path.resolve()}")
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
if __name__ == "__main__":
|
|
197
|
+
main()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sqlite-sh
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: SQLite-backed Tkinter shoe shop demo application
|
|
5
5
|
Author-email: adwedelf <adwedelf@users.noreply.github.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -37,6 +37,8 @@ pip install sqlite-sh
|
|
|
37
37
|
shop
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
+
Detailed usage is also installed inside the package as `sqlite_sh/USAGE.md`.
|
|
41
|
+
|
|
40
42
|
On first import/run, the packaged seed database is copied to:
|
|
41
43
|
|
|
42
44
|
```text
|
|
@@ -93,3 +95,17 @@ PyPI:
|
|
|
93
95
|
```bash
|
|
94
96
|
python -m twine upload dist/*
|
|
95
97
|
```
|
|
98
|
+
|
|
99
|
+
## Easy DB diagram
|
|
100
|
+
|
|
101
|
+
Create a browser-ready HTML/SVG database diagram without extra tools:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
sqlite-sh-diagram
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
This writes `db_diagram.html`, which can be opened directly in Edge or any modern browser. Mermaid output is still available:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
sqlite-sh-diagram --format mermaid -o db_diagram.mmd
|
|
111
|
+
```
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.1.0"
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import sqlite3
|
|
2
|
-
|
|
3
|
-
from sqlite_sh.config import DB_FILE
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def main():
|
|
7
|
-
if not DB_FILE.exists():
|
|
8
|
-
raise SystemExit("База данных не найдена. Сначала выполните: python bootstrap_db.py")
|
|
9
|
-
|
|
10
|
-
with sqlite3.connect(DB_FILE) as conn:
|
|
11
|
-
tables = [
|
|
12
|
-
row[0]
|
|
13
|
-
for row in conn.execute(
|
|
14
|
-
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name"
|
|
15
|
-
)
|
|
16
|
-
]
|
|
17
|
-
|
|
18
|
-
print("erDiagram")
|
|
19
|
-
for table in tables:
|
|
20
|
-
print(f" {table} {{")
|
|
21
|
-
for col in conn.execute(f"PRAGMA table_info({table})"):
|
|
22
|
-
col_name = col[1]
|
|
23
|
-
col_type = col[2] or "TEXT"
|
|
24
|
-
pk = " PK" if col[5] else ""
|
|
25
|
-
print(f" {col_type} {col_name}{pk}")
|
|
26
|
-
print(" }")
|
|
27
|
-
|
|
28
|
-
for table in tables:
|
|
29
|
-
for fk in conn.execute(f"PRAGMA foreign_key_list({table})"):
|
|
30
|
-
ref_table = fk[2]
|
|
31
|
-
from_col = fk[3]
|
|
32
|
-
to_col = fk[4]
|
|
33
|
-
print(f" {ref_table} ||--o{{ {table} : \"{to_col} to {from_col}\"")
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if __name__ == "__main__":
|
|
37
|
-
main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|