Пример #1
0
 def testInvalidMapEntry(self):
     with file_utils.Tempdir() as d:
         imports_info = "%s %s\n" % ("a/b/c.pyi", d["a/b/c.pyi"])
         d.create_file("imports_info", imports_info)
         output = os.path.join(d.path, "a/b.pyi")
         with self.assertRaises(ValueError):
             imports_map_loader.build_imports_map(d["imports_info"], output)
Пример #2
0
 def test_import_map_filter(self):
   with file_utils.Tempdir() as d:
     imp_path = ".".join(d.path[1:].split("/"))
     init_body = """
       from {0}.foo import bar
       from {0}.foo import baz
       Qux = bar.Quack
       """.format(imp_path)
     init_fn = d.create_file("foo/__init__.py", init_body)
     initpyi_fn = d.create_file("foo/__init__.pyi~", """
       from typing import Any
       bar = ...  # type: Any
       baz = ...  # type: Any
       Qux = ...  # type: Any
       """)
     bar_fn = d.create_file("foo/bar.py", "class Quack(object): pass")
     barpyi_fn = d.create_file("foo/bar.pyi", "class Quack(object): pass")
     imports_fn = d.create_file("imports_info", """
       {0} {1}
       {2} {3}
       """.format(init_fn[1:-3], initpyi_fn, bar_fn[1:-3], barpyi_fn))
     imports_map = imports_map_loader.build_imports_map(imports_fn, init_fn)
     ty = self.Infer("""
       from {0}.foo import bar
       Adz = bar.Quack
       """.format(imp_path),
                     deep=False, imports_map=imports_map, pythonpath=[""])
     self.assertTypesMatchPytd(ty, """
       from typing import Any, Type
       bar = ...  # type: module
       Adz = ...  # type: Type[{0}.foo.bar.Quack]
       """.format(imp_path))
Пример #3
0
 def testImportsInfoFilter(self):
     """Test filtering out the current target's entry from the imports info."""
     with utils.Tempdir() as d:
         # The files in our "program" that we're building an imports_map for.
         files = [
             "a/__init__.py",
             "a/b.py",
         ]
         # The files the previous files are mapped to:
         imports = ["prefix{0}/{1}~suffix".format(d.path, f) for f in files]
         # Since we're calling _validate_map (via build_imports_map), the files
         # have to actually exist.
         for f in files + imports:
             d.create_file(f, "")
         # We have to add the path so the import map contains the actual files as
         # they exist in the tempdir.
         imports_map = [
             "%s %s" % (d[f], d[t]) for f, t in zip(files, imports)
         ]
         d.create_file("imports_info", "\n".join(imports_map))
         # build_imports_map should strip out the entry for a/__init__.py, leaving
         # the entry for a/b.py intact.
         self.assertSameElements(
             imports_map_loader.build_imports_map(
                 d["imports_info"], d["a/__init__.py"]).items(),
             [
                 ("%s/a/b" % d.path, "{0}/prefix{0}/a/b.py~suffix".format(
                     d.path)),
                 # These are all added by the last bit of build_imports_map
                 ("__init__", os.devnull),
                 ("tmp/__init__", os.devnull),
                 ("%s/__init__" % d.path[1:], os.devnull),
                 ("%s/a/__init__" % d.path[1:], os.devnull),
             ])
