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:
Samuel Colvin
2020-10-26 10:25:48 +00:00
committed by GitHub
parent 44b639951b
commit 8b4e726be2
3 changed files with 44 additions and 10 deletions
+3 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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}