django-cfg 1.1.78__py3-none-any.whl → 1.1.79__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.
django_cfg/__init__.py CHANGED
@@ -38,7 +38,7 @@ default_app_config = "django_cfg.apps.DjangoCfgConfig"
38
38
  from typing import TYPE_CHECKING
39
39
 
40
40
  # Version information
41
- __version__ = "1.1.78"
41
+ __version__ = "1.1.79"
42
42
  __author__ = "Unrealos Team"
43
43
  __email__ = "info@unrealos.com"
44
44
  __license__ = "MIT"
django_cfg/models/drf.py CHANGED
@@ -103,7 +103,8 @@ class SpectacularConfig(BaseModel):
103
103
  # Schema Settings
104
104
  schema_path_prefix: str = Field(default="/api", description="Schema path prefix")
105
105
  serve_include_schema: bool = Field(default=False, description="Include schema in UI")
106
- component_split_request: bool = Field(default=True, description="Split request components")
106
+ component_split_request: bool = Field(default=False, description="Split request components")
107
+ component_no_read_only_required: bool = Field(default=True, description="No read-only required")
107
108
  sort_operations: bool = Field(default=False, description="Sort operations")
108
109
 
109
110
  # UI Settings
@@ -139,7 +140,8 @@ class SpectacularConfig(BaseModel):
139
140
  "VERSION": self.version,
140
141
  "SERVE_INCLUDE_SCHEMA": self.serve_include_schema,
141
142
  "SCHEMA_PATH_PREFIX": self.schema_path_prefix,
142
- "COMPONENT_SPLIT_REQUEST": self.component_split_request,
143
+ 'COMPONENT_SPLIT_REQUEST': self.component_split_request,
144
+ 'COMPONENT_NO_READ_ONLY_REQUIRED': self.component_no_read_only_required,
143
145
  "SORT_OPERATIONS": self.sort_operations,
144
146
  # UI Settings
145
147
  "SWAGGER_UI_SETTINGS": self.swagger_ui_settings.to_dict(),
@@ -223,7 +223,7 @@ class LLMClient:
223
223
  temperature: Optional[float] = None,
224
224
  response_format: Optional[str] = None,
225
225
  **kwargs
226
- ) -> Dict[str, Any]:
226
+ ) -> ChatCompletionResponse:
227
227
  """
228
228
  Send chat completion request.
229
229
 
@@ -260,7 +260,8 @@ class LLMClient:
260
260
  if cached_response:
261
261
  logger.debug("Cache hit for chat completion")
262
262
  self.stats['cache_hits'] += 1
263
- return cached_response
263
+ # Convert cached dict back to Pydantic model
264
+ return ChatCompletionResponse(**cached_response)
264
265
 
265
266
  self.stats['cache_misses'] += 1
266
267
  self.stats['total_requests'] += 1
@@ -307,23 +308,33 @@ class LLMClient:
307
308
  if response_format == "json" and content:
308
309
  extracted_json = self.extractor.extract_json_from_response(content)
309
310
 
310
- # Create response object
311
- completion_response = {
312
- 'id': response.id,
313
- 'model': response.model,
314
- 'created': datetime.fromtimestamp(response.created).isoformat(),
315
- 'choices': [choice.model_dump() for choice in response.choices] if response.choices else [],
316
- 'usage': response.usage.model_dump() if response.usage else None,
317
- 'finish_reason': response.choices[0].finish_reason if response.choices else None,
318
- 'content': content,
319
- 'tokens_used': tokens_used,
320
- 'cost_usd': cost_usd,
321
- 'processing_time': processing_time,
322
- 'extracted_json': extracted_json
323
- }
311
+ # Create Pydantic response object
312
+ completion_response = ChatCompletionResponse(
313
+ id=response.id,
314
+ model=response.model,
315
+ created=datetime.fromtimestamp(response.created).isoformat(),
316
+ choices=[
317
+ ChatChoice(
318
+ index=choice.index,
319
+ message=choice.message.model_dump() if hasattr(choice.message, 'model_dump') else choice.message,
320
+ finish_reason=choice.finish_reason
321
+ ) for choice in response.choices
322
+ ] if response.choices else [],
323
+ usage=TokenUsage(
324
+ prompt_tokens=response.usage.prompt_tokens if response.usage else 0,
325
+ completion_tokens=response.usage.completion_tokens if response.usage else 0,
326
+ total_tokens=response.usage.total_tokens if response.usage else tokens_used
327
+ ) if response.usage else TokenUsage(total_tokens=tokens_used),
328
+ finish_reason=response.choices[0].finish_reason if response.choices else None,
329
+ content=content,
330
+ tokens_used=tokens_used,
331
+ cost_usd=cost_usd,
332
+ processing_time=processing_time,
333
+ extracted_json=extracted_json
334
+ )
324
335
 
325
- # Cache the response
326
- self.cache.set_response(request_hash, completion_response, model)
336
+ # Cache the response (serialize to dict for caching)
337
+ self.cache.set_response(request_hash, completion_response.model_dump(), model)
327
338
 
328
339
  # Update stats
329
340
  self.stats['successful_requests'] += 1
@@ -2,8 +2,9 @@
2
2
  Pydantic models for LLM client responses.
3
3
  """
