arpakitlib 1.8.257__py3-none-any.whl → 1.8.259__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.
@@ -1,48 +1,41 @@
1
1
  # arpakit
2
- import datetime as dt
3
- from typing import Any, Optional, get_type_hints, get_origin, Union, Annotated, get_args
2
+ from typing import Any, get_type_hints, get_origin, Union, Annotated, get_args
4
3
 
5
- from pydantic import BaseModel, Field, ConfigDict
4
+ from pydantic import BaseModel, ConfigDict
6
5
  from sqlalchemy import inspect
7
- from sqlalchemy.orm import ColumnProperty
8
- from sqlalchemy.sql.sqltypes import (
9
- Boolean, Integer, BigInteger, SmallInteger,
10
- String, Text, Unicode, UnicodeText,
11
- DateTime, Date, Time,
12
- Float, Numeric, DECIMAL, LargeBinary, JSON
13
- )
6
+ from sqlalchemy.orm import ColumnProperty, Mapped
7
+ from sqlalchemy.util import get_annotations
8
+
9
+ from project.sqlalchemy_db_.sqlalchemy_model import UserDBM
14
10
 
15
11
  _ARPAKIT_LIB_MODULE_VERSION = "3.0"
16
12
 
17
- _SQLA_TYPE_MAP = {
18
- Boolean: bool,
19
- Integer: int,
20
- BigInteger: int,
21
- SmallInteger: int,
22
- Float: float,
23
- Numeric: float,
24
- DECIMAL: float,
25
- String: str,
26
- Unicode: str,
27
- Text: str,
28
- UnicodeText: str,
29
- LargeBinary: bytes,
30
- JSON: dict | list,
31
- DateTime: dt.datetime,
32
- Date: dt.date,
33
- Time: dt.time,
34
- }
35
-
36
-
37
- def _python_type_from_col(col) -> type | str:
38
- try:
39
- return col.type.python_type
40
- except Exception:
41
- for sa_t, py_t in _SQLA_TYPE_MAP.items():
42
- if isinstance(col.type, sa_t):
43
- return py_t
13
+
14
+ def __declared_sqlalchemy_column_type(declared_type: Any) -> Any:
15
+ """
16
+ Возвращает тип колонки ИСКЛЮЧИТЕЛЬНО из аннотации поля.
17
+ Разворачивает оболочки:
18
+ - Annotated[T, ...] -> T
19
+ - Mapped[T] -> T
20
+ Если аннотации нет — возвращает Any.
21
+ """
22
+ if declared_type is None or declared_type is Any:
44
23
  return Any
45
24
 
25
+ origin = get_origin(declared_type)
26
+
27
+ # Annotated[T, ...] -> T
28
+ if origin is Annotated:
29
+ args = get_args(declared_type)
30
+ return __declared_sqlalchemy_column_type(args[0]) if args else Any
31
+
32
+ # Mapped[T] -> T
33
+ if origin is Mapped:
34
+ args = get_args(declared_type)
35
+ return __declared_sqlalchemy_column_type(args[0]) if args else Any
36
+
37
+ return declared_type
38
+
46
39
 
