epam / badgerdoc

Apache License 2.0
33 stars 32 forks source link

Annotation fixtures amend testing data #121

Open cakeinsauce opened 1 year ago

cakeinsauce commented 1 year ago

Fixture annotation.tests.conftest.prepare_db_for_annotation_change_task_statuses amend some data so next tests would fail. To reproduce place annotation.tests.test_post_annotation.test_post_annotation_by_user_similar_doc_no_category (just a random test that uses data from this fixture) to the bottom of its module. You would get a similar error:

tests/conftest.py:244:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/conftest.py:188: in add_objects
    db.merge(obj)
venv/lib/python3.8/site-packages/sqlalchemy/orm/session.py:2166: in merge
    return self._merge(
venv/lib/python3.8/site-packages/sqlalchemy/orm/session.py:2306: in _merge
    prop.merge(
venv/lib/python3.8/site-packages/sqlalchemy/orm/properties.py:287: in merge
    impl.set(dest_state, dest_dict, value, None)
venv/lib/python3.8/site-packages/sqlalchemy/orm/attributes.py:867: in set
    old = self.get(state, dict_, PASSIVE_RETURN_NEVER_SET)
venv/lib/python3.8/site-packages/sqlalchemy/orm/attributes.py:725: in get
    value = state._load_expired(state, passive)
venv/lib/python3.8/site-packages/sqlalchemy/orm/state.py:652: in _load_expired
    self.manager.deferred_scalar_loader(self, toload)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

mapper = <Mapper at 0x104281700; ManualAnnotationTask>
state = <sqlalchemy.orm.state.InstanceState object at 0x104acc970>
attribute_names = {'deadline', 'file_id', 'id', 'is_validation', 'job_id', 'pages', ...}

    def load_scalar_attributes(mapper, state, attribute_names):
        """initiate a column-based attribute refresh operation."""

        # assert mapper is _state_mapper(state)
        session = state.session
        if not session:
            raise orm_exc.DetachedInstanceError(
                "Instance %s is not bound to a Session; "
                "attribute refresh operation cannot proceed" % (state_str(state))
            )

        has_key = bool(state.key)

        result = False

        # in the case of inheritance, particularly concrete and abstract
        # concrete inheritance, the class manager might have some keys
        # of attributes on the superclass that we didn't actually map.
        # These could be mapped as "concrete, dont load" or could be completely
        # excluded from the mapping and we know nothing about them.  Filter them
        # here to prevent them from coming through.
        if attribute_names:
            attribute_names = attribute_names.intersection(mapper.attrs.keys())

        if mapper.inherits and not mapper.concrete:
            # because we are using Core to produce a select() that we
            # pass to the Query, we aren't calling setup() for mapped
            # attributes; in 1.0 this means deferred attrs won't get loaded
            # by default
            statement = mapper._optimized_get_statement(state, attribute_names)
            if statement is not None:
                result = load_on_ident(
                    session.query(mapper)
                    .options(strategy_options.Load(mapper).undefer("*"))
                    .from_statement(statement),
                    None,
                    only_load_props=attribute_names,
                    refresh_state=state,
                )

        if result is False:
            if has_key:
                identity_key = state.key
            else:
                # this codepath is rare - only valid when inside a flush, and the
                # object is becoming persistent but hasn't yet been assigned
                # an identity_key.
                # check here to ensure we have the attrs we need.
                pk_attrs = [
                    mapper._columntoproperty[col].key for col in mapper.primary_key
                ]
                if state.expired_attributes.intersection(pk_attrs):
                    raise sa_exc.InvalidRequestError(
                        "Instance %s cannot be refreshed - it's not "
                        " persistent and does not "
                        "contain a full primary key." % state_str(state)
                    )
                identity_key = mapper._identity_key_from_state(state)

            if (
                _none_set.issubset(identity_key) and not mapper.allow_partial_pks
            ) or _none_set.issuperset(identity_key):
                util.warn_limited(
                    "Instance %s to be refreshed doesn't "
                    "contain a full primary key - can't be refreshed "
                    "(and shouldn't be expired, either).",
                    state_str(state),
                )
                return

            result = load_on_ident(
                session.query(mapper),
                identity_key,
                refresh_state=state,
                only_load_props=attribute_names,
            )

        # if instance is pending, a refresh operation
        # may not complete (even if PK attributes are assigned)
        if has_key and result is None:
>           raise orm_exc.ObjectDeletedError(state)
E           sqlalchemy.orm.exc.ObjectDeletedError: Instance '<ManualAnnotationTask at 0x104accbe0>' has been deleted, or its row is otherwise not present.

venv/lib/python3.8/site-packages/sqlalchemy/orm/loading.py:1016: ObjectDeletedError

The problem might be in fixture's scope =module.

serereg commented 1 year ago

# FIXME: Some annotation fixtures amend testing data on previous tests.

https://github.com/serereg/badgerdoc/blob/a35e62817a97fa22e4be1a23382c8f26a1297ce2/annotation/tests/test_tasks_crud_cr.py#L1516