from functools import partial

from impartial import impartial


def f(x: int, y: int, z: int = 0) -> int:
    return x + 2*y + z


def test_simple_call_args():
    assert impartial(f, 1)(2) == f(1, 2)


def test_simple_call_kwargs():
    assert impartial(f, y=2)(x=1) == f(1, 2)


def test_simple_call_empty():
    assert impartial(f, 1, y=2)() == f(1, 2)


def test_decorator():
    @impartial
    def f(x, y):
        return x + 2*y
    assert f.with_y(2)(1) == 5


def test_func():
    assert impartial(f, 1).func is f


def test_with_kwargs():
    assert impartial(f, 1).with_z(3)(2) == f(1, 2, 3)


def test_multiple_with_kwargs():
    assert impartial(f, 1).with_z(3).with_y(2)() == f(1, 2, 3)


def test_with_kwargs_override():
    assert impartial(f, 1, 2).with_z(3).with_z(4)() == f(1, 2, 4)


def test_nested_impartial():
    imp = impartial(f, x=1, y=2)
    imp = impartial(imp, x=2)
    imp = impartial(imp, x=3)
    assert imp() == f(3, 2)
    assert not isinstance(imp.func, impartial)
    assert imp.func is f


def test_nested_partial():
    imp = partial(f, x=1, y=2)
    imp = partial(imp, x=2)
    imp = impartial(imp, x=3)
    assert imp() == f(3, 2)
    assert not isinstance(imp.func, partial)
    assert imp.func is f


def test_configure():
    assert impartial(f, 1, z=2).configure(2, z=3)() == f(1, 2, 3)

[((843, 865), 'impartial.impartial', 'impartial', (['f'], {'x': '(1)', 'y': '(2)'}), '(f, x=1, y=2)\n', (852, 865), False, 'from impartial import impartial\n'), ((876, 895), 'impartial.impartial', 'impartial', (['imp'], {'x': '(2)'}), '(imp, x=2)\n', (885, 895), False, 'from impartial import impartial\n'), ((906, 925), 'impartial.impartial', 'impartial', (['imp'], {'x': '(3)'}), '(imp, x=3)\n', (915, 925), False, 'from impartial import impartial\n'), ((1065, 1085), 'functools.partial', 'partial', (['f'], {'x': '(1)', 'y': '(2)'}), '(f, x=1, y=2)\n', (1072, 1085), False, 'from functools import partial\n'), ((1096, 1113), 'functools.partial', 'partial', (['imp'], {'x': '(2)'}), '(imp, x=2)\n', (1103, 1113), False, 'from functools import partial\n'), ((1124, 1143), 'impartial.impartial', 'impartial', (['imp'], {'x': '(3)'}), '(imp, x=3)\n', (1133, 1143), False, 'from impartial import impartial\n'), ((172, 187), 'impartial.impartial', 'impartial', (['f', '(1)'], {}), '(f, 1)\n', (181, 187), False, 'from impartial import impartial\n'), ((246, 263), 'impartial.impartial', 'impartial', (['f'], {'y': '(2)'}), '(f, y=2)\n', (255, 263), False, 'from impartial import impartial\n'), ((323, 343), 'impartial.impartial', 'impartial', (['f', '(1)'], {'y': '(2)'}), '(f, 1, y=2)\n', (332, 343), False, 'from impartial import impartial\n'), ((497, 512), 'impartial.impartial', 'impartial', (['f', '(1)'], {}), '(f, 1)\n', (506, 512), False, 'from impartial import impartial\n'), ((560, 575), 'impartial.impartial', 'impartial', (['f', '(1)'], {}), '(f, 1)\n', (569, 575), False, 'from impartial import impartial\n'), ((1277, 1297), 'impartial.impartial', 'impartial', (['f', '(1)'], {'z': '(2)'}), '(f, 1, z=2)\n', (1286, 1297), False, 'from impartial import impartial\n'), ((649, 664), 'impartial.impartial', 'impartial', (['f', '(1)'], {}), '(f, 1)\n', (658, 664), False, 'from impartial import impartial\n'), ((747, 765), 'impartial.impartial', 'impartial', (['f', '(1)', '(2)'], {}), '(f, 1, 2)\n', (756, 765), False, 'from impartial import impartial\n')]