|
| 1 | +import pytest |
| 2 | +from typing_extensions import reveal_type |
| 3 | + |
| 4 | +from returns.curry import partial |
| 5 | + |
| 6 | +TEST_STR = 'a' |
| 7 | + |
| 8 | + |
| 9 | +def test_partial_fn( # noqa: WPS221 |
| 10 | + first_arg: int, |
| 11 | + optional_arg: str | None, |
| 12 | +) -> tuple[int, str | None]: |
| 13 | + """Return arguments as a tuple.""" |
| 14 | + return first_arg, optional_arg |
| 15 | + |
| 16 | + |
| 17 | +def test_partial(): |
| 18 | + """Ensures that ``partial`` works correctly.""" |
| 19 | + bound = partial(test_partial_fn, 1) |
| 20 | + reveal_type(bound) # noqa: WPS421 # R: Revealed type is 'def (*, optional_arg: Union[builtins.str, None] =) -> Tuple[builtins.int, Union[builtins.str, None]]' |
| 21 | + |
| 22 | + assert bound() == (1, None) |
| 23 | + assert bound(optional_arg=TEST_STR) == (1, TEST_STR) |
| 24 | + |
| 25 | + |
| 26 | +def test_partial_with_decorator(): |
| 27 | + """Ensures that ``partial`` works correctly with decorators.""" |
| 28 | + |
| 29 | + @partial(first=1) |
| 30 | + def _decorated(first: int, second: str) -> float: # noqa: WPS430 |
| 31 | + return first / float(second) |
| 32 | + |
| 33 | + reveal_type(_decorated) # noqa: WPS421 # R: Revealed type is 'def (second: builtins.str) -> builtins.float' |
| 34 | + |
| 35 | + assert _decorated(second='2') == pytest.approx(0.5) |
| 36 | + |
| 37 | + |
| 38 | +def test_partial_keyword(): |
| 39 | + """Ensures that ``partial`` works correctly with keyword args.""" |
| 40 | + bound = partial(test_partial_fn, optional_arg=TEST_STR) |
| 41 | + reveal_type(bound) # noqa: WPS421 # R: Revealed type is 'def (first_arg: builtins.int) -> Tuple[builtins.int, builtins.str]' |
| 42 | + |
| 43 | + assert bound(1) == (1, TEST_STR) |
| 44 | + |
| 45 | + |
| 46 | +def test_partial_keyword_only(): |
| 47 | + """Ensures that ``partial`` works with keyword only args.""" |
| 48 | + |
| 49 | + def _target(*, arg: int) -> int: # noqa: WPS430 |
| 50 | + return arg |
| 51 | + |
| 52 | + bound = partial(_target, arg=1) |
| 53 | + reveal_type(bound) # noqa: WPS421 # R: Revealed type is 'def () -> builtins.int' |
| 54 | + |
| 55 | + assert bound() == 1 |
| 56 | + |
| 57 | + |
| 58 | +def test_partial_keyword_mixed(): |
| 59 | + """Ensures that ``partial`` works with keyword only args.""" |
| 60 | + |
| 61 | + def _target(arg1: int, *, arg2: int) -> int: # noqa: WPS430 |
| 62 | + return arg1 + arg2 |
| 63 | + |
| 64 | + bound = partial(_target, arg2=1) |
| 65 | + reveal_type(bound) # noqa: WPS421 # R: Revealed type is 'def (arg1: builtins.int) -> builtins.int' |
| 66 | + |
| 67 | + assert bound(1) == 2 |
| 68 | + |
| 69 | + |
| 70 | +def test_partial_wrong_signature(): |
| 71 | + """Ensures that ``partial`` returns ``Any`` for wrong signature.""" |
| 72 | + reveal_type(partial(len, 1)) # noqa: WPS421 # R: Revealed type is 'Any' |
| 73 | + with pytest.raises(TypeError): |
| 74 | + partial(len, 1)() |
0 commit comments