sqlmodel-ext 0.2.0__py3-none-any.whl → 0.3.0__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,10 +20,10 @@ 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.0"
23
+ __version__ = "0.2.1"
24
24
 
25
25
  # Base
26
- from sqlmodel_ext.base import SQLModelBase
26
+ from sqlmodel_ext.base import SQLModelBase, ExtraIgnoreModelBase
27
27
 
28
28
  # Exceptions
29
29
  from sqlmodel_ext._exceptions import RecordNotFoundError
@@ -39,8 +39,12 @@ from sqlmodel_ext.pagination import (
39
39
  # Mixins
40
40
  from sqlmodel_ext.mixins import (
41
41
  # Table
42
+ SESSION_FOR_UPDATE_KEY,
42
43
  TableBaseMixin,
43
44
  UUIDTableBaseMixin,
45
+ rel,
46
+ cond,
47
+ safe_reset,
44
48
  # Polymorphic
45
49
  PolymorphicBaseMixin,
46
50
  AutoPolymorphicIdentityMixin,
@@ -53,6 +57,9 @@ from sqlmodel_ext.mixins import (
53
57
  # Relation Preload
54
58
  RelationPreloadMixin,
55
59
  requires_relations,
60
+ requires_for_update,
61
+ # Cached Table
62
+ CachedTableBaseMixin,
56
63
  # Info Response DTOs
57
64
  IntIdInfoMixin,
58
65
  UUIDIdInfoMixin,
@@ -67,6 +74,7 @@ from sqlmodel_ext.field_types import (
67
74
  DirectoryPathType,
68
75
  FilePathType,
69
76
  # String constraints
77
+ Str16,
70
78
  Str24,
71
79
  Str32,
72
80
  Str36,
@@ -76,21 +84,33 @@ from sqlmodel_ext.field_types import (
76
84
  Str128,
77
85
  Str255,
78
86
  Str256,
87
+ Str500,
88
+ Str512,
89
+ Str2048,
79
90
  Text1K,
80
91
  Text1024,
81
92
  Text2K,
82
93
  Text2500,
83
94
  Text3K,
95
+ Text5K,
84
96
  Text10K,
97
+ Text32K,
85
98
  Text60K,
86
99
  Text64K,
87
100
  Text100K,
101
+ Text1M,
88
102
  # Numeric constraints
103
+ INT32_MAX,
104
+ INT64_MAX,
105
+ JS_MAX_SAFE_INTEGER,
89
106
  Port,
90
107
  Percentage,
91
108
  PositiveInt,
92
109
  NonNegativeInt,
110
+ PositiveBigInt,
111
+ NonNegativeBigInt,
93
112
  PositiveFloat,
113
+ NonNegativeFloat,
94
114
  # Custom types
95
115
  IPAddress,
96
116
  Url,
@@ -101,3 +121,12 @@ from sqlmodel_ext.field_types import (
101
121
  validate_not_private_host,
102
122
  ModuleNameMixin,
103
123
  )
124
+
125
+ # Relation Load Checker (static analysis)
126
+ from sqlmodel_ext.relation_load_checker import (
127
+ RelationLoadChecker,
128
+ RelationLoadWarning,
129
+ RelationLoadCheckMiddleware,
130
+ run_model_checks,
131
+ mark_app_check_completed,
132
+ )
sqlmodel_ext/_compat.py CHANGED
@@ -65,7 +65,25 @@ if sys.version_info >= (3, 14):
65
65
  non_none_args = [a for a in args if a is not type(None)]
66
66
  if non_none_args:
67
67
  first_arg = non_none_args[0]
68
+ # Check for Annotated SA type metadata first (e.g. Array[T] | None).
69
+ # Array[T] desugars to Annotated[list[T], _ArrayTypeHandler(T)];
70
+ # wrapping with | None produces Union[Annotated[...], None],
71
+ # so the SA type must be extracted from the inner Annotated.
72
+ first_arg_type_name = type(first_arg).__name__
73
+ if first_arg_type_name in ('AnnotatedAlias', '_AnnotatedAlias'):
74
+ inner_args = get_args(first_arg)
75
+ for md in inner_args[1:]:
76
+ if hasattr(md, '__get_pydantic_core_schema__'):
77
+ try:
78
+ schema = md.__get_pydantic_core_schema__(None, None)
79
+ if isinstance(schema, dict) and 'metadata' in schema:
80
+ sa_type = schema['metadata'].get('sa_type')
81
+ if sa_type is not None:
82
+ return sa_type
83
+ except (TypeError, AttributeError, KeyError):
84
+ pass
68
85
  first_origin = get_origin(first_arg)
86
+ # Plain list/dict/tuple/set (no Annotated SA type) -> JSONB
69
87
  if first_origin in (list, dict, tuple, set):
70
88
  return JSONB
71
89
 
sqlmodel_ext/_sa_type.py CHANGED
@@ -97,7 +97,8 @@ def _resolve_annotations(attrs: dict[str, Any]) -> tuple[
97
97
 
98
98
  try:
99
99
  temp_cls = type('AnnotationProxy', (object,), dict(attrs))
100
- temp_cls.__module__ = module_name
100
+ if isinstance(module_name, str):
101
+ temp_cls.__module__ = module_name
101
102
  extras_kw = {'include_extras': True} if sys.version_info >= (3, 10) else {}
102
103
  evaluated = get_type_hints(
103
104
  temp_cls,
@@ -132,6 +133,6 @@ def _evaluate_annotation_from_string(
132
133
  return current_type
133
134
 
134
135
  try:
135
- return eval(expr, globalns, localns)
136
+ return eval(expr, dict(globalns), dict(localns))
136
137
  except (NameError, SyntaxError, AttributeError, TypeError):
137
138
  return current_type
sqlmodel_ext/_utils.py CHANGED
@@ -1,5 +1,5 @@
1
1
  """Internal utility functions."""
2
- from datetime import datetime
2
+ from datetime import datetime, timezone
3
3
 
4
- now = lambda: datetime.now()
5
- now_date = lambda: datetime.now().date()
4
+ now = lambda: datetime.now(timezone.utc)
5
+ now_date = lambda: datetime.now(timezone.utc).date()