Skip to content

Commit

Permalink
Separate tests into different files
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex0Blackwell committed Oct 1, 2023
1 parent 16aa2af commit 01e96c6
Show file tree
Hide file tree
Showing 9 changed files with 667 additions and 614 deletions.
10 changes: 9 additions & 1 deletion python_typing/strict.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,11 @@ def _assert_structure(self, structure, expected_structure):
)
if structure is not expected_structure_type:
arg_type = getattr(self._arg_type, "__name__", self._arg_type)
msg = f'Expected type {arg_type} in "{self._func_name}({self._arg_name}={arg_type})" got {structure.__name__}'
msg = (
f"Expected type {arg_type} in "
f'"{self._func_name}({self._arg_name}={arg_type})" '
f"got {structure.__name__}"
)
raise TypeError(msg)

def _is_of_type_list(self, values: list, type: type):
Expand Down Expand Up @@ -140,6 +144,10 @@ def _is_of_type(self, value, type):


def strict(func):
"""
Raises a TypeError if any specified argument or return type mismatches its value.
"""

def inner(*arg_values, **kwargs):
typing = Typing()
typing.check_arg_types(func, arg_values, kwargs)
Expand Down
54 changes: 54 additions & 0 deletions python_typing_tests/test_custom_types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import heapq

import pytest

from python_typing.strict import strict


def test_custom_arg():
class CustomType:
pass

@strict
def _func(_: CustomType):
pass

custom_obj = CustomType()
_func(custom_obj)


def test_custom_arg_fails():
class CustomType:
pass

@strict
def _func(_: CustomType):
pass

with pytest.raises(TypeError) as err:
_func(1)
assert (
str(err.value) == 'Value (1) in "_func(_=CustomType)" is not of type CustomType'
)


def test_heap():
@strict
def _func(_: list):
pass

q = []
heapq.heappush(q, (1, "test"))
_func(q)


def test_heap_expect_dict():
@strict
def _func(_: dict):
pass

q = []
heapq.heappush(q, (1, "test"))
with pytest.raises(TypeError) as err:
_func(q)
assert str(err.value) == 'Expected type dict in "_func(_=dict)" got list'
122 changes: 122 additions & 0 deletions python_typing_tests/test_defaults.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import heapq
from typing import Optional

import pytest

from python_typing.strict import strict


def test_default():
@strict
def _func(_: str = "one"):
pass

_func()


def test_single_default():
@strict
def _func(one: int, two: str = "one"):
pass

_func(1)


def test_single_default_both_specified():
@strict
def _func(one: int, two: str = "one"):
pass

_func(1, "two")


def test_single_default_specified():
@strict
def _func(one: int, two: str = "one"):
pass

_func(1, two="two")


def test_single_specified_with_default():
@strict
def _func(one: int, two: int, three: str = "three"):
pass

_func(1, two=2)


def test_default_wrong_type():
@strict
def _func(_: str = 1):
pass

with pytest.raises(TypeError) as err:
_func()
assert str(err.value) == 'Value (1) in "_func(_=str)" is not of type str'


def test_one_arg_wrong():
@strict
def _func(one: int, two: int, three: str = "three"):
pass

with pytest.raises(TypeError) as err:
_func(1, two="oops!")
assert str(err.value) == 'Value (oops!) in "_func(two=int)" is not of type int'


def test_some_specified_some_not():
@strict
def _func(one: str, two, three: int):
pass

_func("arg", 2, 3)


def test_arg_optional():
@strict
def _func(_: Optional[str]):
pass

_func("arg")


def test_arg_optional_none_specified():
@strict
def _func(_: Optional[str]):
# Note the arg isn't actually optional here
pass

with pytest.raises(TypeError) as err:
_func()
assert str(err.value) == "_func() missing 1 required positional argument: '_'"


def test_arg_optional_give_none():
@strict
def _func(_: Optional[str] = None):
pass

_func()


def test_arg_optional_give_correct_default():
@strict
def _func(_: Optional[str] = "string"):
pass

_func()


def test_arg_optional_give_wrong_default():
@strict
def _func(_: Optional[str] = 1):
pass

with pytest.raises(TypeError) as err:
_func()
assert (
str(err.value)
== 'Value (1) in "_func(_=typing.Optional[str])" is not any of the valid types (str, NoneType)'
)
136 changes: 136 additions & 0 deletions python_typing_tests/test_dict.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
from typing import Dict, List, Union

import pytest

from python_typing.strict import strict


def test_dict_arg():
@strict
def _func(_: Dict[str, int]):
pass

_func({"arg": 1})


def test_dict_non_typing_arg():
@strict
def _func(_: dict[str, int]):
pass

_func({"arg": 1})


def test_dict_arg_as_list():
@strict
def _func(_: Dict[str, int]):
pass

with pytest.raises(TypeError) as err:
_func(["arg", 1])
assert (
str(err.value)
== 'Expected type typing.Dict[str, int] in "_func(_=typing.Dict[str, int])" got list'
)


def test_dict_non_typing_arg_as_list():
@strict
def _func(_: dict[str, int]):
pass

with pytest.raises(TypeError) as err:
_func(["arg", 1])
assert str(err.value) == 'Expected type dict in "_func(_=dict)" got list'


def test_dict_arg_invalid():
@strict
def _func(_: Dict[str, int]):
pass

with pytest.raises(TypeError) as err:
_func({1: 3.14})
assert (
str(err.value)
== 'Value (1) in "_func(_=typing.Dict[str, int])" is not of type str'
)


def test_dict_arg_multiple_key_values():
@strict
def _func(_: Dict[str, int]):
pass

_func(
{
"arg1": 1,
"arg2": 2,
"arg3": 3,
}
)


def test_dict_arg_malformed_multiple_key_values():
@strict
def _func(_: Dict[str, int]):
pass

with pytest.raises(TypeError) as err:
_func(
{
"arg1": 1,
2: "arg2",
"arg3": 3,
}
)
assert (
str(err.value)
== 'Value (2) in "_func(_=typing.Dict[str, int])" is not of type str'
)


def test_dict_arg_multiple_valid_types():
@strict
def _func(_: Dict[Union[str, float], int]):
pass

_func({"arg": 1})
_func({3.14: 1})


def test_dict_of_dict_arg():
@strict
def _func(_: Dict[str, Dict[str, float]]):
pass

_func({"arg": {"val": 3.14}})


def test_dict_of_dict_arg_give_list():
@strict
def _func(_: Dict[str, Dict[str, float]]):
pass

with pytest.raises(TypeError) as err:
_func({"arg": [1, 2, 3]})
assert (
str(err.value)
== 'Expected type typing.Dict[str, typing.Dict[str, float]] in "_func(_=typing.Dict[str, typing.Dict[str, float]])" got list'
)


def test_dict_of_dict_of_list_arg():
@strict
def _func(_: Dict[str, Dict[str, List[int]]]):
pass

_func({"arg": {"val": [1, 2, 3]}})


def test_return_dict():
@strict
def _func() -> Dict[str, int]:
return {"one": 1, "two": 2}

_func()
Loading

0 comments on commit 01e96c6

Please sign in to comment.