def ParsePyTD(src=None, filename=None, python_version=None, module=None, lookup_classes=False): """Parse pytd sourcecode and do name lookup for builtins. This loads a pytd and also makes sure that all names are resolved (i.e., that all primitive types in the AST are ClassType, and not NameType). Args: src: PyTD source code. filename: The filename the source code is from. python_version: The Python version to parse the pytd for. module: The name of the module we're parsing. lookup_classes: If we should also lookup the class of every ClassType. Returns: A pytd.TypeDeclUnit. """ assert python_version if src is None: with open(filename, "rb") as fi: src = fi.read() ast = parser.parse_string(src, filename=filename, name=module, python_version=python_version) if lookup_classes: ast = visitors.LookupClasses(ast, GetBuiltinsPyTD(python_version)) ast = ast.Replace(is_package=utils.is_pyi_directory_init(filename)) return ast
def parse(self, src, name, filename): """Parse a PYI file and return the corresponding AST. Note that parse() should be called exactly once per _Parser instance. It holds aggregated state during parsing and is not designed to be reused. Args: src: The source text to parse. name: The name of the module to be created. filename: The name of the source file. Returns: A pytd.TypeDeclUnit() representing the parsed pyi. Raises: ParseError: If the PYI source could not be parsed. """ # Ensure instances do not get reused. assert not self._used self._used = True self._filename = filename self._ast_name = name self._type_map = {} try: defs = parser_ext.parse(self, src) ast = self._build_type_decl_unit(defs) except ParseError as e: if self._error_location: line = e.line or self._error_location[0] try: text = src.splitlines()[line-1] except IndexError: text = None raise ParseError(utils.message(e), line=line, filename=self._filename, column=self._error_location[1], text=text) else: raise e ast = ast.Visit(_PropertyToConstant()) ast = ast.Visit(_InsertTypeParameters()) # TODO(kramm): This is in the wrong place- it should happen after resolving # local names, in load_pytd. ast = ast.Visit(pep484.ConvertTypingToNative(name)) if name: ast = ast.Replace(name=name) ast = ast.Visit(visitors.AddNamePrefix()) else: # If there's no unique name, hash the sourcecode. ast = ast.Replace(name=hashlib.md5(src.encode("utf-8")).hexdigest()) ast = ast.Visit(visitors.StripExternalNamePrefix()) # Typeshed files that explicitly import and refer to "builtins" need to have # that rewritten to __builtin__ ast = ast.Visit(visitors.RenameBuiltinsPrefix()) return ast.Replace(is_package=utils.is_pyi_directory_init(filename))
def parse_type_definition(pyi_subdir, module, python_version): """Load and parse a *.pyi from typeshed. Args: pyi_subdir: the directory where the module should be found. module: the module name (without any file extension) python_version: sys.version_info[:2] Returns: The AST of the module; None if the module doesn't have a definition. """ assert python_version typeshed = _get_typeshed() try: filename, src = typeshed.get_module_file( pyi_subdir, module, python_version) except IOError: return None ast = parser.parse_string(src, filename=filename, name=module, python_version=python_version) return ast.Replace(is_package=utils.is_pyi_directory_init(filename))
def _create_empty(self, module_name, filename): ast = self.load_file(module_name, filename, pytd_utils.CreateModule(module_name)) return ast.Replace(is_package=utils.is_pyi_directory_init(filename))