def assertTypesMatchPytd(self, ty, pytd_src, version=None): """Parses pytd_src and compares with ty.""" # TODO(pludemann): This is a copy of pytd.parse.parser_test_base.Parse() # TODO(pludemann): Consider using the pytd_tree to call # assertHasOnlySignatures (or similar) to guard against the # inferencer adding additional but harmless calls. pytd_tree = parser.TypeDeclParser(version=version).Parse( textwrap.dedent(pytd_src)) pytd_tree = pytd_tree.Visit( visitors.LookupBuiltins(builtins.GetBuiltinsAndTyping()[0])) pytd_tree = pytd_tree.Visit( visitors.ClassTypeToNamedType()) pytd_tree = pytd_tree.Visit( visitors.CanonicalOrderingVisitor(sort_signatures=True)) pytd_tree.Visit(visitors.VerifyVisitor()) ty = ty.Visit(visitors.ClassTypeToNamedType()) ty = ty.Visit(visitors.AdjustSelf(force=True)) ty = ty.Visit(visitors.CanonicalOrderingVisitor(sort_signatures=True)) ty.Visit(visitors.VerifyVisitor()) ty_src = pytd.Print(ty) + "\n" pytd_tree_src = pytd.Print(pytd_tree) + "\n" log.info("========== result ==========") _LogLines(log.info, ty_src) log.info("========== expected ==========") _LogLines(log.info, pytd_tree_src) log.info("==============================") # In the diff output, mark expected with "-" and actual with "+". # (In other words, display a change from "working" to "broken") self.assertMultiLineEqual(pytd_tree_src, ty_src)
def testASTeq(self): # This creates two ASts that are equivalent but whose sources are slightly # different. The union types are different (int,str) vs (str,int) but the # ordering is ignored when testing for equality (which ASTeq uses). src1 = textwrap.dedent(""" def foo(a: int or str) -> C T = TypeVar('T') class C(typing.Generic[T], object): def bar(x: T) -> NoneType CONSTANT = ... # type: C[float] """) src2 = textwrap.dedent(""" CONSTANT = ... # type: C[float] T = TypeVar('T') class C(typing.Generic[T], object): def bar(x: T) -> NoneType def foo(a: str or int) -> C """) tree1 = parser.TypeDeclParser().Parse(src1) tree2 = parser.TypeDeclParser().Parse(src2) tree1.Visit(visitors.VerifyVisitor()) tree2.Visit(visitors.VerifyVisitor()) self.assertTrue(tree1.constants) self.assertTrue(tree1.classes) self.assertTrue(tree1.functions) self.assertTrue(tree2.constants) self.assertTrue(tree2.classes) self.assertTrue(tree2.functions) self.assertIsInstance(tree1, pytd.TypeDeclUnit) self.assertIsInstance(tree2, pytd.TypeDeclUnit) # For the ==, != tests, TypeDeclUnit uses identity self.assertTrue(tree1 == tree1) self.assertTrue(tree2 == tree2) self.assertFalse(tree1 == tree2) self.assertFalse(tree2 == tree1) self.assertFalse(tree1 != tree1) self.assertFalse(tree2 != tree2) self.assertTrue(tree1 != tree2) self.assertTrue(tree2 != tree1) self.assertEquals(tree1, tree1) self.assertEquals(tree2, tree2) self.assertNotEquals(tree1, tree2) self.assertTrue(tree1.ASTeq(tree2)) self.assertTrue(tree1.ASTeq(tree1)) self.assertTrue(tree2.ASTeq(tree1)) self.assertTrue(tree2.ASTeq(tree2))
def Parse(self, src, version=None, platform=None): # TODO(kramm): Using self.parser here breaks tests. Why? tree = parser.TypeDeclParser(version=version, platform=platform).Parse( textwrap.dedent(src)) tree = tree.Visit(visitors.NamedTypeToClassType()) tree = visitors.AdjustTypeParameters(tree) # Convert back to named types for easier testing tree = tree.Visit(visitors.ClassTypeToNamedType()) tree.Visit(visitors.VerifyVisitor()) return tree
def ParseWithBuiltins(self, src): ast = parser.TypeDeclParser().Parse(textwrap.dedent(src)) b, t = builtins.GetBuiltinsAndTyping() ast = ast.Visit(visitors.LookupExternalTypes( {"__builtin__": b, "typing": t}, full_names=True)) ast = ast.Visit(visitors.NamedTypeToClassType()) ast = visitors.AdjustTypeParameters(ast) ast.Visit(visitors.FillInModuleClasses({"": ast})) ast.Visit(visitors.VerifyVisitor()) return ast
def GetBuiltinsAndTyping(): """Get __builtin__.pytd and typing.pytd.""" global _cached_builtins_pytd if not _cached_builtins_pytd: t = parser.TypeDeclParser().Parse(_FindBuiltinFile("typing"), name="typing") t = t.Visit(visitors.AddNamePrefix()) b = parser.TypeDeclParser().Parse(_FindBuiltinFile("__builtin__"), name="__builtin__") b = b.Visit(visitors.AddNamePrefix()) b = b.Visit(visitors.NamedTypeToClassType()) b = b.Visit( visitors.LookupExternalTypes({"typing": t}, full_names=True, self_name="__builtin__")) t = t.Visit(visitors.LookupBuiltins(b)) t = t.Visit(visitors.NamedTypeToClassType()) b = visitors.AdjustTypeParameters(b) t = visitors.AdjustTypeParameters(t) b.Visit( visitors.FillInModuleClasses({ "": b, "typing": t, "__builtin__": b })) t.Visit( visitors.FillInModuleClasses({ "": t, "typing": t, "__builtin__": b })) b.Visit(visitors.VerifyLookup()) t.Visit(visitors.VerifyLookup()) b.Visit(visitors.VerifyContainers()) t.Visit(visitors.VerifyContainers()) _cached_builtins_pytd = b, t return _cached_builtins_pytd
def GetBuiltinsPyTD(): """Get the "default" AST used to lookup built in types. Get an AST for all Python builtins as well as the most commonly used standard libraries. Returns: A pytd.TypeDeclUnit instance. It'll directly contain the builtin classes and functions, and submodules for each of the standard library modules. """ global _cached_builtins_pytd if not _cached_builtins_pytd: builtins_pytd = parser.TypeDeclParser().Parse( _FindBuiltinFile(_BUILTIN_NAME), name=_BUILTIN_NAME) _cached_builtins_pytd = visitors.LookupClasses(builtins_pytd) return _cached_builtins_pytd
def testTypeParameters(self): """Test parsing of type parameters.""" src = textwrap.dedent(""" T = TypeVar("T") T2 = TypeVar("T2") def f(x: T) -> T class A(Generic[T]): def a(self, x: T2) -> None: self := A[T or T2] """) tree = parser.TypeDeclParser().Parse(src) param1 = tree.Lookup("T") param2 = tree.Lookup("T2") self.assertEquals(param1, pytd.TypeParameter("T", None)) self.assertEquals(param2, pytd.TypeParameter("T2", None)) self.assertEquals(tree.type_params, (param1, param2)) f = tree.Lookup("f") sig, = f.signatures p_x, = sig.params self.assertEquals(p_x.type, pytd.TypeParameter("T", None)) cls = tree.Lookup("A") cls_parent, = cls.parents f_cls, = cls.methods sig_cls, = f_cls.signatures # AdjustSelf has not been called yet, so self may not have the right type _, p_x_cls = sig_cls.params self.assertEquals(cls_parent.parameters, (pytd.TypeParameter("T", None), )) self.assertEquals(p_x_cls.type, pytd.TypeParameter("T2", None)) # The parser should not have attempted to insert templates! It does # not know about imported type parameters. self.assertEquals(sig.template, ()) self.assertEquals(cls.template, ()) self.assertEquals(sig_cls.template, ())
def setUp(self): self.parser = parser.TypeDeclParser()
def Parse(self, src, version=None): # TODO(kramm): Using self.parser here breaks tests. Why? tree = parser.TypeDeclParser(version=version).Parse(textwrap.dedent(src)) tree.Visit(visitors.VerifyVisitor()) return tree
def canonical_pyi(pyi): ast = parser.TypeDeclParser().Parse(pyi) ast = ast.Visit(visitors.ClassTypeToNamedType()) ast = ast.Visit(visitors.CanonicalOrderingVisitor(sort_signatures=True)) ast.Visit(visitors.VerifyVisitor()) return pytd.Print(ast)