core-framework 0.12.13__py3-none-any.whl → 0.12.14__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.13"
290
+ __version__ = "0.12.14"
291
291
  __all__ = [
292
292
  # Models
293
293
  "Model",
core/migrations/engine.py CHANGED
@@ -52,6 +52,41 @@ if TYPE_CHECKING:
52
52
  MIGRATIONS_TABLE = "_core_migrations"
53
53
 
54
54
 
55
+ def _detect_extra_imports(ops_code: str) -> list[str]:
56
+ """
57
+ Detect and return extra import statements needed for migration code.
58
+
59
+ Analyzes the generated operation code to find references like:
60
+ - timezone.now -> from core.datetime import timezone
61
+ - AdvancedField.xxx -> from core.fields import AdvancedField
62
+
63
+ Args:
64
+ ops_code: The generated operation code string
65
+
66
+ Returns:
67
+ List of import statements to add to the migration file
68
+ """
69
+ imports = set()
70
+
71
+ # Patterns for short-form callable references
72
+ # These match the output of _serialize_default()
73
+ patterns = [
74
+ # timezone.xxx -> from core.datetime import timezone
75
+ # Match timezone.now but not datetime.timezone.now
76
+ (r'(?<![.\w])timezone\.\w+', 'from core.datetime import timezone'),
77
+ # AdvancedField.xxx -> from core.fields import AdvancedField
78
+ (r'(?<![.\w])AdvancedField\.\w+', 'from core.fields import AdvancedField'),
79
+ # datetime.xxx -> from datetime import datetime (for full module path)
80
+ (r'(?<![.\w])datetime\.\w+', 'from datetime import datetime'),
81
+ ]
82
+
83
+ for pattern, import_stmt in patterns:
84
+ if re.search(pattern, ops_code):
85
+ imports.add(import_stmt)
86
+
87
+ return sorted(imports)
88
+
89
+
55
90
  def _get_migrations_table_sql(dialect: str) -> str:
56
91
  """
57
92
  Returns dialect-specific SQL for creating migrations table.
@@ -442,6 +477,10 @@ class MigrationEngine:
442
477
 
443
478
  ops_str = ",\n".join(ops_code) if ops_code else " # No operations"
444
479
 
480
+ # Detect and add extra imports needed for callable defaults
481
+ extra_imports = _detect_extra_imports(ops_str)
482
+ extra_imports_str = "\n".join(extra_imports) + "\n" if extra_imports else ""
483
+
445
484
  return f'''"""
446
485
  Migration: {name}
447
486
  Generated at: {timezone.now().isoformat()}
@@ -467,7 +506,7 @@ from core.migrations.operations import (
467
506
  DropEnum,
468
507
  AlterEnum,
469
508
  )
470
-
509
+ {extra_imports_str}
471
510
 
472
511
  migration = Migration(
473
512
  name="{name}",
@@ -26,7 +26,7 @@ def _serialize_default(value: Any) -> str:
26
26
  - None -> "None"
27
27
  - Strings -> repr()
28
28
  - Booleans -> "True"/"False"
29
- - Callables -> "module.function" (importable reference)
29
+ - Callables -> short name (e.g., "timezone.now" not "core.datetime.timezone.now")
30
30
  - Other -> repr()
31
31
 
32
32
  Args:
@@ -41,11 +41,21 @@ def _serialize_default(value: Any) -> str:
41
41
  if callable(value):
42
42
  # Get module and function name for proper serialization
43
43
  module = getattr(value, "__module__", "")
44
- name = getattr(value, "__qualname__", "") or getattr(value, "__name__", "")
45
-
46
- if module and name:
47
- # Return importable reference
48
- return f"{module}.{name}"
44
+ qualname = getattr(value, "__qualname__", "") or getattr(value, "__name__", "")
45
+
46
+ if module and qualname:
47
+ # Use short form for known modules to avoid long paths
48
+ # e.g., "core.datetime.timezone.now" -> "timezone.now"
49
+ # The corresponding import will be added to the migration file
50
+ if module == "core.datetime" and qualname.startswith("timezone."):
51
+ return qualname # Returns "timezone.now"
52
+ if module == "core.fields" and qualname.startswith("AdvancedField."):
53
+ return qualname # Returns "AdvancedField.json_field..."
54
+ if module == "datetime":
55
+ return f"datetime.{qualname}" # Returns "datetime.now"
56
+
57
+ # For other modules, return full path
58
+ return f"{module}.{qualname}"
49
59
 
50
60
  # Fallback for lambdas or unnamed functions
51
61
  return "None"
@@ -139,10 +149,30 @@ class ColumnDef:
139
149
 
140
150
  Returns:
141
151
  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.
142
157
  """
143
158
  if self.default is None:
144
159
  return None
145
160
 
161
+ # Callable defaults cannot be used in SQL - they're Python functions
162
+ # The ORM handles these when creating records
163
+ 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
+
146
176
  if isinstance(self.default, str):
147
177
  return f"DEFAULT '{self.default}'"
148
178
 
@@ -446,6 +476,27 @@ class AlterColumn(Operation):
446
476
  if self.set_default:
447
477
  changes.append(f"default to {self.new_default}")
448
478
  return f"Alter column '{self.column_name}' in '{self.table_name}': {', '.join(changes)}"
479
+
480
+ def to_code(self) -> str:
481
+ """Gera código Python para AlterColumn com serialização correta de callables."""
482
+ new_type_str = f"'{self.new_type}'" if self.new_type else "None"
483
+ old_type_str = f"'{self.old_type}'" if self.old_type else "None"
484
+
485
+ # Serializa defaults corretamente (callables, None, strings, etc.)
486
+ new_default_str = _serialize_default(self.new_default)
487
+ old_default_str = _serialize_default(self.old_default)
488
+
489
+ return f"""AlterColumn(
490
+ table_name='{self.table_name}',
491
+ column_name='{self.column_name}',
492
+ new_type={new_type_str},
493
+ new_nullable={self.new_nullable},
494
+ new_default={new_default_str},
495
+ set_default={self.set_default},
496
+ old_type={old_type_str},
497
+ old_nullable={self.old_nullable},
498
+ old_default={old_default_str},
499
+ )"""
449
500
 
450
501
 
451
502
  @dataclass
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: core-framework
3
- Version: 0.12.13
3
+ Version: 0.12.14
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=r4WjmhThQyLBWtdMdRPtmwvc_ksX_W7S5vQjkfYkSFA,12232
1
+ core/__init__.py,sha256=snols40N_-yCjaz9cgyqalmecS79-JSOyoyRWQJhWKc,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=jk8-wX8aKNBidUGyQ7ckHcUsukNJYpgSva-Sp-Iu-L4,31590
66
+ core/migrations/engine.py,sha256=UKvD7SAE8A7McL72LdOF6NHx7D90FAPyIwnKLZ5vueo,33125
67
67
  core/migrations/migration.py,sha256=Xv5MSNLvGAR9wnuMc4GRwciUSuU22AxWlWZP-hsVliI,2748
68
- core/migrations/operations.py,sha256=K2LuETDJnDFdi2UTa6Z7hTs05ucAPEgHgaBHySY1Z3I,29102
68
+ core/migrations/operations.py,sha256=zAIusGVLae-K3TX7iDrViWRCEBGS1STpAZ67Ghi9vOM,31728
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.13.dist-info/METADATA,sha256=yTAocMiU4__UMmo8YL_t8Uwg7i8_5NsX5J01_imP82M,13021
91
- core_framework-0.12.13.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
92
- core_framework-0.12.13.dist-info/entry_points.txt,sha256=MJytamxHbn0CyH3HbxiP-PqOWekjYUo2CA6EWiKWuSI,78
93
- core_framework-0.12.13.dist-info/RECORD,,
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,,