def test_name(self): # The generated name has to be different from the official name, or we'll # end up with nonsense like X = X. self.assertNotEqual("X", collections_overlay.namedtuple_name("X", [])) # Two namedtuple instances should have the same name iff the instances are # the same. self.assertNotEqual(collections_overlay.namedtuple_name("X", []), collections_overlay.namedtuple_name("X", ["a"])) self.assertNotEqual(collections_overlay.namedtuple_name("X", ["a"]), collections_overlay.namedtuple_name("X", ["b"]))
def test_name_conflict(self): ty = self.Infer(""" import collections X = collections.namedtuple("_", []) Y = collections.namedtuple("_", []) Z = collections.namedtuple("_", "a") """) name_x = collections_overlay.namedtuple_name("_", []) name_z = collections_overlay.namedtuple_name("_", ["a"]) ast_x = collections_overlay.namedtuple_ast(name_x, []) ast_z = collections_overlay.namedtuple_ast(name_z, ["a"]) ast = pytd_utils.Concat(ast_x, ast_z) expected = pytd.Print(ast) + textwrap.dedent("""\ collections = ... # type: module X = {name_x} Y = {name_x} Z = {name_z}""").format(name_x=name_x, name_z=name_z) self.assertTypesMatchPytd(ty, expected)
def testInheritFromNamedTuple(self): ty = self.Infer(""" import collections class Foo( collections.namedtuple('_Foo', 'x y z')): pass """) name = collections_overlay.namedtuple_name("_Foo", ["x", "y", "z"]) ast = collections_overlay.namedtuple_ast(name, ["x", "y", "z"], self.python_version) expected = pytd.Print(ast) + textwrap.dedent("""\ collections = ... # type: module class Foo({name}): ...""").format(name=name) self.assertTypesMatchPytd(ty, expected)
def test_subclass(self): ty = self.Infer(""" import collections class X(collections.namedtuple("X", [])): def __new__(cls, _): return super(X, cls).__new__(cls) """) name = collections_overlay.namedtuple_name("X", []) ast = self._namedtuple_ast(name, []) expected = pytd.Print(ast) + textwrap.dedent("""\ collections = ... # type: module _TX = TypeVar("_TX", bound=X) class X({name}): def __new__(cls: Type[_TX], _) -> _TX: ...""").format(name=name) self.assertTypesMatchPytd(ty, expected)
def _namedtuple_def(self, suffix="", **kws): """Generate the expected pyi for a simple namedtuple definition. Args: suffix: Optionally, extra text to append to the pyi. **kws: Must contain exactly one argument of the form alias=(name, [<fields>]). For example, to generate a definition for X = namedtuple("_X", "y z"), the method call should be _namedtuple_def(X=("_X", ["y", "z"])). Returns: The expected pyi for the namedtuple instance. """ (alias, (name, fields)), = kws.items() name = collections_overlay.namedtuple_name(name, fields) suffix += textwrap.dedent(""" collections = ... # type: module {alias} = {name}""").format(alias=alias, name=name) return pytd.Print(self._namedtuple_ast(name, fields)) + suffix
def testStoreAndLoadFromNamedTuple(self): ty = self.Infer(""" import collections t = collections.namedtuple('t', ['x', 'y', 'z']) t.x = 3 t.y = "foo" t.z = 1j x = t.x y = t.y z = t.z """) name = collections_overlay.namedtuple_name("t", ["x", "y", "z"]) ast = collections_overlay.namedtuple_ast(name, ["x", "y", "z"], self.python_version) expected = pytd.Print(ast) + textwrap.dedent("""\ collections = ... # type: module t = {name} x = ... # type: int y = ... # type: str z = ... # type: complex""").format(name=name) self.assertTypesMatchPytd(ty, expected)