django-cfg 1.4.78__py3-none-any.whl → 1.4.80__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.78"
35
+ __version__ = "1.4.80"
36
36
  __license__ = "MIT"
37
37
 
38
38
  # Import registry for organized lazy loading
@@ -101,6 +101,10 @@ class CryptoFieldsConfig(BaseModel):
101
101
  # RevisionField will use package metadata or pyproject.toml instead
102
102
  if self.ignore_git_dir:
103
103
  settings["DJANGO_REVISION_IGNORE_WORKING_DIR"] = True
104
+ # Completely disable django-revision metadata checks to avoid errors
105
+ settings["DJANGO_REVISION_IGNORE_METADATA"] = True
106
+ # Set static revision to satisfy django-revision requirements
107
+ settings["REVISION"] = "1.0.0"
104
108
 
105
109
  return settings
106
110
 
@@ -333,6 +333,45 @@ class PydanticAdminMixin:
333
333
 
334
334
  return tuple(filtered_fieldsets)
335
335
 
336
+ def formfield_for_dbfield(self, db_field, request, **kwargs):
337
+ """
338
+ Override form field for specific database field types.
339
+
340
+ Automatically detects and customizes encrypted fields from django-crypto-fields.
341
+ """
342
+ # Check if this is an EncryptedTextField or EncryptedCharField
343
+ field_class_name = db_field.__class__.__name__
344
+ if 'Encrypted' in field_class_name and ('TextField' in field_class_name or 'CharField' in field_class_name):
345
+ from django import forms
346
+ from django.forms.widgets import PasswordInput
347
+
348
+ # Determine placeholder based on field name
349
+ placeholder = "Enter value"
350
+ if 'key' in db_field.name.lower():
351
+ placeholder = "Enter API Key"
352
+ elif 'secret' in db_field.name.lower():
353
+ placeholder = "Enter API Secret"
354
+ elif 'passphrase' in db_field.name.lower():
355
+ placeholder = "Enter Passphrase (if required)"
356
+
357
+ # Return CharField with PasswordInput widget for security
358
+ # render_value=True shows masked value (••••••) after save
359
+ return forms.CharField(
360
+ widget=PasswordInput(
361
+ attrs={
362
+ 'placeholder': placeholder,
363
+ 'class': 'appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500'
364
+ },
365
+ render_value=True # Show masked value after save
366
+ ),
367
+ required=not db_field.blank and not db_field.null,
368
+ help_text=db_field.help_text or "This field is encrypted at rest",
369
+ label=db_field.verbose_name if hasattr(db_field, 'verbose_name') else db_field.name.replace('_', ' ').title()
370
+ )
371
+
372
+ # Fall back to default Django behavior
373
+ return super().formfield_for_dbfield(db_field, request, **kwargs)
374
+
336
375
 
337
376
  class PydanticAdmin(PydanticAdminMixin, _get_base_admin_class()):
338
377
  """
@@ -125,7 +125,8 @@ class ModelsGenerator:
125
125
  return template.render(
126
126
  name=schema.name,
127
127
  docstring=docstring,
128
- fields=field_lines
128
+ fields=field_lines,
129
+ is_response_model=schema.is_response_model,
129
130
  )
130
131
 
131
132
  def _generate_field(
@@ -130,9 +130,8 @@ class OperationsGenerator:
130
130
 
131
131
  if return_type != "None":
132
132
  if operation.is_list_operation:
133
- # Paginated list response - extract results
134
- body_lines.append("data = response.json()")
135
- body_lines.append(f'return [{primary_response.schema_name}.model_validate(item) for item in data.get("results", [])]')
133
+ # Paginated list response - return full paginated object
134
+ body_lines.append(f"return {primary_response.schema_name}.model_validate(response.json())")
136
135
  else:
137
136
  body_lines.append(f"return {primary_response.schema_name}.model_validate(response.json())")
138
137
  else:
@@ -247,10 +246,9 @@ class OperationsGenerator:
247
246
  # Parse response
248
247
  if return_type != "None":
249
248
  if operation.is_list_operation:
250
- # List response - validate each item (paginated)
249
+ # List response - return full paginated object
251
250
  primary_schema = primary_response.schema_name
252
- body_lines.append("data = response.json()")
253
- body_lines.append(f'return [{primary_schema}.model_validate(item) for item in data.get("results", [])]')
251
+ body_lines.append(f"return {primary_schema}.model_validate(response.json())")
254
252
  else:
255
253
  # Single object response
256
254
  body_lines.append(f"return {return_type}.model_validate(response.json())")
@@ -7,7 +7,7 @@ class {{ name }}(BaseModel):
7
7
 
8
8
  model_config = ConfigDict(
9
9
  validate_assignment=True,
10
- extra="forbid",
10
+ extra="allow",
11
11
  frozen=False,
12
12
  )
13
13
  {% if fields %}
@@ -268,7 +268,18 @@ class IRSchemaObject(BaseModel):
268
268
  'int'
269
269
  >>> IRSchemaObject(name="x", type="string", nullable=True).python_type
270
270
  'str | None'
271
+ >>> IRSchemaObject(name="x", type="string", read_only=True).python_type
272
+ 'Any'
271
273
  """
