Exemple #1
0
 def init_subclass(self, node, cls):
   # Subclasses of Module call self.setup() when creating instances.
   cls.additional_init_methods.append("setup")
   dc = ModuleDataclass.make(self.vm)
   cls_var = cls.to_variable(node)
   args = function.Args(posargs=(cls_var,), namedargs=abstract.Dict(self.vm))
   node, _ = dc.call(node, None, args)
   return node
Exemple #2
0
 def call(self, node, _, args):
   self.match_args(node, args)
   arg = args.posargs[0]
   node, fn = self.get_underlying_method(node, arg, "__abs__")
   if fn is not None:
     return self.vm.call_function(node, fn, function.Args(()))
   else:
     return node, self.vm.new_unsolvable(node)
Exemple #3
0
 def test_call_with_duplicate_keyword(self):
   f = self._simple_sig([self._vm.convert.int_type]*2)
   args = function.Args(
       posargs=(self._vm.convert.build_int(self._vm.root_node),
                self._vm.convert.build_int(self._vm.root_node)),
       namedargs={"_1": self._vm.convert.build_int(self._vm.root_node)})
   self.assertRaises(function.DuplicateKeyword, f.call, self._vm.root_node, f,
                     args)
Exemple #4
0
 def test_call_wrong_argcount(self):
   self._vm.push_frame(frame_state.SimpleFrame())
   node, result = self._is_instance.call(
       self._node, None, function.Args((), self.new_dict(), None, None))
   self.assertEqual(self._node, node)
   self.assertIsInstance(abstract_utils.get_atomic_value(result),
                         abstract.Unsolvable)
   self.assertRegexpMatches(str(self._vm.errorlog), "missing-parameter")
Exemple #5
0
 def test_simple_call(self):
   f = self._simple_sig([self._vm.convert.str_type],
                        ret_type=self._vm.convert.int_type)
   args = function.Args(
       (self._vm.convert.build_string(self._vm.root_cfg_node, "hello"),))
   node, ret = f.call(self._vm.root_cfg_node, f, args)
   self.assertIs(node, self._vm.root_cfg_node)
   ret_val, = ret.data
   self.assertEqual(ret_val.cls, self._vm.convert.int_type)
Exemple #6
0
 def test_call_empty_type_parameter_instance(self):
   instance = abstract.Instance(self._vm.convert.list_type, self._vm)
   t = abstract.TypeParameter(abstract_utils.T, self._vm)
   t_instance = abstract.TypeParameterInstance(t, instance, self._vm)
   node, ret = t_instance.call(self._node, t_instance.to_binding(self._node),
                               function.Args(posargs=()))
   self.assertIs(node, self._node)
   retval, = ret.data
   self.assertIs(retval, self._vm.convert.empty)
Exemple #7
0
 def call(self, node, _, args):
   self.match_args(node, args)
   arg, default = self._get_args(args)
   node, fn = self.get_underlying_method(node, arg, self.vm.convert.next_attr)
   if fn is not None:
     node, ret = self.vm.call_function(node, fn, function.Args(()))
     ret.PasteVariable(default)
     return node, ret
   else:
     return node, self.vm.new_unsolvable(node)
Exemple #8
0
 def test_call_with_bad_varargs(self):
   f = self._make_func(
       varargs_name="arg",
       annotations={"arg": self._vm.convert.str_type})
   starargs = abstract.Tuple(
       (self._vm.convert.build_string(self._vm.root_node, ""),
        self._vm.convert.build_int(self._vm.root_node)),
       self._vm).to_variable(self._vm.root_node)
   args = function.Args(posargs=(), starargs=starargs)
   self.assertRaises(function.WrongArgTypes, f.call, self._vm.root_node, f,
                     args)
Exemple #9
0
 def test_call_wrong_keywords(self):
   self._vm.push_frame(frame_state.SimpleFrame())
   x = self.new_var(abstract.Unknown(self._vm))
   node, result = self._is_instance.call(
       self._node, None, function.Args(
           (x, x), self.new_dict(foo=x), None, None))
   self.assertEqual(self._node, node)
   self.assertIsInstance(abstract_utils.get_atomic_value(result),
                         abstract.Unsolvable)
   six.assertRegex(self, str(self._vm.errorlog),
                   r"foo.*isinstance.*\[wrong-keyword-args\]")