47
40
  def _get_property_name_to_type_from_model_class(
48
41
  *,
@@ -64,8 +57,9 @@ def _get_property_name_to_type_from_model_class(
64
57
  ret_type = hints.get("return", Any)
65
58
  except Exception:
66
59
  if skip_property_if_cannot_define_type:
67
- continue
68
- ret_type = Any
60
+ ret_type = Any
61
+ else:
62
+ raise
69
63
  if exclude_property_names:
70
64
  if property_name in exclude_property_names:
71
65
  continue
@@ -113,7 +107,7 @@ def pydantic_schema_from_sqlalchemy_model(
113
107
  *,
114
108
  model_name: str | None = None,
115
109
  base_model: type[BaseModel] = BaseModel,
116
- include_column_defaults: bool = False,
110
+ include_columns: bool = True,
117
111
  exclude_column_names: list[str] | None = None,
118
112
  include_properties: bool = False,
119
113
  include_property_names: list[str] | None = None,
@@ -122,7 +116,8 @@ def pydantic_schema_from_sqlalchemy_model(
122
116
  exclude_property_types: list[type] | None = None,
123
117
  filter_property_prefixes: list[str] | None = None,
124
118
  remove_property_prefixes: list[str] | None = None,
125
- skip_property_if_cannot_define_type: bool = True
119
+ skip_property_if_cannot_define_type: bool = True,
120
+ skip_property_name_if_exists: bool = True
126
121
  ) -> type[BaseModel]:
127
122
  """
128
123
  Генерирует Pydantic-модель из колонок SQLAlchemy-модели и (опционально) из @property.
@@ -147,31 +142,18 @@ def pydantic_schema_from_sqlalchemy_model(
147
142
  remove_property_prefixes = set(remove_property_prefixes or [])
148
143
 
149
144
  # 1) Колонки
150
- for prop in mapper.attrs:
151
- if not isinstance(prop, ColumnProperty):
152
- continue
153
- if prop.key in exclude_column_names:
154
- continue
155
-
156
- column = prop.columns[0]
157
- column_type = _python_type_from_col(column)
158
-
159
- # Аннотация типа
160
- if column.nullable:
161
- annotations[prop.key] = Optional[column_type] # type: ignore[name-defined]
162
- else:
163
- annotations[prop.key] = column_type
145
+ if include_columns:
164
146
 
165
- # Дефолты, если нужно
166
- if include_column_defaults:
167
- default_value = None
168
- if column.default is not None and getattr(column.default, "is_scalar", False):
169
- default_value = column.default.arg
170
- elif column.server_default is not None and getattr(column.server_default.arg, "text", None):
171
- default_value = column.server_default.arg.text
147
+ # читаем аннотации класса (include_extras=True нужно для Annotated/Mapped)
148
+ type_hints = get_annotations(sqlalchemy_model)
172
149
 
173
- if default_value is not None:
174
- attrs[prop.key] = Field(default=default_value)
150
+ for prop in mapper.column_attrs:
151
+ if not isinstance(prop, ColumnProperty):
152
+ continue
153
+ if prop.key in exclude_column_names:
154
+ continue
155
+
156
+ annotations[prop.key] = __declared_sqlalchemy_column_type(type_hints.get(prop.key, None))
175
157
 
176
158
  # 2) Свойства (@property)
177
159
  if include_properties:
@@ -240,10 +222,11 @@ def pydantic_schema_from_sqlalchemy_model(
240
222
  ):
241
223
  renamed_property_name_to_type[new_property_name] = property_type
242
224
  else:
243
- raise ValueError(
244
- f"Property name '{property_name}' after removing prefix "
245
- f"conflicts with existing name '{new_property_name}'"
246
- )
225
+ if not skip_property_name_if_exists:
226
+ raise ValueError(
227
+ f"Property name '{property_name}' after removing prefix "
228
+ f"conflicts with existing name '{new_property_name}'"
229
+ )
247
230
  property_name_to_type.update(renamed_property_name_to_type)
248
231
 
249
232
  # добавляем (колонки в приоритете)
@@ -258,3 +241,4 @@ def pydantic_schema_from_sqlalchemy_model(
258
241
  attrs["model_config"] = ConfigDict(extra="ignore", arbitrary_types_allowed=True, from_attributes=True)
259
242
 
260
243
  return type(model_name, (base_model,), attrs)
244
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: arpakitlib
3
- Version: 1.8.257
3
+ Version: 1.8.259
4
4
  Summary: arpakitlib
5
5
  License: Apache-2.0
6
6
  Keywords: arpakitlib,arpakit,arpakit-company,arpakitcompany,arpakit_company
@@ -414,7 +414,7 @@ arpakitlib/ar_need_type_util.py,sha256=XmY1kswz8j9oo5f9CxRu0_zgfvxWrXPYKOj6MM04s
414
414
  arpakitlib/ar_openai_api_client_util.py,sha256=dWgsSPXtxNBxS5VRi_NharGQrUXF_YjIfhU3Bj5cW9M,5651
415
415
  arpakitlib/ar_parse_command.py,sha256=1WTdQoWVshoDZ1jDaKeTzajfqaYHP3FNO0-REyo1aMY,3003
416
416
  arpakitlib/ar_postgresql_util.py,sha256=1AuLjEaa1Lg4pzn-ukCVnDi35Eg1k91APRTqZhIJAdo,945
417
- arpakitlib/ar_pydantic_schema_from_sqlalchemy_model.py,sha256=3FXPiTdDTel8IsWyAmCK7ufzgbbB4WQPlfdEkz7ao3U,10673
417
+ arpakitlib/ar_pydantic_schema_from_sqlalchemy_model.py,sha256=MBIP8VDohDB5Z3awbhJehNNRt0xIO4s6sEBezsPHP3s,10413
418
418
  arpakitlib/ar_raise_own_exception_if_exception.py,sha256=A6TuNSBk1pHaQ_qxnUmE2LgsNGA1IGqX26b1_HEA4Nc,5978
419
419
  arpakitlib/ar_rat_func_util.py,sha256=Ca10o3RJwyx_DJLxjTxgHDO6NU3M6CWgUR4bif67OE4,2006
420
420
  arpakitlib/ar_really_validate_email.py,sha256=HBfhyiDB3INI6Iq6hR2WOMKA5wVWWRl0Qun-x__OZ9o,1201
@@ -430,8 +430,8 @@ arpakitlib/ar_sqlalchemy_util.py,sha256=FDva9onjtCPrYZYIHHb93NMwD1WlmaORjiWgPRJQ
430
430
  arpakitlib/ar_str_util.py,sha256=2lGpnXDf2h1cBZpVf5i1tX_HCv5iBd6IGnrCw4QWWlY,4350
431
431
  arpakitlib/ar_type_util.py,sha256=Cs_tef-Fc5xeyAF54KgISCsP11NHyzIsglm4S3Xx7iM,4049
432
432
  arpakitlib/ar_yookassa_api_client_util.py,sha256=VozuZeCJjmLd1zj2BdC9WfiAQ3XYOrIMsdpNK-AUlm0,5347
433
- arpakitlib-1.8.257.dist-info/LICENSE,sha256=GPEDQMam2r7FSTYqM1mm7aKnxLaWcBotH7UvQtea-ec,11355
434
- arpakitlib-1.8.257.dist-info/METADATA,sha256=zulZ5lal5ER2B_RxZIvOt0ucF8hbMu8ckkHVVsXjruo,3919
435
- arpakitlib-1.8.257.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
436
- arpakitlib-1.8.257.dist-info/entry_points.txt,sha256=36xqR3PJFT2kuwjkM_EqoIy0qFUDPKSm_mJaI7emewE,87
437
- arpakitlib-1.8.257.dist-info/RECORD,,
433
+ arpakitlib-1.8.259.dist-info/LICENSE,sha256=GPEDQMam2r7FSTYqM1mm7aKnxLaWcBotH7UvQtea-ec,11355
434
+ arpakitlib-1.8.259.dist-info/METADATA,sha256=GEDZNXDfp08rmbipsZhX4WwXtmlOGrJbJEpIJ7Q-KDg,3919
435
+ arpakitlib-1.8.259.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
436
+ arpakitlib-1.8.259.dist-info/entry_points.txt,sha256=36xqR3PJFT2kuwjkM_EqoIy0qFUDPKSm_mJaI7emewE,87
437
+ arpakitlib-1.8.259.dist-info/RECORD,,