Done
This commit is contained in:
140
python_parser/core/schema_utils.py
Normal file
140
python_parser/core/schema_utils.py
Normal file
@@ -0,0 +1,140 @@
|
||||
"""
|
||||
Упрощенные утилиты для работы со схемами Pydantic
|
||||
"""
|
||||
from typing import List, Dict, Any, Type
|
||||
from pydantic import BaseModel
|
||||
import inspect
|
||||
|
||||
|
||||
def get_required_fields_from_schema(schema_class: Type[BaseModel]) -> List[str]:
|
||||
"""
|
||||
Извлекает список обязательных полей из схемы Pydantic
|
||||
|
||||
Args:
|
||||
schema_class: Класс схемы Pydantic
|
||||
|
||||
Returns:
|
||||
Список имен обязательных полей
|
||||
"""
|
||||
required_fields = []
|
||||
|
||||
# Используем model_fields для Pydantic v2 или __fields__ для v1
|
||||
if hasattr(schema_class, 'model_fields'):
|
||||
fields = schema_class.model_fields
|
||||
else:
|
||||
fields = schema_class.__fields__
|
||||
|
||||
for field_name, field_info in fields.items():
|
||||
# В Pydantic v2 есть метод is_required()
|
||||
if hasattr(field_info, 'is_required'):
|
||||
if field_info.is_required():
|
||||
required_fields.append(field_name)
|
||||
elif hasattr(field_info, 'required'):
|
||||
if field_info.required:
|
||||
required_fields.append(field_name)
|
||||
else:
|
||||
# Fallback для старых версий - проверяем наличие default
|
||||
has_default = False
|
||||
|
||||
if hasattr(field_info, 'default'):
|
||||
has_default = field_info.default is not ...
|
||||
elif hasattr(field_info, 'default_factory'):
|
||||
has_default = field_info.default_factory is not None
|
||||
|
||||
if not has_default:
|
||||
required_fields.append(field_name)
|
||||
|
||||
return required_fields
|
||||
|
||||
|
||||
def get_optional_fields_from_schema(schema_class: Type[BaseModel]) -> List[str]:
|
||||
"""
|
||||
Извлекает список необязательных полей из схемы Pydantic
|
||||
|
||||
Args:
|
||||
schema_class: Класс схемы Pydantic
|
||||
|
||||
Returns:
|
||||
Список имен необязательных полей
|
||||
"""
|
||||
optional_fields = []
|
||||
|
||||
# Используем model_fields для Pydantic v2 или __fields__ для v1
|
||||
if hasattr(schema_class, 'model_fields'):
|
||||
fields = schema_class.model_fields
|
||||
else:
|
||||
fields = schema_class.__fields__
|
||||
|
||||
for field_name, field_info in fields.items():
|
||||
# В Pydantic v2 есть метод is_required()
|
||||
if hasattr(field_info, 'is_required'):
|
||||
if not field_info.is_required():
|
||||
optional_fields.append(field_name)
|
||||
elif hasattr(field_info, 'required'):
|
||||
if not field_info.required:
|
||||
optional_fields.append(field_name)
|
||||
else:
|
||||
# Fallback для старых версий - проверяем наличие default
|
||||
has_default = False
|
||||
|
||||
if hasattr(field_info, 'default'):
|
||||
has_default = field_info.default is not ...
|
||||
elif hasattr(field_info, 'default_factory'):
|
||||
has_default = field_info.default_factory is not None
|
||||
|
||||
if has_default:
|
||||
optional_fields.append(field_name)
|
||||
|
||||
return optional_fields
|
||||
|
||||
|
||||
def register_getter_from_schema(parser_instance, getter_name: str, method: callable,
|
||||
schema_class: Type[BaseModel], description: str = ""):
|
||||
"""
|
||||
Регистрирует геттер в парсере, используя схему Pydantic для определения параметров
|
||||
|
||||
Args:
|
||||
parser_instance: Экземпляр парсера
|
||||
getter_name: Имя геттера
|
||||
method: Метод для выполнения
|
||||
schema_class: Класс схемы Pydantic
|
||||
description: Описание геттера (если не указано, берется из docstring метода)
|
||||
"""
|
||||
# Извлекаем параметры из схемы
|
||||
required_params = get_required_fields_from_schema(schema_class)
|
||||
optional_params = get_optional_fields_from_schema(schema_class)
|
||||
|
||||
# Если описание не указано, берем из docstring метода
|
||||
if not description:
|
||||
description = inspect.getdoc(method) or ""
|
||||
|
||||
# Регистрируем геттер
|
||||
parser_instance.register_getter(
|
||||
name=getter_name,
|
||||
method=method,
|
||||
required_params=required_params,
|
||||
optional_params=optional_params,
|
||||
description=description
|
||||
)
|
||||
|
||||
|
||||
def validate_params_with_schema(params: Dict[str, Any], schema_class: Type[BaseModel]) -> Dict[str, Any]:
|
||||
"""
|
||||
Валидирует параметры с помощью схемы Pydantic
|
||||
|
||||
Args:
|
||||
params: Словарь параметров
|
||||
schema_class: Класс схемы Pydantic
|
||||
|
||||
Returns:
|
||||
Валидированные параметры
|
||||
|
||||
Raises:
|
||||
ValidationError: Если параметры не прошли валидацию
|
||||
"""
|
||||
try:
|
||||
# Создаем экземпляр схемы для валидации
|
||||
validated_data = schema_class(**params)
|
||||
return validated_data.dict()
|
||||
except Exception as e:
|
||||
raise ValueError(f"Ошибка валидации параметров: {str(e)}")
|
||||
Reference in New Issue
Block a user