From 2e30a26744c71ec6be01a69d1cfdb08b2ef992fa Mon Sep 17 00:00:00 2001 From: Hasan Ramezani Date: Thu, 11 Aug 2022 23:53:32 +0200 Subject: [PATCH] Add support for `re.Pattern` --- changes/4366-hramezani.md | 1 + pydantic/fields.py | 3 ++- pydantic/schema.py | 2 +- pydantic/validators.py | 2 +- tests/test_types.py | 10 ++++++---- 5 files changed, 11 insertions(+), 7 deletions(-) create mode 100644 changes/4366-hramezani.md diff --git a/changes/4366-hramezani.md b/changes/4366-hramezani.md new file mode 100644 index 0000000000..a70bedab38 --- /dev/null +++ b/changes/4366-hramezani.md @@ -0,0 +1 @@ +Add support for `re.Pattern` diff --git a/pydantic/fields.py b/pydantic/fields.py index 917798d726..e8c15aa609 100644 --- a/pydantic/fields.py +++ b/pydantic/fields.py @@ -1,4 +1,5 @@ import copy +import re from collections import Counter as CollectionCounter, defaultdict, deque from collections.abc import Callable, Hashable as CollectionsHashable, Iterable as CollectionsIterable from typing import ( @@ -595,7 +596,7 @@ def _type_analysis(self) -> None: # noqa: C901 (ignore complexity) self.required = False self.allow_none = True return - elif self.type_ is Pattern: + elif self.type_ is Pattern or self.type_ is re.Pattern: # python 3.7 only, Pattern is a typing object but without sub fields return elif is_literal_type(self.type_): diff --git a/pydantic/schema.py b/pydantic/schema.py index 4df0b04a11..b2abae33d7 100644 --- a/pydantic/schema.py +++ b/pydantic/schema.py @@ -803,7 +803,7 @@ def add_field_type_to_schema(field_type: Any, schema_: Dict[str, Any]) -> None: and then modifies the given `schema` with the information from that type. """ for type_, t_schema in field_class_to_schema: - # Fallback for `typing.Pattern` as it is not a valid class + # Fallback for `typing.Pattern` and `re.Pattern` as they are not a valid class if lenient_issubclass(field_type, type_) or field_type is type_ is Pattern: schema_.update(t_schema) break diff --git a/pydantic/validators.py b/pydantic/validators.py index 052edd3e43..59933a0d8c 100644 --- a/pydantic/validators.py +++ b/pydantic/validators.py @@ -684,7 +684,7 @@ def find_validators( # noqa: C901 (ignore complexity) if is_none_type(type_): yield none_validator return - if type_ is Pattern: + if type_ is Pattern or type_ is re.Pattern: yield pattern_validator return if type_ is Hashable or type_ is CollectionsHashable: diff --git a/tests/test_types.py b/tests/test_types.py index 425bf9d02c..b9ec8128ff 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -2540,9 +2540,10 @@ class JsonRequired(BaseModel): assert JsonRequired().dict() == {'json_obj': None} -def test_pattern(): +@pytest.mark.parametrize('pattern_type', [re.Pattern, Pattern]) +def test_pattern(pattern_type): class Foobar(BaseModel): - pattern: Pattern + pattern: pattern_type f = Foobar(pattern=r'^whatev.r\d$') assert f.pattern.__class__.__name__ == 'Pattern' @@ -2563,9 +2564,10 @@ class Foobar(BaseModel): } -def test_pattern_error(): +@pytest.mark.parametrize('pattern_type', [re.Pattern, Pattern]) +def test_pattern_error(pattern_type): class Foobar(BaseModel): - pattern: Pattern + pattern: pattern_type with pytest.raises(ValidationError) as exc_info: Foobar(pattern='[xx')