From 25afdad65439a05ffdebbdd34645d145798f93ef Mon Sep 17 00:00:00 2001 From: David Montague Date: Thu, 9 Feb 2023 09:47:12 -0700 Subject: [PATCH 1/2] Add CoreSchemaType Literal --- pydantic_core/__init__.py | 3 ++- pydantic_core/core_schema.py | 42 +++++++++++++++++++++++++++++ tests/serializers/test_functions.py | 8 +++--- tests/test_misc.py | 18 ++++++++++++- tests/test_typing.py | 6 ++--- 5 files changed, 68 insertions(+), 9 deletions(-) diff --git a/pydantic_core/__init__.py b/pydantic_core/__init__.py index 198a3d2ff..44a7d0027 100644 --- a/pydantic_core/__init__.py +++ b/pydantic_core/__init__.py @@ -13,12 +13,13 @@ __version__, to_json, ) -from .core_schema import CoreConfig, CoreSchema +from .core_schema import CoreConfig, CoreSchema, CoreSchemaType __all__ = ( '__version__', 'CoreConfig', 'CoreSchema', + 'CoreSchemaType', 'SchemaValidator', 'SchemaSerializer', 'Url', diff --git a/pydantic_core/core_schema.py b/pydantic_core/core_schema.py index ea2b45400..db7d3484e 100644 --- a/pydantic_core/core_schema.py +++ b/pydantic_core/core_schema.py @@ -2587,6 +2587,48 @@ def multi_host_url_schema( MultiHostUrlSchema, ] +# to update this, call `pytest -k test_core_schema_type_literal` and copy the output +CoreSchemaType = Literal[ + 'any', + 'none', + 'bool', + 'int', + 'float', + 'str', + 'bytes', + 'date', + 'time', + 'datetime', + 'timedelta', + 'literal', + 'is-instance', + 'is-subclass', + 'callable', + 'list', + 'tuple', + 'set', + 'frozenset', + 'generator', + 'dict', + 'function', + 'default', + 'nullable', + 'union', + 'tagged-union', + 'chain', + 'lax-or-strict', + 'typed-dict', + 'model', + 'arguments', + 'call', + 'recursive-ref', + 'custom-error', + 'json', + 'url', + 'multi-host-url', +] + + # used in _pydantic_core.pyi::PydanticKnownError # to update this, call `pytest -k test_all_errors` and copy the output ErrorType = Literal[ diff --git a/tests/serializers/test_functions.py b/tests/serializers/test_functions.py index 8f21c848f..051fb25fe 100644 --- a/tests/serializers/test_functions.py +++ b/tests/serializers/test_functions.py @@ -164,19 +164,19 @@ def append_args(value, info): ) assert s.to_python(123) == ( "123 info=SerializationInfo(include=None, exclude=None, mode='python', by_alias=True, exclude_unset=False, " - "exclude_defaults=False, exclude_none=False, round_trip=False)" + 'exclude_defaults=False, exclude_none=False, round_trip=False)' ) assert s.to_python(123, mode='other') == ( "123 info=SerializationInfo(include=None, exclude=None, mode='other', by_alias=True, exclude_unset=False, " - "exclude_defaults=False, exclude_none=False, round_trip=False)" + 'exclude_defaults=False, exclude_none=False, round_trip=False)' ) assert s.to_python(123, include={'x'}) == ( "123 info=SerializationInfo(include={'x'}, exclude=None, mode='python', by_alias=True, exclude_unset=False, " - "exclude_defaults=False, exclude_none=False, round_trip=False)" + 'exclude_defaults=False, exclude_none=False, round_trip=False)' ) assert s.to_python(123, mode='json', exclude={1: {2}}) == ( "123 info=SerializationInfo(include=None, exclude={1: {2}}, mode='json', by_alias=True, exclude_unset=False, " - "exclude_defaults=False, exclude_none=False, round_trip=False)" + 'exclude_defaults=False, exclude_none=False, round_trip=False)' ) assert s.to_json(123) == ( b'"123 info=SerializationInfo(include=None, exclude=None, mode=\'json\', by_alias=True, exclude_unset=False, ' diff --git a/tests/test_misc.py b/tests/test_misc.py index 09242ba82..f1776eff5 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -1,10 +1,11 @@ import re import sys from pathlib import Path +from typing import get_args import pytest -from pydantic_core import core_schema +from pydantic_core import CoreSchema, CoreSchemaType, core_schema from pydantic_core._pydantic_core import ( SchemaError, SchemaValidator, @@ -178,3 +179,18 @@ def test_all_errors(): literal = ''.join(f'\n {e!r},' for e in error_types) print(f'python code (end of pydantic_core/core_schema.py):\n\nErrorType = Literal[{literal}\n]') pytest.fail('core_schema.ErrorType needs to be updated') + + +def test_core_schema_type_literal(): + def get_type_value(schema): + type_ = schema.__annotations__['type'] + m = re.search(r"Literal\['(.+?)']", type_.__forward_arg__) + assert m, f'Unknown schema type: {type_}' + return m.group(1) + + schema_types = tuple(get_type_value(x) for x in CoreSchema.__args__) + schema_types = tuple(dict.fromkeys(schema_types)) # remove duplicates while preserving order + if get_args(CoreSchemaType) != schema_types: + literal = ''.join(f'\n {e!r},' for e in schema_types) + print(f'python code (near end of pydantic_core/core_schema.py):\n\nCoreSchemaType = Literal[{literal}\n]') + pytest.fail('core_schema.CoreSchemaType needs to be updated') diff --git a/tests/test_typing.py b/tests/test_typing.py index c10f00952..5da5fbd94 100644 --- a/tests/test_typing.py +++ b/tests/test_typing.py @@ -189,7 +189,7 @@ def f(__input: Any, __info: core_schema.SerializationInfo) -> str: ) assert s.to_python(123) == ( "SerializationInfo(include=None, exclude=None, mode='python', by_alias=True, exclude_unset=False, " - "exclude_defaults=False, exclude_none=False, round_trip=False)" + 'exclude_defaults=False, exclude_none=False, round_trip=False)' ) @@ -204,7 +204,7 @@ def f(__input: Any, __serialize: core_schema.SerializeWrapHandler, __info: core_ ) # insert_assert(s.to_python(123, mode='json')) assert s.to_python(123, mode='json') == ( - "SerializationCallable(serializer=str) " + 'SerializationCallable(serializer=str) ' "SerializationInfo(include=None, exclude=None, mode='json', by_alias=True, exclude_unset=False, " - "exclude_defaults=False, exclude_none=False, round_trip=False)" + 'exclude_defaults=False, exclude_none=False, round_trip=False)' ) From 25728226751ca81463c595a1f9933bf53732daf7 Mon Sep 17 00:00:00 2001 From: David Montague Date: Thu, 9 Feb 2023 10:00:10 -0700 Subject: [PATCH 2/2] Fix typing import for python 3.7 compatibility --- tests/test_misc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_misc.py b/tests/test_misc.py index f1776eff5..a8ca7c4eb 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -1,9 +1,9 @@ import re import sys from pathlib import Path -from typing import get_args import pytest +from typing_extensions import get_args from pydantic_core import CoreSchema, CoreSchemaType, core_schema from pydantic_core._pydantic_core import (