Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revisit test_name_qualname_reuse_typevar_known_issue with pydantic v2. Expected ... #203

Open
github-actions bot opened this issue Sep 16, 2024 · 0 comments
Labels

Comments

@github-actions
Copy link

# TODO: Revisit test_name_qualname_reuse_typevar_known_issue with pydantic v2. Expected to change

    assert MyModel(a=1) != MyInherited(a=1)


def test_name_qualname_and_module() -> None:
    assert Model.__name__ == 'Model'
    assert Model.__qualname__ == 'Model'
    assert Model.__module__ == 'omnipy.data.model'

    assert Model[int].__name__ == 'Model[int]'
    assert Model[int].__qualname__ == 'Model[int]'
    assert Model[int].__module__ == 'omnipy.data.model'

    assert Model[Model[None]].__name__ == 'Model[Model[None]]'
    assert Model[Model[None]].__qualname__ == 'Model[Model[None]]'
    assert Model[Model[None]].__module__ == 'omnipy.data.model'

    assert Model[dict[str, Model[None]]].__name__ == 'Model[dict[str, Model[None]]]'
    assert Model[dict[str, Model[None]]].__qualname__ == 'Model[dict[str, Model[None]]]'
    assert Model[dict[str, Model[None]]].__module__ == 'omnipy.data.model'

    assert Model[list[T]][int].__name__ == 'Model[list[~T]][int]'
    assert Model[list[T]][int].__qualname__ == 'Model[list[~T]][int]'
    assert Model[list[T]][int].__module__ == 'omnipy.data.model'

    ABC_PREFIX = 'test_name_qualname_and_module.<locals>.ABC.'
    DEF_PREFIX = 'test_name_qualname_and_module.<locals>.DEF.'

    class ABC:
        class MyModel(Model[list[T]], Generic[T]):
            ...

        assert MyModel.__name__ == 'MyModel'
        assert MyModel.__qualname__ == ABC_PREFIX + 'MyModel'

        assert MyModel[int].__name__ == 'MyModel[int]'
        assert MyModel[int].__qualname__ == ABC_PREFIX + 'MyModel[int]'

        assert MyModel[U].__name__ == 'MyModel[~U]'
        assert MyModel[U].__qualname__ == ABC_PREFIX + 'MyModel[~U]'

        assert MyModel.__module__ == 'tests.data.test_model'

    class DEF:
        class MyTupleModel(ABC.MyModel[tuple[T, U]], Generic[T, U]):
            ...

        assert MyTupleModel.__name__ == 'MyTupleModel'
        assert MyTupleModel.__qualname__ == DEF_PREFIX + 'MyTupleModel'

        assert MyTupleModel[int, str].__name__ == 'MyTupleModel[int, str]'
        assert MyTupleModel[int, str].__qualname__ == DEF_PREFIX + 'MyTupleModel[int, str]'

        assert MyTupleModel.__module__ == 'tests.data.test_model'

    assert ABC.MyModel[int].__name__ == 'MyModel[int]'
    assert ABC.MyModel[int].__qualname__ == ABC_PREFIX + 'MyModel[int]'

    assert ABC.MyModel[ABC.MyModel[int]].__name__ == 'MyModel[MyModel[int]]'
    assert ABC.MyModel[ABC.MyModel[int]].__qualname__ == ABC_PREFIX + 'MyModel[MyModel[int]]'

    assert ABC.MyModel[Union[str, ABC.MyModel[str | int]]].__name__ == \
           'MyModel[str | MyModel[str | int]]'
    assert ABC.MyModel[Union[str, ABC.MyModel[str | int]]].__qualname__ == \
           ABC_PREFIX + 'MyModel[str | MyModel[str | int]]'

    assert ABC.MyModel[ABC.MyModel[Union[str, int]] | str].__name__ == \
           'MyModel[MyModel[str | int] | str]'
    assert ABC.MyModel[ABC.MyModel[str | int] | str].__qualname__ == \
           ABC_PREFIX + 'MyModel[MyModel[str | int] | str]'

    assert DEF.MyTupleModel[int, str].__name__ == 'MyTupleModel[int, str]'
    assert DEF.MyTupleModel[int, str].__qualname__ == DEF_PREFIX + 'MyTupleModel[int, str]'

    assert DEF.MyTupleModel[int, ABC.MyModel[str]].__name__ == \
           'MyTupleModel[int, MyModel[str]]'
    assert DEF.MyTupleModel[int, ABC.MyModel[str]].__qualname__ == \
           (DEF_PREFIX + 'MyTupleModel[int, MyModel[str]]')

    assert MyFwdRefModel.__name__ == 'MyGenericModel[NumberModel]'
    assert MyFwdRefModel.__qualname__ == 'CBA.MyGenericModel[NumberModel]'
    assert MyFwdRefModel.__module__ == 'tests.data.helpers.models'

    assert MyNestedFwdRefModel.__name__ == 'MyGenericModel[str | NumberModel]'
    assert MyNestedFwdRefModel.__qualname__ == 'CBA.MyGenericModel[str | NumberModel]'
    assert MyNestedFwdRefModel.__module__ == 'tests.data.helpers.models'

    assert (CBA.MyGenericModel[ForwardRef('ABC.MyModel[int]')].__name__ ==  # noqa: W504
            'MyGenericModel[ABC.MyModel[int]]')
    assert (CBA.MyGenericModel[ForwardRef('ABC.MyModel[int]')].__qualname__ ==  # noqa: W504
            'CBA.MyGenericModel[ABC.MyModel[int]]')
    assert (CBA.MyGenericModel[ForwardRef('ABC.MyModel[int]')].__module__ ==  # noqa: W504
            'tests.data.helpers.models')

    assert (CBA.MyGenericModel['Union[str, ABC.MyModel[int]]'].__name__ ==  # noqa: W504
            'MyGenericModel[Union[str, ABC.MyModel[int]]]')
    assert (CBA.MyGenericModel['Union[str, ABC.MyModel[int]]'].__qualname__ ==  # noqa: W504
            'CBA.MyGenericModel[Union[str, ABC.MyModel[int]]]')
    assert (CBA.MyGenericModel['Union[str, ABC.MyModel[int]]'].__module__ ==  # noqa: W504
            'tests.data.helpers.models')


# TODO: Revisit test_name_qualname_reuse_typevar_known_issue with pydantic v2. Expected to change
@pytest.mark.skipif(
    os.getenv('OMNIPY_FORCE_SKIPPED_TEST') != '1',
    reason="""
Known issue due to bug in pydantic v1 where a generic model defined with some TypeVar(s)
parametrized with the exact same TypeVar(s) are assumed to be the same model:

    https://github.com/pydantic/pydantic/blob/5ebcdc13b83fba5da34ad9b0f008f7b4faf89396/pydantic/generics.py#L110

This causes issues if generic models inherit from each other while having the same TypeVar(s).
TypeVar(s) in Python are bound only within the scope of a class or function, so the same TypeVar(s)
in different classes should not be assumed to be the same.

For now, the only consequence of the bug that we are aware of is that the `__name__` and
`__qualname__` of the models are slightly incorrect and will not print the TypeVars. However,
worse consequences might be hidden in the code.
""")
def test_name_qualname_reuse_typevar_known_issue() -> None:
    class MyModel(Model[T], Generic[T]):
        ...

    assert MyModel[T].__name__ == 'MyModel[~T]'
    assert MyModel[T].__qualname__ == 'MyModel[~T]'


def test_repr() -> None:
@github-actions github-actions bot added the todo label Sep 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

0 participants