Bug 2275102 - python-pydantic fails to build with pytest 8: pydantic.warnings.PydanticDeprecatedSince20: BaseConfig is deprecated. Use the `pydantic.ConfigDict` instead
Summary: python-pydantic fails to build with pytest 8: pydantic.warnings.PydanticDepre...
Keywords:
Status: CLOSED RAWHIDE
Alias: None
Product: Fedora
Classification: Fedora
Component: python-pydantic
Version: rawhide
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: ---
Assignee: Maxwell G
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks: 2256331
TreeView+ depends on / blocked
 
Reported: 2024-04-15 12:08 UTC by Tomáš Hrnčiar
Modified: 2024-07-04 07:43 UTC (History)
6 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed: 2024-07-04 07:42:18 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Github pydantic pydantic issues 9046 0 None open 2.6.4: pytest fails in few units 2024-04-15 12:08:52 UTC

Description Tomáš Hrnčiar 2024-04-15 12:08:53 UTC
python-pydantic fails to build with pytest 8.

=================================== FAILURES ===================================
_______________ TestsBaseConfig.test_config_class_is_deprecated ________________

self = <tests.test_config.TestsBaseConfig object at 0x7f0d46d396a0>

    def test_config_class_is_deprecated(self):
>       with pytest.warns(
            PydanticDeprecatedSince20, match='Support for class-based `config` is deprecated, use ConfigDict instead.'
        ):
E       pydantic.warnings.PydanticDeprecatedSince20: BaseConfig is deprecated. Use the `pydantic.ConfigDict` instead. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.6/migration/

tests/test_config.py:349: PydanticDeprecatedSince20
_________ TestsBaseConfig.test_config_class_attributes_are_deprecated __________

self = <tests.test_config.TestsBaseConfig object at 0x7f0d46d39550>

    def test_config_class_attributes_are_deprecated(self):
        with pytest.warns(
            PydanticDeprecatedSince20,
            match='Support for class-based `config` is deprecated, use ConfigDict instead.',
        ):
            assert BaseConfig.validate_assignment is False
    
>       with pytest.warns(
            PydanticDeprecatedSince20,
            match='Support for class-based `config` is deprecated, use ConfigDict instead.',
        ):
E       pydantic.warnings.PydanticDeprecatedSince20: BaseConfig is deprecated. Use the `pydantic.ConfigDict` instead. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.6/migration/

tests/test_config.py:363: PydanticDeprecatedSince20
_____________________________ test_parse_raw_pass ______________________________

    def test_parse_raw_pass():
        class Model(BaseModel):
            x: int
            y: int
    
>       with pytest.warns(PydanticDeprecatedSince20, match='The `parse_raw` method is deprecated'):
E       pydantic.warnings.PydanticDeprecatedSince20: `load_str_bytes` is deprecated. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.6/migration/

tests/test_deprecated.py:276: PydanticDeprecatedSince20
___________________________ test_parse_raw_pass_fail ___________________________

    @pytest.mark.skipif(platform.python_implementation() == 'PyPy', reason='Different error str on PyPy')
    def test_parse_raw_pass_fail():
        class Model(BaseModel):
            x: int
            y: int
    
>       with pytest.warns(PydanticDeprecatedSince20, match='The `parse_raw` method is deprecated'):
E       pydantic.warnings.PydanticDeprecatedSince20: `load_str_bytes` is deprecated. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.6/migration/

tests/test_deprecated.py:287: PydanticDeprecatedSince20
________________________ test_field_include_deprecation ________________________

    def test_field_include_deprecation():
        m = '`include` is deprecated and does nothing. It will be removed, use `exclude` instead'
>       with pytest.warns(PydanticDeprecatedSince20, match=m):
E       pydantic.warnings.PydanticDeprecatedSince20: Using extra keyword arguments on `Field` is deprecated and will be removed. Use `json_schema_extra` instead. (Extra keys: 'include'). Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.6/migration/

tests/test_deprecated.py:438: PydanticDeprecatedSince20
_______________________________ test_parse_file ________________________________

tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_parse_file0')

    def test_parse_file(tmp_path):
        path = tmp_path / 'test.json'
        path.write_text('{"x": 12}')
>       with pytest.warns(
            PydanticDeprecatedSince20, match='^The `parse_file` method is deprecated; load the data from file,'
        ):
E       pydantic.warnings.PydanticDeprecatedSince20: `load_file` is deprecated. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.6/migration/

tests/test_deprecated.py:649: PydanticDeprecatedSince20
____________________________ test_deprecated_module ____________________________

tmp_path = PosixPath('/tmp/pytest-of-mockbuild/pytest-0/test_deprecated_module0')

    def test_deprecated_module(tmp_path: Path) -> None:
        class Model(BaseModel):
            x: int
    
        assert hasattr(parse_obj_as, '__deprecated__')
        with pytest.warns(
            PydanticDeprecatedSince20,
            match='`parse_obj_as` is deprecated. Use `pydantic.TypeAdapter.validate_python` instead.',
        ):
            parse_obj_as(Model, {'x': 1})
    
        assert hasattr(schema_json_of, '__deprecated__')
>       with pytest.warns(
            PydanticDeprecatedSince20,
            match='`schema_json_of` is deprecated. Use `pydantic.TypeAdapter.json_schema` instead.',
        ):
E       pydantic.warnings.PydanticDeprecatedSince20: `schema_of` is deprecated. Use `pydantic.TypeAdapter.json_schema` instead. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.6/migration/

tests/test_deprecated.py:729: PydanticDeprecatedSince20
_ test_callable_fallback_with_non_serializable_default[Cannot generate a JsonSchema for core_schema.CallableSchema \\[skipped-choice\\]] _

warning_match = 'Cannot generate a JsonSchema for core_schema.CallableSchema \\[skipped-choice\\]'

    @pytest.mark.parametrize(
        'warning_match',
        (
            r'Cannot generate a JsonSchema for core_schema.CallableSchema \[skipped-choice\]',
            r'Default value .* is not JSON serializable; excluding default from JSON schema \[non-serializable-default\]',
        ),
    )
    def test_callable_fallback_with_non_serializable_default(warning_match):
        class Model(BaseModel):
            callback: Union[int, Callable[[int], int]] = lambda x: x  # noqa E731
    
        class MyGenerator(GenerateJsonSchema):
            ignored_warning_kinds = ()
    
>       with pytest.warns(PydanticJsonSchemaWarning, match=warning_match):
E       pydantic.json_schema.PydanticJsonSchemaWarning: Default value <function test_callable_fallback_with_non_serializable_default.<locals>.Model.<lambda> at 0x7f0d46030860> is not JSON serializable; excluding default from JSON schema [non-serializable-default]

tests/test_json_schema.py:1400: PydanticJsonSchemaWarning
_ test_callable_fallback_with_non_serializable_default[Default value .* is not JSON serializable; excluding default from JSON schema \\[non-serializable-default\\]] _

warning_match = 'Default value .* is not JSON serializable; excluding default from JSON schema \\[non-serializable-default\\]'

    @pytest.mark.parametrize(
        'warning_match',
        (
            r'Cannot generate a JsonSchema for core_schema.CallableSchema \[skipped-choice\]',
            r'Default value .* is not JSON serializable; excluding default from JSON schema \[non-serializable-default\]',
        ),
    )
    def test_callable_fallback_with_non_serializable_default(warning_match):
        class Model(BaseModel):
            callback: Union[int, Callable[[int], int]] = lambda x: x  # noqa E731
    
        class MyGenerator(GenerateJsonSchema):
            ignored_warning_kinds = ()
    
>       with pytest.warns(PydanticJsonSchemaWarning, match=warning_match):
E       pydantic.json_schema.PydanticJsonSchemaWarning: Cannot generate a JsonSchema for core_schema.CallableSchema [skipped-choice]

tests/test_json_schema.py:1400: PydanticJsonSchemaWarning
________________________________ test_use_bare _________________________________

    class Model(BaseModel):
        a: str
    
        with pytest.warns(PydanticDeprecatedSince20, match=V1_VALIDATOR_DEPRECATION_MATCH):
    
