core-framework 0.12.14__py3-none-any.whl → 0.12.15__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.
core/__init__.py CHANGED
@@ -287,7 +287,7 @@ from core.exceptions import (
287
287
  MissingDependency,
288
288
  )
289
289
 
290
- __version__ = "0.12.14"
290
+ __version__ = "0.12.15"
291
291
  __all__ = [
292
292
  # Models
293
293
  "Model",
core/migrations/engine.py CHANGED
@@ -561,6 +561,10 @@ migration = Migration(
561
561
  return None
562
562
 
563
563
  operations = self._diff_to_operations(diff)
564
+
565
+ if not operations:
566
+ print("No changes detected.")
567
+ return None
564
568
 
565
569
  # Gera nome da migração
566
570
  number = self._get_next_migration_number()
@@ -138,52 +138,80 @@ class ColumnDef:
138
138
 
139
139
  return self.type
140
140
 
141
+ def _format_default_value(self, value: Any, dialect: str) -> str | None:
142
+ """
143
+ Formata um valor para uso em cláusula DEFAULT SQL.
144
+
145
+ Args:
146
+ value: Valor a ser formatado
147
+ dialect: Nome do dialeto SQL
148
+
149
+ Returns:
150
+ String SQL formatada com DEFAULT ou None
151
+ """
152
+ from datetime import datetime, date, time
153
+
154
+ if value is None:
155
+ return None
156
+
157
+ if isinstance(value, bool):
158
+ if dialect == "postgresql":
159
+ return f"DEFAULT {'TRUE' if value else 'FALSE'}"
160
+ return f"DEFAULT {1 if value else 0}"
161
+
162
+ if isinstance(value, datetime):
163
+ # Format datetime as ISO string for SQL
164
+ return f"DEFAULT '{value.isoformat()}'"
165
+
166
+ if isinstance(value, date):
167
+ return f"DEFAULT '{value.isoformat()}'"
168
+
169
+ if isinstance(value, time):
170
+ return f"DEFAULT '{value.isoformat()}'"
171
+
172
+ if isinstance(value, str):
173
+ # Escape single quotes in strings
174
+ escaped = value.replace("'", "''")
175
+ return f"DEFAULT '{escaped}'"
176
+
177
+ if isinstance(value, (int, float)):
178
+ return f"DEFAULT {value}"
179
+
180
+ if isinstance(value, (dict, list)):
181
+ # JSON values - serialize and quote
182
+ import json
183
+ json_str = json.dumps(value).replace("'", "''")
184
+ return f"DEFAULT '{json_str}'"
185
+
186
+ # Fallback: convert to string
187
+ return f"DEFAULT '{str(value)}'"
188
+
141
189
  def _get_default_sql(self, dialect: str) -> str | None:
142
190
  """
143
191
  Gera SQL para valor default considerando o dialeto.
144
192
 
145
- Bug #2: Boolean defaults usando TRUE/FALSE para PostgreSQL
146
-
147
193
  Args:
148
194
  dialect: Nome do dialeto
149
195
 
150
196
  Returns:
151
197
  String SQL para o default ou None
152
-
153
- Note:
154
- Callable defaults (like timezone.now) cannot be used as SQL DEFAULT.
155
- They are handled by the application layer when creating records.
156
- For timestamp defaults, use server-side defaults like CURRENT_TIMESTAMP.
157
198
  """
158
199
  if self.default is None:
159
200
  return None
160
201
 
161
- # Callable defaults cannot be used in SQL - they're Python functions
162
- # The ORM handles these when creating records
202
+ # Callable defaults: execute and use the result
203
+ # This is the most robust approach - no need to detect function names
163
204
  if callable(self.default):
164
- # For datetime-related callables, use SQL equivalent
165
- func_name = getattr(self.default, "__name__", "") or getattr(self.default, "__qualname__", "")
166
- if "now" in func_name.lower() or "utcnow" in func_name.lower():
167
- if dialect == "postgresql":
168
- return "DEFAULT CURRENT_TIMESTAMP"
169
- elif dialect == "sqlite":
170
- return "DEFAULT CURRENT_TIMESTAMP"
171
- elif dialect == "mysql":
172
- return "DEFAULT CURRENT_TIMESTAMP"
173
- # For other callables, skip DEFAULT (handled by ORM)
174
- return None
175
-
176
- if isinstance(self.default, str):
177
- return f"DEFAULT '{self.default}'"
178
-
179
- if isinstance(self.default, bool):
180
- # PostgreSQL exige TRUE/FALSE em vez de 1/0
181
- if dialect == "postgresql":
182
- return f"DEFAULT {'TRUE' if self.default else 'FALSE'}"
183
- else:
184
- return f"DEFAULT {1 if self.default else 0}"
185
-
186
- return f"DEFAULT {self.default}"
205
+ try:
206
+ result = self.default()
207
+ # Format the result as SQL DEFAULT
208
+ return self._format_default_value(result, dialect)
209
+ except Exception:
210
+ # If callable fails (needs arguments, etc.), skip DEFAULT
211
+ return None
212
+
213
+ # Non-callable values: format directly
214
+ return self._format_default_value(self.default, dialect)
187
215
 
188
216
  def to_sql(self, dialect: str = "sqlite") -> str:
189
217
  """Gera SQL para a coluna, adaptado ao dialeto do banco."""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: core-framework
3
- Version: 0.12.14
3
+ Version: 0.12.15
4
4
  Summary: Core Framework - Django-inspired, FastAPI-powered. Alta performance, baixo acoplamento, produtividade extrema.
5
5
  Project-URL: Homepage, https://github.com/SorPuti/core-framework
6
6
  Project-URL: Documentation, https://github.com/SorPuti/core-framework#readme
@@ -1,4 +1,4 @@
1
- core/__init__.py,sha256=snols40N_-yCjaz9cgyqalmecS79-JSOyoyRWQJhWKc,12232
1
+ core/__init__.py,sha256=0zoqkiA-_T1-W1GV1nPu2FN9wKJrKfAz1TcoM2g6CU0,12232
2
2
  core/app.py,sha256=SsMC5Vlj6PNgACXlfeccOm6CQEKfgh3q3X2p9ubRDlQ,23092
3
3
  core/choices.py,sha256=rhcL3p2dB7RK99zIilpmoTFVcibQEIaRpz0CY0kImCE,10502
4
4
  core/config.py,sha256=dq4O7QBdrdwj-fZRe2yhX1fKyi_Uetb6sx9-RovJ-9c,14771
@@ -63,9 +63,9 @@ core/messaging/redis/producer.py,sha256=F9NA1GpYvN-wdW5Ilzi49rrAmxfBmicXX3l6sABW
63
63
  core/migrations/__init__.py,sha256=OF_7XQ9x9V_BWr3d8vDZk8W5QYT0RO3ZXNFnOg8UgDI,1908
64
64
  core/migrations/analyzer.py,sha256=QiwG_Xf_-Mb-Kp4hstkF8xNJD0Tvxgz20vqvYZ6xEXM,27287
65
65
  core/migrations/cli.py,sha256=mR3lIFTlXSvupFOPVlfuC-urJyDfNFR9nqYZn4TjIco,12019
66
- core/migrations/engine.py,sha256=UKvD7SAE8A7McL72LdOF6NHx7D90FAPyIwnKLZ5vueo,33125
66
+ core/migrations/engine.py,sha256=ynOfkP21siJAFibRl_ao6AVfAW2mxqHkLmAPxYliPhw,33243
67
67
  core/migrations/migration.py,sha256=Xv5MSNLvGAR9wnuMc4GRwciUSuU22AxWlWZP-hsVliI,2748
68
- core/migrations/operations.py,sha256=zAIusGVLae-K3TX7iDrViWRCEBGS1STpAZ67Ghi9vOM,31728
68
+ core/migrations/operations.py,sha256=qERdsLpNz3obqvQIAL-sRkFUspsMFaBAE4CBs9ZvGVc,32333
69
69
  core/migrations/state.py,sha256=eb_EYTE1tG-xQIwliS_-QTgr0y8-Jj0Va4C3nfpMrd4,15324
70
70
  core/tasks/__init__.py,sha256=rDP4PD7Qtw8qbSbOtxMco9w2wBxRJl5uHiLUEDM0DYI,1662
71
71
  core/tasks/base.py,sha256=0EWEzWTez0iF6nlI7Aw3stZtBk0Cr7zZ9btI89YdWPU,11762
@@ -87,7 +87,7 @@ example/auth.py,sha256=zBpLutb8lVKnGfQqQ2wnyygsSutHYZzeJBuhnFhxBaQ,4971
87
87
  example/models.py,sha256=xKdx0kJ9n0tZ7sCce3KhV3BTvKvsh6m7G69eFm3ukf0,4549
88
88
  example/schemas.py,sha256=wJ9QofnuHp4PjtM_IuMMBLVFVDJ4YlwcF6uQm1ooKiY,6139
89
89
  example/views.py,sha256=GQwgQcW6yoeUIDbF7-lsaZV7cs8G1S1vGVtiwVpZIQE,14338
90
- core_framework-0.12.14.dist-info/METADATA,sha256=7mZVblvxKc81kmvMiueoMT7WMG-ZCQuvXyl5uAYHP70,13021
91
- core_framework-0.12.14.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
92
- core_framework-0.12.14.dist-info/entry_points.txt,sha256=MJytamxHbn0CyH3HbxiP-PqOWekjYUo2CA6EWiKWuSI,78
93
- core_framework-0.12.14.dist-info/RECORD,,
90
+ core_framework-0.12.15.dist-info/METADATA,sha256=Ar1CjUVZj9hS2V_XmsPqeAKoKNg8IqoVIZn7wHVobaE,13021
91
+ core_framework-0.12.15.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
92
+ core_framework-0.12.15.dist-info/entry_points.txt,sha256=MJytamxHbn0CyH3HbxiP-PqOWekjYUo2CA6EWiKWuSI,78
93
+ core_framework-0.12.15.dist-info/RECORD,,