Exemple #10
0
  def make_class(self, node, f_locals):
    # If BuildClass.call() hits max depth, f_locals will be [unsolvable]
    # Since we don't support defining NamedTuple subclasses in a nested scope
    # anyway, we can just return unsolvable here to prevent a crash, and let the
    # invalid namedtuple error get raised later.
    if f_locals.data[0].isinstance_Unsolvable():
      return node, self.vm.new_unsolvable(node)

    f_locals = abstract_utils.get_atomic_python_constant(f_locals)

    # retrieve __qualname__ to get the name of class
    name = f_locals["__qualname__"]

    # assemble the arguments that are compatible with NamedTupleFuncBuilder.call
    field_list = []
    defaults = []
    cls_locals = classgen.get_class_locals(
        abstract_utils.get_atomic_python_constant(name), allow_methods=True,
        ordering=classgen.Ordering.FIRST_ANNOTATE, vm=self.vm)
    for k, local in cls_locals.items():
      assert local.typ
      if k in f_locals:
        defaults.append(f_locals[k])
      k = self.vm.convert.constant_to_var(k, node=node)
      field_list.append(self.vm.convert.build_tuple(node, (k, local.typ)))
    anno = self.vm.convert.build_list(node, field_list)
    posargs = (name, anno)
    args = function.Args(posargs=posargs)
    node, cls_var = self.namedtuple.call(node, None, args)
    cls_val = abstract_utils.get_atomic_value(cls_var)

    if not isinstance(cls_val, abstract.Unsolvable):
      # set __new__.__defaults__
      defaults = abstract.Tuple(tuple(defaults), self.vm).to_variable(node)
      node, new_attr = self.vm.attribute_handler.get_attribute(
          node, cls_val, "__new__")
      new_attr = abstract_utils.get_atomic_value(new_attr)
      node = self.vm.attribute_handler.set_attribute(
          node, new_attr, "__defaults__", defaults)

      # set the attribute without overriding special namedtuple attributes
      node, fields = self.vm.attribute_handler.get_attribute(
          node, cls_val, "_fields")
      fields = abstract_utils.get_atomic_python_constant(fields, tuple)
      fields = [abstract_utils.get_atomic_python_constant(field, str)
                for field in fields]
      for key in f_locals:
        if key in self._prohibited:
          self.vm.errorlog.not_writable(self.vm.frames, cls_val, key)
        if key not in self._special and  key not in fields:
          node = self.vm.attribute_handler.set_attribute(
              node, cls_val, key, f_locals[key])

    return node, cls_var
Exemple #11
0
 def test_change_defaults(self):
   f = self._make_func(
       param_names=("a", "b", "c"),
       defaults=(self._vm.convert.build_int(self._vm.root_cfg_node),)
   )
   args = function.Args(
       posargs=(self._vm.convert.build_int(self._vm.root_cfg_node),
                self._vm.convert.build_int(self._vm.root_cfg_node))
   )
   f.call(self._vm.root_cfg_node, f, args)
   new_defaults = abstract.Tuple(
       (self._vm.convert.build_int(self._vm.root_cfg_node),
        self._vm.convert.build_int(self._vm.root_cfg_node)),
       self._vm).to_variable(self._vm.root_cfg_node)
   f.set_function_defaults(self._vm.root_cfg_node, new_defaults)
   f.call(self._vm.root_cfg_node, f, args)
   args = function.Args(
       posargs=(self._vm.convert.build_int(self._vm.root_cfg_node),)
   )
   f.call(self._vm.root_cfg_node, f, args)
Exemple #12
0
 def test_call_with_multiple_arg_bindings(self):
   f = self._simple_sig([self._vm.convert.str_type])
   arg = self._vm.program.NewVariable()
   arg.AddBinding(self._vm.convert.primitive_class_instances[str], [],
                  self._vm.root_cfg_node)
   arg.AddBinding(self._vm.convert.primitive_class_instances[int], [],
                  self._vm.root_cfg_node)
   args = function.Args((arg,))
   node, ret = f.call(self._vm.root_cfg_node, f, args)
   self.assertIs(node, self._vm.root_cfg_node)
   self.assertIs(ret.data[0], self._vm.convert.none)