>           @validator

tests/test_validators.py:537: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

__field = <function test_use_bare.<locals>.Model.checker at 0x7f0d43de80e0>
pre = False, each_item = False, always = False, check_fields = None

    def validator(
        __field: str,
        *fields: str,
        pre: bool = False,
        each_item: bool = False,
        always: bool = False,
        check_fields: bool | None = None,
        allow_reuse: bool = False,
    ) -> Callable[[_V1ValidatorType], _V1ValidatorType]:
        """Decorate methods on the class indicating that they should be used to validate fields.
    
        Args:
            __field (str): The first field the validator should be called on; this is separate
                from `fields` to ensure an error is raised if you don't pass at least one.
            *fields (str): Additional field(s) the validator should be called on.
            pre (bool, optional): Whether this validator should be called before the standard
                validators (else after). Defaults to False.
            each_item (bool, optional): For complex objects (sets, lists etc.) whether to validate
                individual elements rather than the whole object. Defaults to False.
            always (bool, optional): Whether this method and other validators should be called even if
                the value is missing. Defaults to False.
            check_fields (bool | None, optional): Whether to check that the fields actually exist on the model.
                Defaults to None.
            allow_reuse (bool, optional): Whether to track and raise an error if another validator refers to
                the decorated function. Defaults to False.
    
        Returns:
            Callable: A decorator that can be used to decorate a
                function to be used as a validator.
        """
        if allow_reuse is True:  # pragma: no cover
            warn(_ALLOW_REUSE_WARNING_MESSAGE, DeprecationWarning)
        fields = tuple((__field, *fields))
        if isinstance(fields[0], FunctionType):
