Example #1
0
    def assertTypesMatchPytd(self, ty, pytd_src):
        """Parses pytd_src and compares with ty."""
        pytd_tree = parser.parse_string(
            textwrap.dedent(pytd_src),
            options=parser.PyiOptions(python_version=self.python_version))
        pytd_tree = pytd_tree.Visit(
            visitors.LookupBuiltins(self.loader.builtins, full_names=False))
        pytd_tree = pytd_tree.Visit(visitors.LookupLocalTypes())
        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())
        ty = ty.Visit(visitors.CanonicalOrderingVisitor(sort_signatures=True))
        ty.Visit(visitors.VerifyVisitor())

        ty_src = pytd_utils.Print(ty) + "\n"
        pytd_tree_src = pytd_utils.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)
Example #2
0
 def load(self, options):
     """Read builtins.pytd and typing.pytd, and return the parsed modules."""
     t = self._parse_predefined("typing", options)
     b = self._parse_predefined("builtins", options)
     b = b.Visit(
         visitors.LookupExternalTypes({"typing": t}, self_name="builtins"))
     t = t.Visit(visitors.LookupBuiltins(b))
     b = b.Visit(visitors.NamedTypeToClassType())
     t = t.Visit(visitors.NamedTypeToClassType())
     b = b.Visit(visitors.AdjustTypeParameters())
     t = t.Visit(visitors.AdjustTypeParameters())
     b = b.Visit(visitors.CanonicalOrderingVisitor())
     t = t.Visit(visitors.CanonicalOrderingVisitor())
     b.Visit(
         visitors.FillInLocalPointers({
             "": b,
             "typing": t,
             "builtins": b
         }))
     t.Visit(
         visitors.FillInLocalPointers({
             "": t,
             "typing": t,
             "builtins": b
         }))
     b.Visit(visitors.VerifyLookup())
     t.Visit(visitors.VerifyLookup())
     b.Visit(visitors.VerifyContainers())
     t.Visit(visitors.VerifyContainers())
     return b, t
Example #3
0
 def testCanonicalOrderingVisitor(self):
   src1 = textwrap.dedent("""
   from typing import TypeVar
   def f() -> ?:
     raise MemoryError()
     raise IOError()
   def f(x: list[a]) -> ?
   def f(x: list[b or c]) -> ?
   def f(x: list[tuple[d]]) -> ?
   A = TypeVar("A")
   C = TypeVar("C")
   B = TypeVar("B")
   D = TypeVar("D")
   def f(d: A, c: B, b: C, a: D) -> ?
   """)
   src2 = textwrap.dedent("""
   def f() -> ?:
     raise IOError()
     raise MemoryError()
   def f(x: list[tuple[d]]) -> ?
   def f(x: list[a]) -> ?
   def f(x: list[b or c]) -> ?
   A = TypeVar("A")
   C = TypeVar("C")
   B = TypeVar("B")
   D = TypeVar("D")
   def f(d: A, c: B, b: C, a: D) -> ?
   """)
   tree1 = self.Parse(src1)
   tree1 = tree1.Visit(visitors.CanonicalOrderingVisitor(sort_signatures=True))
   tree2 = self.Parse(src2)
   tree2 = tree2.Visit(visitors.CanonicalOrderingVisitor(sort_signatures=True))
   self.AssertSourceEquals(tree1, tree2)
   self.assertEqual(tree1.Lookup("f").signatures[0].template,
                    tree2.Lookup("f").signatures[0].template)
Example #4
0
def canonical_pyi(pyi, multiline_args=False, options=None):
  """Rewrite a pyi in canonical form."""
  ast = parse_string(pyi, options=options)
  ast = ast.Visit(visitors.ClassTypeToNamedType())
  ast = ast.Visit(visitors.CanonicalOrderingVisitor(sort_signatures=True))
  ast.Visit(visitors.VerifyVisitor())
  return pytd_utils.Print(ast, multiline_args)
Example #5
0
def StoreAst(ast, filename=None, open_function=open):
    """Loads and stores an ast to disk.

  Args:
    ast: The pytd.TypeDeclUnit to save to disk.
    filename: The filename for the pickled output. If this is None, this
      function instead returns the pickled string.
    open_function: A custom file opening function.

  Returns:
    The pickled string, if no filename was given. (None otherwise.)
  """
    if ast.name.endswith(".__init__"):
        ast = ast.Visit(
            visitors.RenameModuleVisitor(ast.name,
                                         ast.name.rsplit(".__init__", 1)[0]))
    # Collect dependencies
    deps = visitors.CollectDependencies()
    ast.Visit(deps)
    dependencies = deps.dependencies
    late_dependencies = deps.late_dependencies

    # Clean external references
    ast.Visit(visitors.ClearClassPointers())
    indexer = FindClassTypesVisitor()
    ast.Visit(indexer)
    ast = ast.Visit(visitors.CanonicalOrderingVisitor())
    return pytd_utils.SavePickle(SerializableAst(
        ast, sorted(dependencies.items()), sorted(late_dependencies.items()),
        sorted(indexer.class_type_nodes)),
                                 filename,
                                 open_function=open_function)