Exemple #13
0
 def test_call_type_parameter_instance(self):
   instance = abstract.Instance(self._vm.convert.list_type, self._vm)
   instance.merge_instance_type_parameter(
       self._vm.root_cfg_node, abstract_utils.T,
       self._vm.convert.int_type.to_variable(self._vm.root_cfg_node))
   t = abstract.TypeParameter(abstract_utils.T, self._vm)
   t_instance = abstract.TypeParameterInstance(t, instance, self._vm)
   node, ret = t_instance.call(self._node, t_instance.to_binding(self._node),
                               function.Args(posargs=()))
   self.assertIs(node, self._node)
   retval, = ret.data
   self.assertEqual(retval.cls, self._vm.convert.int_type)
Exemple #14
0
 def _get_attribute_computed(self, node, cls, name, valself, compute_function):
   """Call compute_function (if defined) to compute an attribute."""
   assert isinstance(cls, (mixin.Class, abstract.AMBIGUOUS_OR_EMPTY)), cls
   if (valself and not isinstance(valself.data, abstract.Module) and
       self._computable(name)):
     attr_var = self._lookup_from_mro(node, cls, compute_function, valself,
                                      skip=self.vm.convert.object_type)
     if attr_var and attr_var.bindings:
       name_var = abstract.AbstractOrConcreteValue(
           name, self.vm.convert.str_type, self.vm).to_variable(node)
       return self.vm.call_function(node, attr_var, function.Args((name_var,)))
   return node, None
Exemple #15
0
    def make_class(self, node, f_locals):
        f_locals = abstract_utils.get_atomic_python_constant(f_locals)

        # retrieve __qualname__ to get the name of class
        name = f_locals["__qualname__"]
        # retrieve __annotations__ to get the dict
        # with key-value pair of (variable, type)
        anno = f_locals.get("__annotations__", {})
        if anno:
            anno = abstract_utils.get_atomic_value(anno)

        # assemble the arguments that are compatible with NamedTupleFuncBuilder.call
        field_list = []
        defaults = []
        for k, v in anno.items():
            if k in f_locals:
                defaults.append(f_locals.get(k))
                # TODO(ahxun): check if the value matches the declared type
            k = self.vm.convert.constant_to_var(k, node=node)
            field_list.append(self.vm.convert.build_tuple(node, (k, v)))
        anno = self.vm.convert.build_list(node, field_list)
        posargs = (name, anno)
        args = function.Args(posargs=posargs)
        node, cls_var = self.namedtuple.call(node, None, args)
        cls_val = abstract_utils.get_atomic_value(cls_var)

        if not isinstance(cls_val, abstract.Unsolvable):
            # set __new__.__defaults__
            defaults = abstract.Tuple(tuple(defaults),
                                      self.vm).to_variable(node)
            node, new_attr = self.vm.attribute_handler.get_attribute(
                node, cls_val, "__new__")
            new_attr = abstract_utils.get_atomic_value(new_attr)
            node = self.vm.attribute_handler.set_attribute(
                node, new_attr, "__defaults__", defaults)

            # set the attribute without overriding special namedtuple attributes
            node, fields = self.vm.attribute_handler.get_attribute(
                node, cls_val, "_fields")
            fields = abstract_utils.get_atomic_python_constant(fields, tuple)
            fields = [
                abstract_utils.get_atomic_python_constant(field, str)
                for field in fields
            ]
            for key in f_locals:
                if key in self._prohibited:
                    self.vm.errorlog.not_writable(self.vm.frames, cls_val, key)
                if key not in self._special and key not in fields:
                    node = self.vm.attribute_handler.set_attribute(
                        node, cls_val, key, f_locals[key])

        return node, cls_var
