django-cfg 1.4.93__py3-none-any.whl → 1.4.95__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.
Potentially problematic release.
This version of django-cfg might be problematic. Click here for more details.
- django_cfg/__init__.py +1 -1
- django_cfg/apps/frontend/views.py +38 -36
- django_cfg/modules/nextjs_admin/views.py +16 -4
- django_cfg/pyproject.toml +1 -1
- django_cfg/static/frontend/nextjs_admin.zip +0 -0
- django_cfg/templatetags/django_cfg.py +19 -7
- {django_cfg-1.4.93.dist-info → django_cfg-1.4.95.dist-info}/METADATA +1 -1
- {django_cfg-1.4.93.dist-info → django_cfg-1.4.95.dist-info}/RECORD +11 -11
- {django_cfg-1.4.93.dist-info → django_cfg-1.4.95.dist-info}/WHEEL +0 -0
- {django_cfg-1.4.93.dist-info → django_cfg-1.4.95.dist-info}/entry_points.txt +0 -0
- {django_cfg-1.4.93.dist-info → django_cfg-1.4.95.dist-info}/licenses/LICENSE +0 -0
django_cfg/__init__.py
CHANGED
|
@@ -28,21 +28,24 @@ logger = logging.getLogger(__name__)
|
|
|
28
28
|
|
|
29
29
|
class ZipExtractionMixin:
|
|
30
30
|
"""
|
|
31
|
-
Mixin for automatic ZIP extraction with
|
|
31
|
+
Mixin for automatic ZIP extraction with age-based refresh.
|
|
32
32
|
|
|
33
33
|
Provides intelligent ZIP archive handling:
|
|
34
34
|
- Auto-extraction when directory doesn't exist
|
|
35
|
-
- Auto-reextraction when
|
|
36
|
-
-
|
|
35
|
+
- Auto-reextraction when extracted directory is older than 10 minutes
|
|
36
|
+
- Simple age-based logic (no ZIP timestamp comparison needed)
|
|
37
37
|
|
|
38
38
|
Usage:
|
|
39
39
|
class MyView(ZipExtractionMixin, View):
|
|
40
40
|
app_name = 'myapp' # Will look for myapp.zip
|
|
41
41
|
"""
|
|
42
42
|
|
|
43
|
+
# Maximum age of extracted directory before re-extraction (in seconds)
|
|
44
|
+
MAX_DIRECTORY_AGE = 600 # 10 minutes = 600 seconds
|
|
45
|
+
|
|
43
46
|
def extract_zip_if_needed(self, base_dir: Path, zip_path: Path, app_name: str) -> bool:
|
|
44
47
|
"""
|
|
45
|
-
Extract ZIP archive if needed based on
|
|
48
|
+
Extract ZIP archive if needed based on directory age.
|
|
46
49
|
|
|
47
50
|
Args:
|
|
48
51
|
base_dir: Target directory for extraction
|
|
@@ -57,33 +60,25 @@ class ZipExtractionMixin:
|
|
|
57
60
|
# Priority 1: If directory doesn't exist at all - always extract
|
|
58
61
|
if not base_dir.exists():
|
|
59
62
|
should_extract = True
|
|
60
|
-
logger.info(f"[{app_name}] Directory
|
|
61
|
-
|
|
62
|
-
# Priority 2: Directory exists - check if
|
|
63
|
-
|
|
64
|
-
# Get
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
# If
|
|
69
|
-
if
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
logger.
|
|
76
|
-
|
|
77
|
-
shutil.rmtree(base_dir)
|
|
78
|
-
should_extract = True
|
|
79
|
-
except Exception as e:
|
|
80
|
-
logger.error(f"[{app_name}] Failed to remove old directory: {e}")
|
|
81
|
-
return False
|
|
82
|
-
else:
|
|
83
|
-
logger.debug(f"[{app_name}] ZIP is fresh but directory is up-to-date")
|
|
63
|
+
logger.info(f"[{app_name}] Directory doesn't exist, will extract")
|
|
64
|
+
|
|
65
|
+
# Priority 2: Directory exists - check if it's too old
|
|
66
|
+
else:
|
|
67
|
+
# Get directory modification time
|
|
68
|
+
dir_mtime = datetime.fromtimestamp(base_dir.stat().st_mtime)
|
|
69
|
+
directory_age = (datetime.now() - dir_mtime).total_seconds()
|
|
70
|
+
|
|
71
|
+
# If directory is older than MAX_DIRECTORY_AGE - re-extract
|
|
72
|
+
if directory_age > self.MAX_DIRECTORY_AGE:
|
|
73
|
+
logger.info(f"[{app_name}] Directory is old ({directory_age:.0f}s > {self.MAX_DIRECTORY_AGE}s), re-extracting")
|
|
74
|
+
try:
|
|
75
|
+
shutil.rmtree(base_dir)
|
|
76
|
+
should_extract = True
|
|
77
|
+
except Exception as e:
|
|
78
|
+
logger.error(f"[{app_name}] Failed to remove old directory: {e}")
|
|
79
|
+
return False
|
|
84
80
|
else:
|
|
85
|
-
|
|
86
|
-
logger.debug(f"[{app_name}] ZIP is old ({time_since_modification:.0f}s), using existing")
|
|
81
|
+
logger.debug(f"[{app_name}] Directory is fresh ({directory_age:.0f}s), using existing")
|
|
87
82
|
|
|
88
83
|
# Extract ZIP if needed
|
|
89
84
|
if should_extract:
|
|
@@ -102,7 +97,7 @@ class ZipExtractionMixin:
|
|
|
102
97
|
logger.error(f"[{app_name}] ZIP not found: {zip_path}")
|
|
103
98
|
return False
|
|
104
99
|
|
|
105
|
-
# Directory exists and is
|
|
100
|
+
# Directory exists and is fresh
|
|
106
101
|
return True
|
|
107
102
|
|
|
108
103
|
|
|
@@ -113,17 +108,18 @@ class NextJSStaticView(ZipExtractionMixin, View):
|
|
|
113
108
|
|
|
114
109
|
Features:
|
|
115
110
|
- Serves Next.js static export files like a static file server
|
|
116
|
-
- Smart ZIP extraction: auto-
|
|
111
|
+
- Smart ZIP extraction: auto-refreshes when directory older than 10 minutes
|
|
117
112
|
- Automatically injects JWT tokens for authenticated users
|
|
118
113
|
- Tokens injected into HTML responses only
|
|
119
114
|
- Handles Next.js client-side routing (.html fallback)
|
|
120
115
|
- Automatically serves index.html for directory paths
|
|
121
116
|
- X-Frame-Options exempt to allow embedding in iframes
|
|
122
117
|
|
|
123
|
-
ZIP
|
|
124
|
-
- If
|
|
125
|
-
- If
|
|
126
|
-
-
|
|
118
|
+
ZIP Extraction Logic:
|
|
119
|
+
- If directory doesn't exist: extract from ZIP
|
|
120
|
+
- If directory older than 10 minutes: remove and re-extract
|
|
121
|
+
- If directory fresh (< 10 min): use existing files
|
|
122
|
+
- This enables auto-refresh during development while caching in production
|
|
127
123
|
|
|
128
124
|
Path resolution examples:
|
|
129
125
|
- /cfg/admin/ → /cfg/admin/index.html
|
|
@@ -191,6 +187,12 @@ class NextJSStaticView(ZipExtractionMixin, View):
|
|
|
191
187
|
if self._should_inject_jwt(request, response):
|
|
192
188
|
self._inject_jwt_tokens(request, response)
|
|
193
189
|
|
|
190
|
+
# Disable caching for HTML files (prevent Cloudflare/browser caching)
|
|
191
|
+
if is_html_file:
|
|
192
|
+
response['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0'
|
|
193
|
+
response['Pragma'] = 'no-cache'
|
|
194
|
+
response['Expires'] = '0'
|
|
195
|
+
|
|
194
196
|
return response
|
|
195
197
|
|
|
196
198
|
def _resolve_spa_path(self, base_dir, path):
|
|
@@ -4,8 +4,8 @@ Views for Next.js admin integration.
|
|
|
4
4
|
Serves Next.js static files with SPA routing support and JWT injection.
|
|
5
5
|
|
|
6
6
|
Features:
|
|
7
|
-
- Automatic extraction of ZIP archives with
|
|
8
|
-
- Auto-reextraction when
|
|
7
|
+
- Automatic extraction of ZIP archives with age-based refresh
|
|
8
|
+
- Auto-reextraction when directory is older than 10 minutes
|
|
9
9
|
- SPA routing with fallback strategies
|
|
10
10
|
- JWT token injection for authenticated users
|
|
11
11
|
"""
|
|
@@ -31,13 +31,19 @@ class NextJsAdminView(ZipExtractionMixin, LoginRequiredMixin, View):
|
|
|
31
31
|
|
|
32
32
|
Features:
|
|
33
33
|
- Serves Next.js static build files
|
|
34
|
+
- Smart ZIP extraction: auto-refreshes when directory older than 10 minutes
|
|
34
35
|
- Automatic JWT token injection for authenticated users
|
|
35
36
|
- SPA routing support (path/to/route → path/to/route/index.html)
|
|
36
37
|
- Development mode support (proxies to dev server conceptually)
|
|
37
38
|
|
|
39
|
+
ZIP Extraction Logic:
|
|
40
|
+
- If directory doesn't exist: extract from ZIP
|
|
41
|
+
- If directory older than 10 minutes: remove and re-extract
|
|
42
|
+
- If directory fresh (< 10 min): use existing files
|
|
43
|
+
|
|
38
44
|
URL Examples:
|
|
39
|
-
/cfg/admin/ →
|
|
40
|
-
/cfg/admin/
|
|
45
|
+
/cfg/admin/ → admin/index.html
|
|
46
|
+
/cfg/admin/crypto → admin/crypto/index.html
|
|
41
47
|
/cfg/admin/_next/static/... → _next/static/...
|
|
42
48
|
"""
|
|
43
49
|
|
|
@@ -108,6 +114,12 @@ class NextJsAdminView(ZipExtractionMixin, LoginRequiredMixin, View):
|
|
|
108
114
|
if is_html and request.user.is_authenticated:
|
|
109
115
|
self._inject_jwt_tokens(request, response)
|
|
110
116
|
|
|
117
|
+
# Disable caching for HTML files (prevent Cloudflare/browser caching)
|
|
118
|
+
if is_html:
|
|
119
|
+
response['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0'
|
|
120
|
+
response['Pragma'] = 'no-cache'
|
|
121
|
+
response['Expires'] = '0'
|
|
122
|
+
|
|
111
123
|
return response
|
|
112
124
|
|
|
113
125
|
def _resolve_spa_path(self, base_dir: Path, path: str, nextjs_config) -> str:
|
django_cfg/pyproject.toml
CHANGED
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "django-cfg"
|
|
7
|
-
version = "1.4.
|
|
7
|
+
version = "1.4.95"
|
|
8
8
|
description = "Modern Django framework with type-safe Pydantic v2 configuration, Next.js admin integration, real-time WebSockets, and 8 enterprise apps. Replace settings.py with validated models, 90% less code. Production-ready with AI agents, auto-generated TypeScript clients, and zero-config features."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
keywords = [ "django", "configuration", "pydantic", "settings", "type-safety", "pydantic-settings", "django-environ", "startup-validation", "ide-autocomplete", "nextjs-admin", "react-admin", "websocket", "centrifugo", "real-time", "typescript-generation", "ai-agents", "enterprise-django", "django-settings", "type-safe-config", "modern-django",]
|
|
Binary file
|
|
@@ -6,6 +6,7 @@ Provides template tags for accessing django-cfg configuration constants.
|
|
|
6
6
|
|
|
7
7
|
import os
|
|
8
8
|
import socket
|
|
9
|
+
import time
|
|
9
10
|
from django import template
|
|
10
11
|
from django.conf import settings
|
|
11
12
|
from django.utils.safestring import mark_safe
|
|
@@ -183,9 +184,13 @@ def nextjs_admin_url(path=''):
|
|
|
183
184
|
# Normalize path - remove leading/trailing slashes
|
|
184
185
|
path = path.strip('/')
|
|
185
186
|
|
|
187
|
+
# Add cache busting parameter (timestamp in milliseconds)
|
|
188
|
+
cache_buster = f'_={int(time.time() * 1000)}'
|
|
189
|
+
|
|
186
190
|
if not settings.DEBUG:
|
|
187
|
-
# Production mode: always use static files
|
|
188
|
-
|
|
191
|
+
# Production mode: always use static files with cache buster
|
|
192
|
+
base_url = f'/cfg/admin/admin/{path}' if path else '/cfg/admin/admin/'
|
|
193
|
+
return f'{base_url}?{cache_buster}'
|
|
189
194
|
|
|
190
195
|
# Check if port 3001 is available for Tab 1 (built-in admin)
|
|
191
196
|
port_3001_available = _is_port_available('localhost', 3001)
|
|
@@ -193,10 +198,12 @@ def nextjs_admin_url(path=''):
|
|
|
193
198
|
if port_3001_available:
|
|
194
199
|
# Dev server is running on 3001 - use it
|
|
195
200
|
base_url = 'http://localhost:3001/admin'
|
|
196
|
-
|
|
201
|
+
url = f'{base_url}/{path}' if path else base_url
|
|
202
|
+
return f'{url}?{cache_buster}'
|
|
197
203
|
else:
|
|
198
|
-
# No dev server or dev server stopped - use static files
|
|
199
|
-
|
|
204
|
+
# No dev server or dev server stopped - use static files with cache buster
|
|
205
|
+
base_url = f'/cfg/admin/admin/{path}' if path else '/cfg/admin/admin/'
|
|
206
|
+
return f'{base_url}?{cache_buster}'
|
|
200
207
|
|
|
201
208
|
|
|
202
209
|
@register.simple_tag
|
|
@@ -272,14 +279,19 @@ def nextjs_external_admin_url(route=''):
|
|
|
272
279
|
|
|
273
280
|
route = route.strip('/')
|
|
274
281
|
|
|
282
|
+
# Add cache busting parameter (timestamp in milliseconds)
|
|
283
|
+
cache_buster = f'_={int(time.time() * 1000)}'
|
|
284
|
+
|
|
275
285
|
# Auto-detect development mode: DEBUG=True + port 3000 available
|
|
276
286
|
if settings.DEBUG and _is_port_available('localhost', 3000):
|
|
277
287
|
# Development mode: solution project on port 3000
|
|
278
288
|
base_url = 'http://localhost:3000/admin'
|
|
279
|
-
|
|
289
|
+
url = f'{base_url}/{route}' if route else base_url
|
|
290
|
+
return f'{url}?{cache_buster}'
|
|
280
291
|
else:
|
|
281
292
|
# Production mode: use relative URL - Django serves from extracted ZIP with /admin prefix
|
|
282
|
-
|
|
293
|
+
base_url = f"/cfg/nextjs-admin/admin/{route}" if route else "/cfg/nextjs-admin/admin/"
|
|
294
|
+
return f'{base_url}?{cache_buster}'
|
|
283
295
|
except Exception:
|
|
284
296
|
return ''
|
|
285
297
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: django-cfg
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.95
|
|
4
4
|
Summary: Modern Django framework with type-safe Pydantic v2 configuration, Next.js admin integration, real-time WebSockets, and 8 enterprise apps. Replace settings.py with validated models, 90% less code. Production-ready with AI agents, auto-generated TypeScript clients, and zero-config features.
|
|
5
5
|
Project-URL: Homepage, https://djangocfg.com
|
|
6
6
|
Project-URL: Documentation, https://djangocfg.com
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
django_cfg/README.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
django_cfg/__init__.py,sha256=
|
|
2
|
+
django_cfg/__init__.py,sha256=FnIEFVmVUPO1EuonJ9G3Z2YKgVdqMoyS1vyH_zUM2NU,1620
|
|
3
3
|
django_cfg/apps.py,sha256=72m3uuvyqGiLx6gOfE-BD3P61jddCCERuBOYpxTX518,1605
|
|
4
4
|
django_cfg/config.py,sha256=y4Z3rnYsHBE0TehpwAIPaxr---mkvyKrZGGsNwYso74,1398
|
|
5
5
|
django_cfg/apps/__init__.py,sha256=JtDmEYt1OcleWM2ZaeX0LKDnRQzPOavfaXBWG4ECB5Q,26
|
|
@@ -228,7 +228,7 @@ django_cfg/apps/frontend/apps.py,sha256=9eEK0Tq2nOsol7xSK5aobdwTDJTJrWx6Iy1I1DQb
|
|
|
228
228
|
django_cfg/apps/frontend/setup.py,sha256=TxKQwQw4xTF6VSyhrQBzbUsdsVQR9JHdjc36LZKeQh4,2444
|
|
229
229
|
django_cfg/apps/frontend/test_routing.py,sha256=fshJOR9ln7m3gXY9EI1_ix_6E5xua6DR264b16RIF-w,4832
|
|
230
230
|
django_cfg/apps/frontend/urls.py,sha256=Vz22_2i2w1J0KQYDCxHnTF5rUf32kUUSBDJZrP07XgY,284
|
|
231
|
-
django_cfg/apps/frontend/views.py,sha256=
|
|
231
|
+
django_cfg/apps/frontend/views.py,sha256=c2IjtgKKYD-jZO0YtZEUumYtWZ3RKhEfwQaCW2pDn9g,13861
|
|
232
232
|
django_cfg/apps/frontend/templates/frontend/404.html,sha256=LCFig_dcgDDmYKhgOLu8R2KDs_aQS6Es6rAxLTAEXWs,2175
|
|
233
233
|
django_cfg/apps/knowbase/README.md,sha256=HXt_J6WCN-LsMhA7p9mdvih07_vp_r_hkPdmqHhNEeo,3965
|
|
234
234
|
django_cfg/apps/knowbase/__init__.py,sha256=cfGnxDQwjajPhUoleKkgvdabJcB0LdXEglnsBojKkPo,1045
|
|
@@ -1021,7 +1021,7 @@ django_cfg/modules/django_unfold/models/navigation.py,sha256=PPEeqA2HBaA1-VjADiX
|
|
|
1021
1021
|
django_cfg/modules/nextjs_admin/__init__.py,sha256=lfrZYyNRExH3Z5De8G4hQBIZoFlW5Ejze3couNrztbY,312
|
|
1022
1022
|
django_cfg/modules/nextjs_admin/apps.py,sha256=HxVUMmWTKdYpwJ00iIfWVFsBzsawsOVhEPZqjk_izjI,347
|
|
1023
1023
|
django_cfg/modules/nextjs_admin/urls.py,sha256=7n0yStm0WNchw14Rtu_mgsIA3WKQsYP9WZt3-YOUWjU,603
|
|
1024
|
-
django_cfg/modules/nextjs_admin/views.py,sha256=
|
|
1024
|
+
django_cfg/modules/nextjs_admin/views.py,sha256=9mbpt_WxEksx2YJq5FdjNRa0MtOh6Teq89PW6Dlnykc,9927
|
|
1025
1025
|
django_cfg/modules/nextjs_admin/models/__init__.py,sha256=WGw9KXcYd1O9AoA_bpMoz2gLZUlRzjGmUBjjbObcUi0,100
|
|
1026
1026
|
django_cfg/modules/nextjs_admin/models/config.py,sha256=0ADqLuiywSCQfx_z9dkwjFCca3lr3F2uQffIjTr_QXw,5864
|
|
1027
1027
|
django_cfg/modules/nextjs_admin/templatetags/__init__.py,sha256=ChVBnJggCIY8rMhfyJFoA8k0qKo-8FtJknrk54Vx4wM,51
|
|
@@ -1051,7 +1051,7 @@ django_cfg/static/admin/js/alpine/dashboard-tabs.js,sha256=ob8Q_I9lFLDv_hFERXgTy
|
|
|
1051
1051
|
django_cfg/static/admin/js/alpine/system-metrics.js,sha256=m-Fg55K_vpHXToD46PXL9twl4OBF_V9MONvbSWbQqDw,440
|
|
1052
1052
|
django_cfg/static/admin/js/alpine/toggle-section.js,sha256=T141NFmy0fRJyGGuuaCJRjJXwPam-xxtQNW1hi8BJbc,672
|
|
1053
1053
|
django_cfg/static/frontend/admin.zip,sha256=n2G8ajruLqojcjqvw2pMEPjgpSTTwcmJxkeIQxJVw9U,7626768
|
|
1054
|
-
django_cfg/static/frontend/nextjs_admin.zip,sha256=
|
|
1054
|
+
django_cfg/static/frontend/nextjs_admin.zip,sha256=GyHg6vnDOAXyanu-EwWZoSqT3Qz-765ZZ5QCSMbC1ig,7548295
|
|
1055
1055
|
django_cfg/static/js/api-loader.mjs,sha256=boGqqRGnFR-Mzo_RQOjhAzNvsb7QxZddSwMKROzkk9Q,5163
|
|
1056
1056
|
django_cfg/static/js/api/base.mjs,sha256=KUxZHHdELAV8mNnACpwJRvaQhdJxp-n5LFEQ4oUZxBo,4707
|
|
1057
1057
|
django_cfg/static/js/api/index.mjs,sha256=_-Q04jjHcgwi4CGfiaLyiOR6NW7Yu1HBhJWp2J1cjpc,2538
|
|
@@ -1077,7 +1077,7 @@ django_cfg/templates/admin/index.html,sha256=RidRvZwc6LFzRi8l6vHBgyM_CD0yvhPWvr4
|
|
|
1077
1077
|
django_cfg/templates/emails/base_email.html,sha256=TWcvYa2IHShlF_E8jf1bWZStRO0v8G4L_GexPxvz6XQ,8836
|
|
1078
1078
|
django_cfg/templates/unfold/layouts/skeleton.html,sha256=2ArkcNZ34mFs30cOAsTQ1EZiDXcB0aVxkO71lJq9SLE,718
|
|
1079
1079
|
django_cfg/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
1080
|
-
django_cfg/templatetags/django_cfg.py,sha256=
|
|
1080
|
+
django_cfg/templatetags/django_cfg.py,sha256=CXer0Jx7GVX8jZG1NBTGPZ2858BV4d81NklyaLnflOo,9844
|
|
1081
1081
|
django_cfg/utils/__init__.py,sha256=64wwXJuXytvwt8Ze_erSR2HmV07nGWJ6DV5wloRBvYE,435
|
|
1082
1082
|
django_cfg/utils/path_resolution.py,sha256=2n0I04lQkSssFaELu3A93YyMAl1K10KPdpxMt5k4Iy0,13341
|
|
1083
1083
|
django_cfg/utils/smart_defaults.py,sha256=ZUj6K_Deq-fp5O0Dy_Emt257UWFn0f9bkgFv9YCR58U,9239
|
|
@@ -1085,9 +1085,9 @@ django_cfg/utils/version_check.py,sha256=WO51J2m2e-wVqWCRwbultEwu3q1lQasV67Mw2aa
|
|
|
1085
1085
|
django_cfg/CHANGELOG.md,sha256=jtT3EprqEJkqSUh7IraP73vQ8PmKUMdRtznQsEnqDZk,2052
|
|
1086
1086
|
django_cfg/CONTRIBUTING.md,sha256=DU2kyQ6PU0Z24ob7O_OqKWEYHcZmJDgzw-lQCmu6uBg,3041
|
|
1087
1087
|
django_cfg/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
|
|
1088
|
-
django_cfg/pyproject.toml,sha256=
|
|
1089
|
-
django_cfg-1.4.
|
|
1090
|
-
django_cfg-1.4.
|
|
1091
|
-
django_cfg-1.4.
|
|
1092
|
-
django_cfg-1.4.
|
|
1093
|
-
django_cfg-1.4.
|
|
1088
|
+
django_cfg/pyproject.toml,sha256=De2uKACzSxO9s9tWIBeYa9veWb8OHwuuP0eZhdjOnoI,8572
|
|
1089
|
+
django_cfg-1.4.95.dist-info/METADATA,sha256=wHT5AT-_FxOZSLhJnQUA3JPDDHYmoBiAGj1g9m_Hiic,23733
|
|
1090
|
+
django_cfg-1.4.95.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
1091
|
+
django_cfg-1.4.95.dist-info/entry_points.txt,sha256=Ucmde4Z2wEzgb4AggxxZ0zaYDb9HpyE5blM3uJ0_VNg,56
|
|
1092
|
+
django_cfg-1.4.95.dist-info/licenses/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
|
|
1093
|
+
django_cfg-1.4.95.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|