quickscale-cli 0.75.0__tar.gz → 0.79.0__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 (35) hide show
  1. quickscale_cli-0.79.0/PKG-INFO +60 -0
  2. quickscale_cli-0.79.0/README.md +37 -0
  3. {quickscale_cli-0.75.0 → quickscale_cli-0.79.0}/pyproject.toml +18 -19
  4. {quickscale_cli-0.75.0 → quickscale_cli-0.79.0}/src/quickscale_cli/_version.py +1 -1
  5. quickscale_cli-0.79.0/src/quickscale_cli/backups_contract.py +128 -0
  6. {quickscale_cli-0.75.0 → quickscale_cli-0.79.0}/src/quickscale_cli/commands/apply_command.py +522 -28
  7. {quickscale_cli-0.75.0 → quickscale_cli-0.79.0}/src/quickscale_cli/commands/deployment_commands.py +6 -1
  8. {quickscale_cli-0.75.0 → quickscale_cli-0.79.0}/src/quickscale_cli/commands/development_commands.py +122 -2
  9. {quickscale_cli-0.75.0 → quickscale_cli-0.79.0}/src/quickscale_cli/commands/module_commands.py +79 -3
  10. quickscale_cli-0.79.0/src/quickscale_cli/commands/module_config.py +1939 -0
  11. quickscale_cli-0.79.0/src/quickscale_cli/commands/module_wiring_specs.py +634 -0
  12. {quickscale_cli-0.75.0 → quickscale_cli-0.79.0}/src/quickscale_cli/commands/plan_command.py +217 -63
  13. {quickscale_cli-0.75.0 → quickscale_cli-0.79.0}/src/quickscale_cli/commands/status_command.py +1 -1
  14. {quickscale_cli-0.75.0 → quickscale_cli-0.79.0}/src/quickscale_cli/module_catalog.py +20 -0
  15. quickscale_cli-0.79.0/src/quickscale_cli/notifications_contract.py +296 -0
  16. {quickscale_cli-0.75.0 → quickscale_cli-0.79.0}/src/quickscale_cli/schema/config_schema.py +17 -3
  17. {quickscale_cli-0.75.0 → quickscale_cli-0.79.0}/src/quickscale_cli/schema/state_schema.py +11 -2
  18. quickscale_cli-0.79.0/src/quickscale_cli/social_contract.py +483 -0
  19. {quickscale_cli-0.75.0 → quickscale_cli-0.79.0}/src/quickscale_cli/utils/dependency_utils.py +7 -3
  20. {quickscale_cli-0.75.0 → quickscale_cli-0.79.0}/src/quickscale_cli/utils/docker_utils.py +12 -4
  21. {quickscale_cli-0.75.0 → quickscale_cli-0.79.0}/src/quickscale_cli/utils/module_wiring_manager.py +7 -1
  22. {quickscale_cli-0.75.0 → quickscale_cli-0.79.0}/src/quickscale_cli/utils/railway_utils.py +52 -12
  23. quickscale_cli-0.75.0/PKG-INFO +0 -380
  24. quickscale_cli-0.75.0/README.md +0 -354
  25. quickscale_cli-0.75.0/src/quickscale_cli/commands/module_config.py +0 -969
  26. quickscale_cli-0.75.0/src/quickscale_cli/commands/module_wiring_specs.py +0 -199
  27. {quickscale_cli-0.75.0 → quickscale_cli-0.79.0}/src/quickscale_cli/__init__.py +0 -0
  28. {quickscale_cli-0.75.0 → quickscale_cli-0.79.0}/src/quickscale_cli/commands/__init__.py +0 -0
  29. {quickscale_cli-0.75.0 → quickscale_cli-0.79.0}/src/quickscale_cli/commands/remove_command.py +0 -0
  30. {quickscale_cli-0.75.0 → quickscale_cli-0.79.0}/src/quickscale_cli/main.py +0 -0
  31. {quickscale_cli-0.75.0 → quickscale_cli-0.79.0}/src/quickscale_cli/schema/__init__.py +0 -0
  32. {quickscale_cli-0.75.0 → quickscale_cli-0.79.0}/src/quickscale_cli/schema/delta.py +0 -0
  33. {quickscale_cli-0.75.0 → quickscale_cli-0.79.0}/src/quickscale_cli/utils/__init__.py +0 -0
  34. {quickscale_cli-0.75.0 → quickscale_cli-0.79.0}/src/quickscale_cli/utils/project_identity.py +0 -0
  35. {quickscale_cli-0.75.0 → quickscale_cli-0.79.0}/src/quickscale_cli/utils/project_manager.py +0 -0
