gpt4 book ai didi

python - 无法在使用 Fixtures 的 Pytest 函数中实例化 Python 数据类(卡住)

转载 作者:行者123 更新时间:2023-12-03 14:53:47 26 4
gpt4 key购买 nike

我正在关注 Harry Percival 和 Bob Gregory 的 Python 架构模式。
在第三 (3) 章左右,他们介绍了测试 SQLAlchemy 的 ORM。
需要 session 的新测试 fixture ,它正在抛出AttributeError, FrozenInstanceError由于 cannot assign to field '_sa_instance_state'值得注意的是,在创建 OrderLine 的实例时其他测试不会失败。 ,但如果我简单地包含 session,它们确实会失败进入测试参数。
无论如何,我会直接进入代码。
conftest.py

@pytest.fixture
def local_db():
engine = create_engine('sqlite:///:memory:')
metadata.create_all(engine)
return engine


@pytest.fixture
def session(local_db):
start_mappers()
yield sessionmaker(bind=local_db)()
clear_mappers()
模型.py
@dataclass(frozen=True)
class OrderLine:
id: str
sku: str
quantity: int
test_orm.py
def test_orderline_mapper_can_load_lines(session):
session.execute(
'INSERT INTO order_lines (order_id, sku, quantity) VALUES '
'("order1", "RED-CHAIR", 12),'
'("order1", "RED-TABLE", 13),'
'("order2", "BLUE-LIPSTICK", 14)'
)
expected = [
model.OrderLine("order1", "RED-CHAIR", 12),
model.OrderLine("order1", "RED-TABLE", 13),
model.OrderLine("order2", "BLUE-LIPSTICK", 14),
]
assert session.query(model.OrderLine).all() == expected
pipenv run pytest test_orm.py 的控制台错误
============================= test session starts =============================
platform linux -- Python 3.7.6, pytest-5.4.1, py-1.8.1, pluggy-0.13.1
rootdir: /home/[redacted]/Documents/architecture-patterns-python
collected 1 item

test_orm.py F [100%]

================================== FAILURES ===================================
____________________ test_orderline_mapper_can_load_lines _____________________

session = <sqlalchemy.orm.session.Session object at 0x7fd919ac5bd0>

def test_orderline_mapper_can_load_lines(session):
session.execute(
'INSERT INTO order_lines (order_id, sku, quantity) VALUES '
'("order1", "RED-CHAIR", 12),'
'("order1", "RED-TABLE", 13),'
'("order2", "BLUE-LIPSTICK", 14)'
)
expected = [
> model.OrderLine("order1", "RED-CHAIR", 12),
model.OrderLine("order1", "RED-TABLE", 13),
model.OrderLine("order2", "BLUE-LIPSTICK", 14),
]

test_orm.py:13:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
<string>:2: in __init__
???
../../.local/share/virtualenvs/architecture-patterns-python-Qi2y0bev/lib64/python3.7/site-packages/sqlalchemy/orm/instrumentation.py:377: in _new_state_if_none
self._state_setter(instance, state)
<string>:1: in set
???
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <[AttributeError("'OrderLine' object has no attribute '_sa_instance_state'") raised in repr()] OrderLine object at 0x7fd919a8cf50>
name = '_sa_instance_state'
value = <sqlalchemy.orm.state.InstanceState object at 0x7fd9198f7490>

> ???
E dataclasses.FrozenInstanceError: cannot assign to field '_sa_instance_state'

<string>:4: FrozenInstanceError
=========================== short test summary info ===========================
FAILED test_orm.py::test_orderline_mapper_can_load_lines - dataclasses.Froze...
============================== 1 failed in 0.06s ==============================
其他问题
我理解上面的逻辑以及这些文件在做什么,但如果我缺乏基本的理解,请纠正我。
  • conftest.py (用于所有 pytest 配置)正在设置 session fixture ,它基本上在内存中设置了一个临时数据库 - 使用 start 和 clear 映射器来确保 orm 模型定义绑定(bind)到 db 实例。
  • model.py只是一个用于表示原子的数据类OrderLine目的。
  • test_orm.py pytest 提供 session 的类 fixture ,为了setup, execute, teardown一个明确用于运行测试的数据库。

  • https://github.com/cosmicpython/code/issues/17 提供的问题解决方案

    最佳答案

    SqlAlchemy 允许您覆盖一些在使用映射类和表时应用的属性检测。特别是以下允许 sqla 将状态保存在已检测的卡住数据类上。这应该在调用 mapper 之前应用。关联数据类和sql表的函数。

    from sqlalchemy.ext.instrumentation import InstrumentationManager

    ...

    DEL_ATTR = object()


    class FrozenDataclassInstrumentationManager(InstrumentationManager):
    def install_member(self, class_, key, implementation):
    self.originals.setdefault(key, class_.__dict__.get(key, DEL_ATTR))
    setattr(class_, key, implementation)

    def uninstall_member(self, class_, key):
    original = self.originals.pop(key, None)
    if original is not DEL_ATTR:
    setattr(class_, key, original)
    else:
    delattr(class_, key)

    def dispose(self, class_):
    del self.originals
    delattr(class_, "_sa_class_manager")

    def manager_getter(self, class_):
    def get(cls):
    return cls.__dict__["_sa_class_manager"]
    return get

    def manage(self, class_, manager):
    self.originals = {}
    setattr(class_, "_sa_class_manager", manager)

    def get_instance_dict(self, class_, instance):
    return instance.__dict__

    def install_state(self, class_, instance, state):
    instance.__dict__["state"] = state

    def remove_state(self, class_, instance, state):
    del instance.__dict__["state"]

    def state_getter(self, class_):
    def find(instance):
    return instance.__dict__["state"]
    return find




    OrderLine.__sa_instrumentation_manager__ = FrozenDataclassInstrumentationManager
  • Attribute instrumentation docs
  • Custom instrumentation examples
  • 关于python - 无法在使用 Fixtures 的 Pytest 函数中实例化 Python 数据类(卡住),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61419449/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com