Если вам интересно, вы можете проверить это здесь, но оно довольно маленькое, и в этом посте я покажу большую часть кода.
Это буквально все пакет, помимо некоторых методов Dunder, имеет:
Код: Выделить всё
from pydantic import BaseModel, create_model
class ExtendedBaseModel(BaseModel):
"""
A subclass of BaseModel that adds advanced operations for field union, exclusion,
and difference. This class supports bitwise operators (|, &, -) between instances,
where the left instance (self) takes precedence for both values and data types.
"""
@classmethod
def union(cls, _name: str, other: 'ExtendedBaseModel') -> type[BaseModel]:
"""
Creates a new model that merges fields from the current class and another
ExtendedBaseModel class. In case of overlapping fields, values and data types
from the current model (self) take precedence.
Args:
_name (str): The name for the new model.
other (ExtendedBaseModel): Another model to merge fields with.
Returns:
BaseModel: A new model including fields from both the current class and
the other model.
"""
# Merge annotations from both models, with precedence for the current class
fields_data = {*other.__annotations__.items(), *cls.__annotations__.items()}
# Construct new fields with types and make them required (indicated by `...`)
new_fields = {field: (annotation, ...) for field, annotation in fields_data}
return create_model(_name, **new_fields)
@classmethod
def omit(cls, _name: str, *excluded_fields: str) -> type[BaseModel]:
"""
Exclude specified fields from the current model to create a new model with
only the remaining fields.
Args:
_name (str): The name for the new model.
*excluded_fields (str): Fields to exclude from the model.
Returns:
BaseModel: A new model excluding the specified fields.
"""
# Filter out fields specified in excluded_fields
new_fields = {
field: (cls.__annotations__[field], ...)
for field in cls.__annotations__
if field not in excluded_fields
}
return create_model(_name, **new_fields)
@classmethod
def pick(cls, _name: str, *included_fields: str) -> type[BaseModel]:
"""
Generate a new model with only the specified fields from the current model.
Args:
_name (str): The name for the new model.
*included_fields (str): Fields to include in the new model.
Returns:
BaseModel: A new model containing only the specified fields.
"""
# Select fields specified in included_fields
new_fields = {
field: (cls.__annotations__[field], ...)
for field in cls.__annotations__
if field in included_fields
}
return create_model(_name, **new_fields)
...
Единственная проблема заключается в том, что Subversion не обеспечивает автодополнение, и мне бы хотелось, чтобы оно делало это в основном для подсказок по типам.
После некоторых исследований я нашел этот пост, в котором я нашел комментарий пользователя igrinis, в котором упоминаются динамически генерируемые файлы .pyi.
Итак, вот какое решение я придумал:
Код: Выделить всё
class ExtendedBaseModel(BaseModel):
...
@classmethod
def generate_pyi(cls, _name: str, fields: dict):
"""
Generate a .pyi file for the dynamically created model to provide type hints to IDEs.
Args:
_name (str): The name of the new model.
fields (dict): A dictionary of field names and types to be included in the .pyi file.
"""
makedirs('types/', exist_ok=True)
pyi_filename = f"types/{_name}.pyi"
with open(pyi_filename, "w") as pyi_file:
pyi_file.write(f"from pydantic import BaseModel\n\n")
pyi_file.write(f"class {_name}(BaseModel):\n")
for field, (field_type, _) in fields.items():
pyi_file.write(f" {field}: {field_type.__name__}\n")
...
Подробнее здесь: https://stackoverflow.com/questions/791 ... on-support
Мобильная версия