Beispiel #1
0
 def _make_pytd_function(self, params):
     pytd_params = []
     for i, p in enumerate(params):
         p_type = pytd.ClassType(p.name)
         p_type.cls = p
         pytd_params.append(
             pytd.Parameter("_" + str(i), p_type, False, False, None))
     pytd_sig = pytd.Signature(tuple(pytd_params), None, None,
                               pytd.AnythingType(), (), ())
     sig = abstract.PyTDSignature("f", pytd_sig, self._vm)
     return abstract.PyTDFunction("f", (sig, ), pytd.METHOD, self._vm)
Beispiel #2
0
 def test_compatible_with(self):
     pytd_sig = pytd.Signature((), None, None, pytd.AnythingType(), (), ())
     sig = function.PyTDSignature("f", pytd_sig, self._vm)
     f = abstract.PyTDFunction("f", (sig, ), pytd.METHOD, self._vm)
     self.assertTruthy(f)
Beispiel #3
0
  def construct_constant_from_value(self, name, pyval, subst, node):
    """Create a AtomicAbstractValue that represents a python constant.

    This supports both constant from code constant pools and PyTD constants such
    as classes. This also supports builtin python objects such as int and float.

    Args:
      name: The name of this constant. Used for naming its attribute variables.
      pyval: The python or PyTD value to convert.
      subst: The current type parameters.
      node: The current CFG node.
    Returns:
      A Value that represents the constant, or None if we couldn't convert.
    Raises:
      NotImplementedError: If we don't know how to convert a value.
    """
    if pyval is type:
      return abstract.SimpleAbstractValue(name, self.vm)
    elif isinstance(pyval, str):
      return abstract.AbstractOrConcreteValue(
          pyval, self.str_type, self.vm, node)
    elif isinstance(pyval, int) and -1 <= pyval <= MAX_IMPORT_DEPTH:
      # For small integers, preserve the actual value (for things like the
      # level in IMPORT_NAME).
      return abstract.AbstractOrConcreteValue(
          pyval, self.int_type, self.vm, node)
    elif pyval.__class__ in self.primitive_classes:
      return self.primitive_class_instances[pyval.__class__]
    elif isinstance(pyval, (loadmarshal.CodeType, blocks.OrderedCode)):
      return abstract.AbstractOrConcreteValue(
          pyval, self.primitive_classes[types.CodeType], self.vm, node)
    elif pyval.__class__ in [types.FunctionType,
                             types.ModuleType,
                             types.GeneratorType,
                             type]:
      try:
        pyclass = self.vm.vmbuiltins.Lookup("__builtin__." + pyval.__name__)
        return self.convert_constant_to_value(name, pyclass, subst, node)
      except (KeyError, AttributeError):
        log.debug("Failed to find pytd", exc_info=True)
        raise
    elif isinstance(pyval, pytd.TypeDeclUnit):
      data = pyval.constants + pyval.classes + pyval.functions + pyval.aliases
      members = {val.name.rsplit(".")[-1]: val
                 for val in data}
      return abstract.Module(self.vm, node, pyval.name, members)
    elif isinstance(pyval, pytd.Class):
      if "." in pyval.name:
        module, base_name = pyval.name.rsplit(".", 1)
        cls = abstract.PyTDClass(base_name, pyval, self.vm)
        cls.module = module
      else:
        cls = abstract.PyTDClass(name, pyval, self.vm)
      return cls
    elif isinstance(pyval, pytd.Function):
      signatures = [abstract.PyTDSignature(pyval.name, sig, self.vm)
                    for sig in pyval.signatures]
      f = abstract.PyTDFunction(
          pyval.name, signatures, pyval.kind, self.vm, node)
      return f
    elif isinstance(pyval, pytd.ClassType):
      assert pyval.cls
      return self.convert_constant_to_value(pyval.name, pyval.cls, subst, node)
    elif isinstance(pyval, pytd.NothingType):
      return self.nothing
    elif isinstance(pyval, pytd.AnythingType):
      # TODO(kramm): This should be an Unsolveable. We don't need to solve this.
      return self._create_new_unknown_value("AnythingType")
    elif isinstance(pyval, pytd.FunctionType):
      return self.construct_constant_from_value(
          name, pyval.function, subst, node)
    elif isinstance(pyval, pytd.UnionType):
      return abstract.Union([
          self.convert_constant_to_value(pytd.Print(t), t, subst, node)
          for t in pyval.type_list], self.vm)
    elif isinstance(pyval, pytd.TypeParameter):
      return abstract.TypeParameter(pyval.name, self.vm)
    elif isinstance(pyval, abstract.AsInstance):
      cls = pyval.cls
      if isinstance(cls, pytd.ClassType):
        cls = cls.cls
      if isinstance(cls, pytd.Class):
        # This key is also used in __init__
        key = (abstract.Instance, cls)
        if key not in self._convert_cache:
          if cls.name in ["__builtin__.type", "__builtin__.property"]:
            # An instance of "type" or of an anonymous property can be anything.
            instance = self._create_new_unknown_value("type")
          else:
            mycls = self.convert_constant(cls.name, cls, subst, node)
            instance = abstract.Instance(mycls, self.vm, node)
          log.info("New pytd instance for %s: %r", cls.name, instance)
          self._convert_cache[key] = instance
        return self._convert_cache[key]
      elif isinstance(cls, pytd.GenericType):
        assert isinstance(cls.base_type, pytd.ClassType)
        base_cls = cls.base_type.cls
        instance = abstract.Instance(
            self.convert_constant(base_cls.name, base_cls, subst, node),
            self.vm, node)
        for formal, actual in zip(base_cls.template, cls.parameters):
          p = self.convert_constant(
              repr(formal), abstract.AsInstance(actual), subst, node)
          instance.initialize_type_parameter(node, formal.name, p)
        return instance
      else:
        return self.convert_constant_to_value(name, cls, subst, node)
    elif isinstance(pyval, pytd.GenericType):
      assert isinstance(pyval.base_type, pytd.ClassType)
      type_parameters = utils.LazyDict()
      for param, value in zip(pyval.base_type.cls.template, pyval.parameters):
        type_parameters.add_lazy_item(
            param.name, self.convert_constant_to_value,
            param.name, value, subst, node)
      cls = self.convert_constant_to_value(
          pytd.Print(pyval.base_type), pyval.base_type.cls, subst, node)
      return abstract.ParameterizedClass(cls, type_parameters, self.vm)
    elif pyval.__class__ is tuple:  # only match raw tuple, not namedtuple/Node
      return self.tuple_to_value(self.vm.root_cfg_node,
                                 [self.convert_constant("tuple[%d]" % i, item,
                                                        subst, node)
                                  for i, item in enumerate(pyval)])
    else:
      raise NotImplementedError("Can't convert constant %s %r" %
                                (type(pyval), pyval))