Пример #4
0
  def test_submodule_lookup(self):
    # Tests a common Blaze pattern: when mod/__init__.py and mod/submod.py are
    # in the same target, they are analyzed twice, and we should not use the
    # first-pass __init__.pyi to look up types for the second pass, as the
    # former contains a 'submod: Any' entry that masks the actual submodule.

    # The "%s" is used to silence the import error from the first pass.
    init_py = """
      from mod import submod%s
      X = submod.X
    """
    submod_py = """
      class X:
        pass
    """
    init_pyi_1, _ = self.InferWithErrors(
        init_py % "  # import-error", module_name="mod.__init__")
    submod_pyi_1, _ = self.InferWithErrors(submod_py, module_name="mod.submod")
    with file_utils.Tempdir() as d:
      init_path = d.create_file(
          "mod/__init__.pyi", pytd_utils.Print(init_pyi_1))
      submod_path = d.create_file(
          "mod/submod.pyi", pytd_utils.Print(submod_pyi_1))
      imports_info = d.create_file("imports_info", f"""
        mod/__init__ {init_path}
        mod/submod {submod_path}
      """)
      imports_map = imports_map_loader.build_imports_map(imports_info)
      init_pyi = self.Infer(
          init_py % "", imports_map=imports_map, module_name="mod.__init__")
    self.assertTypesMatchPytd(init_pyi, """
      from mod import submod
      from typing import Type
      X: Type[mod.submod.X]
    """)
Пример #5
0
 def test_do_not_filter(self):
   with file_utils.Tempdir() as d:
     d.create_file("a/b/c.pyi")
     imports_info = "%s %s\n" % ("a/b/c.pyi", d["a/b/c.pyi"])
     d.create_file("imports_info", imports_info)
     imports_map = imports_map_loader.build_imports_map(d["imports_info"])
     self.assertEqual(imports_map["a/b/c"], d["a/b/c.pyi"])
Пример #6
0
 def testDoNotFilter(self):
     with file_utils.Tempdir() as d:
         d.create_file("a/b/c.pyi")
         imports_info = "%s %s\n" % ("a/b/c.pyi", d["a/b/c.pyi"])
         d.create_file("imports_info", imports_info)
         output = os.path.join(d.path, "a/b.pyi")
         imports_map = imports_map_loader.build_imports_map(
             d["imports_info"], output)
         self.assertEqual(imports_map["a/b/c"], d["a/b/c.pyi"])
Пример #7
0
    def _store_imports_map(self, imports_map):
        """Postprocess --imports_info."""
        if imports_map:
            if self.output_options.pythonpath not in ([], [""]):
                self.error("Not allowed with --pythonpath", "imports_info")

            self.output_options.imports_map = imports_map_loader.build_imports_map(
                imports_map, self.output_options.output)
        else:
            self.output_options.imports_map = None
Пример #8
0
 def test_submodule_imports_info(self):
     # Tests that the presence of a submodule in imports_info doesn't prevent
     # pytype from finding attributes in a module's __init__ file.
     with file_utils.Tempdir() as d:
         empty = d.create_file("empty.pyi")
         imports_info = d.create_file(
             "imports_info", "email/_header_value_parser {}".format(empty))
         imports_map = imports_map_loader.build_imports_map(imports_info)
         self.Check("""
     from email import message_from_bytes
   """,
                    imports_map=imports_map)
Пример #9
0
 def test_missing_submodule(self):
   with file_utils.Tempdir() as d:
     foo = d.create_file("foo/__init__.pyi", "import bar.baz as baz")
     foo_bar = d.create_file("foo/bar.pyi", "y: str")
     imports_info = d.create_file("imports_info", f"""
       foo {foo}
       foo/bar {foo_bar}
     """)
     imports_map = imports_map_loader.build_imports_map(imports_info)
     self.CheckWithErrors("""
       from foo import baz  # import-error
     """, imports_map=imports_map)