Exemple #16
0
 def test_call_with_kwonly_args(self):
   f = self._make_func(
       param_names=("test",),
       kwonly_params=("a", "b"),
       annotations={
           "test": self._vm.convert.str_type,
           "a": self._vm.convert.str_type,
           "b": self._vm.convert.str_type
       }
   )
   kwargs = abstract.Dict(self._vm)
   kwargs.update(
       self._vm.root_cfg_node,
       {
           "a": self._vm.convert.build_string(self._vm.root_cfg_node, "2"),
           "b": self._vm.convert.build_string(self._vm.root_cfg_node, "3")
       }
   )
   kwargs = kwargs.to_variable(self._vm.root_cfg_node)
   args = function.Args(
       posargs=(self._vm.convert.build_string(self._vm.root_cfg_node, "1"),),
       namedargs=abstract.Dict(self._vm),
       starstarargs=kwargs
   )
   f.call(self._vm.root_cfg_node, f, args)
   kwargs = abstract.Dict(self._vm)
   kwargs.update(
       self._vm.root_cfg_node,
       {"b": self._vm.convert.build_string(self._vm.root_cfg_node, "3")}
   )
   kwargs = kwargs.to_variable(self._vm.root_cfg_node)
   args = function.Args(
       posargs=(self._vm.convert.build_string(self._vm.root_cfg_node, "1"),
                self._vm.convert.build_int(self._vm.root_cfg_node)),
       namedargs=abstract.Dict(self._vm),
       starstarargs=kwargs
   )
   self.assertRaises(function.MissingParameter, f.call,
                     self._vm.root_cfg_node, f, args)
Exemple #17
0
 def test_call_with_multiple_varargs_bindings(self):
   f = self._make_func(
       varargs_name="arg",
       annotations={"arg": self._vm.convert.str_type})
   arg = self._vm.program.NewVariable()
   arg.AddBinding(self._vm.convert.primitive_class_instances[str], [],
                  self._vm.root_cfg_node)
   arg.AddBinding(self._vm.convert.primitive_class_instances[int], [],
                  self._vm.root_cfg_node)
   starargs = abstract.Tuple((arg,), self._vm)
   starargs = starargs.to_variable(self._vm.root_cfg_node)
   args = function.Args(posargs=(), starargs=starargs)
   f.call(self._vm.root_cfg_node, f, args)
Exemple #18
0
 def test_call_with_varargs(self):
   f = self._make_func(
       varargs_name="arg",
       annotations={"arg": self._vm.convert.str_type,
                    "return": self._vm.convert.str_type}
   )
   starargs = abstract.Tuple(
       (self._vm.convert.build_string(self._vm.root_cfg_node, ""),),
       self._vm).to_variable(self._vm.root_cfg_node)
   args = function.Args(posargs=(), starargs=starargs)
   node, ret = f.call(self._vm.root_cfg_node, f, args)
   self.assertIs(node, self._vm.root_cfg_node)
   self.assertIs(ret.data[0].cls, self._vm.convert.str_type)
Exemple #19
0
 def test_call_with_bad_default(self):
   f = self._make_func(
       param_names=("a", "b"),
       defaults=(self._vm.convert.build_string(self._vm.root_node, ""),),
       annotations={
           "a": self._vm.convert.int_type,
           "b": self._vm.convert.str_type
       })
   args = function.Args(
       posargs=(self._vm.convert.build_int(self._vm.root_node),
                self._vm.convert.build_int(self._vm.root_node)))
   self.assertRaises(function.WrongArgTypes, f.call, self._vm.root_node, f,
                     args)
Exemple #20
0
 def test_call_with_defaults(self):
   f = self._make_func(
       param_names=("a", "b", "c"),
       defaults=(self._vm.convert.build_int(self._vm.root_node),),
       annotations={
           "a": self._vm.convert.int_type,
           "b": self._vm.convert.int_type,
           "c": self._vm.convert.int_type
       })
   args = function.Args(
       posargs=(self._vm.convert.build_int(self._vm.root_node),
                self._vm.convert.build_int(self._vm.root_node)))
   f.call(self._vm.root_node, f, args)
   args = function.Args(
       posargs=(self._vm.convert.build_int(self._vm.root_node),
                self._vm.convert.build_int(self._vm.root_node),
                self._vm.convert.build_int(self._vm.root_node)))
   f.call(self._vm.root_node, f, args)
   args = function.Args(
       posargs=(self._vm.convert.build_int(self._vm.root_node),))
   self.assertRaises(function.MissingParameter, f.call, self._vm.root_node, f,
                     args)
