deskkit 1.2.1__tar.gz → 1.2.2__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.
- {deskkit-1.2.1 → deskkit-1.2.2}/PKG-INFO +1 -1
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/__init__.py +1 -1
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/generator/export.py +46 -5
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/generator/templates/qt_loader.py +10 -1
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit.egg-info/PKG-INFO +1 -1
- {deskkit-1.2.1 → deskkit-1.2.2}/pyproject.toml +1 -1
- {deskkit-1.2.1 → deskkit-1.2.2}/LICENSE +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/README.md +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/app.py +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/auth.py +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/builder.py +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/catalog.py +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/config.py +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/database.py +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/exceptions.py +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/features.py +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/flowchart.py +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/generator/__init__.py +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/generator/templates/auth.py +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/generator/templates/database.py +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/generator/templates/images_utils.py +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/generator/templates/main.py +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/images.py +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/presets.py +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/qt_backend.py +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/roles.py +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/tips.py +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/ui/__init__.py +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/ui/login_window.py +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/ui/main_window.py +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/ui/product_form.py +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/ui/styles.py +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit.egg-info/SOURCES.txt +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit.egg-info/dependency_links.txt +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit.egg-info/requires.txt +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/deskkit.egg-info/top_level.txt +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/setup.cfg +0 -0
- {deskkit-1.2.1 → deskkit-1.2.2}/tests/test_catalog.py +0 -0
|
@@ -2,10 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import os
|
|
5
6
|
import re
|
|
6
7
|
import shutil
|
|
8
|
+
import stat
|
|
7
9
|
import subprocess
|
|
8
10
|
import sys
|
|
11
|
+
import time
|
|
9
12
|
from pathlib import Path
|
|
10
13
|
from typing import TYPE_CHECKING
|
|
11
14
|
|
|
@@ -27,6 +30,47 @@ def _write(path: Path, content: str) -> None:
|
|
|
27
30
|
path.write_text(content, encoding="utf-8")
|
|
28
31
|
|
|
29
32
|
|
|
33
|
+
def _on_rm_error(func, path, _exc) -> None:
|
|
34
|
+
"""Снять read-only и повторить удаление (часто на Windows)."""
|
|
35
|
+
try:
|
|
36
|
+
os.chmod(path, stat.S_IWRITE)
|
|
37
|
+
func(path)
|
|
38
|
+
except OSError:
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _clear_output_dir(out: Path) -> None:
|
|
43
|
+
"""Очистить папку экспорта; при блокировке файлов — несколько попыток."""
|
|
44
|
+
if not out.exists():
|
|
45
|
+
return
|
|
46
|
+
|
|
47
|
+
def _rmtree_once() -> None:
|
|
48
|
+
try:
|
|
49
|
+
shutil.rmtree(out, onexc=_on_rm_error)
|
|
50
|
+
except TypeError:
|
|
51
|
+
shutil.rmtree(out, onerror=_on_rm_error)
|
|
52
|
+
|
|
53
|
+
for attempt in range(5):
|
|
54
|
+
_rmtree_once()
|
|
55
|
+
if not out.exists():
|
|
56
|
+
return
|
|
57
|
+
time.sleep(0.25 * (attempt + 1))
|
|
58
|
+
# Если папка всё ещё занята (например, открыт main.py) — чистим содержимое по файлам
|
|
59
|
+
for path in sorted(out.rglob("*"), reverse=True):
|
|
60
|
+
try:
|
|
61
|
+
if path.is_file() or path.is_symlink():
|
|
62
|
+
os.chmod(path, stat.S_IWRITE)
|
|
63
|
+
path.unlink()
|
|
64
|
+
elif path.is_dir():
|
|
65
|
+
path.rmdir()
|
|
66
|
+
except OSError:
|
|
67
|
+
continue
|
|
68
|
+
if out.exists() and any(out.iterdir()):
|
|
69
|
+
raise FileExistsError(
|
|
70
|
+
f"Не удалось очистить папку (закройте файлы/терминал в ней): {out}"
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
30
74
|
def _sql_bundle(config: AppConfig, include_seed: bool) -> str:
|
|
31
75
|
db = config.database
|
|
32
76
|
parts = [
|
|
@@ -235,11 +279,8 @@ def export_project(config: AppConfig) -> Path:
|
|
|
235
279
|
"""Сгенерировать автономный проект без импортов deskkit."""
|
|
236
280
|
project_name = config.project_name or _slug(config.title)
|
|
237
281
|
out = Path(config.output_dir or project_name).resolve()
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
if out.exists():
|
|
241
|
-
raise FileExistsError(f"Не удалось очистить папку: {out}")
|
|
242
|
-
out.mkdir(parents=True)
|
|
282
|
+
_clear_output_dir(out)
|
|
283
|
+
out.mkdir(parents=True, exist_ok=True)
|
|
243
284
|
|
|
244
285
|
files = {
|
|
245
286
|
"settings.py": _settings_py(config),
|
|
@@ -48,7 +48,16 @@ def exec_app(app) -> int:
|
|
|
48
48
|
return app.exec_()
|
|
49
49
|
|
|
50
50
|
|
|
51
|
-
def
|
|
51
|
+
def signal_connect(obj, signal, slot) -> None:
|
|
52
|
+
init()
|
|
53
|
+
getattr(obj, signal).connect(slot)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def get_open_filename(parent, title, directory, filt):
|
|
52
57
|
init()
|
|
53
58
|
path, selected = QtWidgets.QFileDialog.getOpenFileName(parent, title, directory, filt)
|
|
54
59
|
return path, selected
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
# совместимость со старыми шаблонами
|
|
63
|
+
open_file_dialog = get_open_filename
|
|
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
|
|
File without changes
|
|
File without changes
|