How to use the pytype.abstract function in pytype

To help you get started, weā€™ve selected a few pytype examples, based on popular ways it is used in public projects.

Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.

github google / pytype / pytype / convert.py View on Github external
def _create_module(self, ast):
    data = (ast.constants + ast.type_params + ast.classes +
            ast.functions + ast.aliases)
    members = {val.name.rsplit(".")[-1]: val for val in data}
    return abstract.Module(self.vm, ast.name, members, ast)
github google / pytype / pytype / output.py View on Github external
new_template = range(instance.tuple_length)
      if template:
        assert len(template) == 1 and template[0] == abstract_utils.T, template
      else:
        # We have a recursive type. By erasing the instance and value
        # information, we'll return Any for all of the tuple elements.
        v = instance = None
      template = new_template
    if instance is None and isinstance(v, abstract.ParameterizedClass):
      return [self.value_instance_to_pytd_type(
          node, v.get_formal_type_parameter(t), None, seen, view)
              for t in template]
    elif isinstance(instance, abstract.SimpleAbstractValue):
      type_arguments = []
      for t in template:
        if isinstance(instance, abstract.Tuple):
          param_values = self._get_values(node, instance.pyval[t], view)
        elif instance.has_instance_type_parameter(t):
          param_values = self._get_values(
              node, instance.get_instance_type_parameter(t), view)
        elif isinstance(v, abstract.CallableClass):
          param_values = v.get_formal_type_parameter(t).instantiate(
              node or self.vm.root_cfg_node).data
        else:
          param_values = [self.vm.convert.unsolvable]
        if (param_values == [self.vm.convert.unsolvable] and
            isinstance(v, abstract.ParameterizedClass) and
            not self.vm.annotations_util.get_type_parameters(
                v.get_formal_type_parameter(t))):
          # When the instance's parameter value is unsolvable, we can get a
          # more precise type from the class. Note that we need to be careful
          # not to introduce unbound type parameters.
github google / pytype / pytype / matcher.py View on Github external
assert left is other_type.base_cls
        left = other_type
      for type_param in left.template:
        class_param = other_type.get_formal_type_parameter(type_param.name)
        instance_param = instance.get_instance_type_parameter(
            type_param.full_name, node)
        instance_type_param = left.get_formal_type_parameter(type_param.name)
        if (not instance_param.bindings and isinstance(
            instance_type_param, abstract.TypeParameter) and
            instance_type_param.name != type_param.name):
          # This type parameter was renamed!
          instance_param = instance.get_instance_type_parameter(
              type_param.full_name, node)
        if instance_param.bindings and instance_param not in view:
          binding, = instance_param.bindings
          assert isinstance(binding.data, abstract.Unsolvable)
          view = view.copy()
          view[instance_param] = binding
        subst = self.match_var_against_type(instance_param, class_param,
                                            subst, node, view)
        if subst is None:
          return None
    return subst
github google / pytype / pytype / overlay.py View on Github external
"""Base class for module overlays."""
from pytype import abstract
from pytype import datatypes


class Overlay(abstract.Module):
  """A layer between pytype and a module's pytd definition.

  An overlay pretends to be a module, but provides members that generate extra
  typing information that cannot be expressed in a pytd file. For example,
  collections.namedtuple is a factory method that generates class definitions
  at runtime. An overlay is needed for Pytype to generate these classes.

  An Overlay will typically import its underlying module in its __init__, e.g.
  by calling vm.loader.import_name(). Due to this, Overlays should only be used
  when their underlying module is imported by the Python script being analyzed!
  A subclass of Overlay should have an __init__ with the signature:
    def __init__(self, vm)

  Attributes:
    real_module: An abstract.Module wrapping the AST for the underlying module.
  """
github google / pytype / pytype / overlays / typing_overlay.py View on Github external
def _get_value_info(self, inner, ellipses):
    if isinstance(inner[0], list):
      template = (list(moves.range(len(inner[0]))) +
                  [t.name for t in self.base_cls.template])
      combined_args = self.vm.merge_values(inner[0])
      inner = tuple(inner[0]) + (combined_args,) + inner[1:]
      self.vm.errorlog.invalid_ellipses(self.vm.frames, ellipses, self.name)
      return template, inner, abstract.CallableClass
    else:
      # An ellipsis may take the place of the ARGS list.
      return super(Callable, self)._get_value_info(
          inner, ellipses, allowed_ellipses={0})
github google / pytype / pytype / vm.py View on Github external
def _process_base_class(self, node, base):
    """Process a base class for InterpreterClass creation."""
    new_base = self.program.NewVariable()
    for b in base.bindings:
      base_val = b.data
      if isinstance(b.data, abstract.AnnotationContainer):
        base_val = base_val.base_cls
      # A class like `class Foo(List["Foo"])` would lead to infinite recursion
      # when instantiated because we attempt to recursively instantiate its
      # parameters, so we replace any late annotations with Any.
      # TODO(rechen): only replace the current class's name. We should keep
      # other late annotations in order to support things like:
      #   class Foo(List["Bar"]): ...
      #   class Bar: ...
      base_val = self.annotations_util.remove_late_annotations(base_val)
      if isinstance(base_val, abstract.Union):
        # Union[A,B,...] is a valid base class, but we need to flatten it into a
        # single base variable.
        for o in base_val.options:
          new_base.AddBinding(o, {b}, node)
      else:
        new_base.AddBinding(base_val, {b}, node)
