Skip to content

Commit

Permalink
test: add utils tests
Browse files Browse the repository at this point in the history
  • Loading branch information
PrettyWood committed Jan 17, 2021
1 parent 58dbfd7 commit 5663cd3
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 3 deletions.
7 changes: 4 additions & 3 deletions pydantic/typing.py
Expand Up @@ -302,7 +302,8 @@ def all_literal_values(type_: Type[Any]) -> Tuple[Any, ...]:

def is_namedtuple(type_: Type[Any]) -> bool:
"""
Check if a given class is a `NamedTuple`
Check if a given class is a named tuple.
It can be either a `typing.NamedTuple` or `collections.namedtuple`
"""
from .utils import lenient_issubclass

Expand All @@ -311,12 +312,12 @@ def is_namedtuple(type_: Type[Any]) -> bool:

def is_typeddict(type_: Type[Any]) -> bool:
"""
Check if a given class is a `TypedDict`
Check if a given class is a typed dict (from `typing` or `typing_extensions`)
In 3.10, there will be a public method (https://docs.python.org/3.10/library/typing.html#typing.is_typeddict)
"""
from .utils import lenient_issubclass

return lenient_issubclass(type_, dict) and getattr(type_, '__annotations__', None)
return lenient_issubclass(type_, dict) and hasattr(type_, '__total__')


test_type = NewType('test_type', str)
Expand Down
55 changes: 55 additions & 0 deletions tests/test_typing.py
@@ -0,0 +1,55 @@
from collections import namedtuple
from typing import NamedTuple

import pytest

from pydantic.typing import is_namedtuple, is_typeddict

try:
from typing import TypedDict as typing_TypedDict
except ImportError:
typing_TypedDict = None

try:
from typing_extensions import TypedDict as typing_extensions_TypedDict
except ImportError:
typing_extensions_TypedDict = None


try:
from mypy_extensions import TypedDict as mypy_extensions_TypedDict
except ImportError:
mypy_extensions_TypedDict = None

ALL_TYPEDDICT_KINDS = (typing_TypedDict, typing_extensions_TypedDict, mypy_extensions_TypedDict)


def test_is_namedtuple():
class Employee(NamedTuple):
name: str
id: int = 3

assert is_namedtuple(namedtuple('Point', 'x y')) is True
assert is_namedtuple(Employee) is True
assert is_namedtuple(NamedTuple('Employee', [('name', str), ('id', int)])) is True

class SubTuple(tuple):
...

assert is_namedtuple(SubTuple) is False


@pytest.mark.parametrize('TypedDict', (t for t in ALL_TYPEDDICT_KINDS if t is not None))
def test_is_typeddict_typing(TypedDict):
class Employee(TypedDict):
name: str
id: int

assert is_typeddict(Employee) is True
assert is_typeddict(TypedDict('Employee', {'name': str, 'id': int})) is True

class Other(dict):
name: str
id: int

assert is_typeddict(Other) is False

0 comments on commit 5663cd3

Please sign in to comment.