Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- from dataclasses import asdict, dataclass
- from adaptix import Retort, name_mapping
- import pytest
- from sqlalchemy import Column, Integer, String, ForeignKey, create_engine, inspect, select
- from sqlalchemy.orm import (
- declarative_base,
- Session,
- column_property,
- declared_attr,
- Mapped,
- )
- Base = declarative_base()
- class ProductPackagingTypeORM(Base):
- __tablename__ = "product_packaging_types"
- id: Mapped[int] = Column(Integer, primary_key=True)
- name: Mapped[str] = Column(String)
- class ProductORM(Base):
- __tablename__ = "products"
- __allow_unmapped__ = True # позволяет использовать column_property с аннотацией
- id: Mapped[int] = Column(Integer, primary_key=True)
- packaging_type_id: Mapped[int] = Column(
- Integer, ForeignKey("product_packaging_types.id")
- )
- product_packaging_type: Mapped[str]
- @declared_attr
- def product_packaging_type(cls):
- return column_property(
- select(ProductPackagingTypeORM.name)
- .where(ProductPackagingTypeORM.id == cls.packaging_type_id)
- .scalar_subquery()
- .label("product_packaging_type")
- )
- @dataclass
- class Product:
- id: int
- packaging_type_id: int
- product_packaging_type: str | None = None
- @pytest.fixture
- def sqlite_session():
- engine = create_engine("sqlite:///:memory:")
- Base.metadata.create_all(engine)
- with Session(engine) as session:
- session.add_all(
- [
- ProductPackagingTypeORM(id=1, name="Картон"),
- ProductORM(id=1, packaging_type_id=1),
- ]
- )
- session.commit()
- yield session
- def test_product_alias_field_without_retort(sqlite_session):
- orm_product = sqlite_session.query(ProductORM).first()
- assert orm_product.product_packaging_type == "Картон"
- # 🔄 Ручной маппинг ORM → Domain
- product = Product(
- id=orm_product.id,
- packaging_type_id=orm_product.packaging_type_id,
- product_packaging_type=orm_product.product_packaging_type,
- )
- print(product)
- # ✅ Проверка значения
- assert product == Product(
- id=1, packaging_type_id=1, product_packaging_type="Картон"
- )
- # 🔄 Domain → Dict (как dump)
- result_dict = asdict(product)
- # ✅ Проверка словаря вручную
- assert result_dict == {
- "id": 1,
- "packaging_type_id": 1,
- "product_packaging_type": "Картон",
- }
- def test_product_alias_field_with_retort(sqlite_session):
- orm_product = sqlite_session.query(ProductORM).first()
- assert orm_product.product_packaging_type == "Картон"
- # аттрибуты orm_product:
- for attr in inspect(orm_product).attrs:
- print(f"orm_product_attributes: {attr.key} = {attr.value}")
- retort = Retort(hide_traceback=False)
- # Проблема: Retort по умолчанию сериализует только реальные столбцы SQLAlchemy,
- # а `product_packaging_type` — это column_property (alias), и не попадает в dump.
- product = retort.dump(orm_product)
- print(f"product_from_orm: {product}")
- # При десериализации поле product_packaging_type не восстанавливается → None
- product_dataclass = retort.load(product, Product)
- print(f"product_dataclass: {product_dataclass}")
- # ❌ Тест упадёт, потому что product_packaging_type == None вместо "Картон"
- assert product_dataclass == Product(
- id=1, packaging_type_id=1, product_packaging_type="Картон"
- )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement