| # Test cases for tuples (compile and run) | |
| [case testTuple] | |
| from typing import List, Optional, Tuple | |
| from typing import Tuple | |
| def f(x: Tuple[int, int]) -> Tuple[int,int]: | |
| return x | |
| def lurr(x: List[Optional[Tuple[int, str]]]) -> object: | |
| return x[0] | |
| def asdf(x: Tuple[int, str]) -> None: | |
| pass | |
| [file driver.py] | |
| from testutil import assertRaises | |
| from native import f, lurr, asdf | |
| assert f((1,2)) == (1, 2) | |
| assert lurr([(1, '2')]) == (1, '2') | |
| with assertRaises(TypeError): | |
| print(lurr([(1, 2)])) | |
| with assertRaises(TypeError): | |
| asdf((1, 2)) | |
| [case testTupleGet] | |
| from typing import Tuple | |
| def f(x: Tuple[Tuple[int, bool], int]) -> int: | |
| return x[0][0] | |
| [file driver.py] | |
| from native import f | |
| print(f(((1,True),2))) | |
| big_number = pow(2, 80) | |
| print(f(((big_number,True),2))) | |
| [out] | |
| 1 | |
| 1208925819614629174706176 | |
| [case testSequenceTupleArg] | |
| from typing import Tuple | |
| def f(x: Tuple[int, ...]) -> int: | |
| return x[1] | |
| [file driver.py] | |
| from native import f | |
| print(f((1,2,3,4))) | |
| [out] | |
| 2 | |
| [case testTupleAttr] | |
| from typing import Tuple | |
| class C: | |
| b: Tuple[Tuple[Tuple[int, int], int], int, str, object] | |
| c: Tuple[()] | |
| def f() -> None: | |
| c = C() | |
| c.b = (((1, 2), 2), 1, 'hi', 'hi2') | |
| print(c.b) | |
| def g() -> None: | |
| try: | |
| h() | |
| except Exception: | |
| print('caught the exception') | |
| def h() -> Tuple[Tuple[Tuple[int, int], int], int, str, object]: | |
| raise Exception('Intentional exception') | |
| [file driver.py] | |
| from native import f, g, C | |
| f() | |
| g() | |
| assert not hasattr(C(), 'c') | |
| [out] | |
| (((1, 2), 2), 1, 'hi', 'hi2') | |
| caught the exception | |
| [case testNamedTupleAttributeRun] | |
| from typing import NamedTuple | |
| NT = NamedTuple('NT', [('x', int), ('y', int)]) | |
| def f(nt: NT) -> int: | |
| if nt.x > nt.y: | |
| return nt.x | |
| return nt.y | |
| nt = NT(1, 2) | |
| [file driver.py] | |
| from native import NT, nt, f | |
| assert f(nt) == 2 | |
| assert f(NT(3, 2)) == 3 | |
| class Sub(NT): | |
| pass | |
| assert f(Sub(3, 2)) == 3 | |
| -- Ref: https://github.com/mypyc/mypyc/issues/924 | |
| [case testNamedTupleClassSyntax] | |
| from typing import Dict, List, NamedTuple, Optional, Tuple, Union, final | |
| class FuncIR: pass | |
| StealsDescription = Union[bool, List[bool]] | |
| class Record(NamedTuple): | |
| st_mtime: float | |
| st_size: int | |
| is_borrowed: bool | |
| hash: str | |
| python_path: Tuple[str, ...] | |
| type: 'ClassIR' | |
| method: FuncIR | |
| shadow_method: Optional[FuncIR] | |
| classes: Dict[str, 'ClassIR'] | |
| steals: StealsDescription | |
| ordering: Optional[List[int]] | |
| extra_int_constants: List[Tuple[int]] | |
| # Make sure mypyc loads the annotation string for this forward reference. | |
| # Ref: https://github.com/mypyc/mypyc/issues/938 | |
| class ClassIR: pass | |
| # Ref: https://github.com/mypyc/mypyc/issues/927 | |
| @final | |
| class Inextensible(NamedTuple): | |
| x: int | |
| [file driver.py] | |
| import sys | |
| from typing import Optional | |
| from native import ClassIR, FuncIR, Record | |
| HAVE_TEST = False | |
| if sys.version_info >= (3, 14): | |
| try: | |
| from test.support import EqualToForwardRef | |
| type_forward_ref = EqualToForwardRef | |
| HAVE_TEST = True | |
| except ImportError as e: | |
| # catch the case of a pymanager installed Python | |
| # without the test module. It is excluded by default | |
| # on Windows. | |
| msg = 'Missing "test" module.' | |
| if sys.platform == "win32": | |
| msg += (' Please install a version of Python with the test module.' | |
| ' If you are using pymanager, try running pymanager install --force PythonTest\\<version>') | |
| raise ImportError(msg) from e | |
| if not HAVE_TEST: | |
| from typing import ForwardRef | |
| type_forward_ref = ForwardRef | |
| assert Record.__annotations__ == { | |
| 'st_mtime': float, | |
| 'st_size': int, | |
| 'is_borrowed': bool, | |
| 'hash': str, | |
| 'python_path': tuple, | |
| 'type': type_forward_ref('ClassIR'), | |
| 'method': FuncIR, | |
| 'shadow_method': type, | |
| 'classes': dict, | |
| 'steals': type, | |
| 'ordering': type, | |
| 'extra_int_constants': list, | |
| }, Record.__annotations__ | |
| [case testTupleOps] | |
| from typing import Tuple, Final, List, Any, Optional, cast | |
| from testutil import assertRaises | |
| def f() -> Tuple[()]: | |
| return () | |
| def test_empty_tuple() -> None: | |
| assert f() == () | |
| def f2() -> Any: | |
| return () | |
| def test_empty_tuple_with_any_type(): | |
| assert f2() == () | |
| def f3() -> int: | |
| x = (False, 1) | |
| return x[1] | |
| def test_new_tuple() -> None: | |
| assert f3() == 1 | |
| def f4(y: int) -> int: | |
| x = (False, y) | |
| return x[1] | |
| def test_new_tuple_boxed_int() -> None: | |
| big_number = 1208925819614629174706176 | |
| assert f4(big_number) == big_number | |
| def f5(x: List[int]) -> int: | |
| return tuple(x)[1] | |
| def test_sequence_tuple() -> None: | |
| assert f5([1,2,3,4]) == 2 | |
| def f6(x: List[int]) -> int: | |
| return len(tuple(x)) | |
| def test_sequence_tuple_len() -> None: | |
| assert f6([1,2,3,4]) == 4 | |
| def f7(x: List[Tuple[int, int]]) -> int: | |
| a, b = x[0] | |
| return a + b | |
| def test_unbox_tuple() -> None: | |
| assert f7([(5, 6)]) == 11 | |
| def test_comparison() -> None: | |
| assert ('x','y') == ('x','y') | |
| assert not(('x','y') != ('x','y')) | |
| assert ('x','y') != ('x','y',1) | |
| assert not(('x','y') == ('x','y',1)) | |
| assert ('x','y',1) != ('x','y') | |
| assert not(('x','y',1) == ('x','y')) | |
| assert ('x','y') != () | |
| assert not(('x','y') == ()) | |
| assert () != ('x','y') | |
| assert not(() == ('x','y')) | |
| # Test that order is irrelevant to unions. Really I only care that this builds. | |
| class A: | |
| pass | |
| def lol() -> A: | |
| return A() | |
| def foo(x: bool, y: bool) -> Tuple[Optional[A], bool]: | |
| z = lol() | |
| return None if y else z, x | |
| def test_slicing() -> None: | |
| # Use dummy adds to avoid constant folding | |
| zero = int() | |
| two = zero + 2 | |
| s: Tuple[str, ...] = ("f", "o", "o", "b", "a", "r") | |
| assert s[two:] == ("o", "b", "a", "r") | |
| assert s[:two] == ("f", "o") | |
| assert s[two:-two] == ("o", "b") | |
| assert s[two:two] == () | |
| assert s[two:two + 1] == ("o",) | |
| assert s[-two:] == ("a", "r") | |
| assert s[:-two] == ("f", "o", "o", "b") | |
| assert s[:] == ("f", "o", "o", "b", "a", "r") | |
| assert s[two:333] == ("o", "b", "a", "r") | |
| assert s[333:two] == () | |
| assert s[two:-333] == () | |
| assert s[-333:two] == ("f", "o") | |
| long_int: int = 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 | |
| assert s[1:long_int] == ("o", "o", "b", "a", "r") | |
| assert s[long_int:] == () | |
| assert s[-long_int:-1] == ("f", "o", "o", "b", "a") | |
| def f8(val: int) -> bool: | |
| return val % 2 == 0 | |
| abc: Final = "abc" | |
| def known_length() -> tuple[str, ...]: | |
| return tuple(str(x) for x in [*abc, *"def", *b"ghi", ("j", "k"), *("l", "m", "n")]) | |
| def test_sequence_generator() -> None: | |
| source_list = [1, 2, 3] | |
| a = tuple(f8(x) for x in source_list) | |
| assert a == (False, True, False) | |
| source_tuple: Tuple[int, ...] = (1, 2, 3) | |
| a = tuple(f8(x) for x in source_tuple) | |
| assert a == (False, True, False) | |
| source_fixed_length_tuple = (1, 2, 3, 4) | |
| a = tuple(f8(x) for x in source_fixed_length_tuple) | |
| assert a == (False, True, False, True) | |
| source_str = 'abbc' | |
| b = tuple('s:' + x for x in source_str) | |
| assert b == ('s:a', 's:b', 's:b', 's:c') | |
| assert known_length() == ('a', 'b', 'c', 'd', 'e', 'f', '103', '104', '105', "('j', 'k')", 'l', 'm', 'n') | |
| TUPLE: Final[Tuple[str, ...]] = ('x', 'y') | |
| def test_final_boxed_tuple() -> None: | |
| t = TUPLE | |
| assert t == ('x', 'y') | |
| assert 'x' in TUPLE | |
| assert 'y' in TUPLE | |
| b: object = 'z' in TUPLE | |
| assert not b | |
| assert 'z' not in TUPLE | |
| b2: object = 'x' not in TUPLE | |
| assert not b2 | |
| b3: object = 'y' not in TUPLE | |
| assert not b3 | |
| TUP2: Final = ('x', 'y') | |
| TUP1: Final = ('x',) | |
| TUP0: Final = () | |
| def test_final_tuple_in() -> None: | |
| assert 'x' + str() in TUP2 | |
| assert 'y' + str() in TUP2 | |
| b: object = 'z' + str() in TUP2 | |
| assert not b | |
| assert 'x' + str() in TUP1 | |
| b2: object = 'y' in TUP1 | |
| assert not b2 | |
| b3: object = 'x' in TUP0 | |
| assert not b3 | |
| def test_final_tuple_not_in() -> None: | |
| assert 'z' + str() not in TUP2 | |
| b: object = 'x' + str() not in TUP2 | |
| assert not b | |
| b2: object = 'y' + str() not in TUP2 | |
| assert not b2 | |
| assert 'y' + str() not in TUP1 | |
| b3: object = 'x' not in TUP1 | |
| assert not b2 | |
| assert 'x' not in TUP0 | |
| log: list[str] = [] | |
| def f_a() -> str: | |
| log.append('f_a') | |
| return 'a' | |
| def f_a2() -> str: | |
| log.append('f_a2') | |
| return 'a' | |
| def f_b() -> str: | |
| log.append('f_b') | |
| return 'b' | |
| def f_c() -> str: | |
| log.append('f_c') | |
| return 'c' | |
| def test_tuple_in_order_of_evaluation() -> None: | |
| log.clear() | |
| assert f_a() in (f_b(), f_a2()) | |
| assert log ==["f_a", "f_b", "f_a2"] | |
| log.clear() | |
| assert f_a() not in (f_b(), f_c()) | |
| assert log ==["f_a", "f_b", "f_c"] | |
| log.clear() | |
| assert f_a() in (f_b(), f_a2(), f_c()) | |
| assert log ==["f_a", "f_b", "f_a2", "f_c"] | |
| def f_t() -> tuple[str, ...]: | |
| log.append('f_t') | |
| return ('x', 'a') | |
| def test_tuple_in_non_specialized() -> None: | |
| log.clear() | |
| assert f_a() in f_t() | |
| assert log == ["f_a", "f_t"] | |
| log.clear() | |
| assert f_b() not in f_t() | |
| assert log == ["f_b", "f_t"] | |
| def test_add() -> None: | |
| res = (1, 2, 3, 4) | |
| assert (1, 2) + (3, 4) == res | |
| with assertRaises(TypeError, 'can only concatenate tuple (not "list") to tuple'): | |
| assert (1, 2) + cast(Any, [3, 4]) == res | |
| def multiply(a: Tuple[Any, ...], b: int) -> Tuple[Any, ...]: | |
| return a * b | |
| def test_multiply() -> None: | |
| res = (1, 1, 1) | |
| assert (1,) * 3 == res | |
| assert 3 * (1,) == res | |
| assert multiply((1,), 3) == res | |
| # Ref: https://github.com/mypyc/mypyc/issues/1179 | |
| def test_tuple_with_walrus() -> None: | |
| i = 0 | |
| assert (i, (i := i + 1), i, (i := i + 1), i, (i := i + 1), i) == (0, 1, 1, 2, 2, 3, 3) | |
| def test_nested_tuple_with_walrus() -> None: | |
| i = 0 | |
| assert ((i, i), (i := i + 1)) == ((0, 0), 1) | |
| [case testIsInstance] | |
| from copysubclass import subc | |
| def test_built_in() -> None: | |
| assert isinstance((), tuple) | |
| assert isinstance((1, 2), tuple) | |
| assert isinstance(('a', 'b', 'c'), tuple) | |
| assert isinstance(subc(()), tuple) | |
| assert isinstance(subc((1, 2)), tuple) | |
| assert isinstance(subc(('a', 'b', 'c')), tuple) | |
| assert not isinstance(set(), tuple) | |
| assert not isinstance({}, tuple) | |
| assert not isinstance([1,2,3], tuple) | |
| assert not isinstance({'a','b'}, tuple) | |
| assert not isinstance(int() + 1, tuple) | |
| assert not isinstance(str() + 'a', tuple) | |
| def test_user_defined() -> None: | |
| from userdefinedtuple import tuple | |
| assert isinstance(tuple(), tuple) | |
| assert not isinstance((1, tuple()), tuple) | |
| [file copysubclass.py] | |
| from typing import Any | |
| class subc(tuple[Any, ...]): | |
| pass | |
| [file userdefinedtuple.py] | |
| class tuple: | |
| pass |