github google / pytype / pytype / matcher.py View on Github external
Called after the instance has been successfully matched against a
    formal type to do any remaining matching special to the type.

    Args:
      left: The instance type, which may be different from instance.cls
        depending on where in the mro the match happened.
      instance: The instance.
      other_type: The formal type that was successfully matched against.
      subst: The current type parameter assignment.
      node: The current CFG node.
      view: The current mapping of Variable to Value.
    Returns:
      A new type parameter assignment if the matching succeeded, None otherwise.
    """
    if (isinstance(left, abstract.TupleClass) or
        isinstance(instance, abstract.Tuple) or
        isinstance(other_type, abstract.TupleClass)):
      return self._match_heterogeneous_tuple_instance(
          left, instance, other_type, subst, node, view)
    elif (isinstance(left, abstract.CallableClass) or
          isinstance(other_type, abstract.CallableClass)):
      return self._match_callable_instance(
          left, instance, other_type, subst, node, view)
    return self._match_maybe_parameterized_instance(
        left, instance, other_type, subst, node, view)
github google / pytype / pytype / matcher.py View on Github external
def match_from_mro(self, left, other_type, allow_compat_builtins=True):
    """Checks a type's MRO for a match for a formal type.

    Args:
      left: The type.
      other_type: The formal type.
      allow_compat_builtins: Whether to allow compatible builtins to match -
        e.g., int against float.

    Returns:
      The match, if any, None otherwise.
    """
    for base in left.mro:
      if isinstance(base, abstract.ParameterizedClass):
        base_cls = base.base_cls
      else:
        base_cls = base
      if isinstance(base_cls, mixin.Class):
        if other_type.full_name == base_cls.full_name or (
            isinstance(other_type, abstract.ParameterizedClass) and
            other_type.base_cls is base_cls) or (allow_compat_builtins and (
                (base_cls.full_name,
                 other_type.full_name) in _COMPATIBLE_BUILTINS)):
          return base
      elif isinstance(base_cls, abstract.AMBIGUOUS):
        # Note that this is a different logic than in pytd/type_match.py, which
        # assumes that ambiguous base classes never match, to keep the list of
        # types from exploding. Here, however, we want an instance of, say,
        # "class Foo(Any)" to match against everything.
        return base_cls
github google / pytype / pytype / vm.py View on Github external
allow_noreturn: Whether typing.NoReturn is allowed in the return type.
    Returns:
      A tuple (CFGNode, Variable). The Variable is the return value.
    Raises:
      DictKeyMissing: if we retrieved a nonexistent key from a dict and
        fallback_to_unsolvable is False.
      FailedFunctionCall: if the call fails and fallback_to_unsolvable is False.
    """
    assert funcu.bindings
    result = self.program.NewVariable()
    nodes = []
    error = None
    has_noreturn = False
    for funcv in funcu.bindings:
      func = funcv.data
      assert isinstance(func, abstract.AtomicAbstractValue), type(func)
      one_result = None
      try:
        new_node, one_result = func.call(node, funcv, args)
      except (function.DictKeyMissing, function.FailedFunctionCall) as e:
        if e > error:
          error = e
      else:
        if self.convert.no_return in one_result.data:
          if allow_noreturn:
            # Make sure NoReturn was the only thing returned.
            assert len(one_result.data) == 1
            has_noreturn = True
          else:
            for b in one_result.bindings:
              if b.data != self.convert.no_return:
                result.PasteBinding(b)
github google / pytype / pytype / matcher.py View on Github external
# For the latter case, it will be used in byte code `STORE_ANNOTATION`
      # to store the `NoReturn` annotation in a dict.
      return subst if left == other_type else None
    elif isinstance(other_type, mixin.Class):
      # Accumulate substitutions in "subst", or break in case of error:
      return self._match_type_against_type(left, other_type, subst, node, view)
    elif isinstance(other_type, abstract.Union):
      matched = False
      for t in other_type.options:
        new_subst = self._match_value_against_type(value, t, subst, node, view)
        if new_subst is not None:
          matched = True
          subst = new_subst
      return subst if matched else None
    elif (isinstance(other_type, (abstract.Unknown, abstract.Unsolvable)) or
          isinstance(left, (abstract.Unknown, abstract.Unsolvable))):
      # We can match anything against unknown types, and unknown types against
      # anything.
      # TODO(kramm): Do we want to record what we matched them against?
      assert not isinstance(other_type, abstract.ParameterizedClass)
      return subst
    elif isinstance(other_type, abstract.Empty):
      return self._match_type_against_type(left, other_type, subst, node, view)
    else:
      log.error("Invalid type: %s", type(other_type))
      return None