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.
@@ -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
- _Apps.HTTP_COMPRESSION,
73
- _Apps.MINIFY_HTML,
74
- _Apps.BROWSER_RELOAD,
75
- _Apps.WATCHFILES,
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
- _Apps.ADMIN,
80
- _Apps.AUTH,
81
- _Apps.CONTENTTYPES,
82
- _Apps.SESSIONS,
83
- _Apps.MESSAGES,
84
- _Apps.STATICFILES,
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
- class _ContextProcessors(StrEnum):
110
- """Django template context processors enumeration."""
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
- _ContextProcessors.DEBUG, # Debug info (only in DEBUG mode)
154
- _ContextProcessors.REQUEST, # Adds request object to context
155
- _ContextProcessors.AUTH, # Adds user and perms to context
156
- _ContextProcessors.MESSAGES, # Adds messages to context
157
- _ContextProcessors.CSP, # Content Security Policy
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
- class _Middlewares(StrEnum):
196
- """Django middleware enumeration."""
197
-
198
- SECURITY = "django.middleware.security.SecurityMiddleware"
199
- SESSION = "django.contrib.sessions.middleware.SessionMiddleware"
200
- COMMON = "django.middleware.common.CommonMiddleware"
201
- CSRF = "django.middleware.csrf.CsrfViewMiddleware"
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
- _Middlewares.SECURITY, # FIRST - security headers, HTTPS redirect
263
- _Middlewares.SESSION, # Early - needed by auth & messages
264
- _Middlewares.COMMON, # Early - URL normalization
265
- _Middlewares.CSRF, # After session - needs session data
266
- _Middlewares.AUTH, # After session - stores user in session
267
- _Middlewares.MESSAGES, # After session & auth
268
- _Middlewares.CLICKJACKING, # Security headers (X-Frame-Options)
269
- _Middlewares.CSP, # Security headers (Content-Security-Policy)
270
- _Middlewares.HTTP_COMPRESSION, # Before minify - encodes responses (Zstandard, Brotli, Gzip)
271
- _Middlewares.MINIFY_HTML, # After compression, before HTML modifiers
272
- _Middlewares.BROWSER_RELOAD, # LAST - dev only, injects reload script into HTML
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
- path("", include(f"{PROJECT_MAIN_APP_NAME}.urls")),
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.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=jwKJYiHrStAWPLe8XdYpf2WeQgonrbNlEbeNLecn0R0,12006
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=0Gkz_d2O2cEhWho0_4tAP6sXUVx_HE1wGzQ_lflN1WI,3350
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=D-_S_LWPlhqSGeFXYhK6PMxn_FjTlsJOvIjwoIAgK8Y,1364
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=Fj_iLlhpA6SPpOErHTeL_-KWI5Ad3q7A_z9vkurwvsQ,2075
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=DwiFViRLx43nPFNy2gA5rJ3oWjP0IUJ7ymf882eJ6xM,17606
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=0hFTs1GDLgYVgdzZd1uPOPv95vjjQzDDsUs63wmLKzY,10794
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=xTMRABLKsrwptntiGK_-VAXkqH_VLXuXRSY1__TCdvk,507
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.5.dist-info/WHEEL,sha256=iHtWm8nRfs0VRdCYVXocAWFW8ppjHL-uTJkAdZJKOBM,80
80
- djangx-1.5.5.dist-info/entry_points.txt,sha256=F7r_-JbHESYkJqpY3i7zvm1ejiLzKDFTfLWDlS_GMjc,88
81
- djangx-1.5.5.dist-info/METADATA,sha256=q8lxLxfHbaXzAj9Kp9qnN43tGd5m-xEo1Uch5-DwQMM,2204
82
- djangx-1.5.5.dist-info/RECORD,,
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