Exemple #21
0
 def test_call_type_parameter_instance_with_wrong_args(self):
   instance = abstract.Instance(self._vm.convert.list_type, self._vm)
   instance.merge_instance_type_parameter(
       self._vm.root_cfg_node, abstract_utils.T,
       self._vm.convert.int_type.to_variable(self._vm.root_cfg_node))
   t = abstract.TypeParameter(abstract_utils.T, self._vm)
   t_instance = abstract.TypeParameterInstance(t, instance, self._vm)
   posargs = (self._vm.new_unsolvable(self._node),) * 3
   node, ret = t_instance.call(self._node, t_instance.to_binding(self._node),
                               function.Args(posargs=posargs))
   self.assertIs(node, self._node)
   self.assertTrue(ret.bindings)
   error, = self._vm.errorlog
   self.assertEqual(error.name, "wrong-arg-count")
Exemple #22
0
 def test_call_with_bad_kwargs(self):
   f = self._make_func(
       kwargs_name="kwarg",
       annotations={"kwarg": self._vm.convert.str_type})
   kwargs = abstract.Dict(self._vm)
   kwargs.update(self._vm.root_cfg_node,
                 {"_1": self._vm.convert.build_int(self._vm.root_cfg_node)})
   kwargs = kwargs.to_variable(self._vm.root_cfg_node)
   args = function.Args(
       posargs=(),
       namedargs=abstract.Dict(self._vm),
       starstarargs=kwargs
   )
   self.assertRaises(function.WrongArgTypes, f.call,
                     self._vm.root_cfg_node, f, args)
Exemple #23
0
  def _get_default_var(self, node, args):
    if "default" in args.namedargs and "default_factory" in args.namedargs:
      # The pyi signatures should prevent this; check left in for safety.
      raise function.DuplicateKeyword(self.signatures[0].signature, args,
                                      self.vm, "default")
    elif "default" in args.namedargs:
      default_var = args.namedargs["default"]
    elif "default_factory" in args.namedargs:
      factory_var = args.namedargs["default_factory"]
      factory, = factory_var.data
      f_args = function.Args(posargs=())
      node, default_var = factory.call(node, factory_var.bindings[0], f_args)
    else:
      default_var = None

    return node, default_var
Exemple #24
0
 def test_call_with_kwargs(self):
   f = self._make_func(
       kwargs_name="kwarg",
       annotations={"kwarg": self._vm.convert.str_type})
   kwargs = abstract.Dict(self._vm)
   kwargs.update(
       self._vm.root_node, {
           "_1": self._vm.convert.build_string(self._vm.root_node, "1"),
           "_2": self._vm.convert.build_string(self._vm.root_node, "2")
       })
   kwargs = kwargs.to_variable(self._vm.root_node)
   args = function.Args(
       posargs=(),
       namedargs=abstract.Dict(self._vm),
       starstarargs=kwargs
   )
   f.call(self._vm.root_node, f, args)
Exemple #25
0
 def call(self, node, func, args):
     self.match_args(node, args)
     if len(args.posargs) != 2:
         return super().call(node, func, args)
     pred, seq = args.posargs
     # Special case filter(None, seq). We remove None from seq and then call the
     # regular filter() so we don't need to reimplement eveything.
     if pred.data == [self.vm.convert.none]:
         result = self.vm.program.NewVariable()
         for b in seq.bindings:
             ret = self._filter_none(b.data, node)
             if ret:
                 result.PasteVariable(ret, node, {b})
             else:
                 result.PasteBinding(b)
         args = function.Args((pred, result))
     return super().call(node, func, args)
Exemple #26
0
 def _get_default_var(self, node, args):
   if "default" in args.namedargs and "factory" in args.namedargs:
     # attr.ib(factory=x) is syntactic sugar for attr.ib(default=Factory(x)).
     raise function.DuplicateKeyword(self.signatures[0].signature, args,
                                     self.vm, "default")
   elif "default" in args.namedargs:
     default_var = args.namedargs["default"]
   elif "factory" in args.namedargs:
     mod = self.vm.import_module("attr", "attr", 0)
     node, attr = self.vm.attribute_handler.get_attribute(node, mod, "Factory")
     # We know there is only one value because Factory is in the overlay.
     factory, = attr.data
     factory_args = function.Args(posargs=(args.namedargs["factory"],))
     node, default_var = factory.call(node, attr.bindings[0], factory_args)
   else:
     default_var = None
   return node, default_var