Пример #10
0
    def test_circular_dep(self):
        # This test imitates how analyze_project handles circular dependencies.
        # See https://github.com/google/pytype/issues/760. In the test, the circular
        # dep is between a module's __init__.py and a submodule to make it harder
        # for pytype to distinguish this case from test_submodule_lookup.

        # "%s" is used to silence import errors from the first-pass analysis.
        submod_py = """
      from mod import Y%s
      class X:
        pass
    """
        init_py = """
      import typing
      if typing.TYPE_CHECKING:
        from mod.submod import X%s
      class Y:
        def __init__(self, x):
          # type: ('X') -> None
          pass
    """
        submod_pyi_1, _ = self.InferWithErrors(submod_py % "  # import-error",
                                               module_name="mod.submod")
        init_pyi_1, _ = self.InferWithErrors(init_py % "  # import-error",
                                             module_name="mod.__init__")
        with file_utils.Tempdir() as d:
            submod_path = d.create_file("mod/submod.pyi",
                                        pytd_utils.Print(submod_pyi_1))
            init_path = d.create_file("mod/__init__.pyi",
                                      pytd_utils.Print(init_pyi_1))
            imports_info = d.create_file(
                "imports_info", f"""
        mod/submod {submod_path}
        mod/__init__ {init_path}
      """)
            imports_map = imports_map_loader.build_imports_map(imports_info)
            submod_pyi = self.Infer(submod_py % "",
                                    imports_map=imports_map,
                                    module_name="mod.submod")
            with open(submod_path, "w") as f:
                f.write(pytd_utils.Print(submod_pyi))
            init_pyi = self.Infer(init_py % "",
                                  imports_map=imports_map,
                                  module_name="mod.__init__")
        self.assertTypesMatchPytd(
            init_pyi, """
      from typing import Type
      typing: module
      X: Type[mod.submod.X]
      class Y:
        def __init__(self, x: X) -> None: ...
    """)
Пример #11
0
    def _store_imports_info(self, imports_info):
        """Postprocess --imports_info."""
        if imports_info:
            if self.pythonpath not in ([], [""]):
                raise optparse.OptionConflictError(
                    "Not allowed with --pythonpath", "imports_info")

            self.imports_map = imports_map_loader.build_imports_map(
                imports_info, self.src_out)
        else:
            self.imports_map = None

        self.imports_info = imports_info
Пример #12
0
 def test_directory_module_clash(self):
   with file_utils.Tempdir() as d:
     foo = d.create_file("foo.pyi", "x: int")
     foo_bar = d.create_file("foo/bar.pyi", "y: str")
     imports_info = d.create_file("imports_info", f"""
       foo {foo}
       foo/bar {foo_bar}
     """)
     imports_map = imports_map_loader.build_imports_map(imports_info)
     # When both foo.py and a foo/ package exist, the latter shadows the
     # former, so `import foo` gets you the (empty) foo/__init__.py.
     self.CheckWithErrors("""
       import foo
       x = foo.x  # module-attr
     """, imports_map=imports_map)
Пример #13
0
 def testImportMap(self):
   with utils.Tempdir() as d:
     foo_filename = d.create_file("foo.pyi", """
         bar = ...  # type: int
     """)
     imports_map_filename = d.create_file("imports_map.txt", """
         foo %s
     """ % foo_filename)
     imports_map = imports_map_loader.build_imports_map(
         imports_map_filename)
     ty = self.Infer("""\
       from foo import bar
     """, deep=False, solve_unknowns=False, imports_map=imports_map,
                     pythonpath=[""])
     self.assertTypesMatchPytd(ty, """
       bar = ...  # type: int
     """)
Пример #14
0
 def testImportMap(self):
   with utils.Tempdir() as d:
     foo_filename = d.create_file("foo.pyi", """
         bar = ...  # type: int
     """)
     imports_map_filename = d.create_file("imports_map.txt", """
         foo %s
     """ % foo_filename)
     imports_map = imports_map_loader.build_imports_map(
         imports_map_filename)
     with self.Infer("""\
       from foo import bar
     """, deep=False, solve_unknowns=False, imports_map=imports_map,
                     pythonpath=[""]) as ty:
       self.assertTypesMatchPytd(ty, """
         bar = ...  # type: int
       """)
Пример #15
0
 def test_invalid_map_entry(self):
     with file_utils.Tempdir() as d:
         imports_info = "%s %s\n" % ("a/b/c.pyi", d["a/b/c.pyi"])
         d.create_file("imports_info", imports_info)
         with self.assertRaises(ValueError):
             imports_map_loader.build_imports_map(d["imports_info"])