diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml new file mode 100644 index 0000000..059a0a7 --- /dev/null +++ b/.github/workflows/pytest.yml @@ -0,0 +1,23 @@ +name: Run tests with pytest +on: + push: + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Python + uses: actions/setup-python@v5 + with: + python-version: "3.13" + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pytest + pip install pytest-repeat + + - name: Run tests + run: pytest \ No newline at end of file diff --git a/23.10/src/curry.py b/23.10/src/curry.py new file mode 100644 index 0000000..25f63ae --- /dev/null +++ b/23.10/src/curry.py @@ -0,0 +1,45 @@ +def curry(f: callable, arg_count: int) -> callable: + if arg_count < 0 or arg_count != f.__code__.co_argcount: + raise ValueError("Некорректное значение арности") + + def curried(*collected_args): + if len(collected_args) < arg_count: + + def next_arg(new_arg): + return curried(*(list(collected_args) + [new_arg])) + + return next_arg + elif len(collected_args) == arg_count: + return f(*collected_args) + else: + raise ValueError( + "Общее количество аргументов больше нужного \ +(например, если передано слишком много аргументов в каком-то из вызовов)" + ) + + return curried + + +def uncurry(f: callable) -> callable: + if not callable(f): + raise ValueError("Передана не функция") + + def uncurried(*args): + res = f + if len(args) == 0: + try: + res = res() + except TypeError: + raise TypeError from TypeError + + for i in args: + if not callable(res): + raise ValueError("Передано слишком много аргументов") + res = res(i) + + if callable(res): + raise ValueError("Передано недостаточно аргументов") + + return res + + return uncurried diff --git a/23.10/tests/test_curry.py b/23.10/tests/test_curry.py new file mode 100644 index 0000000..a0268e9 --- /dev/null +++ b/23.10/tests/test_curry.py @@ -0,0 +1,49 @@ +import sys +from pathlib import Path + +import pytest + +sys.path.append(f"{Path(__file__).parent.parent}") + +from src.curry import curry + + +def test_curry_zero_args(): + def f(): + return range(10) + + curried = curry(f, 0) + assert curried() == f() + + +def test_curry_one_arg(): + def f(a): + return a + + curried = curry(f, 1) + assert curried(2435234534252) == f(2435234534252) + + +def test_curry_two_args(): + def f(a, b): + return a + b + + curried = curry(f, 2) + assert curried(5)(10) == f(5, 10) + + +def test_curry_three_args(): + def f(a, b, c): + return a - b & c + + curried = curry(f, 3) + assert curried(2)(3)(4) == f(2, 3, 4) + + +def test_curry_insufficient_args(): + def add(a, b): + return a + b + + curried = curry(add, 2) + with pytest.raises(TypeError): + curried(5)() diff --git a/23.10/tests/test_uncurry.py b/23.10/tests/test_uncurry.py new file mode 100644 index 0000000..6236cbe --- /dev/null +++ b/23.10/tests/test_uncurry.py @@ -0,0 +1,70 @@ +import sys +from pathlib import Path + +import pytest + +sys.path.append(f"{Path(__file__).parent.parent}") + +from src.curry import curry, uncurry + + +def test_uncurry_zero_args(): + def f(): + return range(10) + + curried = curry(f, 0) + uncurried = uncurry(curried) + + assert uncurried() == f() + + +def test_uncurry_one_arg(): + def f(a): + return a + + curried = curry(f, 1) + uncurried = uncurry(curried) + + assert uncurried(2435234534252) == f(2435234534252) + + +def test_uncurry_two_args(): + def f(a, b): + return a + b + + curried = curry(f, 2) + uncurried = uncurry(curried) + + assert uncurried(5, 10) == f(5, 10) + + +def test_uncurry_three_args(): + def f(a, b, c): + return a - b & c + + curried = curry(f, 3) + uncurried = uncurry(curried) + + assert uncurried(2, 3, 4) == f(2, 3, 4) + + +def test_uncurry_insufficient_args(): + def add(a, b): + return a + b + + curried = curry(add, 2) + uncurried = uncurry(curried) + + with pytest.raises(ValueError): + uncurried(5) + + +def test_uncurry_excessive_args(): + def f(a, b): + return a + b + + curried = curry(f, 2) + uncurried_add = uncurry(curried) + + with pytest.raises(ValueError): + uncurried_add(1, 2, 3)