mirror of
https://github.com/kennethreitz/pydantic.git
synced 2026-06-05 23:00:18 +00:00
Fix typing coverage (#2032)
* fix coverage * linting * correct forward ref import * fix conlist __args__ * chore: remove useless except * skip test_get_args prior to 3.8 Co-authored-by: PrettyWood <em.jolibois@gmail.com>
This commit is contained in:
+3
-2
@@ -15,6 +15,7 @@ from typing import (
|
||||
Optional,
|
||||
Pattern,
|
||||
Set,
|
||||
Tuple,
|
||||
Type,
|
||||
TypeVar,
|
||||
Union,
|
||||
@@ -132,7 +133,7 @@ T = TypeVar('T')
|
||||
class ConstrainedList(list): # type: ignore
|
||||
# Needed for pydantic to detect that this is a list
|
||||
__origin__ = list
|
||||
__args__: List[Type[T]] # type: ignore
|
||||
__args__: Tuple[Type[T], ...] # type: ignore
|
||||
|
||||
min_items: Optional[int] = None
|
||||
max_items: Optional[int] = None
|
||||
@@ -165,7 +166,7 @@ class ConstrainedList(list): # type: ignore
|
||||
|
||||
def conlist(item_type: Type[T], *, min_items: int = None, max_items: int = None) -> Type[List[T]]:
|
||||
# __args__ is needed to conform to typing generics api
|
||||
namespace = {'min_items': min_items, 'max_items': max_items, 'item_type': item_type, '__args__': [item_type]}
|
||||
namespace = {'min_items': min_items, 'max_items': max_items, 'item_type': item_type, '__args__': (item_type,)}
|
||||
# We use new_class to be able to deal with Generic types
|
||||
return new_class('ConstrainedListValue', (ConstrainedList,), {}, lambda ns: ns.update(namespace))
|
||||
|
||||
|
||||
+1
-5
@@ -124,12 +124,8 @@ else:
|
||||
get_args(Union[int, Tuple[T, int]][str]) == (int, Tuple[str, int])
|
||||
get_args(Callable[[], T][int]) == ([], int)
|
||||
"""
|
||||
try:
|
||||
args = typing_get_args(tp)
|
||||
except IndexError:
|
||||
args = ()
|
||||
# the fallback is needed for the same reasons as `get_origin` (see above)
|
||||
return args or getattr(tp, '__args__', ()) or generic_get_args(tp)
|
||||
return typing_get_args(tp) or getattr(tp, '__args__', ()) or generic_get_args(tp)
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
||||
+40
-3
@@ -1,18 +1,28 @@
|
||||
import os
|
||||
import re
|
||||
import string
|
||||
import sys
|
||||
from copy import copy, deepcopy
|
||||
from distutils.version import StrictVersion
|
||||
from enum import Enum
|
||||
from typing import NewType, Union
|
||||
from typing import Callable, Dict, List, NewType, Tuple, TypeVar, Union
|
||||
|
||||
import pytest
|
||||
|
||||
from pydantic import VERSION, BaseModel
|
||||
from pydantic import VERSION, BaseModel, ConstrainedList, conlist
|
||||
from pydantic.color import Color
|
||||
from pydantic.dataclasses import dataclass
|
||||
from pydantic.fields import Undefined
|
||||
from pydantic.typing import Literal, all_literal_values, display_as_type, is_new_type, new_type_supertype
|
||||
from pydantic.typing import (
|
||||
ForwardRef,
|
||||
Literal,
|
||||
all_literal_values,
|
||||
display_as_type,
|
||||
get_args,
|
||||
is_new_type,
|
||||
new_type_supertype,
|
||||
resolve_annotations,
|
||||
)
|
||||
from pydantic.utils import (
|
||||
BUILTIN_COLLECTIONS,
|
||||
ClassAttribute,
|
||||
@@ -409,3 +419,30 @@ def test_smart_deepcopy_collection(collection, mocker):
|
||||
expected_value = object()
|
||||
mocker.patch('pydantic.utils.deepcopy', return_value=expected_value)
|
||||
assert smart_deepcopy(collection) is expected_value
|
||||
|
||||
|
||||
T = TypeVar('T')
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 8), reason='get_args is only consistent for python >= 3.8')
|
||||
@pytest.mark.parametrize(
|
||||
'input_value,output_value',
|
||||
[
|
||||
(conlist(str), (str,)),
|
||||
(ConstrainedList, ()),
|
||||
(List[str], (str,)),
|
||||
(Dict[str, int], (str, int)),
|
||||
(int, ()),
|
||||
(Union[int, Union[T, int], str][int], (int, str)),
|
||||
(Union[int, Tuple[T, int]][str], (int, Tuple[str, int])),
|
||||
(Callable[[], T][int], ([], int)),
|
||||
],
|
||||
)
|
||||
def test_get_args(input_value, output_value):
|
||||
assert get_args(input_value) == output_value
|
||||
|
||||
|
||||
def test_resolve_annotations_no_module():
|
||||
# TODO: is there a better test for this, can this case really happen?
|
||||
fr = ForwardRef('Foo')
|
||||
assert resolve_annotations({'Foo': ForwardRef('Foo')}, None) == {'Foo': fr}
|
||||
|
||||
Reference in New Issue
Block a user