1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
import collections.abc
import sys
from functools import lru_cache, wraps
from itertools import repeat
from typing import (
AbstractSet,
Awaitable,
Collection,
Dict,
Generic,
List,
Mapping,
Set,
Tuple,
TypeVar,
)
import pytest
from apischema.typing import Annotated, typing_origin
from apischema.utils import is_async, replace_builtins, to_camel_case
def test_to_camel_case():
assert to_camel_case("min_length") == "minLength"
def sync_func():
...
async def async_func():
...
def func_not_returning_awaitable() -> int: # type: ignore
...
def func_returning_awaitable() -> Awaitable[int]: # type: ignore
...
sync_cases = [
sync_func,
wraps(sync_func)(lambda: sync_func()),
lru_cache()(sync_func),
func_not_returning_awaitable,
]
async_cases = [
async_func,
wraps(async_func)(lambda: async_func()),
lru_cache()(async_func),
func_returning_awaitable,
]
@pytest.mark.parametrize(
"func, expected", [*zip(sync_cases, repeat(False)), *zip(async_cases, repeat(True))]
)
def test_is_async(func, expected):
assert is_async(func) == expected
@pytest.mark.parametrize(
"types, expected",
[
({}, False),
({"return": int}, False),
({"return": Awaitable[int]}, True),
({"return": Annotated[int, ...]}, False),
({"return": Annotated[Awaitable[int], ...]}, True),
],
)
def test_is_async_with_types(types, expected):
assert is_async(lambda: ..., types) == expected
T = TypeVar("T")
class GenericClass(Generic[T]):
pass
if sys.version_info < (3, 9):
typing_origin_cases = [(list, List), (collections.abc.Collection, Collection)]
else:
typing_origin_cases = [
(list, list),
(collections.abc.Collection, collections.abc.Collection),
(List, List),
(Collection, Collection),
]
@pytest.mark.parametrize(
"tp, expected", [*typing_origin_cases, (GenericClass, GenericClass)]
)
def test_typing_origin(tp, expected):
assert typing_origin(tp) == expected
if sys.version_info < (3, 9):
replace_builtins_cases = [
(Collection[int], List[int]),
(AbstractSet[int], Set[int]),
(Tuple[int], Tuple[int]),
(Mapping[int, int], Dict[int, int]),
(Tuple[int, ...], List[int]),
]
else:
replace_builtins_cases = [
(Collection[int], list[int]),
(AbstractSet[int], set[int]),
(Tuple[int], tuple[int]),
(Mapping[int, int], dict[int, int]),
(Tuple[int, ...], list[int]),
(collections.abc.Collection[int], list[int]),
(set[int], set[int]),
(tuple[int], tuple[int]),
(dict[int, int], dict[int, int]),
(tuple[int, ...], list[int]),
]
@pytest.mark.parametrize("annotated", [False, True])
@pytest.mark.parametrize("wrapped", [False, True])
@pytest.mark.parametrize("tp, expected", replace_builtins_cases)
def test_replace_builtins(tp, expected, annotated, wrapped):
if wrapped:
tp = Collection[tp] # type: ignore
expected = (list if sys.version_info >= (3, 9) else List)[expected] # type: ignore
if annotated:
tp, expected = Annotated[tp, 0], Annotated[expected, 0]
assert replace_builtins(tp) == expected
|