Example #6
0
def GetBuiltinsAndTyping(python_version):  # Deprecated. Use load_pytd instead.
    """Get __builtin__.pytd and typing.pytd."""
    assert python_version
    global _cached_builtins_pytd
    if _cached_builtins_pytd.cache:
        assert _cached_builtins_pytd.version == python_version
    else:
        t = parser.parse_string(_FindBuiltinFile("typing", python_version),
                                name="typing",
                                python_version=python_version)
        b = parser.parse_string(_FindBuiltinFile("__builtin__",
                                                 python_version),
                                name="__builtin__",
                                python_version=python_version)
        b = b.Visit(
            visitors.LookupExternalTypes({"typing": t},
                                         full_names=True,
                                         self_name="__builtin__"))
        t = t.Visit(visitors.LookupBuiltins(b))
        b = b.Visit(visitors.NamedTypeToClassType())
        t = t.Visit(visitors.NamedTypeToClassType())
        b = b.Visit(visitors.AdjustTypeParameters())
        t = t.Visit(visitors.AdjustTypeParameters())
        b = b.Visit(visitors.CanonicalOrderingVisitor())
        t = t.Visit(visitors.CanonicalOrderingVisitor())
        b.Visit(
            visitors.FillInLocalPointers({
                "": b,
                "typing": t,
                "__builtin__": b
            }))
        t.Visit(
            visitors.FillInLocalPointers({
                "": t,
                "typing": t,
                "__builtin__": b
            }))
        b.Visit(visitors.VerifyLookup())
        t.Visit(visitors.VerifyLookup())
        b.Visit(visitors.VerifyContainers())
        t.Visit(visitors.VerifyContainers())
        _cached_builtins_pytd = Cache(python_version, (b, t))
    return _cached_builtins_pytd.cache
Example #7
0
def GetBuiltinsAndTyping(python_version):  # Deprecated. Use load_pytd instead.
    """Get builtins.pytd and typing.pytd."""
    assert python_version
    if python_version not in _cached_builtins_pytd:
        t = parser.parse_string(_FindBuiltinFile("typing", python_version),
                                name="typing",
                                python_version=python_version)
        b = parser.parse_string(_FindBuiltinFile("builtins", python_version),
                                name="builtins",
                                python_version=python_version)
        b = b.Visit(
            visitors.LookupExternalTypes({"typing": t}, self_name="builtins"))
        t = t.Visit(visitors.LookupBuiltins(b))
        b = b.Visit(visitors.NamedTypeToClassType())
        t = t.Visit(visitors.NamedTypeToClassType())
        b = b.Visit(visitors.AdjustTypeParameters())
        t = t.Visit(visitors.AdjustTypeParameters())
        b = b.Visit(visitors.CanonicalOrderingVisitor())
        t = t.Visit(visitors.CanonicalOrderingVisitor())
        b.Visit(
            visitors.FillInLocalPointers({
                "": b,
                "typing": t,
                "builtins": b
            }))
        t.Visit(
            visitors.FillInLocalPointers({
                "": t,
                "typing": t,
                "builtins": b
            }))
        b.Visit(visitors.VerifyLookup())
        t.Visit(visitors.VerifyLookup())
        b.Visit(visitors.VerifyContainers())
        t.Visit(visitors.VerifyContainers())
        _cached_builtins_pytd[python_version] = (b, t)
    return _cached_builtins_pytd[python_version]
Example #8
0
 def test_builtin_superclasses(self):
     src = pytd_src("""
     def f(x: Union[list, object], y: Union[complex, memoryview]) -> Union[int, bool]: ...
 """)
     expected = pytd_src("""
     def f(x: builtins.object, y: builtins.object) -> builtins.int: ...
 """)
     hierarchy = self.builtins.Visit(visitors.ExtractSuperClassesByName())
     hierarchy.update(
         self.typing.Visit(visitors.ExtractSuperClassesByName()))
     visitor = optimize.FindCommonSuperClasses(
         optimize.SuperClassHierarchy(hierarchy))
     ast = self.ParseAndResolve(src)
     ast = ast.Visit(visitor)
     ast = ast.Visit(visitors.CanonicalOrderingVisitor())
     self.AssertSourceEquals(ast, expected)
