def InferWithErrors(self, code, deep=True, pythonpath=(), module_name=None, analyze_annotated=True, quick=False, imports_map=None, **kwargs): """Runs inference on code expected to have type errors.""" kwargs.update( self._SetUpErrorHandling(code, pythonpath, analyze_annotated, quick, imports_map)) self.ConfigureOptions(module_name=module_name) unit, builtins_pytd = analyze.infer_types(deep=deep, **kwargs) unit.Visit(visitors.VerifyVisitor()) unit = optimize.Optimize(unit, builtins_pytd, lossy=False, use_abcs=False, max_union=7, remove_mutable=False) errorlog = kwargs["errorlog"] errorlog.assert_errors_match_expected() return pytd_utils.CanonicalOrdering(unit), errorlog
def Infer(self, srccode, pythonpath=(), deep=True, report_errors=True, analyze_annotated=True, pickle=False, module_name=None, **kwargs): """Runs inference on srccode.""" types, builtins_pytd = self._InferAndVerify( _Format(srccode), pythonpath=pythonpath, deep=deep, analyze_annotated=analyze_annotated, module_name=module_name, 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) if pickle: return self._Pickle(types, module_name) else: return types
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 InferWithErrors(self, code, deep=True, pythonpath=(), analyze_annotated=True, quick=False, **kwargs): kwargs.update( self._SetUpErrorHandling(code, pythonpath, analyze_annotated, quick)) unit, builtins_pytd = analyze.infer_types(deep=deep, **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), kwargs["errorlog"]
def InferFromFile(self, filename, pythonpath): with open(filename, "r") as fi: code = fi.read() errorlog = errors.ErrorLog() self.ConfigureOptions( module_name=load_pytd.get_module_name(filename, pythonpath), pythonpath=pythonpath) unit, _ = analyze.infer_types(code, errorlog, self.options, loader=self.loader, filename=filename) unit.Visit(visitors.VerifyVisitor()) return pytd_utils.CanonicalOrdering(unit)
def InferFromFile(self, filename, pythonpath): with open(filename, "r") as fi: code = fi.read() errorlog = test_utils.TestErrorLog(code) if errorlog.expected: self.fail( "Cannot assert errors with InferFromFile(); use InferWithErrors()") self.ConfigureOptions( module_name=load_pytd.get_module_name(filename, pythonpath), pythonpath=pythonpath) unit, _ = analyze.infer_types(code, errorlog, self.options, loader=self.loader, filename=filename) unit.Visit(visitors.VerifyVisitor()) return pytd_utils.CanonicalOrdering(unit)
def InferFromFile(self, filename, pythonpath, python_version=None): with open(filename, "rb") as fi: code = fi.read() errorlog = errors.ErrorLog() self.options.tweak(module_name=load_pytd.get_module_name( filename, pythonpath), pythonpath=pythonpath, python_version=python_version) self._CreateLoader() unit, _ = analyze.infer_types(code, errorlog, self.options, loader=self.loader, filename=filename) unit.Visit(visitors.VerifyVisitor()) return pytd_utils.CanonicalOrdering(unit)
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 parameters 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(module_name=module_name, quick=quick) errorlog = errors.ErrorLog() self.loader = load_pytd.PickledPyiLoader( use_pickled_typeshed=False, base_module=module_name, python_version=self.PYTHON_VERSION, pythonpath=[""] if (not pythonpath and imports_map) else pythonpath, imports_map=imports_map) unit, builtins_pytd = analyze.infer_types(src, errorlog, self.options, loader=self.loader, **kwargs) unit.Visit(visitors.VerifyVisitor()) unit = pytd_utils.CanonicalOrdering(unit) if report_errors and len(errorlog): errorlog.print_to_stderr() self.fail("Inferencer found %d errors" % len(errorlog)) return unit, builtins_pytd
def generate_pyi(input_filename, errorlog, options, loader): """Run the inferencer on one file, producing output. Args: input_filename: name of the file to process errorlog: Where error messages go. Instance of errors.ErrorLog. options: config.Options object. loader: A load_pytd.Loader instance. Returns: A tuple, (PYI Ast as string, TypeDeclUnit). Raises: CompileError: If we couldn't parse the input file. UsageError: If the input filepath is invalid. """ mod, builtins = _call(analyze.infer_types, input_filename, errorlog, options, loader) mod.Visit(visitors.VerifyVisitor()) mod = optimize.Optimize( mod, builtins, # TODO(kramm): Add FLAGs for these lossy=False, use_abcs=False, max_union=7, remove_mutable=False) mod = pytd_utils.CanonicalOrdering(mod, sort_signatures=True) result = pytd.Print(mod) log.info("=========== pyi optimized =============") log.info("\n%s", result) log.info("========================================") if not result.endswith("\n"): result += "\n" result_prefix = "" if options.quick: result_prefix += "# (generated with --quick)\n" if result_prefix: result = result_prefix + "\n" + result return result, mod
def _pytd_print(self, pytd_type): """Print the name of the pytd type.""" name = pytd_utils.Print(pytd_utils.CanonicalOrdering(optimize.Optimize( pytd_type.Visit(visitors.RemoveUnknownClasses())))) # 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 escape.unpack_namedtuple(name) nested_class_match = re.search(r"_(?:\w+)_DOT_", name) if nested_class_match: # Pytype doesn't have true support for nested classes. Instead, for # class Foo: # class Bar: ... # it outputs: # class _Foo_DOT_Bar: ... # class Foo: # Bar = ... # type: Type[_Foo_DOT_Bar] # Replace _Foo_DOT_Bar with Foo.Bar in error messages for readability. # TODO(b/35138984): Get rid of this hack. start = nested_class_match.start() return name[:start] + name[start+1:].replace("_DOT_", ".") return name
def generate_pyi(src, options=None, loader=None): """Run the inferencer on a string of source code, producing output. Args: src: The source code. options: config.Options object. loader: A load_pytd.Loader instance. Returns: A tuple, (errors.ErrorLog, PYI Ast as string, TypeDeclUnit). Raises: CompileError: If we couldn't parse the input file. UsageError: If the input filepath is invalid. """ options = options or config.Options.create() with config.verbosity_from(options): errorlog, (mod, builtins) = _call(analyze.infer_types, src, options, loader) mod.Visit(visitors.VerifyVisitor()) mod = optimize.Optimize( mod, builtins, # TODO(b/159038508): Add FLAGs for these lossy=False, use_abcs=False, max_union=7, remove_mutable=False) mod = pytd_utils.CanonicalOrdering(mod, sort_signatures=True) result = pytd_utils.Print(mod) log.info("=========== pyi optimized =============") log.info("\n%s", result) log.info("========================================") result += "\n" if options.quick: result = "# (generated with --quick)\n\n" + result return errorlog, result, mod