274
+ # For read-only string fields, use Any since they often return complex objects
275
+ # from SerializerMethodField in Django (e.g., dicts instead of strings)
276
+ if self.read_only and self.type == "string":
277
+ return "Any | None" if self.nullable else "Any"
278
+
279
+ # For object fields without defined properties (like JSONField), use Any
280
+ if self.type == "object" and not self.properties:
281
+ return "Any | None" if self.nullable else "Any"
282
+
272
283
  type_map = {
273
284
  "string": "str",
274
285
  "integer": "int",
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.78"
7
+ version = "1.4.80"
8
8
  description = "Django AI framework with built-in agents, type-safe Pydantic v2 configuration, and 8 enterprise apps. Replace settings.py, validate at startup, 90% less code. Production-ready AI workflows for Django."
9
9
  readme = "README.md"
10
10
  keywords = [ "django", "configuration", "pydantic", "settings", "type-safety", "pydantic-settings", "django-environ", "startup-validation", "ide-autocomplete", "ai-agents", "enterprise-django", "django-settings", "type-safe-config",]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-cfg
3
- Version: 1.4.78
3
+ Version: 1.4.80
4
4
  Summary: Django AI framework with built-in agents, type-safe Pydantic v2 configuration, and 8 enterprise apps. Replace settings.py, validate at startup, 90% less code. Production-ready AI workflows for Django.
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=21SK6gwhcOqj9Lnv_SO7096Ttzk7mUK9gTytijxj__s,1620
2
+ django_cfg/__init__.py,sha256=23kwp6ZhrcdJ5AfibXPHviP6XGkCWYqGVjwyPLv_eUI,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
@@ -637,7 +637,7 @@ django_cfg/models/base/module.py,sha256=nxN1Y9J4l94kOfSXLQJ2eGgIGWTq8kyh7hUGvCQN
637
637
  django_cfg/models/django/__init__.py,sha256=xY_ts1oGmMROXfKHLuERqwG35dQf3EpsZxqj9DcRYwI,397
638
638
  django_cfg/models/django/axes.py,sha256=-4nk2gSfpj7lNY5vnm_2jHVLz8VAKoEd9yF2TuCR8O8,5624
639
639
  django_cfg/models/django/constance.py,sha256=E4U3HS_gFq5_q2nhI1R8inONGtD7IgvSwxOEGNGGrEI,9127
640
- django_cfg/models/django/crypto_fields.py,sha256=HZgV0lA8T7hvx8Np0l1OQoJbM_fA1VIrSoMDwXP25RE,3426
640
+ django_cfg/models/django/crypto_fields.py,sha256=ed8NC9aZr4F0ULt2-DjWFTx3i2FGGFF6XWGaXjQwNBI,3687
641
641
  django_cfg/models/django/environment.py,sha256=lBCHBs1lphv9tlu1BCTfLZeH_kUame0p66A_BIjBY7M,9440
642
642
  django_cfg/models/django/openapi.py,sha256=avE3iapaCj8eyOqVUum_v2EExR3V-hwHrexqtXMHtTQ,3739
643
643
  django_cfg/models/django/revolution_legacy.py,sha256=Z4SPUS7QSv62EuPAeFFoXGEgqLmdXnVEr7Ofk1IDtVc,8918
@@ -669,7 +669,7 @@ django_cfg/modules/__init__.py,sha256=Ip9WMpzImEwIAywpFwU056_v0O9oIGG7nCT1YSArxk
669
669
  django_cfg/modules/base.py,sha256=Grmgxc5dvnAEM1sudWEWO4kv8L0Ks-y32nxTk2vwdjQ,6272
670
670
  django_cfg/modules/django_admin/__init__.py,sha256=rWUY6Le2gO-szuuQyrUUP8sLIaTwkNDBexdK8Vbwzv0,3094
671
671
  django_cfg/modules/django_admin/base/__init__.py,sha256=tzre09bnD_SlS-pA30WzYZRxyvch7eLq3q0wLEcZOmc,118
672
- django_cfg/modules/django_admin/base/pydantic_admin.py,sha256=0xKaELl6rCdSkw_U2n0zxQehzlrFqAoF7KRJpGHxVII,13950
672
+ django_cfg/modules/django_admin/base/pydantic_admin.py,sha256=jCsueX1r_nD73FNeiFwhI149JKdpwIyQm0NCHmtNzXU,15976
673
673
  django_cfg/modules/django_admin/base/unfold_admin.py,sha256=iqpRWSkzW5HktXDuuG7G3J6RoIfW48dWPMJTa7Yk08g,729
674
674
  django_cfg/modules/django_admin/config/__init__.py,sha256=UJGJMP1iAguzd33E1BgeIjWaooFYylku3aR_Arib-cg,604
675
675
  django_cfg/modules/django_admin/config/action_config.py,sha256=JjS01JxLT-FzUVq7RlKaB7L38wmVL8uibXO_iXZcljo,1668
@@ -736,8 +736,8 @@ django_cfg/modules/django_client/core/generator/python/__init__.py,sha256=DOPkZB
736
736
  django_cfg/modules/django_client/core/generator/python/async_client_gen.py,sha256=zFviFo0PLg3Zb-0TL5AS_Ghhvl-jS180Cl-AWIAWIa0,6030
737
737
  django_cfg/modules/django_client/core/generator/python/files_generator.py,sha256=cgJVL6OZFXQFiy3trgCK5NDfGQWygQBJNaDepDQx4Vc,6420
738
738
  django_cfg/modules/django_client/core/generator/python/generator.py,sha256=N-wkvS9uzAD_EveO9Df74Hfseu47Zi2ZjDfklZtVbO0,7672
739
- django_cfg/modules/django_client/core/generator/python/models_generator.py,sha256=OszWuv1VgUJIUw-yH0KZBs1xpdiGNvAI9Jnn-DwaMXA,11922
740
- django_cfg/modules/django_client/core/generator/python/operations_generator.py,sha256=cOrL8wZhRlOECMXDTgfqjjhzZyhxJa1yQYMbGJjl1ms,10363
739
+ django_cfg/modules/django_client/core/generator/python/models_generator.py,sha256=STHAzFMXa_WluOmjR4HVM7ZK0LNz3nMCkaGdq6R-4h8,11979
740
+ django_cfg/modules/django_client/core/generator/python/operations_generator.py,sha256=RVrfxr6gdki9rJ8j9bXTn7sxKopTTtp1uRReO6aw83w,10200
741
741
  django_cfg/modules/django_client/core/generator/python/sync_client_gen.py,sha256=3UeC901JBWhlN5XfC1WDH9ulnZmddyB9nR6ncntelTU,3489
742
742
  django_cfg/modules/django_client/core/generator/python/templates/__init__.py.jinja,sha256=eZEZQSz9dc7wjMiFtBtXv_8zVevZozAXwEQ1r1ODpsc,136
743
743
  django_cfg/modules/django_client/core/generator/python/templates/api_wrapper.py.jinja,sha256=tSUUFmv7-UYE-proGfYsdNNe88fS69kzqfC6Afkg66Q,4513
@@ -758,7 +758,7 @@ django_cfg/modules/django_client/core/generator/python/templates/models/app_mode
758
758
  django_cfg/modules/django_client/core/generator/python/templates/models/enum_class.py.jinja,sha256=cRiJm1Vuhvs9lss_4uMa8SNR68awCZCMUVcEWUDYBXg,263
759
759
  django_cfg/modules/django_client/core/generator/python/templates/models/enums.py.jinja,sha256=bZQfel62sIuRVnkDprr2MUWpS1BSyZv68maKb8uak08,286
760
760
  django_cfg/modules/django_client/core/generator/python/templates/models/models.py.jinja,sha256=WzGhM3sQ6tQQ5XjGw-hVaiJSuhcp1Mh5RtXgFI0PFCw,251
761
- django_cfg/modules/django_client/core/generator/python/templates/models/schema_class.py.jinja,sha256=JszU-wAAwvQ3mSMkiyDtVOGKg_lUiSU3dbXWg1GORws,339
761
+ django_cfg/modules/django_client/core/generator/python/templates/models/schema_class.py.jinja,sha256=Cv82MTJjbxPVv_sKJptHjdR2vmeE-TloFDKFY7oFbG0,338
762
762
  django_cfg/modules/django_client/core/generator/python/templates/utils/logger.py.jinja,sha256=-mESMBFEsr8Jgy-76V5bm_Hiqqfg7xV_BasKS6zyBZA,7612
763
763
  django_cfg/modules/django_client/core/generator/python/templates/utils/retry.py.jinja,sha256=ie7oYfpO7_gUpJHkXcM70-POIldGdStHo12sd04v1n4,8141
764
764
  django_cfg/modules/django_client/core/generator/python/templates/utils/schema.py.jinja,sha256=xrnhAc-hNk6DigxHmTvhR3dyDFI9ocnkhL-_Hz9hCs8,270
@@ -811,7 +811,7 @@ django_cfg/modules/django_client/core/groups/manager.py,sha256=GLeIgCPoOy-pNHOH0
811
811
  django_cfg/modules/django_client/core/ir/__init__.py,sha256=58JBUka_gxjScbyTqGKrjOhIPbPQVqdyMMqs13vrSx0,2009
812
812
  django_cfg/modules/django_client/core/ir/context.py,sha256=We-XTjfhEOlasUv2wMhDuZonQ10O8c2-i5hJWcXRD-k,13801
813
813
  django_cfg/modules/django_client/core/ir/operation.py,sha256=gwvTciqIAUS0Hb7TqVU1Zr_StU9ulG3Vf73V7jYTp_U,17182
814
- django_cfg/modules/django_client/core/ir/schema.py,sha256=RlKWpTx44D6xyRkPlpFJjRvFJs_ar9bEc554KkKn1xg,11978
814
+ django_cfg/modules/django_client/core/ir/schema.py,sha256=TfG6iLlAJVa8Jtxis_nPmz4TrfTqRlocZFlv8pvBNj8,12561
815
815
  django_cfg/modules/django_client/core/parser/__init__.py,sha256=8luZt53hRdtLRPVMWG3zpaWK53sKGBabQGmkDCye4ow,2312
816
816
  django_cfg/modules/django_client/core/parser/base.py,sha256=BDivevszxdBThBEadv4yogBPdbdzuFsKDABUz4Ltf4E,23248
817
817
  django_cfg/modules/django_client/core/parser/openapi30.py,sha256=f4v4bNODtLf6ifajpmATarUDStDts_Lnh-_T87ZwYdA,1641
@@ -1124,9 +1124,9 @@ django_cfg/utils/version_check.py,sha256=WO51J2m2e-wVqWCRwbultEwu3q1lQasV67Mw2aa
1124
1124
  django_cfg/CHANGELOG.md,sha256=jtT3EprqEJkqSUh7IraP73vQ8PmKUMdRtznQsEnqDZk,2052
1125
1125
  django_cfg/CONTRIBUTING.md,sha256=DU2kyQ6PU0Z24ob7O_OqKWEYHcZmJDgzw-lQCmu6uBg,3041
1126
1126
  django_cfg/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
1127
- django_cfg/pyproject.toml,sha256=fSXYmVkODWUdpp7E6UGpJZH1uhCchV2In-tm8y8Z32c,8164
1128
- django_cfg-1.4.78.dist-info/METADATA,sha256=eid1ojBP7Qxwdx_73z__jpmiHo_ZOJD6GPddB3Y484A,22624
1129
- django_cfg-1.4.78.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
1130
- django_cfg-1.4.78.dist-info/entry_points.txt,sha256=Ucmde4Z2wEzgb4AggxxZ0zaYDb9HpyE5blM3uJ0_VNg,56
1131
- django_cfg-1.4.78.dist-info/licenses/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
1132
- django_cfg-1.4.78.dist-info/RECORD,,
1127
+ django_cfg/pyproject.toml,sha256=eHbkEV-f6L9c5uCtHaEyy49fzdU6FWSPuHLcHvSHGHw,8164
1128
+ django_cfg-1.4.80.dist-info/METADATA,sha256=H5IW2GvO9MKeeRKLhEzNghPDHgtBC36Rnbi7dKihSRA,22624
1129
+ django_cfg-1.4.80.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
1130
+ django_cfg-1.4.80.dist-info/entry_points.txt,sha256=Ucmde4Z2wEzgb4AggxxZ0zaYDb9HpyE5blM3uJ0_VNg,56
1131
+ django_cfg-1.4.80.dist-info/licenses/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
1132
+ django_cfg-1.4.80.dist-info/RECORD,,