4
4
 
5
+ import math
5
6
  from typing import List, Optional, Dict, Any, Union
6
- from pydantic import BaseModel, Field
7
+ from pydantic import BaseModel, Field, validator
7
8
  from datetime import datetime
8
9
 
9
10
 
@@ -34,6 +35,20 @@ class ChatCompletionResponse(BaseModel):
34
35
  cost_usd: float = Field(default=0.0, description="Cost in USD")
35
36
  processing_time: float = Field(default=0.0, description="Processing time in seconds")
36
37
  extracted_json: Optional[Dict[str, Any]] = Field(default=None, description="Extracted JSON if any")
38
+
39
+ @validator('cost_usd')
40
+ def validate_cost_usd(cls, v):
41
+ """Validate cost_usd to prevent NaN values."""
42
+ if v is None or math.isnan(v) or math.isinf(v):
43
+ return 0.0
44
+ return v
45
+
46
+ @validator('processing_time')
47
+ def validate_processing_time(cls, v):
48
+ """Validate processing_time to prevent NaN values."""
49
+ if v is None or math.isnan(v) or math.isinf(v):
50
+ return 0.0
51
+ return v
37
52
 
38
53
 
39
54
  class EmbeddingResponse(BaseModel):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-cfg
3
- Version: 1.1.78
3
+ Version: 1.1.79
4
4
  Summary: 🚀 Production-ready Django configuration framework with type-safe settings, smart automation, and modern developer experience
5
5
  Project-URL: Homepage, https://github.com/markolofsen/django-cfg
6
6
  Project-URL: Documentation, https://django-cfg.readthedocs.io
@@ -1,5 +1,5 @@
1
1
  django_cfg/README.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- django_cfg/__init__.py,sha256=MbG9uWTmuWMaiiEr0N5-NjZPefox3akijvvn-GRu9qw,14288
2
+ django_cfg/__init__.py,sha256=TXttkJ3xkHyfxtP_jCR0o6gDcDPRHsfs4DY8AmG0qFs,14288
3
3
  django_cfg/apps.py,sha256=k84brkeXJI7EgKZLEpTkM9YFZofKI4PzhFOn1cl9Msc,1656
4
4
  django_cfg/exceptions.py,sha256=RTQEoU3PfR8lqqNNv5ayd_HY2yJLs3eioqUy8VM6AG4,10378
5
5
  django_cfg/integration.py,sha256=jUO-uZXLmBXy9iugqgsl_xnYA_xoH3LZg5RxZbobVrc,4988
@@ -188,7 +188,7 @@ django_cfg/models/__init__.py,sha256=du24ZdqKdvc3VNXjgufEz_6B6gxdHtlqVHG4PJWaOQM
188
188
  django_cfg/models/cache.py,sha256=Oq6VwVgWAscMM3B91sEvbCX4rXNrP4diSt68_R4XCQk,12131
189
189
  django_cfg/models/constance.py,sha256=goR5gjvXIuuBWJJgUgdwzJXMvsGtnGFp8EwEPpviUWM,9694
190
190
  django_cfg/models/database.py,sha256=rewKwvBKwzsH-NBQZqIXv2xHheoPcz4KiDdyM-qCC3Q,16902
191
- django_cfg/models/drf.py,sha256=zOCj8yiNFMxWVIYIBWnaipJ8DywAGSNsz-LlsTGHsGQ,9362
191
+ django_cfg/models/drf.py,sha256=vewPiWFCyROPcM52cDxFPQEstyH7_bJ22B8acQe0zDw,9549
192
192
  django_cfg/models/jwt.py,sha256=3R_dpLmVZIcH4zdtwA4qKnuCB8RZQACrgsbbgWY2q4c,9025
193
193
  django_cfg/models/limits.py,sha256=NnTvz4iwtZEKZNx1LFudkLIqOgQq4fd5NVHSlDySXes,7444
