def InferAndCheck(self, code): errorlog = errors.ErrorLog() unit = infer.infer_types( textwrap.dedent(code), self.PYTHON_VERSION, errorlog, deep=True, reverse_operators=True, cache_unknowns=True) unit.Visit(visitors.VerifyVisitor()) return pytd_utils.CanonicalOrdering(unit), errorlog
def _InferAndVerify(self, src, pythonpath=(), module_name=None, imports_map=None, report_errors=False, quick=False, **kwargs): """Infer types for the source code treating it as a module. Used by Infer(). Args: src: The source code of a module. Treat it as "__main__". pythonpath: --pythonpath as list/tuple of string module_name: Name of the module we're analyzing. E.g. "foo.bar.mymodule". imports_map: --imports_info data report_errors: Whether to fail if the type inferencer reports any errors in the program. quick: Try to run faster, by avoiding costly computations. **kwargs: Keyword paramters to pass through to the type inferencer. Raises: AssertionError: If report_errors is True and we found errors. Returns: A pytd.TypeDeclUnit """ self.options.tweak(pythonpath=pythonpath, module_name=module_name, imports_map=imports_map, quick=quick) errorlog = self._InitErrorLog(src) unit = infer.infer_types(src, errorlog, self.options, **kwargs) unit = pytd_utils.CanonicalOrdering(unit.Visit(visitors.VerifyVisitor())) if report_errors and errorlog.has_error(): errorlog.print_to_stderr() self.fail("Inferencer found %d errors" % len(errorlog)) return unit
def Infer(self, srccode, pythonpath=(), deep=False, solve_unknowns=False, report_errors=True, analyze_annotated=True, **kwargs): types, builtins_pytd = self._InferAndVerify( textwrap.dedent(srccode), pythonpath=pythonpath, deep=deep, cache_unknowns=True, analyze_annotated=analyze_annotated, solve_unknowns=solve_unknowns, report_errors=report_errors, **kwargs) types = optimize.Optimize(types, builtins_pytd, lossy=False, use_abcs=False, max_union=7, remove_mutable=False) types = pytd_utils.CanonicalOrdering(types) return types
def InferAndCheck(self, code, deep=True, pythonpath=(), **kwargs): self.options.tweak(pythonpath=pythonpath) code = textwrap.dedent(code) errorlog = self._InitErrorLog(code) unit = infer.infer_types( code, errorlog, self.options, deep=deep, cache_unknowns=True, **kwargs) unit.Visit(visitors.VerifyVisitor()) return pytd_utils.CanonicalOrdering(unit), errorlog
def _pytd_print(self, pytd_type): name = pytd.Print( pytd_utils.CanonicalOrdering(optimize.Optimize(pytd_type))) # Clean up autogenerated namedtuple names, e.g. "namedtuple-X-a-_0-c" # becomes just "X", by extracting out just the type name. if "namedtuple-" in name: return re.sub(r"\bnamedtuple-([^-]+)-[-_\w]*", r"\1", name) return name
def InferFromFile(self, filename, pythonpath): self.options.tweak(pythonpath=pythonpath) with open(filename, "rb") as fi: code = fi.read() errorlog = self._InitErrorLog(code, filename) unit = infer.infer_types(code, errorlog, self.options, filename=filename, cache_unknowns=True) unit.Visit(visitors.VerifyVisitor()) return pytd_utils.CanonicalOrdering(unit)
def InferFromFile(self, filename, pythonpath, find_pytd_import_ext=".pytd"): errorlog = errors.ErrorLog() with open(filename, "rb") as fi: unit = infer.infer_types(fi.read(), self.PYTHON_VERSION, errorlog, filename=filename, cache_unknowns=True, pythonpath=pythonpath, find_pytd_import_ext=find_pytd_import_ext) unit.Visit(visitors.VerifyVisitor()) return pytd_utils.CanonicalOrdering(unit)
def __init__(self, test, srccode, deep=False, solve_unknowns=False, extract_locals=False, extra_verbose=False, report_errors=True, **kwargs): """Constructor for Infer. Args: test: the Testcase (see inferenceTest.Infer) srccode: the Python source code to do type inferencing on deep: see class comments (assume --api - analyize all methods, even those that don't have a caller) solve_unknowns: try to solve for all ~unknown types extract_locals: strip ~unknown types from the output pytd extra_verbose: extra intermeidate output (for debugging) report_errors: Whether to fail if the type inferencer reports any erros. **kwargs: Additional options to pass through to infer_types(). """ # TODO(pludemann): There are eight possible combinations of these three # boolean flags. Do all of these combinations make sense? Or would it be # possible to simplify this into something like a "mode" parameter: # mode="solve" => deep=True, solve_unknowns=True # mode="structural" => deep=True, solve_unknowns=False, extract_locals=False # mode="deep" => deep=True, solve_unknowns=False, extract_locals=True # mode="main" => deep=False, solve_unknowns=False, extract_locals=True self.srccode = textwrap.dedent(srccode) self.inferred = None self.optimized_types = None self.extract_locals = None # gets set if extract_locals is set (below) self.extra_verbose = extra_verbose self.canonical_types = None # We need to catch any exceptions here and preserve them for __exit__. # Exceptions raised in the body of 'with' will be presented to __exit__. try: self.types = test._InferAndVerify( self.srccode, deep=deep, cache_unknowns=True, solve_unknowns=solve_unknowns, report_errors=report_errors, **kwargs) self.inferred = self.types if extract_locals: # Rename "~unknown" to "?" self.types = self.types.Visit(visitors.RemoveUnknownClasses()) # Remove "~list" etc.: self.types = convert_structural.extract_local(self.types) self.extract_locals = self.types # TODO(pludemann): These flags are the same as those in main.py; there # should be a way of ensuring that they're the same. self.types = self.optimized_types = optimize.Optimize( self.types, lossy=False, use_abcs=False, max_union=7, remove_mutable=False) self.types = self.canonical_types = pytd_utils.CanonicalOrdering( self.types) except Exception: # pylint: disable=broad-except self.types = None if not self.__exit__(*sys.exc_info()): raise
def InferFromFile(self, filename, pythonpath): self.options.tweak(pythonpath=pythonpath) with open(filename, "rb") as fi: code = fi.read() errorlog = errors.ErrorLog() loader = load_pytd.Loader( infer.get_module_name(filename, self.options), self.options) unit, _ = infer.infer_types(code, errorlog, self.options, loader=loader, filename=filename, cache_unknowns=True) unit.Visit(visitors.VerifyVisitor()) return pytd_utils.CanonicalOrdering(unit)
def assertNoErrors(self, code, raises=None, pythonpath=(), report_errors=True): """Run an inference smoke test for the given code.""" if raises is not None: # TODO(kramm): support this log.warning("Ignoring 'raises' parameter to assertNoErrors") self.options.tweak(pythonpath=pythonpath) errorlog = self._InitErrorLog(code) unit = infer.infer_types( textwrap.dedent(code), errorlog, self.options, deep=True, solve_unknowns=True, cache_unknowns=True) if report_errors and errorlog.has_error(): errorlog.print_to_stderr() self.fail("Inferencer found %d errors" % len(errorlog)) unit.Visit(visitors.VerifyVisitor()) return pytd_utils.CanonicalOrdering(unit)
def assertNoErrors(self, code, raises=None, pythonpath=(), find_pytd_import_ext=".pytd", report_errors=True): """Run an inference smoke test for the given code.""" if raises is not None: # TODO(kramm): support this log.warning("Ignoring 'raises' parameter to assertNoErrors") errorlog = errors.ErrorLog() unit = infer.infer_types( textwrap.dedent(code), self.PYTHON_VERSION, errorlog, deep=False, solve_unknowns=False, reverse_operators=True, pythonpath=pythonpath, find_pytd_import_ext=find_pytd_import_ext, cache_unknowns=True) if report_errors and errorlog.errors: errorlog.print_to_stderr() self.fail("Inferencer found %d errors" % len(errorlog)) unit.Visit(visitors.VerifyVisitor()) return pytd_utils.CanonicalOrdering(unit)
def InferAndCheck(self, code, deep=True, pythonpath=(), **kwargs): self.options.tweak(pythonpath=pythonpath) code = textwrap.dedent(code) errorlog = errors.ErrorLog() unit, builtins_pytd = infer.infer_types(code, errorlog, self.options, deep=deep, analyze_annotated=True, cache_unknowns=True, **kwargs) unit.Visit(visitors.VerifyVisitor()) unit = optimize.Optimize(unit, builtins_pytd, lossy=False, use_abcs=False, max_union=7, remove_mutable=False) return pytd_utils.CanonicalOrdering(unit), errorlog
def _InferAndVerify(self, src, report_errors=False, **kwargs): """Infer types for the source code treating it as a module. Used by class Infer (which sets up a 'with' framework) Args: src: The source code of a module. Treat it as "__main__". report_errors: Whether to fail if the type inferencer reports any errors in the program. **kwargs: Keyword paramters to pass through to the type inferencer. Raises: AssertionError: If report_errors is True and we found errors. Returns: A pytd.TypeDeclUnit """ errorlog = errors.ErrorLog() unit = infer.infer_types(src, self.PYTHON_VERSION, errorlog, **kwargs) unit = pytd_utils.CanonicalOrdering(unit.Visit(visitors.VerifyVisitor())) if report_errors and errorlog: errorlog.print_to_stderr() self.fail("Inferencer found %d errors" % len(errorlog)) return unit
def _pytd_print(self, pytd_type): return pytd.Print(pytd_utils.CanonicalOrdering(pytd_type))