# 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\\') 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