python-pydantic/support-pytest-8.patch

383 lines
15 KiB
Diff

From 7fb31529124f51cceb32d1d7b8ae9b58c0606b17 Mon Sep 17 00:00:00 2001
From: Steve Kowalik <steven@wedontsleep.org>
Date: Thu, 30 May 2024 14:14:04 +1000
Subject: [PATCH] Ignore other warnings when checking warnings
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Building on Michał's amazing work in PR#9040, extend the pattern to also
ignore other warnings that are emitted by pytest.warns() when running
under Pytest 8.x. This also continues to support Pytest 7.x.
Co-authored-by: Michał Górny <mgorny@gentoo.org>
Fixes: #9025
---
tests/conftest.py | 2 +-
tests/test_config.py | 84 +++++++++++---------
tests/test_deprecated.py | 156 ++++++++++++++++++++++----------------
tests/test_json_schema.py | 9 ++-
tests/test_validators.py | 1 +
5 files changed, 146 insertions(+), 106 deletions(-)
diff --git a/tests/conftest.py b/tests/conftest.py
index e0c0dee018..421afade2e 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -49,7 +49,7 @@ def _create_module_file(code, tmp_path, name):
def disable_error_urls():
# Don't add URLs during docs tests when printing
# Otherwise we'll get version numbers in the URLs that will update frequently
- os.environ['PYDANTIC_ERRORS_OMIT_URL'] = 'true'
+ os.environ['PYDANTIC_ERRORS_INCLUDE_URL'] = 'false'
@pytest.fixture
diff --git a/tests/test_config.py b/tests/test_config.py
index 1a5e31628a..31b2320326 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -1,6 +1,7 @@
import json
import re
import sys
+import warnings
from contextlib import nullcontext as does_not_raise
from decimal import Decimal
from inspect import signature
@@ -349,45 +350,54 @@ class Model(BaseModel):
assert m == m.model_copy()
def test_config_class_is_deprecated(self):
- with pytest.warns(
- PydanticDeprecatedSince20, match='Support for class-based `config` is deprecated, use ConfigDict instead.'
- ):
-
- class Config(BaseConfig):
- pass
+ with warnings.catch_warnings():
+ # we need to explicitly ignore the other warning in pytest-8
+ # TODO: rewrite it to use two nested pytest.warns() when pytest-7 is no longer supported
+ warnings.simplefilter('ignore')
+ with pytest.warns(
+ PydanticDeprecatedSince20,
+ match='Support for class-based `config` is deprecated, use ConfigDict instead.',
+ ):
+
+ class Config(BaseConfig):
+ pass
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.',
- ):
- assert BaseConfig().validate_assignment is False
-
- with pytest.warns(
- PydanticDeprecatedSince20,
- match='Support for class-based `config` is deprecated, use ConfigDict instead.',
- ):
-
- class Config(BaseConfig):
- pass
-
- with pytest.warns(
- PydanticDeprecatedSince20,
- match='Support for class-based `config` is deprecated, use ConfigDict instead.',
- ):
- assert Config.validate_assignment is False
-
- with pytest.warns(
- PydanticDeprecatedSince20,
- match='Support for class-based `config` is deprecated, use ConfigDict instead.',
- ):
- assert Config().validate_assignment is False
+ with warnings.catch_warnings():
+ # we need to explicitly ignore the other warning in pytest-8
+ # TODO: rewrite it to use two nested pytest.warns() when pytest-7 is no longer supported
+ warnings.simplefilter('ignore')
+ 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.',
+ ):
+ assert BaseConfig().validate_assignment is False
+
+ with pytest.warns(
+ PydanticDeprecatedSince20,
+ match='Support for class-based `config` is deprecated, use ConfigDict instead.',
+ ):
+
+ class Config(BaseConfig):
+ pass
+
+ with pytest.warns(
+ PydanticDeprecatedSince20,
+ match='Support for class-based `config` is deprecated, use ConfigDict instead.',
+ ):
+ assert Config.validate_assignment is False
+
+ with pytest.warns(
+ PydanticDeprecatedSince20,
+ match='Support for class-based `config` is deprecated, use ConfigDict instead.',
+ ):
+ assert Config().validate_assignment is False
@pytest.mark.filterwarnings('ignore:.* is deprecated.*:DeprecationWarning')
def test_config_class_missing_attributes(self):
diff --git a/tests/test_deprecated.py b/tests/test_deprecated.py
index fda6879597..2e58e8b433 100644
--- a/tests/test_deprecated.py
+++ b/tests/test_deprecated.py
@@ -1,5 +1,6 @@
import platform
import re
+import warnings
from datetime import date, timedelta
from pathlib import Path
from types import SimpleNamespace
@@ -273,8 +274,12 @@ class Model(BaseModel):
x: int
y: int
- with pytest.warns(PydanticDeprecatedSince20, match='The `parse_raw` method is deprecated'):
- model = Model.parse_raw('{"x": 1, "y": 2}')
+ with warnings.catch_warnings():
+ # we need to explicitly ignore the other warning in pytest-8
+ # TODO: rewrite it to use two nested pytest.warns() when pytest-7 is no longer supported
+ warnings.simplefilter('ignore')
+ with pytest.warns(PydanticDeprecatedSince20, match='The `parse_raw` method is deprecated'):
+ model = Model.parse_raw('{"x": 1, "y": 2}')
assert model.model_dump() == {'x': 1, 'y': 2}
@@ -284,9 +289,13 @@ class Model(BaseModel):
x: int
y: int
- with pytest.warns(PydanticDeprecatedSince20, match='The `parse_raw` method is deprecated'):
- with pytest.raises(ValidationError, match='1 validation error for Model') as exc_info:
- Model.parse_raw('invalid')
+ with warnings.catch_warnings():
+ # we need to explicitly ignore the other warning in pytest-8
+ # TODO: rewrite it to use two nested pytest.warns() when pytest-7 is no longer supported
+ warnings.simplefilter('ignore')
+ with pytest.warns(PydanticDeprecatedSince20, match='The `parse_raw` method is deprecated'):
+ with pytest.raises(ValidationError, match='1 validation error for Model') as exc_info:
+ Model.parse_raw('invalid')
# insert_assert(exc_info.value.errors(include_url=False))
assert exc_info.value.errors(include_url=False) == [
@@ -435,10 +444,14 @@ class Model(BaseModel):
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):
+ with warnings.catch_warnings():
+ # we need to explicitly ignore the other warning in pytest-8
+ # TODO: rewrite it to use two nested pytest.warns() when pytest-7 is no longer supported
+ warnings.simplefilter('ignore')
+ with pytest.warns(PydanticDeprecatedSince20, match=m):
- class Model(BaseModel):
- x: int = Field(include=True)
+ class Model(BaseModel):
+ x: int = Field(include=True)
def test_unique_items_items():
@@ -664,10 +677,14 @@ def test_parse_obj():
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,'
- ):
- assert SimpleModel.parse_file(str(path)).model_dump() == {'x': 12}
+ with warnings.catch_warnings():
+ # we need to explicitly ignore the other warning in pytest-8
+ # TODO: rewrite it to use two nested pytest.warns() when pytest-7 is no longer supported
+ warnings.simplefilter('ignore')
+ with pytest.warns(
+ PydanticDeprecatedSince20, match='^The `parse_file` method is deprecated; load the data from file,'
+ ):
+ assert SimpleModel.parse_file(str(path)).model_dump() == {'x': 12}
def test_construct():
@@ -736,61 +753,68 @@ 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.',
- ):
- schema_json_of(Model)
-
- assert hasattr(schema_of, '__deprecated__')
- with pytest.warns(
- PydanticDeprecatedSince20, match='`schema_of` is deprecated. Use `pydantic.TypeAdapter.json_schema` instead.'
- ):
- schema_of(Model)
-
- assert hasattr(load_str_bytes, '__deprecated__')
- with pytest.warns(PydanticDeprecatedSince20, match='`load_str_bytes` is deprecated.'):
- load_str_bytes('{"x": 1}')
-
- assert hasattr(load_file, '__deprecated__')
- file = tmp_path / 'main.py'
- file.write_text('{"x": 1}')
- with pytest.warns(PydanticDeprecatedSince20, match='`load_file` is deprecated.'):
- load_file(file)
-
- assert hasattr(pydantic_encoder, '__deprecated__')
- with pytest.warns(
- PydanticDeprecatedSince20,
- match='`pydantic_encoder` is deprecated, use `pydantic_core.to_jsonable_python` instead.',
- ):
- pydantic_encoder(Model(x=1))
-
- assert hasattr(custom_pydantic_encoder, '__deprecated__')
- with pytest.warns(
- PydanticDeprecatedSince20, match='`custom_pydantic_encoder` is deprecated, use `BaseModel.model_dump` instead.'
- ):
- custom_pydantic_encoder({int: lambda x: str(x)}, Model(x=1))
-
- assert hasattr(timedelta_isoformat, '__deprecated__')
- with pytest.warns(PydanticDeprecatedSince20, match='`timedelta_isoformat` is deprecated.'):
- timedelta_isoformat(timedelta(seconds=1))
-
- with pytest.warns(
- PydanticDeprecatedSince20, match='The `validate_arguments` method is deprecated; use `validate_call` instead.'
- ):
-
- def test(a: int, b: int):
- pass
+ with warnings.catch_warnings():
+ # we need to explicitly ignore the other warning in pytest-8
+ # TODO: rewrite it to use two nested pytest.warns() when pytest-7 is no longer supported
+ warnings.simplefilter('ignore')
+ 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.',
+ ):
+ schema_json_of(Model)
+
+ assert hasattr(schema_of, '__deprecated__')
+ with pytest.warns(
+ PydanticDeprecatedSince20,
+ match='`schema_of` is deprecated. Use `pydantic.TypeAdapter.json_schema` instead.',
+ ):
+ schema_of(Model)
+
+ assert hasattr(load_str_bytes, '__deprecated__')
+ with pytest.warns(PydanticDeprecatedSince20, match='`load_str_bytes` is deprecated.'):
+ load_str_bytes('{"x": 1}')
+
+ assert hasattr(load_file, '__deprecated__')
+ file = tmp_path / 'main.py'
+ file.write_text('{"x": 1}')
+ with pytest.warns(PydanticDeprecatedSince20, match='`load_file` is deprecated.'):
+ load_file(file)
+
+ assert hasattr(pydantic_encoder, '__deprecated__')
+ with pytest.warns(
+ PydanticDeprecatedSince20,
+ match='`pydantic_encoder` is deprecated, use `pydantic_core.to_jsonable_python` instead.',
+ ):
+ pydantic_encoder(Model(x=1))
+
+ assert hasattr(custom_pydantic_encoder, '__deprecated__')
+ with pytest.warns(
+ PydanticDeprecatedSince20,
+ match='`custom_pydantic_encoder` is deprecated, use `BaseModel.model_dump` instead.',
+ ):
+ custom_pydantic_encoder({int: lambda x: str(x)}, Model(x=1))
+
+ assert hasattr(timedelta_isoformat, '__deprecated__')
+ with pytest.warns(PydanticDeprecatedSince20, match='`timedelta_isoformat` is deprecated.'):
+ timedelta_isoformat(timedelta(seconds=1))
+
+ with pytest.warns(
+ PydanticDeprecatedSince20,
+ match='The `validate_arguments` method is deprecated; use `validate_call` instead.',
+ ):
+
+ def test(a: int, b: int):
+ pass
- validate_arguments()(test)
+ validate_arguments()(test)
def test_deprecated_color():
diff --git a/tests/test_json_schema.py b/tests/test_json_schema.py
index e6c60557a5..85d833c15c 100644
--- a/tests/test_json_schema.py
+++ b/tests/test_json_schema.py
@@ -5,6 +5,7 @@
import re
import sys
import typing
+import warnings
from datetime import date, datetime, time, timedelta
from decimal import Decimal
from enum import Enum, IntEnum
@@ -1385,8 +1386,12 @@ class Model(BaseModel):
class MyGenerator(GenerateJsonSchema):
ignored_warning_kinds = ()
- with pytest.warns(PydanticJsonSchemaWarning, match=warning_match):
- model_schema = Model.model_json_schema(schema_generator=MyGenerator)
+ with warnings.catch_warnings():
+ # we need to explicitly ignore the other warning in pytest-8
+ # TODO: rewrite it to use two nested pytest.warns() when pytest-7 is no longer supported
+ warnings.simplefilter('ignore')
+ with pytest.warns(PydanticJsonSchemaWarning, match=warning_match):
+ model_schema = Model.model_json_schema(schema_generator=MyGenerator)
assert model_schema == {
'properties': {'callback': {'title': 'Callback', 'type': 'integer'}},
'title': 'Model',
diff --git a/tests/test_validators.py b/tests/test_validators.py
index 52a8bda88f..b286c49b1b 100644
--- a/tests/test_validators.py
+++ b/tests/test_validators.py
@@ -2554,6 +2554,7 @@ class Model(BaseModel):
assert Model(x=1, y=2).model_dump() == {'x': 2, 'y': 3}
+@pytest.mark.filterwarnings('ignore:Pydantic V1 style `@root_validator` validators are deprecated.*:pydantic.warnings.PydanticDeprecatedSince20')
def test_root_validator_allow_reuse_same_field():
with pytest.warns(UserWarning, match='`root_val` overrides an existing Pydantic `@root_validator` decorator'):