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.
Files changed (40) hide show
  1. {sqlite_sh-0.1.0/sqlite_sh.egg-info → sqlite_sh-0.1.1}/PKG-INFO +17 -1
  2. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/README.md +16 -0
  3. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/pyproject.toml +2 -1
  4. sqlite_sh-0.1.1/sqlite_sh/USAGE.md +95 -0
  5. sqlite_sh-0.1.1/sqlite_sh/__init__.py +1 -0
  6. sqlite_sh-0.1.1/sqlite_sh/diagram.py +197 -0
  7. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1/sqlite_sh.egg-info}/PKG-INFO +17 -1
  8. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh.egg-info/SOURCES.txt +1 -0
  9. sqlite_sh-0.1.0/sqlite_sh/__init__.py +0 -1
  10. sqlite_sh-0.1.0/sqlite_sh/diagram.py +0 -37
  11. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/LICENSE +0 -0
  12. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/setup.cfg +0 -0
  13. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/__main__.py +0 -0
  14. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/algorithm_flowchart_gost.pdf +0 -0
  15. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/1.jpg +0 -0
  16. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/10.jpg +0 -0
  17. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/2.jpg +0 -0
  18. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/3.jpg +0 -0
  19. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/4.jpg +0 -0
  20. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/5.jpg +0 -0
  21. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/6.jpg +0 -0
  22. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/7.jpg +0 -0
  23. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/8.jpg +0 -0
  24. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/9.jpg +0 -0
  25. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/Icon.JPG +0 -0
  26. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/Icon.ico +0 -0
  27. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/Icon.png +0 -0
  28. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/__init__.py +0 -0
  29. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/assets/picture.png +0 -0
  30. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/bootstrap.py +0 -0
  31. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/config.py +0 -0
  32. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/data/__init__.py +0 -0
  33. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/data/shop.db +0 -0
  34. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/database.sql +0 -0
  35. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/db_uml_diagram.pdf +0 -0
  36. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/gui.py +0 -0
  37. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh/storage.py +0 -0
  38. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh.egg-info/dependency_links.txt +0 -0
  39. {sqlite_sh-0.1.0 → sqlite_sh-0.1.1}/sqlite_sh.egg-info/entry_points.txt +0 -0
  40. {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.0
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.0"
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.0
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,6 +1,7 @@
1
1
  LICENSE
2
2
  README.md
3
3
  pyproject.toml
4
+ sqlite_sh/USAGE.md
4
5
  sqlite_sh/__init__.py
5
6
  sqlite_sh/__main__.py
6
7
  sqlite_sh/algorithm_flowchart_gost.pdf
@@ -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