arpakitlib 1.8.251__py3-none-any.whl → 1.8.253__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.
- arpakitlib/ar_pydantic_schema_from_sqlalchemy_model.py +46 -9
- arpakitlib/ar_sqlalchemy_util.py +4 -1
- {arpakitlib-1.8.251.dist-info → arpakitlib-1.8.253.dist-info}/METADATA +1 -1
- {arpakitlib-1.8.251.dist-info → arpakitlib-1.8.253.dist-info}/RECORD +7 -7
- {arpakitlib-1.8.251.dist-info → arpakitlib-1.8.253.dist-info}/LICENSE +0 -0
- {arpakitlib-1.8.251.dist-info → arpakitlib-1.8.253.dist-info}/WHEEL +0 -0
- {arpakitlib-1.8.251.dist-info → arpakitlib-1.8.253.dist-info}/entry_points.txt +0 -0
@@ -44,7 +44,7 @@ def _python_type_from_col(col) -> type | str:
|
|
44
44
|
return Any
|
45
45
|
|
46
46
|
|
47
|
-
def
|
47
|
+
def _get_property_name_to_type_from_model_class(model_class: type) -> dict[str, Any]:
|
48
48
|
"""
|
49
49
|
Находит все @property в классе и вытаскивает их возвращаемый тип.
|
50
50
|
Если тип не удаётся получить — подставляем Any.
|
@@ -64,13 +64,15 @@ def _collect_properties_with_types(model_class: type) -> dict[str, Any]:
|
|
64
64
|
def pydantic_schema_from_sqlalchemy_model(
|
65
65
|
sqlalchemy_model: type,
|
66
66
|
*,
|
67
|
-
|
67
|
+
model_name: str | None = None,
|
68
68
|
base_model: type[BaseModel] = BaseModel,
|
69
69
|
include_column_defaults: bool = False,
|
70
70
|
exclude_column_names: list[str] | None = None,
|
71
71
|
include_properties: bool = False,
|
72
72
|
include_property_names: list[str] | None = None,
|
73
73
|
exclude_property_names: list[str] | None = None,
|
74
|
+
filter_property_prefixes: list[str] | None = None,
|
75
|
+
remove_property_prefixes: list[str] | None = None,
|
74
76
|
) -> type[BaseModel]:
|
75
77
|
"""
|
76
78
|
Генерирует Pydantic-модель из колонок SQLAlchemy-модели и (опционально) из @property.
|
@@ -83,7 +85,7 @@ def pydantic_schema_from_sqlalchemy_model(
|
|
83
85
|
- exclude_property_names: blacklist имён свойств (исключаются после whitelist'а).
|
84
86
|
"""
|
85
87
|
mapper = inspect(sqlalchemy_model).mapper
|
86
|
-
model_name =
|
88
|
+
model_name = model_name or f"{sqlalchemy_model.__name__}Schema"
|
87
89
|
|
88
90
|
annotations: dict[str, Any] = {}
|
89
91
|
attrs: dict[str, Any] = {}
|
@@ -91,6 +93,8 @@ def pydantic_schema_from_sqlalchemy_model(
|
|
91
93
|
exclude_column_names = set(exclude_column_names or [])
|
92
94
|
include_property_names = set(include_property_names or [])
|
93
95
|
exclude_property_names = set(exclude_property_names or [])
|
96
|
+
filter_property_prefixes = set(filter_property_prefixes or [])
|
97
|
+
remove_property_prefixes = set(remove_property_prefixes or [])
|
94
98
|
|
95
99
|
# 1) Колонки
|
96
100
|
for prop in mapper.attrs:
|
@@ -121,9 +125,17 @@ def pydantic_schema_from_sqlalchemy_model(
|
|
121
125
|
|
122
126
|
# 2) Свойства (@property)
|
123
127
|
if include_properties:
|
124
|
-
property_name_to_type =
|
128
|
+
property_name_to_type = _get_property_name_to_type_from_model_class(sqlalchemy_model)
|
125
129
|
|
126
|
-
#
|
130
|
+
# фильтр по префиксам (если задан и не пуст)
|
131
|
+
if filter_property_prefixes:
|
132
|
+
property_name_to_type = {
|
133
|
+
property_name: property_type
|
134
|
+
for property_name, property_type in property_name_to_type.items()
|
135
|
+
if any(property_name.startswith(v) for v in filter_property_prefixes)
|
136
|
+
}
|
137
|
+
|
138
|
+
# whitelist по именам
|
127
139
|
if include_property_names:
|
128
140
|
property_name_to_type = {
|
129
141
|
k: v
|
@@ -133,13 +145,38 @@ def pydantic_schema_from_sqlalchemy_model(
|
|
133
145
|
else:
|
134
146
|
property_name_to_type = dict(property_name_to_type)
|
135
147
|
|
136
|
-
# blacklist
|
148
|
+
# blacklist по именам
|
137
149
|
if exclude_property_names:
|
138
150
|
for property_name in list(property_name_to_type.keys()):
|
139
151
|
if property_name in exclude_property_names:
|
140
|
-
property_name_to_type.pop(
|
141
|
-
|
142
|
-
#
|
152
|
+
property_name_to_type.pop(property_name, None)
|
153
|
+
|
154
|
+
# удаляем префиксы
|
155
|
+
if remove_property_prefixes:
|
156
|
+
renamed_property_name_to_type = {}
|
157
|
+
for property_name, property_type in property_name_to_type.items():
|
158
|
+
new_property_name = property_name
|
159
|
+
for prefix in remove_property_prefixes:
|
160
|
+
if new_property_name.startswith(prefix):
|
161
|
+
new_property_name = new_property_name[len(prefix):].strip()
|
162
|
+
break
|
163
|
+
if new_property_name != property_name:
|
164
|
+
property_name_to_type.pop(property_name)
|
165
|
+
# избегаем коллизий
|
166
|
+
if (
|
167
|
+
new_property_name not in annotations
|
168
|
+
and new_property_name not in property_name_to_type
|
169
|
+
and new_property_name not in renamed_property_name_to_type
|
170
|
+
):
|
171
|
+
renamed_property_name_to_type[new_property_name] = property_type
|
172
|
+
else:
|
173
|
+
raise ValueError(
|
174
|
+
f"Property name '{property_name}' after removing prefix "
|
175
|
+
f"conflicts with existing name '{new_property_name}'"
|
176
|
+
)
|
177
|
+
property_name_to_type.update(renamed_property_name_to_type)
|
178
|
+
|
179
|
+
# добавляем (колонки в приоритете)
|
143
180
|
for property_name, property_type in property_name_to_type.items():
|
144
181
|
if property_name in annotations:
|
145
182
|
continue
|
arpakitlib/ar_sqlalchemy_util.py
CHANGED
@@ -174,6 +174,7 @@ class BaseDBM(DeclarativeBase):
|
|
174
174
|
exclude_sd_properties: Collection[str] | None = None,
|
175
175
|
include_columns_and_sd_properties: Collection[str] | None = None,
|
176
176
|
prefix: str = "sdp_",
|
177
|
+
remove_prefix: bool = True,
|
177
178
|
kwargs: dict[str, Any] | None = None
|
178
179
|
) -> dict[str, Any]:
|
179
180
|
if exclude_columns is None:
|
@@ -199,7 +200,9 @@ class BaseDBM(DeclarativeBase):
|
|
199
200
|
if not attr_name.startswith(prefix) or not isinstance(getattr(type(self), attr_name, None), property):
|
200
201
|
continue
|
201
202
|
|
202
|
-
sd_property_name = attr_name
|
203
|
+
sd_property_name = attr_name
|
204
|
+
if remove_prefix:
|
205
|
+
sd_property_name = sd_property_name.removeprefix(prefix)
|
203
206
|
|
204
207
|
if (
|
205
208
|
include_columns_and_sd_properties is not None
|
@@ -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=
|
417
|
+
arpakitlib/ar_pydantic_schema_from_sqlalchemy_model.py,sha256=Nmyyz3UANvKKxugfW79M7yyY3kwDNYkbvh2rI3p3Yhk,7387
|
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
|
@@ -426,12 +426,12 @@ arpakitlib/ar_schedule_uust_api_client_util.py,sha256=rXI2_3OTaIBgR-GixM1Ti-Ue1f
|
|
426
426
|
arpakitlib/ar_settings_util.py,sha256=Y5wi_cmsjDjfJpM0VJHjbo0NoVPKfypKaD1USowwDtQ,1327
|
427
427
|
arpakitlib/ar_sleep_util.py,sha256=ggaj7ML6QK_ADsHMcyu6GUmUpQ_9B9n-SKYH17h-9lM,1045
|
428
428
|
arpakitlib/ar_sqladmin_util.py,sha256=SEoaowAPF3lhxPsNjwmOymNJ55Ty9rmzvsDm7gD5Ceo,861
|
429
|
-
arpakitlib/ar_sqlalchemy_util.py,sha256=
|
429
|
+
arpakitlib/ar_sqlalchemy_util.py,sha256=FDva9onjtCPrYZYIHHb93NMwD1WlmaORjiWgPRJQKoU,16180
|
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.
|
434
|
-
arpakitlib-1.8.
|
435
|
-
arpakitlib-1.8.
|
436
|
-
arpakitlib-1.8.
|
437
|
-
arpakitlib-1.8.
|
433
|
+
arpakitlib-1.8.253.dist-info/LICENSE,sha256=GPEDQMam2r7FSTYqM1mm7aKnxLaWcBotH7UvQtea-ec,11355
|
434
|
+
arpakitlib-1.8.253.dist-info/METADATA,sha256=6otWI1aGoN2mIVI0uz8f9rZ5KMKovtUIGZEGyFTWzls,3919
|
435
|
+
arpakitlib-1.8.253.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
436
|
+
arpakitlib-1.8.253.dist-info/entry_points.txt,sha256=36xqR3PJFT2kuwjkM_EqoIy0qFUDPKSm_mJaI7emewE,87
|
437
|
+
arpakitlib-1.8.253.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|