sqlmodel-ext 0.3.0__py3-none-any.whl → 0.3.2__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.
sqlmodel_ext/__init__.py CHANGED
@@ -20,7 +20,7 @@ Quick start::
20
20
  user = await user.save(session)
21
21
  users = await User.get(session, fetch_mode="all")
22
22
  """
23
- __version__ = "0.2.1"
23
+ __version__ = "0.3.0"
24
24
 
25
25
  # Base
26
26
  from sqlmodel_ext.base import SQLModelBase, ExtraIgnoreModelBase
sqlmodel_ext/_compat.py CHANGED
@@ -14,6 +14,7 @@ if sys.version_info >= (3, 14):
14
14
  from enum import StrEnum
15
15
  from typing import Literal, Union, get_args, get_origin
16
16
 
17
+ from pydantic_core import PydanticUndefined
17
18
  from sqlalchemy import String
18
19
  from sqlalchemy.orm.attributes import InstrumentedAttribute
19
20
 
@@ -27,6 +28,24 @@ if sys.version_info >= (3, 14):
27
28
  import sqlmodel.main
28
29
  _original_get_sqlalchemy_type = sqlmodel.main.get_sqlalchemy_type
29
30
 
31
+ def _get_explicit_sa_type(field):
32
+ """
33
+ Extract an explicit ``sa_type`` from a SQLModel/Pydantic FieldInfo.
34
+
35
+ Matches upstream ``sqlmodel.main._get_sqlmodel_field_value`` semantics:
36
+ prefers ``FieldInfoMetadata.sa_type`` then falls back to the direct
37
+ ``field.sa_type`` attribute. Returns ``PydanticUndefined`` when unset.
38
+ """
39
+ # Prefer FieldInfoMetadata.sa_type (set via Field(sa_type=...))
40
+ metadata = getattr(field, 'metadata', None)
41
+ if metadata:
42
+ for item in metadata:
43
+ sa_type = getattr(item, 'sa_type', PydanticUndefined)
44
+ if sa_type is not PydanticUndefined:
45
+ return sa_type
46
+ # Fallback to direct attribute
47
+ return getattr(field, 'sa_type', PydanticUndefined)
48
+
30
49
  def _patched_get_sqlalchemy_type(field):
31
50
  """
32
51
  Fix SQLModel's get_sqlalchemy_type for Python 3.14 type issues.
@@ -34,6 +53,17 @@ if sys.version_info >= (3, 14):
34
53
  Handles ForwardRef, ClassVar, Literal, Mapped, and custom types
35
54
  that cause issubclass errors under PEP 649.
36
55
  """
56
+ # Respect explicit sa_type from Field(sa_type=...) — must take
57
+ # precedence over annotation-based auto-detection, matching upstream
58
+ # SQLModel behavior (sqlmodel/main.py::get_sqlalchemy_type checks
59
+ # sa_type before everything else). Without this, fields like
60
+ # ``options: list[str] | None = Field(sa_type=JSON)`` incorrectly
61
+ # get JSONB from the Union[list, None] -> JSONB branch below,
62
+ # breaking non-PostgreSQL dialects (e.g., SQLite in tests).
63
+ explicit_sa_type = _get_explicit_sa_type(field)
64
+ if explicit_sa_type is not PydanticUndefined:
65
+ return explicit_sa_type
66
+
37
67
  # Check field.metadata (Pydantic-processed Annotated types)
38
68
  metadata = getattr(field, 'metadata', None)
39
69
  if metadata:
@@ -453,6 +453,22 @@ class AutoPolymorphicIdentityMixin:
453
453
  # other subclasses' rows won't have values for these columns.
454
454
  # Pydantic-level constraints still apply when creating specific subclasses.
455
455
  column.nullable = True
456
+
457
+ # Clear Python-side and server-side defaults on the shared column.
458
+ # Otherwise, a Pydantic field default (e.g. ``some_field: int = 5``)
459
+ # gets propagated into Column.default by ``get_column_from_field()``.
460
+ # When sibling subclasses that do NOT declare this field are inserted,
461
+ # the attribute is absent from their model_fields and from the
462
+ # instance's ``__dict__``; the ORM falls back to Column.default and
463
+ # writes the declaring subclass's default into the sibling row,
464
+ # silently polluting unrelated rows across the STI table.
465
+ # The declaring subclass itself is unaffected: Pydantic populates the
466
+ # instance attribute at ``__init__`` time, and the ORM reads the
467
+ # value directly from the instance on flush without ever consulting
468
+ # Column.default.
469
+ column.default = None
470
+ column.server_default = None
471
+
456
472
  parent_table.append_column(column)
457
473
  except Exception as e:
458
474
  logger.warning(f"Failed to create column {field_name} for {cls.__name__}: {e}")