Example #9
0
 def testBuiltinSuperClasses(self):
   src = textwrap.dedent("""
       def f(x: list or object, y: complex or memoryview) -> int or bool
   """)
   expected = textwrap.dedent("""
       def f(x: object, y: object) -> int
   """)
   hierarchy = self.builtins.Visit(visitors.ExtractSuperClassesByName())
   hierarchy.update(self.typing.Visit(visitors.ExtractSuperClassesByName()))
   visitor = optimize.FindCommonSuperClasses(
       optimize.SuperClassHierarchy(hierarchy))
   ast = self.ParseAndResolve(src)
   ast = ast.Visit(visitor)
   ast = ast.Visit(visitors.DropBuiltinPrefix())
   ast = ast.Visit(visitors.CanonicalOrderingVisitor())
   self.AssertSourceEquals(ast, expected)
Example #10
0
def PrepareForExport(module_name, python_version, ast, loader):
    """Prepare an ast as if it was parsed and loaded.

  External dependencies will not be resolved, as the ast generated by this
  method is supposed to be exported.

  Args:
    module_name: The module_name as a string for the returned ast.
    python_version: A tuple of (major, minor) python version as string
      (see config.python_version).
    ast: pytd.TypeDeclUnit, is only used if src is None.
    loader: A load_pytd.Loader instance.

  Returns:
    A pytd.TypeDeclUnit representing the supplied AST as it would look after
    being written to a file and parsed.
  """
    # This is a workaround for functionality which crept into places it doesn't
    # belong. Ideally this would call some transformation Visitors on ast to
    # transform it into the same ast we get after parsing and loading (compare
    # load_pytd.Loader.load_file). Unfortunately parsing has some special cases,
    # e.g. '__init__' return type and '__new__' being a 'staticmethod', which
    # need to be moved to visitors before we can do this. Printing an ast also
    # applies transformations,
    # e.g. visitors.PrintVisitor._FormatContainerContents, which need to move to
    # their own visitors so they can be applied without printing.
    src = pytd_utils.Print(ast)
    ast = parser.parse_string(src=src,
                              name=module_name,
                              python_version=python_version)
    ast = ast.Visit(visitors.LookupBuiltins(loader.builtins, full_names=False))
    ast = ast.Visit(
        visitors.ExpandCompatibleBuiltins(loader.builtins, python_version))
    ast = ast.Visit(visitors.LookupLocalTypes())
    ast = ast.Visit(visitors.AdjustTypeParameters())
    ast = ast.Visit(visitors.NamedTypeToClassType())
    ast = ast.Visit(visitors.FillInLocalPointers({"": ast, module_name: ast}))
    ast = ast.Visit(visitors.CanonicalOrderingVisitor())
    ast = ast.Visit(
        visitors.ClassTypeToLateType(
            ignore=[module_name + ".", "__builtin__.", "typing."]))
    return ast
Example #11
0
    def _get_ast(self, temp_dir, module_name, src=None):
        src = src or ("""
        import module2
        from module2 import f
        from typing import List

        constant = True

        x = List[int]
        b = List[int]

        class SomeClass(object):
          def __init__(self, a: module2.ObjectMod2):
            pass

        def ModuleFunction():
          pass
    """)
        pyi_filename = temp_dir.create_file("module1.pyi", src)
        temp_dir.create_file(
            "module2.pyi", """
        import queue
        def f() -> queue.Queue: ...
        class ObjectMod2(object):
          def __init__(self):
            pass
    """)

        loader = load_pytd.Loader(base_module=None,
                                  python_version=self.python_version,
                                  pythonpath=[temp_dir.path])
        ast = loader.load_file(module_name, pyi_filename)
        # serialize_ast.StoreAst sorts the ast for determinism, so we should do the
        # same to the original ast to do pre- and post-pickling comparisons.
        loader._modules[module_name].ast = ast = ast.Visit(
            visitors.CanonicalOrderingVisitor())
        return ast, loader
Example #12
0
def canonical_pyi(pyi, python_version, multiline_args=False):
    ast = parser.parse_string(pyi, python_version=python_version)
    ast = ast.Visit(visitors.ClassTypeToNamedType())
    ast = ast.Visit(visitors.CanonicalOrderingVisitor(sort_signatures=True))
    ast.Visit(visitors.VerifyVisitor())
    return Print(ast, multiline_args)
Example #13
0
def CanonicalOrdering(n, sort_signatures=False):
    """Convert a PYTD node to a canonical (sorted) ordering."""
    return n.Visit(
        visitors.CanonicalOrderingVisitor(sort_signatures=sort_signatures))
 def assertPytd(self, val, expected):
     pytd_tree = val.to_type()
     pytd_tree = pytd_tree.Visit(visitors.CanonicalOrderingVisitor())
     actual = pytd_utils.Print(pytd_tree)
     self.assertEqual(actual, expected)