djangx 1.5.5__py3-none-any.whl → 1.5.7__py3-none-any.whl
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.
- djangx/__init__.py +14 -6
- djangx/api/enums.py +8 -0
- djangx/api/settings/databases.py +9 -8
- djangx/enums.py +2 -0
- djangx/management/cli.py +14 -1
- djangx/management/commands/generate.py +213 -14
- djangx/management/commands/startproject.py +562 -115
- djangx/management/enums.py +63 -0
- djangx/management/settings/apps.py +41 -83
- djangx/management/urls.py +5 -1
- {djangx-1.5.5.dist-info → djangx-1.5.7.dist-info}/METADATA +2 -1
- {djangx-1.5.5.dist-info → djangx-1.5.7.dist-info}/RECORD +14 -13
- djangx/management/commands/generators/__init__.py +0 -1
- djangx/management/commands/generators/file.py +0 -217
- {djangx-1.5.5.dist-info → djangx-1.5.7.dist-info}/WHEEL +0 -0
- {djangx-1.5.5.dist-info → djangx-1.5.7.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
from enum import StrEnum
|
|
2
|
+
|
|
3
|
+
from christianwhocodes.generators import FileGeneratorOption
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class FileOption(StrEnum):
|
|
7
|
+
PG_SERVICE = FileGeneratorOption.PG_SERVICE.value
|
|
8
|
+
PGPASS = FileGeneratorOption.PGPASS.value
|
|
9
|
+
SSH_CONFIG = FileGeneratorOption.SSH_CONFIG.value
|
|
10
|
+
ENV = "env"
|
|
11
|
+
SERVER = "server"
|
|
12
|
+
VERCEL = "vercel"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class PresetType(StrEnum):
|
|
16
|
+
"""Available project presets."""
|
|
17
|
+
|
|
18
|
+
DEFAULT = "default"
|
|
19
|
+
VERCEL = "vercel"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Apps(StrEnum):
|
|
23
|
+
"""Django applications enumeration."""
|
|
24
|
+
|
|
25
|
+
ADMIN = "django.contrib.admin"
|
|
26
|
+
AUTH = "django.contrib.auth"
|
|
27
|
+
CONTENTTYPES = "django.contrib.contenttypes"
|
|
28
|
+
SESSIONS = "django.contrib.sessions"
|
|
29
|
+
MESSAGES = "django.contrib.messages"
|
|
30
|
+
STATICFILES = "django.contrib.staticfiles"
|
|
31
|
+
HTTP_COMPRESSION = "django_http_compression"
|
|
32
|
+
MINIFY_HTML = "django_minify_html"
|
|
33
|
+
BROWSER_RELOAD = "django_browser_reload"
|
|
34
|
+
WATCHFILES = "django_watchfiles"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class ContextProcessors(StrEnum):
|
|
38
|
+
"""Django template context processors enumeration."""
|
|
39
|
+
|
|
40
|
+
DEBUG = "django.template.context_processors.debug"
|
|
41
|
+
REQUEST = "django.template.context_processors.request"
|
|
42
|
+
AUTH = "django.contrib.auth.context_processors.auth"
|
|
43
|
+
MESSAGES = "django.contrib.messages.context_processors.messages"
|
|
44
|
+
CSP = "django.template.context_processors.csp"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class Middlewares(StrEnum):
|
|
48
|
+
"""Django middleware enumeration."""
|
|
49
|
+
|
|
50
|
+
SECURITY = "django.middleware.security.SecurityMiddleware"
|
|
51
|
+
SESSION = "django.contrib.sessions.middleware.SessionMiddleware"
|
|
52
|
+
COMMON = "django.middleware.common.CommonMiddleware"
|
|
53
|
+
CSRF = "django.middleware.csrf.CsrfViewMiddleware"
|
|
54
|
+
AUTH = "django.contrib.auth.middleware.AuthenticationMiddleware"
|
|
55
|
+
MESSAGES = "django.contrib.messages.middleware.MessageMiddleware"
|
|
56
|
+
CLICKJACKING = "django.middleware.clickjacking.XFrameOptionsMiddleware"
|
|
57
|
+
CSP = "django.middleware.csp.ContentSecurityPolicyMiddleware"
|
|
58
|
+
HTTP_COMPRESSION = "django_http_compression.middleware.HttpCompressionMiddleware"
|
|
59
|
+
MINIFY_HTML = "django_minify_html.middleware.MinifyHtmlMiddleware"
|
|
60
|
+
BROWSER_RELOAD = "django_browser_reload.middleware.BrowserReloadMiddleware"
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
__all__: list[str] = ["FileOption", "PresetType", "Apps", "ContextProcessors", "Middlewares"]
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
"""# DjangX settings: Installed apps, middleware, templates, context processors."""
|
|
2
|
-
# TODO: Refactor so that the user can specify the order of apps, middleware, and context processors more flexibly.
|
|
3
|
-
|
|
4
|
-
from enum import StrEnum
|
|
5
|
-
|
|
6
1
|
from ... import (
|
|
2
|
+
INCLUDE_PROJECT_MAIN_APP,
|
|
7
3
|
PKG_API_NAME,
|
|
8
4
|
PKG_MANAGEMENT_NAME,
|
|
9
5
|
PKG_NAME,
|
|
@@ -12,28 +8,16 @@ from ... import (
|
|
|
12
8
|
Conf,
|
|
13
9
|
ConfField,
|
|
14
10
|
)
|
|
11
|
+
from ..enums import Apps, ContextProcessors, Middlewares
|
|
15
12
|
from ..types import TemplatesDict
|
|
16
13
|
|
|
14
|
+
# TODO: Refactor so that the user can specify the order of apps, middleware, and context processors more flexibly.
|
|
15
|
+
|
|
17
16
|
# ===============================================================
|
|
18
17
|
# Apps
|
|
19
18
|
# ===============================================================
|
|
20
19
|
|
|
21
20
|
|
|
22
|
-
class _Apps(StrEnum):
|
|
23
|
-
"""Django applications enumeration."""
|
|
24
|
-
|
|
25
|
-
ADMIN = "django.contrib.admin"
|
|
26
|
-
AUTH = "django.contrib.auth"
|
|
27
|
-
CONTENTTYPES = "django.contrib.contenttypes"
|
|
28
|
-
SESSIONS = "django.contrib.sessions"
|
|
29
|
-
MESSAGES = "django.contrib.messages"
|
|
30
|
-
STATICFILES = "django.contrib.staticfiles"
|
|
31
|
-
HTTP_COMPRESSION = "django_http_compression"
|
|
32
|
-
MINIFY_HTML = "django_minify_html"
|
|
33
|
-
BROWSER_RELOAD = "django_browser_reload"
|
|
34
|
-
WATCHFILES = "django_watchfiles"
|
|
35
|
-
|
|
36
|
-
|
|
37
21
|
class AppsConf(Conf):
|
|
38
22
|
"""Apps configuration settings."""
|
|
39
23
|
|
|
@@ -62,26 +46,26 @@ def _get_installed_apps() -> list[str]:
|
|
|
62
46
|
"""
|
|
63
47
|
|
|
64
48
|
base_apps: list[str] = [
|
|
65
|
-
PROJECT_MAIN_APP_NAME,
|
|
49
|
+
*([PROJECT_MAIN_APP_NAME] if INCLUDE_PROJECT_MAIN_APP else []),
|
|
66
50
|
PKG_NAME,
|
|
67
51
|
f"{PKG_NAME}.{PKG_API_NAME}",
|
|
68
52
|
f"{PKG_NAME}.{PKG_UI_NAME}",
|
|
69
53
|
]
|
|
70
54
|
|
|
71
55
|
third_party_apps: list[str] = [
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
56
|
+
Apps.HTTP_COMPRESSION,
|
|
57
|
+
Apps.MINIFY_HTML,
|
|
58
|
+
Apps.BROWSER_RELOAD,
|
|
59
|
+
Apps.WATCHFILES,
|
|
76
60
|
]
|
|
77
61
|
|
|
78
62
|
django_apps: list[str] = [
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
63
|
+
Apps.ADMIN,
|
|
64
|
+
Apps.AUTH,
|
|
65
|
+
Apps.CONTENTTYPES,
|
|
66
|
+
Apps.SESSIONS,
|
|
67
|
+
Apps.MESSAGES,
|
|
68
|
+
Apps.STATICFILES,
|
|
85
69
|
]
|
|
86
70
|
|
|
87
71
|
# Collect apps that should be removed except for base apps
|
|
@@ -106,19 +90,9 @@ INSTALLED_APPS: list[str] = _get_installed_apps()
|
|
|
106
90
|
# ===============================================================
|
|
107
91
|
|
|
108
92
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
DEBUG = "django.template.context_processors.debug"
|
|
113
|
-
REQUEST = "django.template.context_processors.request"
|
|
114
|
-
AUTH = "django.contrib.auth.context_processors.auth"
|
|
115
|
-
MESSAGES = "django.contrib.messages.context_processors.messages"
|
|
116
|
-
CSP = "django.template.context_processors.csp"
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
_APP_CONTEXT_PROCESSOR_MAP: dict[_Apps, list[_ContextProcessors]] = {
|
|
120
|
-
_Apps.AUTH: [_ContextProcessors.AUTH],
|
|
121
|
-
_Apps.MESSAGES: [_ContextProcessors.MESSAGES],
|
|
93
|
+
_APP_CONTEXT_PROCESSOR_MAP: dict[Apps, list[ContextProcessors]] = {
|
|
94
|
+
Apps.AUTH: [ContextProcessors.AUTH],
|
|
95
|
+
Apps.MESSAGES: [ContextProcessors.MESSAGES],
|
|
122
96
|
}
|
|
123
97
|
|
|
124
98
|
|
|
@@ -150,11 +124,11 @@ def _get_context_processors(installed_apps: list[str]) -> list[str]:
|
|
|
150
124
|
"""
|
|
151
125
|
# Django context processors in recommended order
|
|
152
126
|
django_context_processors: list[str] = [
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
127
|
+
ContextProcessors.DEBUG, # Debug info (only in DEBUG mode)
|
|
128
|
+
ContextProcessors.REQUEST, # Adds request object to context
|
|
129
|
+
ContextProcessors.AUTH, # Adds user and perms to context
|
|
130
|
+
ContextProcessors.MESSAGES, # Adds messages to context
|
|
131
|
+
ContextProcessors.CSP, # Content Security Policy
|
|
158
132
|
]
|
|
159
133
|
|
|
160
134
|
# Collect context processors that should be removed based on missing apps
|
|
@@ -192,29 +166,13 @@ TEMPLATES: TemplatesDict = [
|
|
|
192
166
|
# ===============================================================
|
|
193
167
|
|
|
194
168
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
AUTH = "django.contrib.auth.middleware.AuthenticationMiddleware"
|
|
203
|
-
MESSAGES = "django.contrib.messages.middleware.MessageMiddleware"
|
|
204
|
-
CLICKJACKING = "django.middleware.clickjacking.XFrameOptionsMiddleware"
|
|
205
|
-
CSP = "django.middleware.csp.ContentSecurityPolicyMiddleware"
|
|
206
|
-
HTTP_COMPRESSION = "django_http_compression.middleware.HttpCompressionMiddleware"
|
|
207
|
-
MINIFY_HTML = "django_minify_html.middleware.MinifyHtmlMiddleware"
|
|
208
|
-
BROWSER_RELOAD = "django_browser_reload.middleware.BrowserReloadMiddleware"
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
_APP_MIDDLEWARE_MAP: dict[_Apps, list[_Middlewares]] = {
|
|
212
|
-
_Apps.SESSIONS: [_Middlewares.SESSION],
|
|
213
|
-
_Apps.AUTH: [_Middlewares.AUTH],
|
|
214
|
-
_Apps.MESSAGES: [_Middlewares.MESSAGES],
|
|
215
|
-
_Apps.HTTP_COMPRESSION: [_Middlewares.HTTP_COMPRESSION],
|
|
216
|
-
_Apps.MINIFY_HTML: [_Middlewares.MINIFY_HTML],
|
|
217
|
-
_Apps.BROWSER_RELOAD: [_Middlewares.BROWSER_RELOAD],
|
|
169
|
+
_APP_MIDDLEWARE_MAP: dict[Apps, list[Middlewares]] = {
|
|
170
|
+
Apps.SESSIONS: [Middlewares.SESSION],
|
|
171
|
+
Apps.AUTH: [Middlewares.AUTH],
|
|
172
|
+
Apps.MESSAGES: [Middlewares.MESSAGES],
|
|
173
|
+
Apps.HTTP_COMPRESSION: [Middlewares.HTTP_COMPRESSION],
|
|
174
|
+
Apps.MINIFY_HTML: [Middlewares.MINIFY_HTML],
|
|
175
|
+
Apps.BROWSER_RELOAD: [Middlewares.BROWSER_RELOAD],
|
|
218
176
|
}
|
|
219
177
|
|
|
220
178
|
|
|
@@ -259,17 +217,17 @@ def _get_middleware(installed_apps: list[str]) -> list[str]:
|
|
|
259
217
|
- ABOVE any middleware that modifies HTML (like BrowserReloadMiddleware)
|
|
260
218
|
"""
|
|
261
219
|
django_middleware: list[str] = [
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
220
|
+
Middlewares.SECURITY, # FIRST - security headers, HTTPS redirect
|
|
221
|
+
Middlewares.SESSION, # Early - needed by auth & messages
|
|
222
|
+
Middlewares.COMMON, # Early - URL normalization
|
|
223
|
+
Middlewares.CSRF, # After session - needs session data
|
|
224
|
+
Middlewares.AUTH, # After session - stores user in session
|
|
225
|
+
Middlewares.MESSAGES, # After session & auth
|
|
226
|
+
Middlewares.CLICKJACKING, # Security headers (X-Frame-Options)
|
|
227
|
+
Middlewares.CSP, # Security headers (Content-Security-Policy)
|
|
228
|
+
Middlewares.HTTP_COMPRESSION, # Before minify - encodes responses (Zstandard, Brotli, Gzip)
|
|
229
|
+
Middlewares.MINIFY_HTML, # After compression, before HTML modifiers
|
|
230
|
+
Middlewares.BROWSER_RELOAD, # LAST - dev only, injects reload script into HTML
|
|
273
231
|
]
|
|
274
232
|
|
|
275
233
|
# Collect middleware that should be removed based on missing apps
|
djangx/management/urls.py
CHANGED
|
@@ -11,5 +11,9 @@ urlpatterns: list[URLPattern | URLResolver] = [
|
|
|
11
11
|
),
|
|
12
12
|
path("api/", include(f"{PKG_NAME}.api.urls")),
|
|
13
13
|
path("ui/", include(f"{PKG_NAME}.ui.urls")),
|
|
14
|
-
|
|
14
|
+
*(
|
|
15
|
+
[path("", include(f"{PROJECT_MAIN_APP_NAME}.urls"))]
|
|
16
|
+
if PROJECT_MAIN_APP_NAME in INSTALLED_APPS
|
|
17
|
+
else []
|
|
18
|
+
),
|
|
15
19
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: djangx
|
|
3
|
-
Version: 1.5.
|
|
3
|
+
Version: 1.5.7
|
|
4
4
|
Summary: Build and deploy Django apps with confidence.
|
|
5
5
|
Author: Kevin Wasike Wakhisi
|
|
6
6
|
Author-email: Kevin Wasike Wakhisi <kevin@christianwhocodes.space>
|
|
@@ -34,6 +34,7 @@ Requires-Dist: django-phonenumber-field[phonenumberslite]>=8.4.0
|
|
|
34
34
|
Requires-Dist: django-watchfiles>=1.4.0
|
|
35
35
|
Requires-Dist: pyperclip>=1.11.0
|
|
36
36
|
Requires-Dist: python-dotenv>=1.2.1
|
|
37
|
+
Requires-Dist: rich>=14.3.2
|
|
37
38
|
Requires-Python: >=3.12
|
|
38
39
|
Project-URL: homepage, https://github.com/christianwhocodes/djangx#readme
|
|
39
40
|
Project-URL: repository, https://github.com/christianwhocodes/djangx
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
djangx/__init__.py,sha256=
|
|
1
|
+
djangx/__init__.py,sha256=pQL6hUV-JZB182c8v2tg1o8znK2HM83NLi1Wcfwkdbo,12158
|
|
2
2
|
djangx/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
3
|
djangx/api/backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
djangx/api/backends/auth.py,sha256=VhV1jsLhLc5vNxg_1zeHOGxTL1rlcTx186OX7kaVhUg,1306
|
|
@@ -6,9 +6,10 @@ djangx/api/backends/server/__init__.py,sha256=5kCbtOg7dwz22NYBB8dksaHH4G3qLJ_8KU
|
|
|
6
6
|
djangx/api/backends/server/asgi.py,sha256=aMe3K0ow5ko5tHahnT4Ygux9O9eCf-WcPWP9iotEUYk,293
|
|
7
7
|
djangx/api/backends/server/wsgi.py,sha256=AHMDe1sDhZ3Is98ZcWUs8cFEiuMHR5VzG7J3Hvz2do4,293
|
|
8
8
|
djangx/api/backends/storages.py,sha256=zRQehQ7BEEamA9_1HS8WYIjOYRmGIZB4srlSaI6fbfQ,2726
|
|
9
|
+
djangx/api/enums.py,sha256=J0q9JV9D8KdcV_XE9kDu7vTQEz2lmYsD6lePLGhZa8c,153
|
|
9
10
|
djangx/api/settings/__init__.py,sha256=F2Qx0rqmUBNGdb6B6N8XLtJa73a44hq9DWxJgabSevs,147
|
|
10
11
|
djangx/api/settings/auth.py,sha256=iwFMOxsNByUI-6hl5114HfHAuKnKVd40mK85CAMlvnI,788
|
|
11
|
-
djangx/api/settings/databases.py,sha256=
|
|
12
|
+
djangx/api/settings/databases.py,sha256=2gLQYFifM6kS8YPlgrU51YuNmJu2M0RP6OYKuvce18w,3494
|
|
12
13
|
djangx/api/settings/server.py,sha256=pIz-OKy_M4xEVhnepDOS8xwHxFsDAOPodSO5fAK7cQc,550
|
|
13
14
|
djangx/api/settings/storages.py,sha256=R_BV2rZ0kWVb1f-XsRtwhOtzJ7TDOWA8nHNJab8rm6o,2156
|
|
14
15
|
djangx/api/types/__init__.py,sha256=v3jQUN6vGG5PxlUovE6ASkrVpmCIS9SEMQR17LHzd48,111
|
|
@@ -16,29 +17,29 @@ djangx/api/types/auth.py,sha256=UbOlzuqdnI23OUkD5EnVnA5i3hobD9MX2b7CsEZufNE,199
|
|
|
16
17
|
djangx/api/types/databases.py,sha256=RWym2lqzYGlszdPaV3kjJDxqxBWNHyQzRXA1zyxvmHk,738
|
|
17
18
|
djangx/api/types/storages.py,sha256=9_EFUS7NCnRF-5-zVDdrRod0mJM49HhhWSpIKGGvaSM,383
|
|
18
19
|
djangx/api/urls.py,sha256=PgfEM7aN03L2wxYDzx8Cn5ive2URfY-6lX-qWZvvwnA,98
|
|
20
|
+
djangx/enums.py,sha256=Z2fdGhX3ETR7oJ5n0Bx7yYjsdl1AfmqtV-Q_XFJ7zPQ,85
|
|
19
21
|
djangx/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
|
-
djangx/management/cli.py,sha256=
|
|
22
|
+
djangx/management/cli.py,sha256=G-81uWzW8u8fvoCp8tOnmdFnB7iXRh48EkEAWzE_ZlQ,2005
|
|
21
23
|
djangx/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
24
|
djangx/management/commands/collectstatic.py,sha256=vApmt5DNXhEfQkEBCypEkWePxKRk-FTJ756NnC21N3Q,1436
|
|
23
|
-
djangx/management/commands/generate.py,sha256=
|
|
24
|
-
djangx/management/commands/generators/__init__.py,sha256=_jGKXC6ojwGHLir15PDbTTgcnszlMTwFokUooFiDqP8,34
|
|
25
|
-
djangx/management/commands/generators/file.py,sha256=IB5QL1Ua_rjsHpO0dJapWgR9bHoku6GpAhVZ_mRX-QI,7456
|
|
25
|
+
djangx/management/commands/generate.py,sha256=TE0coXKuuUu5l0hep7s3dNpkp8GRYCHboplh7WCGgnI,9021
|
|
26
26
|
djangx/management/commands/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
27
|
djangx/management/commands/helpers/art.py,sha256=SuIYMx-HYGIsPfGtH5Fw4uRqw7ldXxi0vdzuZZsLheo,10148
|
|
28
28
|
djangx/management/commands/helpers/run.py,sha256=3GbtcIxQ5q1VwMR9S7H3ILaIQ0OB0yaTjzKGUDlZUAg,14624
|
|
29
29
|
djangx/management/commands/runbuild.py,sha256=0vkkJ2Z6bYj8V76q6igDB_JfueGpsXt1SG0jFftE2rc,2054
|
|
30
30
|
djangx/management/commands/runinstall.py,sha256=Jygt4EThDvvl6X0wsMw0o_WAacZllVVvLxPIykI7CRs,2082
|
|
31
31
|
djangx/management/commands/runserver.py,sha256=ZCmRm9BE3Q8XjjXy_-S9BS1zZBwoDDk9rxMshF5nXlc,11584
|
|
32
|
-
djangx/management/commands/startproject.py,sha256=
|
|
32
|
+
djangx/management/commands/startproject.py,sha256=A7mzyknRiDPkGhV7ZQPqCN3MS1tvkFExTkPTRaH-ahg,35739
|
|
33
33
|
djangx/management/commands/tailwind.py,sha256=FNDLwz6pSLkArW9yovGx8RoSSIRO7hS02r8W45NpNgM,20706
|
|
34
|
+
djangx/management/enums.py,sha256=7AJcuEWuAZsGYenaXF67JGN6gM_a3BImYWA2oXuOkKE,2242
|
|
34
35
|
djangx/management/settings/__init__.py,sha256=sjXuGaL_zPVsUEV-mkykhrzSM28_sfr_FdMEZaIqrKg,151
|
|
35
|
-
djangx/management/settings/apps.py,sha256=
|
|
36
|
+
djangx/management/settings/apps.py,sha256=V230WpGzXEbMjHCnq1GRISCQ-hxvdYKlCsbogrQ2p-4,9060
|
|
36
37
|
djangx/management/settings/runcommands.py,sha256=-zWhnrQY9ZuIPJB21gJvzkQtNzYFbdUX7afMKakjVLU,525
|
|
37
38
|
djangx/management/settings/security.py,sha256=ut6Chv53PiPZp4aLy0sLH4SMiON3v4JfdWojj_R84Y4,2030
|
|
38
39
|
djangx/management/settings/tailwind.py,sha256=cFYJvNUwege2xusvAt1McPckBKSchY8M6QwWoGBZb1Y,911
|
|
39
40
|
djangx/management/types/__init__.py,sha256=qI99KOrK1GVcV4wvJyz8whH2eObuLhleZBCZHlkMlmc,34
|
|
40
41
|
djangx/management/types/apps.py,sha256=yvzKQssr6B6pT4nAq9WSxZdE9eJkMZ8wxuzriQpNAkw,533
|
|
41
|
-
djangx/management/urls.py,sha256=
|
|
42
|
+
djangx/management/urls.py,sha256=gR8N8D9qlg51eEr0YPt25D-ZGJp0WpR0W3V_gMrgxAo,593
|
|
42
43
|
djangx/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
43
44
|
djangx/settings.py,sha256=rqEko9K7ZAPbAUmfN4lh-L9wugGRcHhZq5nRwMcETno,1151
|
|
44
45
|
djangx/types.py,sha256=48ZQEjzN4lPMUlw453XdZ28CX6itErzwvYik2eL0LFE,123
|
|
@@ -76,7 +77,7 @@ djangx/ui/types/contactinfo.py,sha256=nHRfZK_BBYMVk7TTibgRODSrwGKLlkHb-u1KFuMfRY
|
|
|
76
77
|
djangx/ui/types/org.py,sha256=nN2EFUu9tpdWguN7b2dmObVKHctuzkdS0c7Yfeh5MyI,215
|
|
77
78
|
djangx/ui/types/social.py,sha256=YD-SmQOkgYHpTAsQE0WqMurWAZH2GmNdn8PxFSt6qAc,206
|
|
78
79
|
djangx/ui/urls.py,sha256=PgfEM7aN03L2wxYDzx8Cn5ive2URfY-6lX-qWZvvwnA,98
|
|
79
|
-
djangx-1.5.
|
|
80
|
-
djangx-1.5.
|
|
81
|
-
djangx-1.5.
|
|
82
|
-
djangx-1.5.
|
|
80
|
+
djangx-1.5.7.dist-info/WHEEL,sha256=iHtWm8nRfs0VRdCYVXocAWFW8ppjHL-uTJkAdZJKOBM,80
|
|
81
|
+
djangx-1.5.7.dist-info/entry_points.txt,sha256=F7r_-JbHESYkJqpY3i7zvm1ejiLzKDFTfLWDlS_GMjc,88
|
|
82
|
+
djangx-1.5.7.dist-info/METADATA,sha256=rjThoKF2wEthsbEAVBnw4ROlUrdi5O9yBqFJoTHlSvs,2232
|
|
83
|
+
djangx-1.5.7.dist-info/RECORD,,
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from .file import * # noqa: F403
|
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
import builtins
|
|
2
|
-
import pathlib
|
|
3
|
-
from typing import Any, Optional, cast
|
|
4
|
-
|
|
5
|
-
from christianwhocodes.generators import FileGenerator
|
|
6
|
-
|
|
7
|
-
from .... import PKG_DISPLAY_NAME, PKG_NAME, PROJECT_API_DIR, PROJECT_DIR, Conf
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class ServerFileGenerator(FileGenerator):
|
|
11
|
-
f"""
|
|
12
|
-
Generator for ASGI / WSGI configuration in api/server.py file.
|
|
13
|
-
|
|
14
|
-
Creates an server.py file in the /api directory.
|
|
15
|
-
Required for running {PKG_DISPLAY_NAME} apps with ASGI or WSGI servers.
|
|
16
|
-
Note that the type of api gateway dependes on the SERVER_USE_ASGI setting.
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
@property
|
|
20
|
-
def file_path(self) -> pathlib.Path:
|
|
21
|
-
"""Return the path for the api/server.py"""
|
|
22
|
-
return PROJECT_API_DIR / "server.py"
|
|
23
|
-
|
|
24
|
-
@property
|
|
25
|
-
def data(self) -> str:
|
|
26
|
-
"""Return template content for api/server.py."""
|
|
27
|
-
return f"from {PKG_NAME}.api.backends.server import application\n\napp = application\n"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
class VercelFileGenerator(FileGenerator):
|
|
31
|
-
"""
|
|
32
|
-
Generator for Vercel configuration file (vercel.json).
|
|
33
|
-
|
|
34
|
-
Creates a vercel.json file in the base directory.
|
|
35
|
-
Useful for deploying to Vercel with custom install/build commands.
|
|
36
|
-
"""
|
|
37
|
-
|
|
38
|
-
@property
|
|
39
|
-
def file_path(self) -> pathlib.Path:
|
|
40
|
-
return PROJECT_DIR / "vercel.json"
|
|
41
|
-
|
|
42
|
-
@property
|
|
43
|
-
def data(self) -> str:
|
|
44
|
-
"""Return template content for vercel.json."""
|
|
45
|
-
lines = [
|
|
46
|
-
"{",
|
|
47
|
-
' "$schema": "https://openapi.vercel.sh/vercel.json",',
|
|
48
|
-
f' "installCommand": "uv run {PKG_NAME} runinstall",',
|
|
49
|
-
f' "buildCommand": "uv run {PKG_NAME} runbuild",',
|
|
50
|
-
' "rewrites": [',
|
|
51
|
-
" {",
|
|
52
|
-
' "source": "/(.*)",',
|
|
53
|
-
' "destination": "/api/server"',
|
|
54
|
-
" }",
|
|
55
|
-
" ]",
|
|
56
|
-
"}",
|
|
57
|
-
]
|
|
58
|
-
|
|
59
|
-
return "\n".join(lines) + "\n"
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
class EnvFileGenerator(FileGenerator):
|
|
63
|
-
"""
|
|
64
|
-
Generator for environment configuration file (.env.example).
|
|
65
|
-
|
|
66
|
-
Creates a .env.example file in the base directory with all
|
|
67
|
-
possible environment variables from configuration classes.
|
|
68
|
-
All variables are commented out by default.
|
|
69
|
-
"""
|
|
70
|
-
|
|
71
|
-
@property
|
|
72
|
-
def file_path(self) -> pathlib.Path:
|
|
73
|
-
"""Return the path for the .env.example file."""
|
|
74
|
-
return PROJECT_DIR / ".env.example"
|
|
75
|
-
|
|
76
|
-
@property
|
|
77
|
-
def data(self) -> str:
|
|
78
|
-
"""Generate .env file content based on all ConfFields from Conf subclasses."""
|
|
79
|
-
|
|
80
|
-
lines: list[str] = []
|
|
81
|
-
|
|
82
|
-
# Add header
|
|
83
|
-
lines.extend(self._add_header())
|
|
84
|
-
|
|
85
|
-
# Get all fields from Conf subclasses
|
|
86
|
-
env_fields = Conf.get_env_fields()
|
|
87
|
-
|
|
88
|
-
# Group fields by class
|
|
89
|
-
fields_by_class: dict[str, list[dict[str, Any]]] = {}
|
|
90
|
-
for field in env_fields:
|
|
91
|
-
class_name = cast(str, field["class"])
|
|
92
|
-
if class_name not in fields_by_class:
|
|
93
|
-
fields_by_class[class_name] = []
|
|
94
|
-
fields_by_class[class_name].append(field)
|
|
95
|
-
|
|
96
|
-
# Generate content for each class group
|
|
97
|
-
for class_name in sorted(fields_by_class.keys()):
|
|
98
|
-
fields = fields_by_class[class_name]
|
|
99
|
-
|
|
100
|
-
# Add section header
|
|
101
|
-
lines.extend(self._add_section_header(class_name))
|
|
102
|
-
|
|
103
|
-
# Process each field in this class
|
|
104
|
-
for field in fields:
|
|
105
|
-
env_var = field["env"]
|
|
106
|
-
toml_key = field["toml"]
|
|
107
|
-
choices_key = field["choices"]
|
|
108
|
-
default_value = field["default"]
|
|
109
|
-
field_type = field["type"]
|
|
110
|
-
|
|
111
|
-
# Add field documentation with proper format hints
|
|
112
|
-
lines.append(
|
|
113
|
-
f"# Variable: {self._format_variable_hint(env_var, choices_key, field_type)}"
|
|
114
|
-
)
|
|
115
|
-
if toml_key:
|
|
116
|
-
lines.append(f"# TOML Key: {toml_key}")
|
|
117
|
-
|
|
118
|
-
# Format default value for display
|
|
119
|
-
if default_value is not None:
|
|
120
|
-
formatted_default = self._format_default_value(default_value, field_type)
|
|
121
|
-
lines.append(f"# Default: {formatted_default}")
|
|
122
|
-
else:
|
|
123
|
-
lines.append("# Default: (none)")
|
|
124
|
-
|
|
125
|
-
lines.append(f"# {env_var}=")
|
|
126
|
-
|
|
127
|
-
lines.append("")
|
|
128
|
-
|
|
129
|
-
lines.append("")
|
|
130
|
-
|
|
131
|
-
# Add footer
|
|
132
|
-
lines.extend(self._add_footer())
|
|
133
|
-
|
|
134
|
-
return "\n".join(lines)
|
|
135
|
-
|
|
136
|
-
def _add_header(self) -> list[str]:
|
|
137
|
-
"""Add header to the .env.example file."""
|
|
138
|
-
lines: list[str] = []
|
|
139
|
-
lines.append("# " + "=" * 78)
|
|
140
|
-
lines.append(f"# {PKG_DISPLAY_NAME} Environment Configuration")
|
|
141
|
-
lines.append("# " + "=" * 78)
|
|
142
|
-
lines.append("#")
|
|
143
|
-
lines.append("# This file contains all available environment variables for configuration.")
|
|
144
|
-
lines.append("#")
|
|
145
|
-
lines.append("# Configuration Priority: ENV > TOML > Default")
|
|
146
|
-
lines.append("# " + "=" * 78)
|
|
147
|
-
lines.append("")
|
|
148
|
-
return lines
|
|
149
|
-
|
|
150
|
-
def _add_section_header(self, class_name: str) -> list[str]:
|
|
151
|
-
"""Add section header for a configuration class."""
|
|
152
|
-
lines: list[str] = []
|
|
153
|
-
lines.append("# " + "-" * 78)
|
|
154
|
-
lines.append(f"# {class_name} Configuration")
|
|
155
|
-
lines.append("# " + "-" * 78)
|
|
156
|
-
lines.append("")
|
|
157
|
-
return lines
|
|
158
|
-
|
|
159
|
-
def _add_footer(self) -> list[str]:
|
|
160
|
-
"""Add footer to the .env.example file."""
|
|
161
|
-
lines: list[str] = []
|
|
162
|
-
lines.append("# " + "=" * 78)
|
|
163
|
-
lines.append("# End of Configuration")
|
|
164
|
-
lines.append("# " + "=" * 78)
|
|
165
|
-
return lines
|
|
166
|
-
|
|
167
|
-
def _format_choices(self, choices: list[str]) -> str:
|
|
168
|
-
"""Format choices as 'choice1' | 'choice2' | 'choice3'."""
|
|
169
|
-
return " | ".join(f'"{choice}"' for choice in choices)
|
|
170
|
-
|
|
171
|
-
def _get_type_example(self, field_type: type) -> str:
|
|
172
|
-
"""Get example value for a field type."""
|
|
173
|
-
match field_type:
|
|
174
|
-
case builtins.bool:
|
|
175
|
-
return '"true" | "false"'
|
|
176
|
-
case builtins.int:
|
|
177
|
-
return '"123"'
|
|
178
|
-
case builtins.float:
|
|
179
|
-
return '"123.45"'
|
|
180
|
-
case builtins.list:
|
|
181
|
-
return '"value1,value2,value3"'
|
|
182
|
-
case pathlib.Path:
|
|
183
|
-
return '"/full/path/to/something"'
|
|
184
|
-
case _:
|
|
185
|
-
return '"value"'
|
|
186
|
-
|
|
187
|
-
def _format_variable_hint(
|
|
188
|
-
self, env_var: str, choices_key: Optional[list[str]], field_type: type
|
|
189
|
-
) -> str:
|
|
190
|
-
"""Format variable hint showing proper syntax based on type."""
|
|
191
|
-
if choices_key:
|
|
192
|
-
return f"{env_var}={self._format_choices(choices_key)}"
|
|
193
|
-
else:
|
|
194
|
-
return f"{env_var}={self._get_type_example(field_type)}"
|
|
195
|
-
|
|
196
|
-
def _format_default_value(self, value: Any, field_type: type) -> str:
|
|
197
|
-
"""Format default value for display in comments."""
|
|
198
|
-
if value is None:
|
|
199
|
-
return "(none)"
|
|
200
|
-
|
|
201
|
-
match field_type:
|
|
202
|
-
case builtins.bool:
|
|
203
|
-
return "true" if value else "false"
|
|
204
|
-
case builtins.list:
|
|
205
|
-
if isinstance(value, list):
|
|
206
|
-
list_items = cast(list[Any], value)
|
|
207
|
-
if not list_items:
|
|
208
|
-
return "(empty list)"
|
|
209
|
-
return ",".join(str(v) for v in list_items)
|
|
210
|
-
return str(value)
|
|
211
|
-
case pathlib.Path:
|
|
212
|
-
return str(pathlib.PurePosixPath(value))
|
|
213
|
-
case _:
|
|
214
|
-
return str(value)
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
__all__: list[str] = ["EnvFileGenerator", "ServerFileGenerator", "VercelFileGenerator"]
|
|
File without changes
|
|
File without changes
|