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.
Files changed (38) hide show
  1. {deskkit-1.2.1 → deskkit-1.2.2}/PKG-INFO +1 -1
  2. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/__init__.py +1 -1
  3. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/generator/export.py +46 -5
  4. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/generator/templates/qt_loader.py +10 -1
  5. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit.egg-info/PKG-INFO +1 -1
  6. {deskkit-1.2.1 → deskkit-1.2.2}/pyproject.toml +1 -1
  7. {deskkit-1.2.1 → deskkit-1.2.2}/LICENSE +0 -0
  8. {deskkit-1.2.1 → deskkit-1.2.2}/README.md +0 -0
  9. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/app.py +0 -0
  10. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/auth.py +0 -0
  11. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/builder.py +0 -0
  12. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/catalog.py +0 -0
  13. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/config.py +0 -0
  14. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/database.py +0 -0
  15. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/exceptions.py +0 -0
  16. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/features.py +0 -0
  17. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/flowchart.py +0 -0
  18. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/generator/__init__.py +0 -0
  19. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/generator/templates/auth.py +0 -0
  20. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/generator/templates/database.py +0 -0
  21. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/generator/templates/images_utils.py +0 -0
  22. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/generator/templates/main.py +0 -0
  23. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/images.py +0 -0
  24. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/presets.py +0 -0
  25. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/qt_backend.py +0 -0
  26. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/roles.py +0 -0
  27. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/tips.py +0 -0
  28. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/ui/__init__.py +0 -0
  29. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/ui/login_window.py +0 -0
  30. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/ui/main_window.py +0 -0
  31. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/ui/product_form.py +0 -0
  32. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit/ui/styles.py +0 -0
  33. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit.egg-info/SOURCES.txt +0 -0
  34. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit.egg-info/dependency_links.txt +0 -0
  35. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit.egg-info/requires.txt +0 -0
  36. {deskkit-1.2.1 → deskkit-1.2.2}/deskkit.egg-info/top_level.txt +0 -0
  37. {deskkit-1.2.1 → deskkit-1.2.2}/setup.cfg +0 -0
  38. {deskkit-1.2.1 → deskkit-1.2.2}/tests/test_catalog.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deskkit
3
- Version: 1.2.1
3
+ Version: 1.2.2
4
4
  Summary: Конструктор десктоп-приложений на Qt и MySQL с модульной сборкой и экспортом проекта
5
5
  Author: DeskKit Team
6
6
  License-Expression: MIT
@@ -16,7 +16,7 @@ from deskkit.qt_backend import backend_name, init_qt
16
16
  from deskkit.roles import ADMIN, CLIENT, GUEST, MANAGER
17
17
  from deskkit.tips import generate_tips
18
18
 
19
- __version__ = "1.2.1"
19
+ __version__ = "1.2.2"
20
20
 
21
21
  __all__ = [
22
22
  "ShopApp",
@@ -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
- if out.exists():
239
- shutil.rmtree(out, ignore_errors=True)
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 open_file_dialog(parent, title, directory, filt):
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deskkit
3
- Version: 1.2.1
3
+ Version: 1.2.2
4
4
  Summary: Конструктор десктоп-приложений на Qt и MySQL с модульной сборкой и экспортом проекта
5
5
  Author: DeskKit Team
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "deskkit"
7
- version = "1.2.1"
7
+ version = "1.2.2"
8
8
  description = "Конструктор десктоп-приложений на Qt и MySQL с модульной сборкой и экспортом проекта"
9
9
  readme = "README.md"
10
10
  license = "MIT"
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