@@ -0,0 +1,60 @@
1
+ Metadata-Version: 2.4
2
+ Name: quickscale-cli
3
+ Version: 0.79.0
4
+ Summary: Command-line interface for QuickScale Django project generator
5
+ License-Expression: Apache-2.0
6
+ Keywords: django,cli,project-generator,saas
7
+ Author: Experto AI
8
+ Author-email: victor@experto.ai
9
+ Requires-Python: >=3.14,<4.0
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.14
14
+ Classifier: Framework :: Django
15
+ Classifier: Framework :: Django :: 6.0
16
+ Requires-Dist: click (>=8.3.1,<9.0.0)
17
+ Requires-Dist: quickscale-core (>=0.79.0,<0.80.0)
18
+ Project-URL: Documentation, https://github.com/Experto-AI/quickscale/tree/main/docs
19
+ Project-URL: Homepage, https://github.com/Experto-AI/quickscale
20
+ Project-URL: Repository, https://github.com/Experto-AI/quickscale
21
+ Description-Content-Type: text/markdown
22
+
23
+ # quickscale-cli
24
+
25
+ Command-line interface package for QuickScale.
26
+
27
+ This package exposes the `quickscale` command used to plan, apply, inspect, and operate generated projects.
28
+
29
+ ## Command groups
30
+
31
+ - Project lifecycle: `plan`, `apply`, `status`, `remove`
32
+ - Local development: `up`, `down`, `ps`, `logs`, `shell`, `manage`
33
+ - Deployment: `deploy`
34
+ - Module workflows: `update`, `push`
35
+
36
+ ## Relationship to other packages
37
+
38
+ - `quickscale-cli` is the command surface
39
+ - `quickscale-core` contains the underlying scaffolding and template logic
40
+ - `quickscale` installs both together for convenience
41
+
42
+ ## Install
43
+
44
+ Usually installed via the meta-package:
45
+
46
+ ```bash
47
+ pip install quickscale
48
+ ```
49
+
50
+ Standalone package installs can use this package's published metadata and dependency constraints.
51
+
52
+ ## Documentation
53
+
54
+ - Repository overview: [QuickScale README](https://github.com/Experto-AI/quickscale/blob/main/README.md)
55
+ - Start guide: [START_HERE.md](https://github.com/Experto-AI/quickscale/blob/main/START_HERE.md)
56
+ - Technical decisions: [docs/technical/decisions.md](https://github.com/Experto-AI/quickscale/blob/main/docs/technical/decisions.md)
57
+ - CLI source entrypoint: [src/quickscale_cli/main.py](https://github.com/Experto-AI/quickscale/blob/main/quickscale_cli/src/quickscale_cli/main.py)
58
+
59
+ This README is package-local context only. Root documentation remains authoritative for repo-wide policy and scope.
60
+
@@ -0,0 +1,37 @@
1
+ # quickscale-cli
2
+
3
+ Command-line interface package for QuickScale.
4
+
5
+ This package exposes the `quickscale` command used to plan, apply, inspect, and operate generated projects.
6
+
7
+ ## Command groups
8
+
9
+ - Project lifecycle: `plan`, `apply`, `status`, `remove`
10
+ - Local development: `up`, `down`, `ps`, `logs`, `shell`, `manage`
11
+ - Deployment: `deploy`
12
+ - Module workflows: `update`, `push`
13
+
14
+ ## Relationship to other packages
15
+
16
+ - `quickscale-cli` is the command surface
17
+ - `quickscale-core` contains the underlying scaffolding and template logic
18
+ - `quickscale` installs both together for convenience
19
+
20
+ ## Install
21
+
22
+ Usually installed via the meta-package:
23
+
24
+ ```bash
25
+ pip install quickscale
26
+ ```
27
+
28
+ Standalone package installs can use this package's published metadata and dependency constraints.
29
+
30
+ ## Documentation
31
+
32
+ - Repository overview: [QuickScale README](https://github.com/Experto-AI/quickscale/blob/main/README.md)
33
+ - Start guide: [START_HERE.md](https://github.com/Experto-AI/quickscale/blob/main/START_HERE.md)
34
+ - Technical decisions: [docs/technical/decisions.md](https://github.com/Experto-AI/quickscale/blob/main/docs/technical/decisions.md)
35
+ - CLI source entrypoint: [src/quickscale_cli/main.py](https://github.com/Experto-AI/quickscale/blob/main/quickscale_cli/src/quickscale_cli/main.py)
36
+
37
+ This README is package-local context only. Root documentation remains authoritative for repo-wide policy and scope.
@@ -1,39 +1,42 @@
1
- [tool.poetry]
1
+ [project]
2
2
  name = "quickscale-cli"
3
- version = "0.75.0"
3
+ version = "0.79.0"
4
4
  description = "Command-line interface for QuickScale Django project generator"
5
- authors = ["Experto AI <victor@experto.ai>"]
5
+ requires-python = ">=3.14,<4.0"
6
+ readme = "README.md"
6
7
  license = "Apache-2.0"
8
+ authors = [{name = "Experto AI", email = "victor@experto.ai"}]
7
9
  keywords = ["django", "cli", "project-generator", "saas"]
8
- homepage = "https://github.com/Experto-AI/quickscale"
9
- repository = "https://github.com/Experto-AI/quickscale"
10
- documentation = "https://github.com/Experto-AI/quickscale/tree/main/docs"
11
- readme = "README.md"
12
10
  classifiers = [
13
11
  "Development Status :: 3 - Alpha",
14
12
  "Intended Audience :: Developers",
15
- "License :: OSI Approved :: Apache Software License",
16
13
  "Programming Language :: Python :: 3",
17
- "Programming Language :: Python :: 3.12",
18
- "Programming Language :: Python :: 3.13",
19
14
  "Programming Language :: Python :: 3.14",
20
15
  "Framework :: Django",
21
16
  "Framework :: Django :: 6.0",
22
17
  ]
18
+ dynamic = ["dependencies"]
19
+
20
+ [project.urls]
21
+ Homepage = "https://github.com/Experto-AI/quickscale"
22
+ Repository = "https://github.com/Experto-AI/quickscale"
23
+ Documentation = "https://github.com/Experto-AI/quickscale/tree/main/docs"
24
+
25
+ [project.scripts]
26
+ quickscale = "quickscale_cli.main:cli"
27
+
28
+ [tool.poetry]
23
29
  packages = [{include = "quickscale_cli", from = "src"}]
24
30
 
25
31
  [tool.poetry.dependencies]
26
- python = "^3.12"
32
+ python = "^3.14"
27
33
  click = "^8.3.1"
28
- quickscale-core = "^0.75.0"
34
+ quickscale-core = "^0.79.0"
29
35
 
30
36
  [tool.poetry.group.dev.dependencies]
31
37
  # Dev dependencies centralized in root pyproject.toml
32
38
  # Use: poetry install from repository root
33
39
 
34
- [tool.poetry.scripts]
35
- quickscale = "quickscale_cli.main:cli"
36
-
37
40
  [build-system]
38
41
  requires = ["poetry-core"]
39
42
  build-backend = "poetry.core.masonry.api"
@@ -46,10 +49,6 @@ python_functions = ["test_*"]
46
49
  addopts = [
47
50
  "--strict-markers",
48
51
  "--strict-config",
49
- "--cov=quickscale_cli",
50
- "--cov-report=term-missing",
51
- "--cov-report=html",
52
- "--cov-fail-under=90",
53
52
  "-m", "not e2e", # Skip E2E tests by default (run with: pytest -m e2e)
54
53
  ]
55
54
  markers = [
@@ -1,2 +1,2 @@
1
1
  # Auto-generated by scripts/version_tool.sh
2
- __version__ = "0.75.0"
2
+ __version__ = "0.79.0"
@@ -0,0 +1,128 @@
1
+ """Shared backups-module configuration helpers.
2
+
3
+ This module centralizes the non-secret configuration contract used by the
4
+ planner, apply flow, and state persistence for the backups module.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from collections.abc import Mapping
10
+ import re
11
+ from typing import Any
12
+
13
+ from quickscale_cli.notifications_contract import normalize_notifications_module_options
14
+ from quickscale_cli.social_contract import normalize_social_module_options
15
+
16
+ DEFAULT_BACKUPS_REMOTE_ACCESS_KEY_ID_ENV_VAR = "QUICKSCALE_BACKUPS_REMOTE_ACCESS_KEY_ID"
17
+ DEFAULT_BACKUPS_REMOTE_SECRET_ACCESS_KEY_ENV_VAR = (
18
+ "QUICKSCALE_BACKUPS_REMOTE_SECRET_ACCESS_KEY"
19
+ )
20
+
21
+ BACKUPS_REMOTE_ACCESS_KEY_ID_ENV_VAR_OPTION = "remote_access_key_id_env_var"
22
+ BACKUPS_REMOTE_SECRET_ACCESS_KEY_ENV_VAR_OPTION = "remote_secret_access_key_env_var"
23
+
24
+ _LEGACY_BACKUPS_SECRET_OPTIONS = {
25
+ "remote_access_key_id": DEFAULT_BACKUPS_REMOTE_ACCESS_KEY_ID_ENV_VAR,
26
+ "remote_secret_access_key": DEFAULT_BACKUPS_REMOTE_SECRET_ACCESS_KEY_ENV_VAR,
27
+ }
28
+
29
+ _BACKUPS_ENV_VAR_NAME_PATTERN = re.compile(r"^[A-Z][A-Z0-9_]*$")
30
+ _LIKELY_AWS_ACCESS_KEY_ID_PATTERN = re.compile(r"^(?:AKIA|ASIA)[A-Z0-9]{16}$")
31
+
32
+
33
+ def normalize_backups_module_options(
34
+ options: Mapping[str, Any] | None,
35
+ ) -> dict[str, Any]:
36
+ """Return backups options with legacy raw-secret keys removed.
37
+
38
+ Legacy raw credential values are converted into conventional environment-variable
39
+ references so downstream persistence layers never re-store the secret values.
40
+ """
41
+ normalized = dict(options or {})
42
+
43
+ legacy_access_key_id = str(normalized.pop("remote_access_key_id", "")).strip()
44
+ legacy_secret_access_key = str(
45
+ normalized.pop("remote_secret_access_key", "")
46
+ ).strip()
47
+
48
+ access_key_env_var = str(
49
+ normalized.get(BACKUPS_REMOTE_ACCESS_KEY_ID_ENV_VAR_OPTION, "")
50
+ ).strip()
51
+ secret_access_key_env_var = str(
52
+ normalized.get(BACKUPS_REMOTE_SECRET_ACCESS_KEY_ENV_VAR_OPTION, "")
53
+ ).strip()
54
+
55
+ if legacy_access_key_id and not access_key_env_var:
56
+ normalized[BACKUPS_REMOTE_ACCESS_KEY_ID_ENV_VAR_OPTION] = (
57
+ DEFAULT_BACKUPS_REMOTE_ACCESS_KEY_ID_ENV_VAR
58
+ )
59
+ if legacy_secret_access_key and not secret_access_key_env_var:
60
+ normalized[BACKUPS_REMOTE_SECRET_ACCESS_KEY_ENV_VAR_OPTION] = (
61
+ DEFAULT_BACKUPS_REMOTE_SECRET_ACCESS_KEY_ENV_VAR
62
+ )
63
+
64
+ return normalized
65
+
66
+
67
+ def has_legacy_backups_secret_values(options: Mapping[str, Any] | None) -> bool:
68
+ """Return whether backups options still include legacy raw-secret keys."""
69
+ if not options:
70
+ return False
71
+
72
+ for option_name in _LEGACY_BACKUPS_SECRET_OPTIONS:
73
+ if str(options.get(option_name, "")).strip():
74
+ return True
75
+ return False
76
+
77
+
78
+ def validate_backups_env_var_reference(option_name: str, value: Any) -> str | None:
79
+ """Validate a backups env-var reference field.
80
+
81
+ Returns an actionable error string when the value is not a safe environment
82
+ variable name or appears to be a literal credential value.
83
+ """
84
+ candidate = str(value).strip()
85
+ if not candidate:
86
+ return None
87
+
88
+ qualified_option = f"modules.backups.{option_name}"
89
+ if not _BACKUPS_ENV_VAR_NAME_PATTERN.fullmatch(candidate):
90
+ return (
91
+ f"{qualified_option} must be an environment variable name matching "
92
+ "^[A-Z][A-Z0-9_]*$"
93
+ )
94
+
95
+ if option_name == BACKUPS_REMOTE_ACCESS_KEY_ID_ENV_VAR_OPTION:
96
+ if _LIKELY_AWS_ACCESS_KEY_ID_PATTERN.fullmatch(candidate):
97
+ return (
98
+ f"{qualified_option} must reference an environment variable name, "
99
+ "not a literal AWS access key id"
100
+ )
101
+
102
+ return None
103
+
104
+
105
+ def sanitize_module_options(
106
+ module_name: str,
107
+ options: Mapping[str, Any] | None,
108
+ ) -> dict[str, Any]:
109
+ """Return module options safe for config/state persistence."""
110
+ if module_name == "backups":
111
+ return normalize_backups_module_options(options)
112
+ if module_name == "notifications":
113
+ return normalize_notifications_module_options(options)
114
+ if module_name == "social":
115
+ return normalize_social_module_options(dict(options or {}))
116
+ return dict(options or {})
117
+
118
+
119
+ __all__ = [
120
+ "BACKUPS_REMOTE_ACCESS_KEY_ID_ENV_VAR_OPTION",
121
+ "BACKUPS_REMOTE_SECRET_ACCESS_KEY_ENV_VAR_OPTION",
122
+ "DEFAULT_BACKUPS_REMOTE_ACCESS_KEY_ID_ENV_VAR",
123
+ "DEFAULT_BACKUPS_REMOTE_SECRET_ACCESS_KEY_ENV_VAR",
124
+ "has_legacy_backups_secret_values",
125
+ "normalize_backups_module_options",
126
+ "sanitize_module_options",
127
+ "validate_backups_env_var_reference",
128
+ ]