>           raise PydanticUserError(
                '`@validator` should be used with fields and keyword arguments, not bare. '
                "E.g. usage should be `@validator('<field_name>', ...)`",
                code='validator-no-fields',
E               pydantic.errors.PydanticUserError: `@validator` should be used with fields and keyword arguments, not bare. E.g. usage should be `@validator('<field_name>', ...)`
E               
E               For further information visit https://errors.pydantic.dev/2.6/u/validator-no-fields

pydantic/deprecated/class_validators.py:116: PydanticUserError

During handling of the above exception, another exception occurred:

    def test_use_bare():
        with pytest.raises(TypeError, match='`@validator` should be used with fields'):
    
>           class Model(BaseModel):

tests/test_validators.py:532: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    class Model(BaseModel):
        a: str
    
>       with pytest.warns(PydanticDeprecatedSince20, match=V1_VALIDATOR_DEPRECATION_MATCH):
E       Failed: DID NOT WARN. No warnings of type (<class 'pydantic.warnings.PydanticDeprecatedSince20'>,) were emitted.
E        Emitted warnings: [].

tests/test_validators.py:535: Failed
______________________________ test_use_no_fields ______________________________

    class Model(BaseModel):
        a: str
    
        with pytest.warns(PydanticDeprecatedSince20, match=V1_VALIDATOR_DEPRECATION_MATCH):
    
>           @validator()
E           TypeError: validator() missing 1 required positional argument: '__field'

tests/test_validators.py:561: TypeError

During handling of the above exception, another exception occurred:

    def test_use_no_fields():
        with pytest.raises(TypeError, match=re.escape("validator() missing 1 required positional argument: '__field'")):
    
>           class Model(BaseModel):

tests/test_validators.py:556: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    class Model(BaseModel):
        a: str
    
>       with pytest.warns(PydanticDeprecatedSince20, match=V1_VALIDATOR_DEPRECATION_MATCH):
E       Failed: DID NOT WARN. No warnings of type (<class 'pydantic.warnings.PydanticDeprecatedSince20'>,) were emitted.
E        Emitted warnings: [].

tests/test_validators.py:559: Failed
_________________ test_validator_bad_fields_throws_configerror _________________

    class Model(BaseModel):
        a: str
        b: str
    
        with pytest.warns(PydanticDeprecatedSince20, match=V1_VALIDATOR_DEPRECATION_MATCH):
    
>           @validator(['a', 'b'])

tests/test_validators.py:592: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

__field = ['a', 'b'], pre = False, each_item = False, always = False
check_fields = None

    def validator(
        __field: str,
        *fields: str,
        pre: bool = False,
        each_item: bool = False,
        always: bool = False,
        check_fields: bool | None = None,
        allow_reuse: bool = False,
    ) -> Callable[[_V1ValidatorType], _V1ValidatorType]:
        """Decorate methods on the class indicating that they should be used to validate fields.
    
        Args:
            __field (str): The first field the validator should be called on; this is separate
                from `fields` to ensure an error is raised if you don't pass at least one.
            *fields (str): Additional field(s) the validator should be called on.
            pre (bool, optional): Whether this validator should be called before the standard
                validators (else after). Defaults to False.
            each_item (bool, optional): For complex objects (sets, lists etc.) whether to validate
                individual elements rather than the whole object. Defaults to False.
            always (bool, optional): Whether this method and other validators should be called even if
                the value is missing. Defaults to False.
            check_fields (bool | None, optional): Whether to check that the fields actually exist on the model.
                Defaults to None.
            allow_reuse (bool, optional): Whether to track and raise an error if another validator refers to
                the decorated function. Defaults to False.
    
        Returns:
            Callable: A decorator that can be used to decorate a
                function to be used as a validator.
        """
        if allow_reuse is True:  # pragma: no cover
            warn(_ALLOW_REUSE_WARNING_MESSAGE, DeprecationWarning)
        fields = tuple((__field, *fields))
        if isinstance(fields[0], FunctionType):
            raise PydanticUserError(
                '`@validator` should be used with fields and keyword arguments, not bare. '
                "E.g. usage should be `@validator('<field_name>', ...)`",
                code='validator-no-fields',
            )
        elif not all(isinstance(field, str) for field in fields):
>           raise PydanticUserError(
                '`@validator` fields should be passed as separate string args. '
                "E.g. usage should be `@validator('<field_name_1>', '<field_name_2>', ...)`",
                code='validator-invalid-fields',
            )
E           pydantic.errors.PydanticUserError: `@validator` fields should be passed as separate string args. E.g. usage should be `@validator('<field_name_1>', '<field_name_2>', ...)`
E           
E           For further information visit https://errors.pydantic.dev/2.6/u/validator-invalid-fields

pydantic/deprecated/class_validators.py:122: PydanticUserError

During handling of the above exception, another exception occurred:

    def test_validator_bad_fields_throws_configerror():
        """
        Attempts to create a validator with fields set as a list of strings,
        rather than just multiple string args. Expects ConfigError to be raised.
        """
        with pytest.raises(TypeError, match='`@validator` fields should be passed as separate string args.'):
    
>           class Model(BaseModel):

tests/test_validators.py:586: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

    class Model(BaseModel):
        a: str
        b: str
    
>       with pytest.warns(PydanticDeprecatedSince20, match=V1_VALIDATOR_DEPRECATION_MATCH):
E       Failed: DID NOT WARN. No warnings of type (<class 'pydantic.warnings.PydanticDeprecatedSince20'>,) were emitted.
E        Emitted warnings: [].

tests/test_validators.py:590: Failed
_____________________ test_assert_raises_validation_error ______________________

    def test_assert_raises_validation_error():
        class Model(BaseModel):
            a: str
    
            @field_validator('a')
            @classmethod
            def check_a(cls, v: Any):
                assert v == 'a', 'invalid a'
                return v
    
        Model(a='a')
    
        with pytest.raises(ValidationError) as exc_info:
            Model(a='snap')
        injected_by_pytest = "assert 'snap' == 'a'\n  - a\n  + snap"
>       assert exc_info.value.errors(include_url=False) == [
            {
                'ctx': {'error': HasRepr(repr(AssertionError("invalid a\nassert 'snap' == 'a'\n  - a\n  + snap")))},
                'input': 'snap',
                'loc': ('a',),
                'msg': f'Assertion failed, invalid a\n{injected_by_pytest}',
                'type': 'assertion_error',
            }
        ]
E       assert [{'ctx': {'er...+ snap', ...}] == [{'ctx': {'er...+ snap', ...}]
E         
E         At index 0 diff: {'type': 'assertion_error', 'loc': ('a',), 'msg': "Assertion failed, invalid a\nassert 'snap' == 'a'\n  \n  - a\n  + snap", 'input': 'snap', 'ctx': {'error': AssertionError("invalid a\nassert 'snap' == 'a'\n  \n  - a\n  + snap")}} != {'ctx': {'error': HasRepr('AssertionError("invalid a\\nassert \'snap\' == \'a\'\\n  - a\\n  + snap")')}, 'input': 'snap', 'loc': ('a',), 'msg': "Assertion failed, invalid a\nassert 'snap' == 'a'\n  - a\n  + snap", 'type': 'assertion_error'}
E         Use -v to get more diff

tests/test_validators.py:1311: AssertionError
__________________ test_root_validator_allow_reuse_same_field __________________

    def test_root_validator_allow_reuse_same_field():
>       with pytest.warns(UserWarning, match='`root_val` overrides an existing Pydantic `@root_validator` decorator'):
E       pydantic.warnings.PydanticDeprecatedSince20: Pydantic V1 style `@root_validator` validators are deprecated. You should migrate to Pydantic V2 style `@model_validator` validators, see the migration guide for more details. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.6/migration/

tests/test_validators.py:2511: PydanticDeprecatedSince20
=========================== short test summary info ============================
FAILED tests/test_config.py::TestsBaseConfig::test_config_class_is_deprecated
FAILED tests/test_config.py::TestsBaseConfig::test_config_class_attributes_are_deprecated
FAILED tests/test_deprecated.py::test_parse_raw_pass - pydantic.warnings.Pyda...
FAILED tests/test_deprecated.py::test_parse_raw_pass_fail - pydantic.warnings...
FAILED tests/test_deprecated.py::test_field_include_deprecation - pydantic.wa...
FAILED tests/test_deprecated.py::test_parse_file - pydantic.warnings.Pydantic...
FAILED tests/test_deprecated.py::test_deprecated_module - pydantic.warnings.P...
FAILED tests/test_json_schema.py::test_callable_fallback_with_non_serializable_default[Cannot generate a JsonSchema for core_schema.CallableSchema \\[skipped-choice\\]]
FAILED tests/test_json_schema.py::test_callable_fallback_with_non_serializable_default[Default value .* is not JSON serializable; excluding default from JSON schema \\[non-serializable-default\\]]
FAILED tests/test_validators.py::test_use_bare - Failed: DID NOT WARN. No war...
FAILED tests/test_validators.py::test_use_no_fields - Failed: DID NOT WARN. N...
FAILED tests/test_validators.py::test_validator_bad_fields_throws_configerror
FAILED tests/test_validators.py::test_assert_raises_validation_error - assert...
FAILED tests/test_validators.py::test_root_validator_allow_reuse_same_field
=========== 14 failed, 4244 passed, 93 skipped, 10 xfailed in 16.87s ===========


https://docs.pytest.org/en/stable/changelog.html

For the build logs, see:
https://copr-be.cloud.fedoraproject.org/results/thrnciar/pytest/fedora-rawhide-x86_64/07248598-python-pydantic/

For all our attempts to build python-pydantic with pytest 8, see:
https://copr.fedorainfracloud.org/coprs/thrnciar/pytest/package/python-pydantic/

Let us know here if you have any questions.

Pytest 8 is planned to be included in Fedora 41. And this bugzilla is a
heads up before we merge new pytest into rawhide. For more info see a Fedora Change
proposal https://fedoraproject.org/wiki/Changes/Pytest_8

We'd appreciate help from the people who know this package best,
but if you don't want to work on this now, let us know so we can try to work around it on our side.

Comment 1 Tomáš Hrnčiar 2024-07-04 07:43:19 UTC
pydantic 2.8.1~b1 builds with pytest 8.


Note You need to log in before you can comment on or make changes to this bug.