Exemple #1
0
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
Exemple #2
0
  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))
Exemple #3
0
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))
Exemple #4
0
 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))