|
1 | 1 | from testutils import assert_raises |
2 | 2 |
|
3 | 3 |
|
| 4 | +def error(call, expected): |
| 5 | + try: |
| 6 | + call() |
| 7 | + except TypeError as exc: |
| 8 | + assert str(exc) == expected, (str(exc), expected) |
| 9 | + else: |
| 10 | + raise AssertionError("expected TypeError") |
| 11 | + |
| 12 | + |
| 13 | +error(lambda: id(obj=1), "id() takes no keyword arguments") |
| 14 | +error(lambda: id(**{"obj": 1}), "id() takes no keyword arguments") |
| 15 | +error(lambda: id(1, 2, obj=1), "id() takes no keyword arguments") |
| 16 | +error(lambda: list.append(x=1), "unbound method list.append() needs an argument") |
| 17 | +error(lambda: list.append(**{"x": 1}), "unbound method list.append() needs an argument") |
| 18 | +error( |
| 19 | + lambda: list.append(1, x=1), |
| 20 | + "descriptor 'append' for 'list' objects doesn't apply to a 'int' object", |
| 21 | +) |
| 22 | +error(lambda: list.append([], x=1), "list.append() takes no keyword arguments") |
| 23 | +error(lambda: list.append([], **{"x": 1}), "list.append() takes no keyword arguments") |
| 24 | +error(lambda: [].append(x=1), "list.append() takes no keyword arguments") |
| 25 | +error(lambda: [].clear(1, x=1), "list.clear() takes no keyword arguments") |
| 26 | + |
| 27 | + |
| 28 | +class Index: |
| 29 | + def __index__(self): |
| 30 | + raise AssertionError("conversion ran before keyword check") |
| 31 | + |
| 32 | + |
| 33 | +error(lambda: bin(Index(), x=1), "bin() takes no keyword arguments") |
| 34 | +assert id(1, **{}) == id(1) |
| 35 | +assert round(1.25, ndigits=1) == 1.2 |
| 36 | +assert pow(2, exp=3) == 8 |
| 37 | +assert sorted([2, 1], reverse=True) == [2, 1] |
| 38 | +assert sum([1, 2], start=4) == 7 |
| 39 | +values = [] |
| 40 | +list.append(values, 1) |
| 41 | +values.append(2) |
| 42 | +assert values == [1, 2] |
| 43 | +list.clear(values) |
| 44 | +assert values == [] |
| 45 | + |
| 46 | +# Keyword metadata must forward raw arguments without changing body validation. |
| 47 | +for choose in (min, max): |
| 48 | + assert choose([], default=42) == 42 |
| 49 | + assert choose([1, 2], key=lambda value: -value) == (2 if choose is min else 1) |
| 50 | + try: |
| 51 | + choose(bogus=1) |
| 52 | + except TypeError as exc: |
| 53 | + assert str(exc) == f"{choose.__name__} expected at least 1 argument, got 0" |
| 54 | + else: |
| 55 | + raise AssertionError("missing positional argument was accepted") |
| 56 | + try: |
| 57 | + choose(1, 2, default=0) |
| 58 | + except TypeError as exc: |
| 59 | + assert str(exc) == ( |
| 60 | + f"Cannot specify a default for {choose.__name__}() " |
| 61 | + "with multiple positional arguments" |
| 62 | + ) |
| 63 | + else: |
| 64 | + raise AssertionError("default with multiple arguments was accepted") |
| 65 | + |
| 66 | +# Named fields in argument structs must override positional-only arguments. |
| 67 | +assert eval("value", globals={"value": 42}) == 42 |
| 68 | +namespace = {} |
| 69 | +exec("value = 42", globals=namespace) |
| 70 | +assert namespace["value"] == 42 |
| 71 | +assert compile(source="42", filename="<inference>", mode="eval") |
| 72 | +assert __import__(name="sys").__name__ == "sys" |
| 73 | + |
| 74 | +from io import StringIO |
| 75 | + |
| 76 | +output = StringIO() |
| 77 | +print(1, 2, sep=":", end="!", file=output) |
| 78 | +assert output.getvalue() == "1:2!" |
| 79 | + |
| 80 | +# Methods using a keyword-only argument struct must keep accepting keywords. |
| 81 | +values = [1, 2] |
| 82 | +values.sort(reverse=True) |
| 83 | +assert values == [2, 1] |
| 84 | + |
| 85 | +# Definitions built without the macros infer their calling convention too. |
| 86 | +assert int.__new__(int, "11", base=2) == 3 |
| 87 | + |
4 | 88 | def sum(x, y): |
5 | 89 | return x+y |
6 | 90 |
|
|
0 commit comments