194
194
  django_cfg/models/ngrok.py,sha256=MVgcKWx0DRSW0QcwhiSx2vVwTSG49vbVrzPkZqDK-zw,3575
@@ -215,10 +215,10 @@ django_cfg/modules/django_llm/__init__.py,sha256=Nirl7Ap3sv5qS5EWM0IEUl_ul-mSYac
215
215
  django_cfg/modules/django_llm/example.py,sha256=uL3hbRHHuvmWrNzMI7uSV5wrbIck5yqcgrfRGmA76Wg,13066
216
216
  django_cfg/modules/django_llm/llm/__init__.py,sha256=sLx3bbLUx1h-k5aYoljlAeIg9tDzyd5C9ZFJvccbNSA,192
217
217
  django_cfg/modules/django_llm/llm/cache.py,sha256=cYcbGpVF7zLUvLVvbqKtrJJnAPwno4ubL77UBI7x4bo,5653
218
- django_cfg/modules/django_llm/llm/client.py,sha256=MLAboZIGB0MFclvTtKZx1sVEVCmCujPULSRYkzxSoQY,22117
218
+ django_cfg/modules/django_llm/llm/client.py,sha256=g-AZ8K9dbLCFUd5eCmhFvyWfZB4kEIF-NO5rPVouJhc,22844
219
219
  django_cfg/modules/django_llm/llm/costs.py,sha256=1L5YTlIIJTWmY0_jKC8sEMZs1YRMDeStz-r-BpyZ2Vo,7490
220
220
  django_cfg/modules/django_llm/llm/extractor.py,sha256=6LCq3IZUO5zKefwNEQ4EkszLGLGEA_YFLvAUPoRBdMc,2694
221
- django_cfg/modules/django_llm/llm/models.py,sha256=6MxlRp2ll09mbSZrG6kNH6W_NZcLn_zHJ7d8YWAk1Ac,5529
221
+ django_cfg/modules/django_llm/llm/models.py,sha256=0bgKsjveu3wpfBTaDsFbdwMC95e08j8EQtlAuRyxVg8,6009
222
222
  django_cfg/modules/django_llm/llm/models_cache.py,sha256=HjnrikmqpaM9UguaAEE7SCXlPXYsw2Qj4bKYjUHF0Zk,20819
223
223
  django_cfg/modules/django_llm/llm/tokenizer.py,sha256=MMrb34Xl1u0yMUGQ4TRW40fP4NWbnOuwjBKkoOswu9g,2678
224
224
  django_cfg/modules/django_llm/translator/__init__.py,sha256=_gMsHBWEfiTFQvTk4UsHcXCyQBf2ilF82ISFRBbRBSU,247
@@ -271,8 +271,8 @@ django_cfg/templates/emails/base_email.html,sha256=TWcvYa2IHShlF_E8jf1bWZStRO0v8
271
271
  django_cfg/utils/__init__.py,sha256=64wwXJuXytvwt8Ze_erSR2HmV07nGWJ6DV5wloRBvYE,435
272
272
  django_cfg/utils/path_resolution.py,sha256=eML-6-RIGTs5TePktIQN8nxfDUEFJ3JA0AzWBcihAbs,13894
273
273
  django_cfg/utils/smart_defaults.py,sha256=-qaoiOQ1HKDOzwK2uxoNlmrOX6l8zgGlVPgqtdj3y4g,22319
274
- django_cfg-1.1.78.dist-info/METADATA,sha256=0AgHcZubcEDhURU4YIZaF6kauXiRNDS15vU0F6-oWP8,45783
275
- django_cfg-1.1.78.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
276
- django_cfg-1.1.78.dist-info/entry_points.txt,sha256=Ucmde4Z2wEzgb4AggxxZ0zaYDb9HpyE5blM3uJ0_VNg,56
277
- django_cfg-1.1.78.dist-info/licenses/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
278
- django_cfg-1.1.78.dist-info/RECORD,,
274
+ django_cfg-1.1.79.dist-info/METADATA,sha256=i_3vJLi7lYNsX5J1xj8UWKXvHxBnreYkfCFXSMj3DLk,45783
275
+ django_cfg-1.1.79.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
276
+ django_cfg-1.1.79.dist-info/entry_points.txt,sha256=Ucmde4Z2wEzgb4AggxxZ0zaYDb9HpyE5blM3uJ0_VNg,56
277
+ django_cfg-1.1.79.dist-info/licenses/LICENSE,sha256=xHuytiUkSZCRG3N11nk1X6q1_EGQtv6aL5O9cqNRhKE,1071
278
+ django_cfg-1.1.79.dist-info/RECORD,,