django-cfg 1.4.110__py3-none-any.whl → 1.4.111__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 CHANGED
@@ -32,7 +32,7 @@ Example:
32
32
  default_app_config = "django_cfg.apps.DjangoCfgConfig"
33
33
 
34
34
  # Version information
35
- __version__ = "1.4.110"
35
+ __version__ = "1.4.111"
36
36
  __license__ = "MIT"
37
37
 
38
38
  # Import registry for organized lazy loading
@@ -521,6 +521,11 @@ class PydanticAdminMixin:
521
521
  if doc_config.show_management_commands:
522
522
  extra_context['management_commands'] = doc_config._discover_management_commands(app_path)
523
523
 
524
+ # Add Mermaid resources if plugins enabled
525
+ if doc_config.enable_plugins:
526
+ from django_cfg.modules.django_admin.utils.mermaid_plugin import get_mermaid_resources
527
+ extra_context['mermaid_resources'] = get_mermaid_resources()
528
+
524
529
  return super().changelist_view(request, extra_context)
525
530
 
526
531
  def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
@@ -541,6 +546,11 @@ class PydanticAdminMixin:
541
546
  if doc_config.show_management_commands:
542
547
  extra_context['management_commands'] = doc_config._discover_management_commands(app_path)
543
548
 
549
+ # Add Mermaid resources if plugins enabled
550
+ if doc_config.enable_plugins:
551
+ from django_cfg.modules.django_admin.utils.mermaid_plugin import get_mermaid_resources
552
+ extra_context['mermaid_resources'] = get_mermaid_resources()
553
+
544
554
  return super().changeform_view(request, object_id, form_url, extra_context)
545
555
 
546
556
  def formfield_for_dbfield(self, db_field, request, **kwargs):
@@ -1,5 +1,11 @@
1
1
  {% load static %}
