[arch-commits] Commit in python-pydantic/trunk (PKGBUILD python310.patch)
David Runge
dvzrv at gemini.archlinux.org
Tue Jul 12 10:51:02 UTC 2022
Date: Tuesday, July 12, 2022 @ 10:51:02
Author: dvzrv
Revision: 1250382
upgpkg: python-pydantic 1.9.1-1: Upgrade to 1.9.1.
Remove unnecessary quotes and curly braces.
Remove unneeded patch.
Add additional optdepends for python-dotenv.
Switch to PEP517.
Modified:
python-pydantic/trunk/PKGBUILD
Deleted:
python-pydantic/trunk/python310.patch
-----------------+
PKGBUILD | 56 +-
python310.patch | 1276 ------------------------------------------------------
2 files changed, 25 insertions(+), 1307 deletions(-)
Modified: PKGBUILD
===================================================================
--- PKGBUILD 2022-07-12 10:12:34 UTC (rev 1250381)
+++ PKGBUILD 2022-07-12 10:51:02 UTC (rev 1250382)
@@ -1,43 +1,37 @@
+# Maintainer: David Runge <dvzrv at archlinux.org>
# Maintainer: Filipe Laíns (FFY00) <lains at archlinux.org>
-_pkgname=pydantic
-pkgname=python-$_pkgname
-pkgver=1.8.2
-pkgrel=3
+_name=pydantic
+pkgname=python-$_name
+pkgver=1.9.1
+pkgrel=1
pkgdesc='Data parsing and validation using Python type hints'
-arch=('any')
-url='https://github.com/samuelcolvin/pydantic'
-license=('MIT')
-depends=('python' 'python-typing-extensions')
-optdepends=('python-email-validator: email')
-makedepends=('python-setuptools')
-checkdepends=('python-pytest-runner' 'python-pytest-mock')
-source=("$pkgname-$pkgver.tar.gz::$url/archive/v$pkgver.tar.gz"
- python310.patch)
-sha512sums=('0a28c64b97678b932092e546da877a4a6d104fc7d3b7cb043b3494f0b7c6900cdc1ab8a83bdbd1879956a81da1b28ca27578b1a003bdca3e08f0f107e5690e06'
- '488ffd8a76a0b99a830a1765518da4e67cec42c45db9ca45600fb78f3f5b17542522cdc4aa0f1b74618b7cdebd7410f162cb717bb146478746dfd31a0e2f6991')
+arch=(any)
+url="https://github.com/samuelcolvin/pydantic"
+license=(MIT)
+depends=(python python-typing-extensions)
+optdepends=(
+ 'python-dotenv: for .env file support'
+ 'python-email-validator: for email validation'
+)
+makedepends=(python-build python-installer python-setuptools python-wheel)
+checkdepends=(python-pytest python-pytest-mock)
+source=($_name-$pkgver.tar.gz::$url/archive/v$pkgver.tar.gz)
+sha512sums=('6343a4cbaf49c38bcf038da21ace9f37cbcd3f05364307c0b9b5006f3fe4c9db4513f557b5388783dbb08892dbdc2a54689988edf7d1bdc6e794b0e755213ecb')
+b2sums=('94022c7ca8cfa29f51f814171d85d1b95f5a605fd685d47309f3f233bbb10d434a1f691f95c40dc99619284c81556d322cad7f63d486f7c3dcbe3d875827617c')
-prepare() {
- cd $_pkgname-$pkgver
- patch -Np1 -i ../python310.patch
-}
-
build() {
- cd $_pkgname-$pkgver
-
- python setup.py build
+ cd $_name-$pkgver
+ python -m build --wheel --no-isolation
}
check() {
- cd $_pkgname-$pkgver
-
- python setup.py pytest
+ cd $_name-$pkgver
+ pytest -vv
}
package() {
- cd $_pkgname-$pkgver
-
- python setup.py install --root="$pkgdir" --optimize=1 --skip-build
-
- install -Dm 644 LICENSE "$pkgdir"/usr/share/licenses/$pkgname/LICENSE
+ cd $_name-$pkgver
+ python -m installer --destdir="$pkgdir" dist/*.whl
+ install -vDm 644 LICENSE -t "$pkgdir/usr/share/licenses/$pkgname/"
}
Deleted: python310.patch
===================================================================
--- python310.patch 2022-07-12 10:12:34 UTC (rev 1250381)
+++ python310.patch 2022-07-12 10:51:02 UTC (rev 1250382)
@@ -1,1276 +0,0 @@
-From 4cace55bfbbc1439d08209641e49e886b7808f20 Mon Sep 17 00:00:00 2001
-From: Eric Jolibois <em.jolibois at gmail.com>
-Date: Mon, 19 Jul 2021 15:23:07 +0200
-Subject: [PATCH 1/3] Add python 3.10 support (#2885)
-
-* refactor: extra `BaseConfig` and `Extra` in dedicated `config` module
-
-* refactor: clean useless `#noqa: F401`
-
-* refactor: clean useless `#noqa: F811`
-
-* refactor: replace enum check
-
-Error with 3.10
-> DeprecationWarning: accessing one member from another is not supported
-
-* refactor: avoid using `distutils` directly
-
-error with python 3.10
-> DeprecationWarning: The distutils package is deprecated and slated
-> for removal in Python 3.12.
-> Use setuptools or check PEP 632 for potential alternatives
-
-* fix: `__annotations__` always exists
-
-* fix: origin of `typing.Hashable` is not `None`
-
-* ci: add run with 3.10.0b2
-
-* docs: add 3.10
-
-* feat: support `|` union operator properly
-
-`|` operator has origin `types.Union` (and not `typing.Union`)
-
-* fix: enum repr is different with 3.10+
-
-* fix: error message changed a bit
-
-change from basic `__init__` to `test_hashable_required.<locals>.MyDataclass.__init__()` (with `__qualname__`)
-
-* fix: always exists and is not inherited anymore
-
-* fix: avoid calling `asyncio.get_event_loop` directly
-
-With python 3.10, calling it results in
-> DeprecationWarning: There is no current event loop
-
-* fix(ci): do not run 3.10 on linux for now
-
-For now it can not be compiled.
-Let's just skip the check on linux for now instead of tuning the CI pipeline
-
-* fix(ci): ignore DeprecationWarning raised by `mypy` on windows
-
-* docs: add change file
-
-(cherry picked from commit 4a54f393ad20ee91b51cd7a49ec46771ba4f8a18)
----
- .github/workflows/ci.yml | 2 +-
- changes/2885-PrettyWood.md | 1 +
- docs/contributing.md | 2 +-
- docs/install.md | 2 +-
- pydantic/__init__.py | 6 +-
- pydantic/annotated_types.py | 7 +-
- pydantic/class_validators.py | 2 +-
- pydantic/config.py | 124 +++++++++++++++++++++++++++++++++++
- pydantic/dataclasses.py | 3 +-
- pydantic/decorator.py | 3 +-
- pydantic/env_settings.py | 3 +-
- pydantic/error_wrappers.py | 4 +-
- pydantic/fields.py | 18 ++---
- pydantic/main.py | 121 ++--------------------------------
- pydantic/networks.py | 2 +-
- pydantic/schema.py | 11 ++--
- pydantic/types.py | 4 +-
- pydantic/typing.py | 14 ++++
- pydantic/utils.py | 15 +++--
- pydantic/validators.py | 7 +-
- setup.cfg | 3 +
- setup.py | 3 +-
- tests/test_dataclasses.py | 2 +-
- tests/test_decorator.py | 2 +-
- tests/test_edge_cases.py | 5 +-
- tests/test_main.py | 25 ++++++-
- tests/test_types.py | 10 ++-
- tests/test_utils.py | 6 +-
- 28 files changed, 242 insertions(+), 165 deletions(-)
- create mode 100644 changes/2885-PrettyWood.md
- create mode 100644 pydantic/config.py
-
-diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
-index 2c865ed..7f847eb 100644
---- a/.github/workflows/ci.yml
-+++ b/.github/workflows/ci.yml
-@@ -119,7 +119,7 @@ jobs:
- fail-fast: false
- matrix:
- os: [macos, windows]
-- python-version: ['3.6', '3.7', '3.8', '3.9']
-+ python-version: ['3.6', '3.7', '3.8', '3.9', '3.10.0-beta.2']
- env:
- PYTHON: ${{ matrix.python-version }}
- OS: ${{ matrix.os }}
-diff --git a/changes/2885-PrettyWood.md b/changes/2885-PrettyWood.md
-new file mode 100644
-index 0000000..1cc2afe
---- /dev/null
-+++ b/changes/2885-PrettyWood.md
-@@ -0,0 +1 @@
-+add python 3.10 support
-diff --git a/docs/contributing.md b/docs/contributing.md
-index dfbacbc..b0e0dc5 100644
---- a/docs/contributing.md
-+++ b/docs/contributing.md
-@@ -33,7 +33,7 @@ To make contributing as easy and fast as possible, you'll want to run tests and
- *pydantic* has few dependencies, doesn't require compiling and tests don't need access to databases, etc.
- Because of this, setting up and running the tests should be very simple.
-
--You'll need to have **python 3.6**, **3.7**, **3.8**, or **3.9**, **virtualenv**, **git**, and **make** installed.
-+You'll need to have a version between **python 3.6 and 3.10**, **virtualenv**, **git**, and **make** installed.
-
- ```bash
- # 1. clone your fork and cd into the repo directory
-diff --git a/docs/install.md b/docs/install.md
-index 9cbd9e2..c50d20c 100644
---- a/docs/install.md
-+++ b/docs/install.md
-@@ -4,7 +4,7 @@ Installation is as simple as:
- pip install pydantic
- ```
-
--*pydantic* has no required dependencies except python 3.6, 3.7, 3.8, or 3.9,
-+*pydantic* has no required dependencies except python 3.6, 3.7, 3.8, 3.9 or 3.10,
- [`typing-extensions`](https://pypi.org/project/typing-extensions/), and the
- [`dataclasses`](https://pypi.org/project/dataclasses/) backport package for python 3.6.
- If you've got python 3.6+ and `pip` installed, you're good to go.
-diff --git a/pydantic/__init__.py b/pydantic/__init__.py
-index 2e7aab4..79917a4 100644
---- a/pydantic/__init__.py
-+++ b/pydantic/__init__.py
-@@ -2,6 +2,7 @@
- from . import dataclasses
- from .annotated_types import create_model_from_namedtuple, create_model_from_typeddict
- from .class_validators import root_validator, validator
-+from .config import BaseConfig, Extra
- from .decorator import validate_arguments
- from .env_settings import BaseSettings
- from .error_wrappers import ValidationError
-@@ -25,6 +26,9 @@ __all__ = [
- # class_validators
- 'root_validator',
- 'validator',
-+ # config
-+ 'BaseConfig',
-+ 'Extra',
- # decorator
- 'validate_arguments',
- # env_settings
-@@ -35,9 +39,7 @@ __all__ = [
- 'Field',
- 'Required',
- # main
-- 'BaseConfig',
- 'BaseModel',
-- 'Extra',
- 'compiled',
- 'create_model',
- 'validate_model',
-diff --git a/pydantic/annotated_types.py b/pydantic/annotated_types.py
-index bffcdc6..0a2a24f 100644
---- a/pydantic/annotated_types.py
-+++ b/pydantic/annotated_types.py
-@@ -42,9 +42,10 @@ def create_model_from_namedtuple(namedtuple_cls: Type['NamedTuple'], **kwargs: A
- but also with `collections.namedtuple`, in this case we consider all fields
- to have type `Any`.
- """
-- namedtuple_annotations: Dict[str, Type[Any]] = getattr(
-- namedtuple_cls, '__annotations__', {k: Any for k in namedtuple_cls._fields}
-- )
-+ # With python 3.10+, `__annotations__` always exists but can be empty hence the `getattr... or...` logic
-+ namedtuple_annotations: Dict[str, Type[Any]] = getattr(namedtuple_cls, '__annotations__', None) or {
-+ k: Any for k in namedtuple_cls._fields
-+ }
- field_definitions: Dict[str, Any] = {
- field_name: (field_type, Required) for field_name, field_type in namedtuple_annotations.items()
- }
-diff --git a/pydantic/class_validators.py b/pydantic/class_validators.py
-index 9cd951a..a93d570 100644
---- a/pydantic/class_validators.py
-+++ b/pydantic/class_validators.py
-@@ -33,8 +33,8 @@ class Validator:
- if TYPE_CHECKING:
- from inspect import Signature
-
-+ from .config import BaseConfig
- from .fields import ModelField
-- from .main import BaseConfig
- from .types import ModelOrDc
-
- ValidatorCallable = Callable[[Optional[ModelOrDc], Any, Dict[str, Any], ModelField, Type[BaseConfig]], Any]
-diff --git a/pydantic/config.py b/pydantic/config.py
-new file mode 100644
-index 0000000..acd20da
---- /dev/null
-+++ b/pydantic/config.py
-@@ -0,0 +1,124 @@
-+import json
-+from enum import Enum
-+from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Tuple, Type, Union
-+
-+from .typing import AnyCallable
-+from .utils import GetterDict
-+
-+if TYPE_CHECKING:
-+ from typing import overload
-+
-+ import typing_extensions
-+
-+ from .fields import ModelField
-+ from .main import BaseModel
-+
-+ ConfigType = Type['BaseConfig']
-+
-+ class SchemaExtraCallable(typing_extensions.Protocol):
-+ @overload
-+ def __call__(self, schema: Dict[str, Any]) -> None:
-+ pass
-+
-+ @overload
-+ def __call__(self, schema: Dict[str, Any], model_class: Type[BaseModel]) -> None:
-+ pass
-+
-+
-+else:
-+ SchemaExtraCallable = Callable[..., None]
-+
-+__all__ = 'BaseConfig', 'Extra', 'inherit_config', 'prepare_config'
-+
-+
-+class Extra(str, Enum):
-+ allow = 'allow'
-+ ignore = 'ignore'
-+ forbid = 'forbid'
-+
-+
-+class BaseConfig:
-+ title = None
-+ anystr_lower = False
-+ anystr_strip_whitespace = False
-+ min_anystr_length = None
-+ max_anystr_length = None
-+ validate_all = False
-+ extra = Extra.ignore
-+ allow_mutation = True
-+ frozen = False
-+ allow_population_by_field_name = False
-+ use_enum_values = False
-+ fields: Dict[str, Union[str, Dict[str, str]]] = {}
-+ validate_assignment = False
-+ error_msg_templates: Dict[str, str] = {}
-+ arbitrary_types_allowed = False
-+ orm_mode: bool = False
-+ getter_dict: Type[GetterDict] = GetterDict
-+ alias_generator: Optional[Callable[[str], str]] = None
-+ keep_untouched: Tuple[type, ...] = ()
-+ schema_extra: Union[Dict[str, Any], 'SchemaExtraCallable'] = {}
-+ json_loads: Callable[[str], Any] = json.loads
-+ json_dumps: Callable[..., str] = json.dumps
-+ json_encoders: Dict[Type[Any], AnyCallable] = {}
-+ underscore_attrs_are_private: bool = False
-+
-+ # Whether or not inherited models as fields should be reconstructed as base model
-+ copy_on_model_validation: bool = True
-+
-+ @classmethod
-+ def get_field_info(cls, name: str) -> Dict[str, Any]:
-+ """
-+ Get properties of FieldInfo from the `fields` property of the config class.
-+ """
-+
-+ fields_value = cls.fields.get(name)
-+
-+ if isinstance(fields_value, str):
-+ field_info: Dict[str, Any] = {'alias': fields_value}
-+ elif isinstance(fields_value, dict):
-+ field_info = fields_value
-+ else:
-+ field_info = {}
-+
-+ if 'alias' in field_info:
-+ field_info.setdefault('alias_priority', 2)
-+
-+ if field_info.get('alias_priority', 0) <= 1 and cls.alias_generator:
-+ alias = cls.alias_generator(name)
-+ if not isinstance(alias, str):
-+ raise TypeError(f'Config.alias_generator must return str, not {alias.__class__}')
-+ field_info.update(alias=alias, alias_priority=1)
-+ return field_info
-+
-+ @classmethod
-+ def prepare_field(cls, field: 'ModelField') -> None:
-+ """
-+ Optional hook to check or modify fields during model creation.
-+ """
-+ pass
-+
-+
-+def inherit_config(self_config: 'ConfigType', parent_config: 'ConfigType', **namespace: Any) -> 'ConfigType':
-+ if not self_config:
-+ base_classes: Tuple['ConfigType', ...] = (parent_config,)
-+ elif self_config == parent_config:
-+ base_classes = (self_config,)
-+ else:
-+ base_classes = self_config, parent_config
-+
-+ namespace['json_encoders'] = {
-+ **getattr(parent_config, 'json_encoders', {}),
-+ **getattr(self_config, 'json_encoders', {}),
-+ **namespace.get('json_encoders', {}),
-+ }
-+
-+ return type('Config', base_classes, namespace)
-+
-+
-+def prepare_config(config: Type[BaseConfig], cls_name: str) -> None:
-+ if not isinstance(config.extra, Extra):
-+ try:
-+ config.extra = Extra(config.extra)
-+ except ValueError:
-+ raise ValueError(f'"{cls_name}": {config.extra} is not a valid value for "extra"')
-diff --git a/pydantic/dataclasses.py b/pydantic/dataclasses.py
-index 42ae685..a61dbc8 100644
---- a/pydantic/dataclasses.py
-+++ b/pydantic/dataclasses.py
-@@ -9,7 +9,8 @@ from .typing import resolve_annotations
- from .utils import ClassAttribute
-
- if TYPE_CHECKING:
-- from .main import BaseConfig, BaseModel # noqa: F401
-+ from .config import BaseConfig
-+ from .main import BaseModel
- from .typing import CallableGenerator, NoArgAnyCallable
-
- DataclassT = TypeVar('DataclassT', bound='Dataclass')
-diff --git a/pydantic/decorator.py b/pydantic/decorator.py
-index 266195c..869afee 100644
---- a/pydantic/decorator.py
-+++ b/pydantic/decorator.py
-@@ -2,8 +2,9 @@ from functools import wraps
- from typing import TYPE_CHECKING, Any, Callable, Dict, List, Mapping, Optional, Tuple, Type, TypeVar, Union, overload
-
- from . import validator
-+from .config import Extra
- from .errors import ConfigError
--from .main import BaseModel, Extra, create_model
-+from .main import BaseModel, create_model
- from .typing import get_all_type_hints
- from .utils import to_camel
-
-diff --git a/pydantic/env_settings.py b/pydantic/env_settings.py
-index 71b5a97..2c8c11f 100644
---- a/pydantic/env_settings.py
-+++ b/pydantic/env_settings.py
-@@ -3,8 +3,9 @@ import warnings
- from pathlib import Path
- from typing import AbstractSet, Any, Callable, Dict, List, Mapping, Optional, Tuple, Union
-
-+from .config import BaseConfig, Extra
- from .fields import ModelField
--from .main import BaseConfig, BaseModel, Extra
-+from .main import BaseModel
- from .typing import display_as_type
- from .utils import deep_update, path_type, sequence_like
-
-diff --git a/pydantic/error_wrappers.py b/pydantic/error_wrappers.py
-index 92d957f..59301eb 100644
---- a/pydantic/error_wrappers.py
-+++ b/pydantic/error_wrappers.py
-@@ -5,8 +5,8 @@ from .json import pydantic_encoder
- from .utils import Representation
-
- if TYPE_CHECKING:
-- from .main import BaseConfig # noqa: F401
-- from .types import ModelOrDc # noqa: F401
-+ from .config import BaseConfig
-+ from .types import ModelOrDc
- from .typing import ReprArgs
-
- Loc = Tuple[Union[int, str], ...]
-diff --git a/pydantic/fields.py b/pydantic/fields.py
-index 0c95d8a..3fdb88f 100644
---- a/pydantic/fields.py
-+++ b/pydantic/fields.py
-@@ -1,5 +1,5 @@
- from collections import defaultdict, deque
--from collections.abc import Iterable as CollectionsIterable
-+from collections.abc import Hashable as CollectionsHashable, Iterable as CollectionsIterable
- from typing import (
- TYPE_CHECKING,
- Any,
-@@ -41,6 +41,7 @@ from .typing import (
- is_literal_type,
- is_new_type,
- is_typeddict,
-+ is_union,
- new_type_supertype,
- )
- from .utils import PyObjectStr, Representation, lenient_issubclass, sequence_like, smart_deepcopy
-@@ -68,11 +69,11 @@ class UndefinedType:
- Undefined = UndefinedType()
-
- if TYPE_CHECKING:
-- from .class_validators import ValidatorsList # noqa: F401
-+ from .class_validators import ValidatorsList
-+ from .config import BaseConfig
- from .error_wrappers import ErrorList
-- from .main import BaseConfig, BaseModel # noqa: F401
-- from .types import ModelOrDc # noqa: F401
-- from .typing import ReprArgs # noqa: F401
-+ from .types import ModelOrDc
-+ from .typing import ReprArgs
-
- ValidateReturn = Tuple[Optional[Any], Optional[ErrorList]]
- LocStr = Union[Tuple[Union[int, str], ...], str]
-@@ -514,7 +515,8 @@ class ModelField(Representation):
- return
-
- origin = get_origin(self.type_)
-- if origin is None:
-+ # add extra check for `collections.abc.Hashable` for python 3.10+ where origin is not `None`
-+ if origin is None or origin is CollectionsHashable:
- # field is not "typing" object eg. Union, Dict, List etc.
- # allow None for virtual superclasses of NoneType, e.g. Hashable
- if isinstance(self.type_, type) and isinstance(None, self.type_):
-@@ -526,7 +528,7 @@ class ModelField(Representation):
- return
- if origin is Callable:
- return
-- if origin is Union:
-+ if is_union(origin):
- types_ = []
- for type_ in get_args(self.type_):
- if type_ is NoneType:
-@@ -919,7 +921,7 @@ class ModelField(Representation):
- """
- Whether the field is "complex" eg. env variables should be parsed as JSON.
- """
-- from .main import BaseModel # noqa: F811
-+ from .main import BaseModel
-
- return (
- self.shape != SHAPE_SINGLETON
-diff --git a/pydantic/main.py b/pydantic/main.py
-index a77e101..0d9dac2 100644
---- a/pydantic/main.py
-+++ b/pydantic/main.py
-@@ -1,4 +1,3 @@
--import json
- import sys
- import warnings
- from abc import ABCMeta
-@@ -22,10 +21,10 @@ from typing import (
- Union,
- cast,
- no_type_check,
-- overload,
- )
-
- from .class_validators import ValidatorGroup, extract_root_validators, extract_validators, inherit_validators
-+from .config import BaseConfig, Extra, inherit_config, prepare_config
- from .error_wrappers import ErrorWrapper, ValidationError
- from .errors import ConfigError, DictError, ExtraError, MissingError
- from .fields import MAPPING_LIKE_SHAPES, ModelField, ModelPrivateAttr, PrivateAttr, Undefined
-@@ -39,6 +38,7 @@ from .typing import (
- get_origin,
- is_classvar,
- is_namedtuple,
-+ is_union,
- resolve_annotations,
- update_field_forward_refs,
- )
-@@ -61,11 +61,9 @@ from .utils import (
- if TYPE_CHECKING:
- from inspect import Signature
-
-- import typing_extensions
--
- from .class_validators import ValidatorListDict
- from .types import ModelOrDc
-- from .typing import ( # noqa: F401
-+ from .typing import (
- AbstractSetIntStr,
- CallableGenerator,
- DictAny,
-@@ -76,21 +74,8 @@ if TYPE_CHECKING:
- TupleGenerator,
- )
-
-- ConfigType = Type['BaseConfig']
- Model = TypeVar('Model', bound='BaseModel')
-
-- class SchemaExtraCallable(typing_extensions.Protocol):
-- @overload
-- def __call__(self, schema: Dict[str, Any]) -> None:
-- pass
--
-- @overload # noqa: F811
-- def __call__(self, schema: Dict[str, Any], model_class: Type['Model']) -> None: # noqa: F811
-- pass
--
--
--else:
-- SchemaExtraCallable = Callable[..., None]
-
- try:
- import cython # type: ignore
-@@ -102,103 +87,7 @@ else: # pragma: no cover
- except AttributeError:
- compiled = False
-
--__all__ = 'BaseConfig', 'BaseModel', 'Extra', 'compiled', 'create_model', 'validate_model'
--
--
--class Extra(str, Enum):
-- allow = 'allow'
-- ignore = 'ignore'
-- forbid = 'forbid'
--
--
--class BaseConfig:
-- title = None
-- anystr_lower = False
-- anystr_strip_whitespace = False
-- min_anystr_length = None
-- max_anystr_length = None
-- validate_all = False
-- extra = Extra.ignore
-- allow_mutation = True
-- frozen = False
-- allow_population_by_field_name = False
-- use_enum_values = False
-- fields: Dict[str, Union[str, Dict[str, str]]] = {}
-- validate_assignment = False
-- error_msg_templates: Dict[str, str] = {}
-- arbitrary_types_allowed = False
-- orm_mode: bool = False
-- getter_dict: Type[GetterDict] = GetterDict
-- alias_generator: Optional[Callable[[str], str]] = None
-- keep_untouched: Tuple[type, ...] = ()
-- schema_extra: Union[Dict[str, Any], 'SchemaExtraCallable'] = {}
-- json_loads: Callable[[str], Any] = json.loads
-- json_dumps: Callable[..., str] = json.dumps
-- json_encoders: Dict[Type[Any], AnyCallable] = {}
-- underscore_attrs_are_private: bool = False
--
-- # Whether or not inherited models as fields should be reconstructed as base model
-- copy_on_model_validation: bool = True
--
-- @classmethod
-- def get_field_info(cls, name: str) -> Dict[str, Any]:
-- """
-- Get properties of FieldInfo from the `fields` property of the config class.
-- """
--
-- fields_value = cls.fields.get(name)
--
-- if isinstance(fields_value, str):
-- field_info: Dict[str, Any] = {'alias': fields_value}
-- elif isinstance(fields_value, dict):
-- field_info = fields_value
-- else:
-- field_info = {}
--
-- if 'alias' in field_info:
-- field_info.setdefault('alias_priority', 2)
--
-- if field_info.get('alias_priority', 0) <= 1 and cls.alias_generator:
-- alias = cls.alias_generator(name)
-- if not isinstance(alias, str):
-- raise TypeError(f'Config.alias_generator must return str, not {alias.__class__}')
-- field_info.update(alias=alias, alias_priority=1)
-- return field_info
--
-- @classmethod
-- def prepare_field(cls, field: 'ModelField') -> None:
-- """
-- Optional hook to check or modify fields during model creation.
-- """
-- pass
--
--
--def inherit_config(self_config: 'ConfigType', parent_config: 'ConfigType', **namespace: Any) -> 'ConfigType':
-- if not self_config:
-- base_classes: Tuple['ConfigType', ...] = (parent_config,)
-- elif self_config == parent_config:
-- base_classes = (self_config,)
-- else:
-- base_classes = self_config, parent_config
--
-- namespace['json_encoders'] = {
-- **getattr(parent_config, 'json_encoders', {}),
-- **getattr(self_config, 'json_encoders', {}),
-- **namespace.get('json_encoders', {}),
-- }
--
-- return type('Config', base_classes, namespace)
--
--
--EXTRA_LINK = 'https://pydantic-docs.helpmanual.io/usage/model_config/'
--
--
--def prepare_config(config: Type[BaseConfig], cls_name: str) -> None:
-- if not isinstance(config.extra, Extra):
-- try:
-- config.extra = Extra(config.extra)
-- except ValueError:
-- raise ValueError(f'"{cls_name}": {config.extra} is not a valid value for "extra"')
-+__all__ = 'BaseModel', 'compiled', 'create_model', 'validate_model'
-
-
- def validate_custom_root_type(fields: Dict[str, ModelField]) -> None:
-@@ -287,7 +176,7 @@ class ModelMetaclass(ABCMeta):
- elif is_valid_field(ann_name):
- validate_field_name(bases, ann_name)
- value = namespace.get(ann_name, Undefined)
-- allowed_types = get_args(ann_type) if get_origin(ann_type) is Union else (ann_type,)
-+ allowed_types = get_args(ann_type) if is_union(get_origin(ann_type)) else (ann_type,)
- if (
- is_untouched(value)
- and ann_type != PyObject
-diff --git a/pydantic/networks.py b/pydantic/networks.py
-index edace1f..187bb23 100644
---- a/pydantic/networks.py
-+++ b/pydantic/networks.py
-@@ -32,8 +32,8 @@ from .validators import constr_length_validator, str_validator
- if TYPE_CHECKING:
- import email_validator
-
-+ from .config import BaseConfig
- from .fields import ModelField
-- from .main import BaseConfig # noqa: F401
- from .typing import AnyCallable
-
- CallableGenerator = Generator[AnyCallable, None, None]
-diff --git a/pydantic/schema.py b/pydantic/schema.py
-index 32a4367..e4b90d4 100644
---- a/pydantic/schema.py
-+++ b/pydantic/schema.py
-@@ -71,12 +71,13 @@ from .typing import (
- is_callable_type,
- is_literal_type,
- is_namedtuple,
-+ is_union,
- )
- from .utils import ROOT_KEY, get_model, lenient_issubclass, sequence_like
-
- if TYPE_CHECKING:
-- from .dataclasses import Dataclass # noqa: F401
-- from .main import BaseModel # noqa: F401
-+ from .dataclasses import Dataclass
-+ from .main import BaseModel
-
- default_prefix = '#/definitions/'
- default_ref_template = '#/definitions/{model}'
-@@ -364,7 +365,7 @@ def get_flat_models_from_field(field: ModelField, known_models: TypeModelSet) ->
- :return: a set with the model used in the declaration for this field, if any, and all its sub-models
- """
- from .dataclasses import dataclass, is_builtin_dataclass
-- from .main import BaseModel # noqa: F811
-+ from .main import BaseModel
-
- flat_models: TypeModelSet = set()
-
-@@ -765,7 +766,7 @@ def field_singleton_schema( # noqa: C901 (ignore complexity)
-
- Take a single Pydantic ``ModelField``, and return its schema and any additional definitions from sub-models.
- """
-- from .main import BaseModel # noqa: F811
-+ from .main import BaseModel
-
- definitions: Dict[str, Any] = {}
- nested_models: Set[str] = set()
-@@ -959,7 +960,7 @@ def get_annotation_with_constraints(annotation: Any, field_info: FieldInfo) -> T
-
- if origin is Annotated:
- return go(args[0])
-- if origin is Union:
-+ if is_union(origin):
- return Union[tuple(go(a) for a in args)] # type: ignore
-
- if issubclass(origin, List) and (field_info.min_items is not None or field_info.max_items is not None):
-diff --git a/pydantic/types.py b/pydantic/types.py
-index 2e4eb28..94db8f3 100644
---- a/pydantic/types.py
-+++ b/pydantic/types.py
-@@ -105,8 +105,8 @@ OptionalIntFloatDecimal = Union[OptionalIntFloat, Decimal]
- StrIntFloat = Union[str, int, float]
-
- if TYPE_CHECKING:
-- from .dataclasses import Dataclass # noqa: F401
-- from .main import BaseConfig, BaseModel # noqa: F401
-+ from .dataclasses import Dataclass
-+ from .main import BaseModel
- from .typing import CallableGenerator
-
- ModelOrDc = Type[Union['BaseModel', 'Dataclass']]
-diff --git a/pydantic/typing.py b/pydantic/typing.py
-index 1a3bf43..b98b543 100644
---- a/pydantic/typing.py
-+++ b/pydantic/typing.py
-@@ -189,6 +189,19 @@ else:
- return _typing_get_args(tp) or getattr(tp, '__args__', ()) or _generic_get_args(tp)
-
-
-+if sys.version_info < (3, 10):
-+
-+ def is_union(tp: Type[Any]) -> bool:
-+ return tp is Union
-+
-+
-+else:
-+ import types
-+
-+ def is_union(tp: Type[Any]) -> bool:
-+ return tp is Union or tp is types.Union
-+
-+
- if TYPE_CHECKING:
- from .fields import ModelField
-
-@@ -238,6 +251,7 @@ __all__ = (
- 'get_origin',
- 'typing_base',
- 'get_all_type_hints',
-+ 'is_union',
- )
-
-
-diff --git a/pydantic/utils.py b/pydantic/utils.py
-index 8a8351c..c50863f 100644
---- a/pydantic/utils.py
-+++ b/pydantic/utils.py
-@@ -31,10 +31,11 @@ if TYPE_CHECKING:
- from inspect import Signature
- from pathlib import Path
-
-- from .dataclasses import Dataclass # noqa: F401
-- from .fields import ModelField # noqa: F401
-- from .main import BaseConfig, BaseModel # noqa: F401
-- from .typing import AbstractSetIntStr, DictIntStrAny, IntStr, MappingIntStrAny, ReprArgs # noqa: F401
-+ from .config import BaseConfig
-+ from .dataclasses import Dataclass
-+ from .fields import ModelField
-+ from .main import BaseModel
-+ from .typing import AbstractSetIntStr, DictIntStrAny, IntStr, MappingIntStrAny, ReprArgs
-
- __all__ = (
- 'import_string',
-@@ -202,6 +203,8 @@ def generate_model_signature(
- """
- from inspect import Parameter, Signature, signature
-
-+ from .config import Extra
-+
- present_params = signature(init).parameters.values()
- merged_params: Dict[str, Parameter] = {}
- var_kw = None
-@@ -232,7 +235,7 @@ def generate_model_signature(
- param_name, Parameter.KEYWORD_ONLY, annotation=field.outer_type_, **kwargs
- )
-
-- if config.extra is config.extra.allow:
-+ if config.extra is Extra.allow:
- use_var_kw = True
-
- if var_kw and use_var_kw:
-@@ -258,7 +261,7 @@ def generate_model_signature(
-
-
- def get_model(obj: Union[Type['BaseModel'], Type['Dataclass']]) -> Type['BaseModel']:
-- from .main import BaseModel # noqa: F811
-+ from .main import BaseModel
-
- try:
- model_cls = obj.__pydantic_model__ # type: ignore
-diff --git a/pydantic/validators.py b/pydantic/validators.py
-index 57a1a23..6d14c53 100644
---- a/pydantic/validators.py
-+++ b/pydantic/validators.py
-@@ -1,6 +1,6 @@
- import re
- from collections import OrderedDict, deque
--from collections.abc import Hashable
-+from collections.abc import Hashable as CollectionsHashable
- from datetime import date, datetime, time, timedelta
- from decimal import Decimal, DecimalException
- from enum import Enum, IntEnum
-@@ -14,6 +14,7 @@ from typing import (
- Dict,
- FrozenSet,
- Generator,
-+ Hashable,
- List,
- NamedTuple,
- Pattern,
-@@ -45,8 +46,8 @@ from .utils import almost_equal_floats, lenient_issubclass, sequence_like
-
- if TYPE_CHECKING:
- from .annotated_types import TypedDict
-+ from .config import BaseConfig
- from .fields import ModelField
-- from .main import BaseConfig
- from .types import ConstrainedDecimal, ConstrainedFloat, ConstrainedInt
-
- ConstrainedNumber = Union[ConstrainedDecimal, ConstrainedFloat, ConstrainedInt]
-@@ -662,7 +663,7 @@ def find_validators( # noqa: C901 (ignore complexity)
- if type_ is Pattern:
- yield pattern_validator
- return
-- if type_ is Hashable:
-+ if type_ is Hashable or type_ is CollectionsHashable:
- yield hashable_validator
- return
- if is_callable_type(type_):
-diff --git a/setup.cfg b/setup.cfg
-index 93865e1..2e24183 100644
---- a/setup.cfg
-+++ b/setup.cfg
-@@ -5,6 +5,9 @@ filterwarnings =
- error
- ignore::DeprecationWarning:distutils
- ignore::DeprecationWarning:Cython
-+ # for python 3.10+: mypy still relies on distutils on windows. We hence ignore those warnings
-+ ignore:The distutils package is deprecated and slated for removal in Python 3.12:DeprecationWarning
-+ ignore:The distutils.sysconfig module is deprecated, use sysconfig instead:DeprecationWarning
-
- [flake8]
- max-line-length = 120
-diff --git a/setup.py b/setup.py
-index 52baae2..88db225 100644
---- a/setup.py
-+++ b/setup.py
-@@ -7,7 +7,7 @@ from pathlib import Path
- from setuptools import setup
-
- if os.name == 'nt':
-- from distutils.command import build_ext
-+ from setuptools.command import build_ext
-
- def get_export_symbols(self, ext):
- """
-@@ -106,6 +106,7 @@ setup(
- 'Programming Language :: Python :: 3.7',
- 'Programming Language :: Python :: 3.8',
- 'Programming Language :: Python :: 3.9',
-+ 'Programming Language :: Python :: 3.10',
- 'Intended Audience :: Developers',
- 'Intended Audience :: Information Technology',
- 'Intended Audience :: System Administrators',
-diff --git a/tests/test_dataclasses.py b/tests/test_dataclasses.py
-index fd122f8..c5e6a1e 100644
---- a/tests/test_dataclasses.py
-+++ b/tests/test_dataclasses.py
-@@ -637,7 +637,7 @@ def test_hashable_required():
- ]
- with pytest.raises(TypeError) as exc_info:
- MyDataclass()
-- assert str(exc_info.value) == "__init__() missing 1 required positional argument: 'v'"
-+ assert "__init__() missing 1 required positional argument: 'v'" in str(exc_info.value)
-
-
- @pytest.mark.parametrize('default', [1, None, ...])
-diff --git a/tests/test_decorator.py b/tests/test_decorator.py
-index 6b11fb2..cbfc2dd 100644
---- a/tests/test_decorator.py
-+++ b/tests/test_decorator.py
-@@ -267,7 +267,7 @@ def test_async():
- v = await foo(1, 2)
- assert v == 'a=1 b=2'
-
-- loop = asyncio.get_event_loop()
-+ loop = asyncio.get_event_loop_policy().get_event_loop()
- loop.run_until_complete(run())
- with pytest.raises(ValidationError) as exc_info:
- loop.run_until_complete(foo('x'))
-diff --git a/tests/test_edge_cases.py b/tests/test_edge_cases.py
-index 6e77f26..f8662a6 100644
---- a/tests/test_edge_cases.py
-+++ b/tests/test_edge_cases.py
-@@ -859,7 +859,10 @@ def test_annotation_inheritance():
- class B(A):
- integer = 2
-
-- assert B.__annotations__['integer'] == int
-+ if sys.version_info < (3, 10):
-+ assert B.__annotations__['integer'] == int
-+ else:
-+ assert B.__annotations__ == {}
- assert B.__fields__['integer'].type_ == int
-
- class C(A):
-diff --git a/tests/test_main.py b/tests/test_main.py
-index 5eefe3b..5351e0a 100644
---- a/tests/test_main.py
-+++ b/tests/test_main.py
-@@ -801,10 +801,15 @@ def test_literal_enum_values():
- with pytest.raises(ValidationError) as exc_info:
- Model(baz=FooEnum.bar)
-
-+ if sys.version_info < (3, 10):
-+ enum_repr = "<FooEnum.foo: 'foo_value'>"
-+ else:
-+ enum_repr = 'FooEnum.foo'
-+
- assert exc_info.value.errors() == [
- {
- 'loc': ('baz',),
-- 'msg': "unexpected value; permitted: <FooEnum.foo: 'foo_value'>",
-+ 'msg': f'unexpected value; permitted: {enum_repr}',
- 'type': 'value_error.const',
- 'ctx': {'given': FooEnum.bar, 'permitted': (FooEnum.foo,)},
- },
-@@ -1753,3 +1758,21 @@ def test_class_kwargs_custom_config():
- a: int
-
- assert Model.__config__.some_config == 'new_value'
-+
-+
-+ at pytest.mark.skipif(sys.version_info < (3, 10), reason='need 3.10 version')
-+def test_new_union_origin():
-+ """On 3.10+, origin of `int | str` is `types.Union`, not `typing.Union`"""
-+
-+ class Model(BaseModel):
-+ x: int | str
-+
-+ assert Model(x=3).x == 3
-+ assert Model(x='3').x == 3
-+ assert Model(x='pika').x == 'pika'
-+ assert Model.schema() == {
-+ 'title': 'Model',
-+ 'type': 'object',
-+ 'properties': {'x': {'title': 'X', 'anyOf': [{'type': 'integer'}, {'type': 'string'}]}},
-+ 'required': ['x'],
-+ }
-diff --git a/tests/test_types.py b/tests/test_types.py
-index 4b6ef72..ab1f0aa 100644
---- a/tests/test_types.py
-+++ b/tests/test_types.py
-@@ -794,7 +794,10 @@ def test_enum_successful():
- m = CookingModel(tool=2)
- assert m.fruit == FruitEnum.pear
- assert m.tool == ToolEnum.wrench
-- assert repr(m.tool) == '<ToolEnum.wrench: 2>'
-+ if sys.version_info < (3, 10):
-+ assert repr(m.tool) == '<ToolEnum.wrench: 2>'
-+ else:
-+ assert repr(m.tool) == 'ToolEnum.wrench'
-
-
- def test_enum_fails():
-@@ -814,7 +817,10 @@ def test_enum_fails():
- def test_int_enum_successful_for_str_int():
- m = CookingModel(tool='2')
- assert m.tool == ToolEnum.wrench
-- assert repr(m.tool) == '<ToolEnum.wrench: 2>'
-+ if sys.version_info < (3, 10):
-+ assert repr(m.tool) == '<ToolEnum.wrench: 2>'
-+ else:
-+ assert repr(m.tool) == 'ToolEnum.wrench'
-
-
- def test_enum_type():
-diff --git a/tests/test_utils.py b/tests/test_utils.py
-index 0f331a5..b68ca41 100644
---- a/tests/test_utils.py
-+++ b/tests/test_utils.py
-@@ -5,10 +5,10 @@ import re
- import string
- import sys
- from copy import copy, deepcopy
--from distutils.version import StrictVersion
- from typing import Callable, Dict, List, NewType, Tuple, TypeVar, Union
-
- import pytest
-+from pkg_resources import safe_version
- from typing_extensions import Annotated, Literal
-
- from pydantic import VERSION, BaseModel, ConstrainedList, conlist
-@@ -328,8 +328,8 @@ def test_version_info():
- assert s.count('\n') == 5
-
-
--def test_version_strict():
-- assert str(StrictVersion(VERSION)) == VERSION
-+def test_standard_version():
-+ assert safe_version(VERSION) == VERSION
-
-
- def test_class_attribute():
-
-From 1d0682053cfdca249b39afda03939b2600fb8376 Mon Sep 17 00:00:00 2001
-From: Eric Jolibois <em.jolibois at gmail.com>
-Date: Mon, 19 Jul 2021 20:25:05 +0200
-Subject: [PATCH 2/3] chore(ci): update python 3.10 version (#3000)
-
-* chore(ci): update python 3.10 version
-
-* Revert "fix: enum repr is different with 3.10+"
-
-This reverts commit b1c8d9ef1396959ff9d88bb2ed16d99dd3146151.
-
-(cherry picked from commit 0c26c1c4e288e0d41d2c3890d5b3befa7579455c)
----
- .github/workflows/ci.yml | 2 +-
- tests/test_main.py | 7 +------
- tests/test_types.py | 10 ++--------
- 3 files changed, 4 insertions(+), 15 deletions(-)
-
-diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
-index 7f847eb..2b3e0d6 100644
---- a/.github/workflows/ci.yml
-+++ b/.github/workflows/ci.yml
-@@ -119,7 +119,7 @@ jobs:
- fail-fast: false
- matrix:
- os: [macos, windows]
-- python-version: ['3.6', '3.7', '3.8', '3.9', '3.10.0-beta.2']
-+ python-version: ['3.6', '3.7', '3.8', '3.9', '3.10.0-beta.4']
- env:
- PYTHON: ${{ matrix.python-version }}
- OS: ${{ matrix.os }}
-diff --git a/tests/test_main.py b/tests/test_main.py
-index 5351e0a..75ed3fd 100644
---- a/tests/test_main.py
-+++ b/tests/test_main.py
-@@ -801,15 +801,10 @@ def test_literal_enum_values():
- with pytest.raises(ValidationError) as exc_info:
- Model(baz=FooEnum.bar)
-
-- if sys.version_info < (3, 10):
-- enum_repr = "<FooEnum.foo: 'foo_value'>"
-- else:
-- enum_repr = 'FooEnum.foo'
--
- assert exc_info.value.errors() == [
- {
- 'loc': ('baz',),
-- 'msg': f'unexpected value; permitted: {enum_repr}',
-+ 'msg': "unexpected value; permitted: <FooEnum.foo: 'foo_value'>",
- 'type': 'value_error.const',
- 'ctx': {'given': FooEnum.bar, 'permitted': (FooEnum.foo,)},
- },
-diff --git a/tests/test_types.py b/tests/test_types.py
-index ab1f0aa..4b6ef72 100644
---- a/tests/test_types.py
-+++ b/tests/test_types.py
-@@ -794,10 +794,7 @@ def test_enum_successful():
- m = CookingModel(tool=2)
- assert m.fruit == FruitEnum.pear
- assert m.tool == ToolEnum.wrench
-- if sys.version_info < (3, 10):
-- assert repr(m.tool) == '<ToolEnum.wrench: 2>'
-- else:
-- assert repr(m.tool) == 'ToolEnum.wrench'
-+ assert repr(m.tool) == '<ToolEnum.wrench: 2>'
-
-
- def test_enum_fails():
-@@ -817,10 +814,7 @@ def test_enum_fails():
- def test_int_enum_successful_for_str_int():
- m = CookingModel(tool='2')
- assert m.tool == ToolEnum.wrench
-- if sys.version_info < (3, 10):
-- assert repr(m.tool) == '<ToolEnum.wrench: 2>'
-- else:
-- assert repr(m.tool) == 'ToolEnum.wrench'
-+ assert repr(m.tool) == '<ToolEnum.wrench: 2>'
-
-
- def test_enum_type():
-
-From e5a072a7427bf1616afad333ee042cadf35e2564 Mon Sep 17 00:00:00 2001
-From: Eric Jolibois <em.jolibois at gmail.com>
-Date: Fri, 3 Sep 2021 22:56:11 +0200
-Subject: [PATCH 3/3] chore(ci): update to python 3.10.0-rc.1 (#3085)
-
-* refactor: rename `is_union` into `is_union_origin`
-
-* fix: "new" union and generic types are not the same as `typing.GenericAlias`
-
-* chore: rename param
-
-* fix(ci): name changed for 3.10
-
-* fix: mypy
-
-(cherry picked from commit 21d002ec6e5ac4d38eed88b1ec1808f5c44b24e6)
----
- .github/workflows/ci.yml | 2 +-
- pydantic/fields.py | 4 ++--
- pydantic/main.py | 4 ++--
- pydantic/schema.py | 4 ++--
- pydantic/typing.py | 22 +++++++++++++---------
- pydantic/utils.py | 4 ++--
- 6 files changed, 22 insertions(+), 18 deletions(-)
-
-diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
-index 2b3e0d6..9820267 100644
---- a/.github/workflows/ci.yml
-+++ b/.github/workflows/ci.yml
-@@ -119,7 +119,7 @@ jobs:
- fail-fast: false
- matrix:
- os: [macos, windows]
-- python-version: ['3.6', '3.7', '3.8', '3.9', '3.10.0-beta.4']
-+ python-version: ['3.6', '3.7', '3.8', '3.9', '3.10.0-rc.1']
- env:
- PYTHON: ${{ matrix.python-version }}
- OS: ${{ matrix.os }}
-diff --git a/pydantic/fields.py b/pydantic/fields.py
-index 3fdb88f..725ec11 100644
---- a/pydantic/fields.py
-+++ b/pydantic/fields.py
-@@ -41,7 +41,7 @@ from .typing import (
- is_literal_type,
- is_new_type,
- is_typeddict,
-- is_union,
-+ is_union_origin,
- new_type_supertype,
- )
- from .utils import PyObjectStr, Representation, lenient_issubclass, sequence_like, smart_deepcopy
-@@ -528,7 +528,7 @@ class ModelField(Representation):
- return
- if origin is Callable:
- return
-- if is_union(origin):
-+ if is_union_origin(origin):
- types_ = []
- for type_ in get_args(self.type_):
- if type_ is NoneType:
-diff --git a/pydantic/main.py b/pydantic/main.py
-index 0d9dac2..3745ebd 100644
---- a/pydantic/main.py
-+++ b/pydantic/main.py
-@@ -38,7 +38,7 @@ from .typing import (
- get_origin,
- is_classvar,
- is_namedtuple,
-- is_union,
-+ is_union_origin,
- resolve_annotations,
- update_field_forward_refs,
- )
-@@ -176,7 +176,7 @@ class ModelMetaclass(ABCMeta):
- elif is_valid_field(ann_name):
- validate_field_name(bases, ann_name)
- value = namespace.get(ann_name, Undefined)
-- allowed_types = get_args(ann_type) if is_union(get_origin(ann_type)) else (ann_type,)
-+ allowed_types = get_args(ann_type) if is_union_origin(get_origin(ann_type)) else (ann_type,)
- if (
- is_untouched(value)
- and ann_type != PyObject
-diff --git a/pydantic/schema.py b/pydantic/schema.py
-index e4b90d4..cce1566 100644
---- a/pydantic/schema.py
-+++ b/pydantic/schema.py
-@@ -71,7 +71,7 @@ from .typing import (
- is_callable_type,
- is_literal_type,
- is_namedtuple,
-- is_union,
-+ is_union_origin,
- )
- from .utils import ROOT_KEY, get_model, lenient_issubclass, sequence_like
-
-@@ -960,7 +960,7 @@ def get_annotation_with_constraints(annotation: Any, field_info: FieldInfo) -> T
-
- if origin is Annotated:
- return go(args[0])
-- if is_union(origin):
-+ if is_union_origin(origin):
- return Union[tuple(go(a) for a in args)] # type: ignore
-
- if issubclass(origin, List) and (field_info.min_items is not None or field_info.max_items is not None):
-diff --git a/pydantic/typing.py b/pydantic/typing.py
-index b98b543..7004c7b 100644
---- a/pydantic/typing.py
-+++ b/pydantic/typing.py
-@@ -28,10 +28,10 @@ except ImportError:
- from typing import _Final as typing_base # type: ignore
-
- try:
-- from typing import GenericAlias # type: ignore
-+ from typing import GenericAlias as TypingGenericAlias # type: ignore
- except ImportError:
- # python < 3.9 does not have GenericAlias (list[int], tuple[str, ...] and so on)
-- GenericAlias = ()
-+ TypingGenericAlias = ()
-
-
- if sys.version_info < (3, 7):
-@@ -191,15 +191,19 @@ else:
-
- if sys.version_info < (3, 10):
-
-- def is_union(tp: Type[Any]) -> bool:
-+ def is_union_origin(tp: Type[Any]) -> bool:
- return tp is Union
-
-+ WithArgsTypes = (TypingGenericAlias,)
-
- else:
- import types
-+ import typing
-
-- def is_union(tp: Type[Any]) -> bool:
-- return tp is Union or tp is types.Union
-+ def is_union_origin(origin: Type[Any]) -> bool:
-+ return origin is Union or origin is types.UnionType # noqa: E721
-+
-+ WithArgsTypes = (typing._GenericAlias, types.GenericAlias, types.UnionType)
-
-
- if TYPE_CHECKING:
-@@ -246,12 +250,12 @@ __all__ = (
- 'CallableGenerator',
- 'ReprArgs',
- 'CallableGenerator',
-- 'GenericAlias',
-+ 'WithArgsTypes',
- 'get_args',
- 'get_origin',
- 'typing_base',
- 'get_all_type_hints',
-- 'is_union',
-+ 'is_union_origin',
- )
-
-
-@@ -260,10 +264,10 @@ NONE_TYPES: Set[Any] = {None, NoneType, Literal[None]}
-
-
- def display_as_type(v: Type[Any]) -> str:
-- if not isinstance(v, typing_base) and not isinstance(v, GenericAlias) and not isinstance(v, type):
-+ if not isinstance(v, typing_base) and not isinstance(v, WithArgsTypes) and not isinstance(v, type):
- v = v.__class__
-
-- if isinstance(v, GenericAlias):
-+ if isinstance(v, WithArgsTypes):
- # Generic alias are constructs like `list[int]`
- return str(v).replace('typing.', '')
-
-diff --git a/pydantic/utils.py b/pydantic/utils.py
-index c50863f..31de6c6 100644
---- a/pydantic/utils.py
-+++ b/pydantic/utils.py
-@@ -24,7 +24,7 @@ from typing import (
- no_type_check,
- )
-
--from .typing import GenericAlias, NoneType, display_as_type
-+from .typing import NoneType, WithArgsTypes, display_as_type
- from .version import version_info
-
- if TYPE_CHECKING:
-@@ -153,7 +153,7 @@ def lenient_issubclass(cls: Any, class_or_tuple: Union[Type[Any], Tuple[Type[Any
- try:
- return isinstance(cls, type) and issubclass(cls, class_or_tuple)
- except TypeError:
-- if isinstance(cls, GenericAlias):
-+ if isinstance(cls, WithArgsTypes):
- return False
- raise # pragma: no cover
-
More information about the arch-commits
mailing list