Exemple #27
0
 def call(self, node, _, args):
   posargs = args.posargs
   namedargs = self.vm.convert.value_to_constant(args.namedargs, dict)
   if namedargs and self.vm.python_version < (3, 6):
     errmsg = "Keyword syntax for NamedTuple is only supported in Python 3.6+"
     self.vm.errorlog.invalid_namedtuple_arg(self.vm.frames, err_msg=errmsg)
   if namedargs and len(posargs) == 1:
     namedargs = [abstract.Tuple(
         (self.vm.convert.build_string(node, k), v), self.vm).to_variable(node)
                  for k, v in namedargs.items()]
     namedargs = abstract.List(namedargs, self.vm).to_variable(node)
     posargs += (namedargs,)
     args = function.Args(posargs)
   elif namedargs:
     errmsg = ("Either list of fields or keywords can be provided to "
               "NamedTuple, not both")
     self.vm.errorlog.invalid_namedtuple_arg(self.vm.frames, err_msg=errmsg)
   return self.namedtuple.call(node, None, args)
 def call_metaclass_init(self, node):
   """Call the metaclass's __init__ method if it does anything interesting."""
   if not self.cls:
     return node
   node, init = self.vm.attribute_handler.get_attribute(
       node, self.cls, "__init__")
   if not init or not any(
       f.isinstance_InterpreterFunction() for f in init.data):
     # Only an InterpreterFunction has interesting side effects.
     return node
   # TODO(rechen): The signature is (cls, name, bases, dict); should we fill in
   # the last three args more precisely?
   args = function.Args(posargs=(self.to_variable(node),) + tuple(
       self.vm.new_unsolvable(node) for _ in range(3)))
   log.debug("Calling __init__ on metaclass %s of class %s",
             self.cls.name, self.name)
   node, _ = self.vm.call_function(node, init, args)
   return node
Exemple #29
0
    def create_method_arguments(self, node, method, use_defaults=False):
        """Create arguments for the given method.

    Creates Unknown objects as arguments for the given method. Note that we
    don't need to take parameter annotations into account as
    InterpreterFunction.call() will take care of that.

    Args:
      node: The current node.
      method: An abstract.InterpreterFunction.
      use_defaults: Whether to use parameter defaults for arguments. When True,
        unknown arguments are created with force=False, as it is fine to use
        Unsolvable rather than Unknown objects for type-checking defaults.

    Returns:
      A tuple of a node and a function.Args object.
    """
        args = []
        num_posargs = method.argcount(node)
        num_posargs_no_default = num_posargs - len(method.defaults)
        for i in range(num_posargs):
            default_idx = i - num_posargs_no_default
            if use_defaults and default_idx >= 0:
                arg = method.defaults[default_idx]
            else:
                arg = self.convert.create_new_unknown(node,
                                                      force=not use_defaults)
            args.append(arg)
        kws = {}
        for key in method.signature.kwonly_params:
            if use_defaults and key in method.kw_defaults:
                kws[key] = method.kw_defaults[key]
            else:
                kws[key] = self.convert.create_new_unknown(
                    node, force=not use_defaults)
        starargs = self.create_varargs(node) if method.has_varargs() else None
        starstarargs = self.create_kwargs(
            node) if method.has_kwargs() else None
        return node, function.Args(posargs=tuple(args),
                                   namedargs=kws,
                                   starargs=starargs,
                                   starstarargs=starstarargs)
Exemple #30
0
 def test_call_with_type_parameter(self):
   ret_cls = abstract.ParameterizedClass(
       self._vm.convert.list_type,
       {abstract_utils.T: abstract.TypeParameter(abstract_utils.T, self._vm)},
       self._vm
   )
   f = self._make_func(
       param_names=("test",),
       annotations={
           "test": abstract.TypeParameter(abstract_utils.T, self._vm),
           "return": ret_cls
       }
   )
   args = function.Args(
       posargs=(self._vm.convert.build_int(self._vm.root_cfg_node),))
   _, ret = f.call(self._vm.root_cfg_node, f, args)
   # ret is an Instance(ParameterizedClass(list, {abstract_utils.T: int}))
   # but we really only care about T.
   self.assertIs(ret.data[0].cls.formal_type_parameters[abstract_utils.T],
                 self._vm.convert.int_type)