2
- {# Multi-Section Markdown Documentation Block with Management Commands - Used with unfold hooks #}
2
+ {# Multi-Section Markdown Documentation Block with Management Commands and Mermaid Support #}
3
+
4
+ {# Load Mermaid resources once per page #}
5
+ {% if documentation_config.enable_plugins and not mermaid_loaded %}
6
+ {{ mermaid_resources|safe }}
7
+ {% with mermaid_loaded=True %}{% endwith %}
8
+ {% endif %}
3
9
 
4
10
  {% if documentation_config and documentation_sections or management_commands %}
5
11
  <div class="mb-6">
@@ -58,16 +58,32 @@ class MarkdownRenderer:
58
58
  _md_without_plugins = None
59
59
 
60
60
  @classmethod
61
- def _get_markdown_parser(cls, enable_plugins: bool = True):
62
- """Get or create markdown parser instance (singleton pattern)."""
61
+ def _get_markdown_parser(cls, enable_plugins: bool = True, enable_mermaid: bool = True):
62
+ """
63
+ Get or create markdown parser instance (singleton pattern).
64
+
65
+ Args:
66
+ enable_plugins: Enable standard mistune plugins
67
+ enable_mermaid: Enable Mermaid diagram support
68
+ """
63
69
  if not MISTUNE_AVAILABLE:
64
70
  return None
65
71
 
66
72
  if enable_plugins:
67
73
  if cls._md_with_plugins is None:
68
- cls._md_with_plugins = mistune.create_markdown(
74
+ # Import Mermaid plugin
75
+ from .mermaid_plugin import mermaid_plugin
76
+
77
+ # Create markdown with standard plugins
78
+ md = mistune.create_markdown(
69
79
  plugins=['strikethrough', 'table', 'url', 'task_lists', 'def_list']
70
80
  )
81
+
82
+ # Add Mermaid plugin if enabled
83
+ if enable_mermaid:
84
+ md = mermaid_plugin(md)
85
+
86
+ cls._md_with_plugins = md
71
87
  return cls._md_with_plugins
72
88
  else:
73
89
  if cls._md_without_plugins is None:
@@ -0,0 +1,288 @@
1
+ """
2
+ Mermaid diagram plugin for Mistune markdown parser.
3
+
4
+ Renders ```mermaid code blocks as interactive diagrams using Mermaid.js.
5
+ """
6
+
7
+ import re
8
+ from typing import Any, Dict
9
+
10
+
11
+ def mermaid_plugin(md):
12
+ """
13
+ Mistune plugin to render Mermaid diagrams.
14
+
15
+ Detects code fences with 'mermaid' language and renders them as
16
+ Mermaid diagram containers that will be processed by Mermaid.js.
17
+
18
+ Usage:
19
+ ```mermaid
20
+ graph TD
21
+ A[Start] --> B{Decision}
22
+ B -->|Yes| C[OK]
23
+ B -->|No| D[Cancel]
24
+ ```
25
+
26
+ Args:
27
+ md: Mistune markdown instance
28
+ """
29
+
30
+ def render_mermaid(text: str, **attrs: Any) -> str:
31
+ """
32
+ Render Mermaid diagram HTML.
33
+
34
+ Args:
35
+ text: Mermaid diagram code
36
+ **attrs: Additional attributes
37
+
38
+ Returns:
39
+ HTML with Mermaid container
40
+ """
41
+ # Generate unique ID for this diagram
42
+ import hashlib
43
+ diagram_id = f"mermaid-{hashlib.md5(text.encode()).hexdigest()[:8]}"
44
+
45
+ # Escape HTML special characters but preserve Mermaid syntax
46
+ escaped_text = text.strip()
47
+
48
+ # Return HTML container with Mermaid code
49
+ return f'''<div class="mermaid-container">
50
+ <div class="mermaid-wrapper">
51
+ <pre class="mermaid" id="{diagram_id}">
52
+ {escaped_text}
53
+ </pre>
54
+ </div>
55
+ </div>'''
56
+
57
+ # Override code block renderer for mermaid language
58
+ original_code = md.renderer.block_code
59
+
60
+ def patched_code(code: str, info: str = None, **attrs: Any) -> str:
61
+ """
62
+ Patched code block renderer that checks for mermaid language.
63
+
64
+ Args:
65
+ code: Code content
66
+ info: Language info
67
+ **attrs: Additional attributes
68
+
69
+ Returns:
70
+ Rendered code block (either Mermaid or normal code)
71
+ """
72
+ if info and info.strip().lower() == 'mermaid':
73
+ return render_mermaid(code, **attrs)
74
+ return original_code(code, info, **attrs)
75
+
76
+ md.renderer.block_code = patched_code
77
+
78
+ return md
79
+
80
+
81
+ def get_mermaid_styles() -> str:
82
+ """
83
+ Get CSS styles for Mermaid diagrams with Unfold semantic colors.
84
+
85
+ Returns:
86
+ CSS string for Mermaid container styling
87
+ """
88
+ return """
89
+ <style>
90
+ /* Mermaid container styles with Unfold semantic colors */
91
+ .mermaid-container {
92
+ margin: 1.5rem 0;
93
+ padding: 0;
94
+ }
95
+
96
+ .mermaid-wrapper {
97
+ border: 1px solid rgb(var(--color-base-200));
98
+ border-radius: 0.5rem;
99
+ padding: 1.5rem;
100
+ background: rgb(var(--color-base-50));
101
+ overflow-x: auto;
102
+ }
103
+
104
+ /* Dark mode styles with semantic colors */
105
+ .dark .mermaid-wrapper {
106
+ border-color: rgb(var(--color-base-700));
107
+ background: rgb(var(--color-base-900));
108
+ }
109
+
110
+ /* Mermaid diagram */
111
+ .mermaid {
112
+ display: flex;
113
+ justify-content: center;
114
+ background: transparent !important;
115
+ border: none !important;
116
+ padding: 0 !important;
117
+ margin: 0 !important;
118
+ font-family: inherit !important;
119
+ }
120
+
121
+ /* Ensure diagrams are centered */
122
+ .mermaid svg {
123
+ max-width: 100%;
124
+ height: auto;
125
+ }
126
+
127
+ /* Loading state with semantic colors */
128
+ .mermaid[data-processed="false"] {
129
+ color: rgb(var(--color-base-400));
130
+ text-align: center;
131
+ padding: 2rem;
132
+ }
133
+
134
+ .dark .mermaid[data-processed="false"] {
135
+ color: rgb(var(--color-base-500));
136
+ }
137
+
138
+ /* Error state with semantic colors */
139
+ .mermaid.error {
140
+ color: rgb(239, 68, 68);
141
+ border: 1px solid rgb(252, 165, 165);
142
+ background: rgb(254, 242, 242);
143
+ padding: 1rem;
144
+ border-radius: 0.375rem;
145
+ }
146
+
147
+ .dark .mermaid.error {
148
+ color: rgb(248, 113, 113);
149
+ border-color: rgb(153, 27, 27);
150
+ background: rgb(127, 29, 29);
151
+ }
152
+ </style>
153
+ """
154
+
155
+
156
+ def get_mermaid_script(theme: str = "default") -> str:
157
+ """
158
+ Get Mermaid.js initialization script with Unfold semantic colors.
159
+
160
+ Args:
161
+ theme: Mermaid theme ('default', 'dark', 'forest', 'neutral')
162
+
163
+ Returns:
164
+ HTML script tag with Mermaid.js and initialization
165
+ """
166
+ return f"""
167
+ <script type="module">
168
+ import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
169
+
170
+ // Helper to get CSS variable value
171
+ function getCSSVar(name) {{
172
+ const value = getComputedStyle(document.documentElement).getPropertyValue(name).trim();
173
+ // Convert "R, G, B" format to "#RRGGBB"
174
+ if (value.includes(',')) {{
175
+ const [r, g, b] = value.split(',').map(x => parseInt(x.trim()));
176
+ return '#' + [r, g, b].map(x => x.toString(16).padStart(2, '0')).join('');
177
+ }}
178
+ return value;
179
+ }}
180
+
181
+ // Auto-detect dark mode
182
+ const isDarkMode = document.documentElement.classList.contains('dark') ||
183
+ window.matchMedia('(prefers-color-scheme: dark)').matches;
184
+
185
+ // Get Unfold semantic colors
186
+ function getThemeColors() {{
187
+ if (isDarkMode) {{
188
+ return {{
189
+ primaryColor: '#3b82f6',
190
+ primaryTextColor: getCSSVar('--color-base-100'),
191
+ primaryBorderColor: getCSSVar('--color-base-700'),
192
+ lineColor: getCSSVar('--color-base-600'),
193
+ secondaryColor: getCSSVar('--color-base-800'),
194
+ tertiaryColor: getCSSVar('--color-base-700'),
195
+ background: getCSSVar('--color-base-900'),
196
+ mainBkg: getCSSVar('--color-base-800'),
197
+ secondBkg: getCSSVar('--color-base-700'),
198
+ border1: getCSSVar('--color-base-700'),
199
+ border2: getCSSVar('--color-base-600'),
200
+ note: getCSSVar('--color-base-800'),
201
+ noteText: getCSSVar('--color-base-200'),
202
+ noteBorder: getCSSVar('--color-base-600'),
203
+ text: getCSSVar('--color-base-200'),
204
+ critical: '#ef4444',
205
+ done: '#10b981',
206
+ active: '#3b82f6',
207
+ }};
208
+ }} else {{
209
+ return {{
210
+ primaryColor: '#2563eb',
211
+ primaryTextColor: getCSSVar('--color-base-900'),
212
+ primaryBorderColor: getCSSVar('--color-base-300'),
213
+ lineColor: getCSSVar('--color-base-400'),
214
+ secondaryColor: getCSSVar('--color-base-100'),
215
+ tertiaryColor: '#ffffff',
216
+ background: '#ffffff',
217
+ mainBkg: getCSSVar('--color-base-50'),
218
+ secondBkg: '#ffffff',
219
+ border1: getCSSVar('--color-base-300'),
220
+ border2: getCSSVar('--color-base-200'),
221
+ note: '#fef3c7',
222
+ noteText: getCSSVar('--color-base-900'),
223
+ noteBorder: '#fbbf24',
224
+ text: getCSSVar('--color-base-900'),
225
+ critical: '#dc2626',
226
+ done: '#059669',
227
+ active: '#2563eb',
228
+ }};
229
+ }}
230
+ }}
231
+
232
+ // Initialize Mermaid with Unfold semantic colors
233
+ mermaid.initialize({{
234
+ startOnLoad: true,
235
+ theme: 'base',
236
+ securityLevel: 'loose',
237
+ fontFamily: 'ui-sans-serif, system-ui, sans-serif',
238
+ themeVariables: getThemeColors()
239
+ }});
240
+
241
+ // Listen for dark mode changes and re-render
242
+ const observer = new MutationObserver((mutations) => {{
243
+ mutations.forEach((mutation) => {{
244
+ if (mutation.attributeName === 'class') {{
245
+ // Re-initialize with new theme colors
246
+ mermaid.initialize({{
247
+ startOnLoad: true,
248
+ theme: 'base',
249
+ securityLevel: 'loose',
250
+ fontFamily: 'ui-sans-serif, system-ui, sans-serif',
251
+ themeVariables: getThemeColors()
252
+ }});
253
+ // Re-render all diagrams
254
+ mermaid.run({{
255
+ querySelector: '.mermaid',
256
+ }});
257
+ }}
258
+ }});
259
+ }});
260
+
261
+ observer.observe(document.documentElement, {{
262
+ attributes: true,
263
+ attributeFilter: ['class'],
264
+ }});
265
+
266
+ // Error handling
267
+ window.addEventListener('error', (event) => {{
268
+ if (event.message && event.message.includes('mermaid')) {{
269
+ console.error('Mermaid error:', event);
270
+ const mermaidElements = document.querySelectorAll('.mermaid[data-processed="false"]');
271
+ mermaidElements.forEach(el => {{
272
+ el.classList.add('error');
273
+ el.textContent = 'Error rendering diagram. Check console for details.';
274
+ }});
275
+ }}
276
+ }});
277
+ </script>
278
+ """
279
+
280
+
281
+ def get_mermaid_resources() -> str:
282
+ """
283
+ Get complete Mermaid resources (styles + script).
284
+
285
+ Returns:
286
+ HTML string with styles and script for Mermaid support
287
+ """
288
+ return get_mermaid_styles() + get_mermaid_script()
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.110"
7
+ version = "1.4.111"
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",]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-cfg
3
- Version: 1.4.110
3
+ Version: 1.4.111
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=HbtRDtHlqf7LLLnJjYEq_tMe99Y4cjV_Kx8txhAOD_k,1621
2
+ django_cfg/__init__.py,sha256=nlFfAVPhDfA96placDSiyW_fDaW9Op6e1pCYQC1crb4,1621
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
@@ -670,7 +670,7 @@ django_cfg/modules/__init__.py,sha256=Ip9WMpzImEwIAywpFwU056_v0O9oIGG7nCT1YSArxk
670
670
  django_cfg/modules/base.py,sha256=Grmgxc5dvnAEM1sudWEWO4kv8L0Ks-y32nxTk2vwdjQ,6272
671
671
  django_cfg/modules/django_admin/__init__.py,sha256=ncTMbxR7ccVd5xS-sZE_yJODjVMFq8HDFaDnP6lyvIg,3328
672
672
  django_cfg/modules/django_admin/base/__init__.py,sha256=tzre09bnD_SlS-pA30WzYZRxyvch7eLq3q0wLEcZOmc,118
673
- django_cfg/modules/django_admin/base/pydantic_admin.py,sha256=EZnkPFXDHvqR-JtDfYvJfg5_Nocn7svgXvQdVsTbv9A,24389
673
+ django_cfg/modules/django_admin/base/pydantic_admin.py,sha256=6tB_8hZLT3ZzwUu6rlvzhkQ_BkDq8niaTE3TIa0IcgM,24977
674
674
  django_cfg/modules/django_admin/base/unfold_admin.py,sha256=iqpRWSkzW5HktXDuuG7G3J6RoIfW48dWPMJTa7Yk08g,729
675
675
  django_cfg/modules/django_admin/config/__init__.py,sha256=HDuJxhAS27EiL1pXLNvMePREB2gfoS2i_0Ur1ITCjAM,926
676
676
  django_cfg/modules/django_admin/config/action_config.py,sha256=JjS01JxLT-FzUVq7RlKaB7L38wmVL8uibXO_iXZcljo,1668
@@ -691,7 +691,7 @@ django_cfg/modules/django_admin/models/base.py,sha256=fmgS-X3GAGEBXiBy4OQGeOMzB7
691
691
  django_cfg/modules/django_admin/models/display_models.py,sha256=rONmja60Qz8n4qNvzjXIQryO_-UGZK136SrElO8iFfM,1087
692
692
  django_cfg/modules/django_admin/templates/django_admin/change_form_docs.html,sha256=MtP-UKebcOdz6YsZxLV5-UFq6WfmlV3mEF7qsCdYOKg,815
693
693
  django_cfg/modules/django_admin/templates/django_admin/change_list_docs.html,sha256=MfH6mf9v6E3y97TjvjvZ2A7RMhOkKd6CtxEw3tPV5WE,802
694
- django_cfg/modules/django_admin/templates/django_admin/documentation_block.html,sha256=IHB1dDGavvHNnez6modI1wJxvoXuZSQmsBu0nheYcZA,13974
694
+ django_cfg/modules/django_admin/templates/django_admin/documentation_block.html,sha256=fDUZYDWuB68NOm4fjTr0OLfqG2m-UpE-MZL1upkUNHc,14174
695
695
  django_cfg/modules/django_admin/templates/django_admin/markdown_docs_block.html,sha256=nO9oEyDYozYF-euaLzE0Cn_Yo_LGUlta-BsRgShDG10,1992
696
696
  django_cfg/modules/django_admin/utils/CODE_BLOCK_DOCS.md,sha256=rp5qMG-Ci30fIs6EyZctjEbhQwxfNq9e36B4CTZOnR0,9456
697
697
  django_cfg/modules/django_admin/utils/__init__.py,sha256=5V1Og6fpIpRqDIoqF7jYnBmPl9TjV5kByghzT6iOpPs,745
@@ -699,7 +699,8 @@ django_cfg/modules/django_admin/utils/badges.py,sha256=eZ1UThdwvv2cHAIDc4vTrD5xA
699
699
  django_cfg/modules/django_admin/utils/decorators.py,sha256=s4jTcgPklY4T4xjXsMHpShd71K_LzgKogem9JKBgNzk,8371
700
700
  django_cfg/modules/django_admin/utils/displays.py,sha256=f-FT1mD-X56X6xLDJ9FuCi4oz_UYirdLosYrXnJP3hI,7862
701
701
  django_cfg/modules/django_admin/utils/html_builder.py,sha256=EMzz1rGJCM7jTgfWb8LKqSdok1oq_oaWbBk6v9qvCrU,12831
702
- django_cfg/modules/django_admin/utils/markdown_renderer.py,sha256=nrMopdVA114W_UOvYFUtnbfj_Di0LHmtmrxG53hsn_Y,13834
702
+ django_cfg/modules/django_admin/utils/markdown_renderer.py,sha256=eMYde8cDo9y5CO5qNjy7juYe_OPpSpFB1-d84ylpbk4,14324
703
+ django_cfg/modules/django_admin/utils/mermaid_plugin.py,sha256=37x_0FQE5IyR6TiaDZDrQQHeQmAsPtlZBnq5N8eAKqA,8889
703
704
  django_cfg/modules/django_admin/widgets/__init__.py,sha256=mmPw5FMYR21GDGFMr-MOCcdM4G2_ZR60ClInHjdnTBE,115
704
705
  django_cfg/modules/django_admin/widgets/registry.py,sha256=q0Yyaze5ZTYLJslPyX9e4Few_FGLnGBQwtNln9Okyt4,5610
705
706
  django_cfg/modules/django_client/__init__.py,sha256=iHaGKbsyR2wMmVCWNsETC7cwB60fZudvnFMiK1bchW8,529
@@ -1053,9 +1054,9 @@ django_cfg/utils/version_check.py,sha256=WO51J2m2e-wVqWCRwbultEwu3q1lQasV67Mw2aa
1053
1054
  django_cfg/CHANGELOG.md,sha256=jtT3EprqEJkqSUh7IraP73vQ8PmKUMdRtznQsEnqDZk,2052
1054
1055
  django_cfg/CONTRIBUTING.md,sha256=DU2kyQ6PU0Z24ob7O_OqKWEYHcZmJDgzw-lQCmu6uBg,3041
1055
1056
  django_cfg/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
1056
- django_cfg/pyproject.toml,sha256=lz106jlJ2YsUxr9D0NqVgp5x2TZSNT1vbTrZ_YaeydQ,8637
1057
- django_cfg-1.4.110.dist-info/METADATA,sha256=xG_TAByn-K2qm3HlL_4cMNNHz4UpMrpV5hVIzTNGdKU,23836
1058
- django_cfg-1.4.110.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
1059
- django_cfg-1.4.110.dist-info/entry_points.txt,sha256=Ucmde4Z2wEzgb4AggxxZ0zaYDb9HpyE5blM3uJ0_VNg,56
1060
- django_cfg-1.4.110.dist-info/licenses/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
1061
- django_cfg-1.4.110.dist-info/RECORD,,
1057
+ django_cfg/pyproject.toml,sha256=gPSeLcWnzT8nOM1SW0-4PTlRjLnYYLTqGXeRnoDXN5w,8637
1058
+ django_cfg-1.4.111.dist-info/METADATA,sha256=zMEB1rQo52w6G3TcTEChugaK1CMRMdkJ9ClhP0VzcJ0,23836
1059
+ django_cfg-1.4.111.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
1060
+ django_cfg-1.4.111.dist-info/entry_points.txt,sha256=Ucmde4Z2wEzgb4AggxxZ0zaYDb9HpyE5blM3uJ0_VNg,56
1061
+ django_cfg-1.4.111.dist-info/licenses/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
1062
+ django_cfg-1.4.111.dist-info/RECORD,,