コード例 #1
0
 def test_call_with_kwonly_args(self):
   f = self._make_func(
       param_names=("test",),
       kwonly_params=("a", "b"),
       annotations={
           "test": self._ctx.convert.str_type,
           "a": self._ctx.convert.str_type,
           "b": self._ctx.convert.str_type
       })
   kwargs = abstract.Dict(self._ctx)
   kwargs.update(
       self._ctx.root_node, {
           "a": self._ctx.convert.build_string(self._ctx.root_node, "2"),
           "b": self._ctx.convert.build_string(self._ctx.root_node, "3")
       })
   kwargs = kwargs.to_variable(self._ctx.root_node)
   args = function.Args(
       posargs=(self._ctx.convert.build_string(self._ctx.root_node, "1"),),
       namedargs=abstract.Dict(self._ctx),
       starstarargs=kwargs)
   f.call(self._ctx.root_node, f, args)
   kwargs = abstract.Dict(self._ctx)
   kwargs.update(
       self._ctx.root_node,
       {"b": self._ctx.convert.build_string(self._ctx.root_node, "3")})
   kwargs = kwargs.to_variable(self._ctx.root_node)
   args = function.Args(
       posargs=(self._ctx.convert.build_string(self._ctx.root_node, "1"),
                self._ctx.convert.build_int(self._ctx.root_node)),
       namedargs=abstract.Dict(self._ctx),
       starstarargs=kwargs)
   self.assertRaises(function.MissingParameter, f.call, self._ctx.root_node, f,
                     args)
コード例 #2
0
 def test_call_with_all_args(self):
   f = self._make_func(
       param_names=("a", "b", "c"),
       varargs_name="arg",
       kwargs_name="kwarg",
       defaults=(self._ctx.convert.build_int(self._ctx.root_node),),
       annotations={
           "a": self._ctx.convert.str_type,
           "b": self._ctx.convert.int_type,
           "c": self._ctx.convert.int_type,
           "arg": self._ctx.convert.primitive_classes[float],
           "kwarg": self._ctx.convert.primitive_classes[bool]
       })
   posargs = (self._ctx.convert.build_string(self._ctx.root_node, "1"),
              self._ctx.convert.build_int(self._ctx.root_node))
   float_inst = self._ctx.convert.primitive_class_instances[float]
   stararg = self._ctx.convert.build_tuple(
       self._ctx.root_node, (float_inst.to_variable(self._ctx.root_node),))
   namedargs = abstract.Dict(self._ctx)
   kwarg = abstract.Dict(self._ctx)
   kwarg.update(
       self._ctx.root_node, {
           "x": self._ctx.convert.build_bool(self._ctx.root_node),
           "y": self._ctx.convert.build_bool(self._ctx.root_node)
       })
   kwarg = kwarg.to_variable(self._ctx.root_node)
   args = function.Args(posargs, namedargs, stararg, kwarg)
   f.call(self._ctx.root_node, f, args)
コード例 #3
0
  def assert_call(self, expected, left, right):
    """Check that call() returned the desired results.

    Args:
      expected: A dict from values to source sets, where a source set is
          represented by the sorted binding names separated by spaces, for
          example "left:0 right:1" would indicate binding #0 of variable
          "left" and binding #1 of variable "right".
      left: A Variable to use as the first arg to call().
      right: A Variable to use as the second arg to call().
    """
    name_map = {left: "left", right: "right"}
    node, result = self._is_instance.call(
        self._node, None, function.Args(
            (left, right), self.new_dict(), None, None))
    self.assertIn(node, self._node.outgoing)
    result_map = {}
    # Turning source sets into canonical string representations of the binding
    # names makes it much easier to debug failures.
    for b in result.bindings:
      terms = set()
      for o in b.origins:
        self.assertEqual(node, o.where)
        for sources in o.source_sets:
          terms.add(" ".join(sorted(
              "%s:%d" % (name_map[b.variable], b.variable.bindings.index(b))
              for b in sources)))
      result_map[b.data] = terms
    self.assertEqual(expected, result_map)
コード例 #4
0
 def test_call_with_wrong_arg_count(self):
   f = self._simple_sig([self._ctx.convert.int_type])
   args = function.Args(
       posargs=(self._ctx.convert.build_int(self._ctx.root_node),
                self._ctx.convert.build_int(self._ctx.root_node)))
   self.assertRaises(function.WrongArgCount, f.call, self._ctx.root_node, f,
                     args)
コード例 #5
0
 def _lookup_from_mro_and_handle_descriptors(self, node, cls, name, valself,
                                             skip):
     attr = self._lookup_from_mro(node, cls, name, valself, skip)
     if not attr.bindings:
         return node, None
     if isinstance(cls, abstract.InterpreterClass):
         result = self.ctx.program.NewVariable()
         nodes = []
         # Deal with descriptors as a potential additional level of indirection.
         for v in attr.bindings:
             value = v.data
             if (isinstance(value, special_builtins.PropertyInstance)
                     and valself and valself.data == cls):
                 node2, getter = node, None
             else:
                 node2, getter = self.get_attribute(node, value, "__get__",
                                                    v)
             if getter is not None:
                 posargs = []
                 if valself and valself.data != cls:
                     posargs.append(valself.AssignToNewVariable())
                 else:
                     posargs.append(self.ctx.convert.none.to_variable(node))
                 posargs.append(cls.to_variable(node))
                 node2, get_result = function.call_function(
                     self.ctx, node2, getter, function.Args(tuple(posargs)))
                 for getter in get_result.bindings:
                     result.AddBinding(getter.data, [getter], node2)
             else:
                 result.AddBinding(value, [v], node2)
             nodes.append(node2)
         if nodes:
             return self.ctx.join_cfg_nodes(nodes), result
     return node, attr
コード例 #6
0
 def default_slot(self, node, default):
   # If the default is a method, call it and use its return type.
   fn = default.data[0]
   # TODO(mdemello): it is not clear what to use for self in fn_args; using
   # fn.cls.instantiate(node) is fraught because we are in the process of
   # constructing the class. If fn does not use `self` setting self=Any will
   # make no difference; if it does use `self` we might as well fall back to a
   # return type of `Any` rather than raising attribute errors in cases like
   # class A:
   #   x = attr.ib(default=42)
   #   y = attr.ib()
   #   @y.default
   #   def _y(self):
   #     return self.x
   #
   # The correct thing to do would probably be to defer inference if we see a
   # default method, then infer all the method-based defaults after the class
   # is fully constructed. The workaround is simply to use type annotations,
   # which users should ideally be doing anyway.
   self_var = self.ctx.new_unsolvable(node)
   fn_args = function.Args(posargs=(self_var,))
   node, default_var = fn.call(node, default.bindings[0], fn_args)
   self.default = default_var
   # If we don't have a type, set the type from the default type
   if not self.type_source:
     self.typ = get_type_from_default(default_var, self.ctx)
     self.type_source = TypeSource.DEFAULT
   # Return the original decorated method so we don't lose it.
   return node, default
コード例 #7
0
  def make_class(self, node, bases, 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 isinstance(f_locals.data[0], abstract.Unsolvable):
      return node, self.ctx.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__"]
    nameval = abstract_utils.get_atomic_python_constant(name)
    if "." in nameval:
      nameval = nameval.rsplit(".", 1)[-1]
      name = self.ctx.convert.constant_to_var(nameval)

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

    if not isinstance(cls_val, abstract.Unsolvable):
      # set __new__.__defaults__
      defaults = self.ctx.convert.build_tuple(node, defaults)
      node, new_attr = self.ctx.attribute_handler.get_attribute(
          node, cls_val, "__new__")
      new_attr = abstract_utils.get_atomic_value(new_attr)
      node = self.ctx.attribute_handler.set_attribute(node, new_attr,
                                                      "__defaults__", defaults)

      # set the attribute without overriding special namedtuple attributes
      node, fields = self.ctx.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.ctx.errorlog.not_writable(self.ctx.vm.frames, cls_val, key)
        if key not in abstract_utils.CLASS_LEVEL_IGNORE and  key not in fields:
          node = self.ctx.attribute_handler.set_attribute(
              node, cls_val, key, f_locals[key])

    return node, cls_var
コード例 #8
0
 def test_call_with_duplicate_keyword(self):
   f = self._simple_sig([self._ctx.convert.int_type] * 2)
   args = function.Args(
       posargs=(self._ctx.convert.build_int(self._ctx.root_node),
                self._ctx.convert.build_int(self._ctx.root_node)),
       namedargs={"_1": self._ctx.convert.build_int(self._ctx.root_node)})
   self.assertRaises(function.DuplicateKeyword, f.call, self._ctx.root_node, f,
                     args)
コード例 #9
0
 def test_change_defaults(self):
   f = self._make_func(
       param_names=("a", "b", "c"),
       defaults=(self._ctx.convert.build_int(self._ctx.root_node),))
   args = function.Args(
       posargs=(self._ctx.convert.build_int(self._ctx.root_node),
                self._ctx.convert.build_int(self._ctx.root_node)))
   f.call(self._ctx.root_node, f, args)
   new_defaults = self._ctx.convert.build_tuple(
       self._ctx.root_node,
       (self._ctx.convert.build_int(self._ctx.root_node),
        self._ctx.convert.build_int(self._ctx.root_node)))
   f.set_function_defaults(self._ctx.root_node, new_defaults)
   f.call(self._ctx.root_node, f, args)
   args = function.Args(
       posargs=(self._ctx.convert.build_int(self._ctx.root_node),))
   f.call(self._ctx.root_node, f, args)
コード例 #10
0
 def test_call_wrong_argcount(self):
   self._ctx.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.assertRegex(str(self._ctx.errorlog), "missing-parameter")
コード例 #11
0
ファイル: mixin.py プロジェクト: astroparam/pytype
 def call_pytd(self, node, name, *args):
   """Call the (original) pytd version of a method we overwrote."""
   return function.call_function(
       self.ctx,
       node,
       self._super[name],
       function.Args(args),
       fallback_to_unsolvable=False)
コード例 #12
0
 def test_simple_call(self):
   f = self._simple_sig([self._ctx.convert.str_type],
                        ret_type=self._ctx.convert.int_type)
   args = function.Args(
       (self._ctx.convert.build_string(self._ctx.root_node, "hello"),))
   node, ret = f.call(self._ctx.root_node, f, args)
   self.assertIs(node, self._ctx.root_node)
   ret_val, = ret.data
   self.assertEqual(ret_val.cls, self._ctx.convert.int_type)
コード例 #13
0
 def test_call_empty_type_parameter_instance(self):
   instance = abstract.Instance(self._ctx.convert.list_type, self._ctx)
   t = abstract.TypeParameter(abstract_utils.T, self._ctx)
   t_instance = abstract.TypeParameterInstance(t, instance, self._ctx)
   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._ctx.convert.empty)
コード例 #14
0
ファイル: special_builtins.py プロジェクト: astroparam/pytype
 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 function.call_function(self.ctx, node, fn, function.Args(
             ()))
     else:
         return node, self.ctx.new_unsolvable(node)
コード例 #15
0
 def test_call_with_bad_varargs(self):
   f = self._make_func(
       varargs_name="arg", annotations={"arg": self._ctx.convert.str_type})
   starargs = self._ctx.convert.build_tuple(
       self._ctx.root_node,
       (self._ctx.convert.build_string(self._ctx.root_node, ""),
        self._ctx.convert.build_int(self._ctx.root_node)))
   args = function.Args(posargs=(), starargs=starargs)
   self.assertRaises(function.WrongArgTypes, f.call, self._ctx.root_node, f,
                     args)
コード例 #16
0
 def test_call_with_multiple_varargs_bindings(self):
   f = self._make_func(
       varargs_name="arg", annotations={"arg": self._ctx.convert.str_type})
   arg = self._ctx.program.NewVariable()
   arg.AddBinding(self._ctx.convert.primitive_class_instances[str], [],
                  self._ctx.root_node)
   arg.AddBinding(self._ctx.convert.primitive_class_instances[int], [],
                  self._ctx.root_node)
   starargs = self._ctx.convert.build_tuple(self._ctx.root_node, (arg,))
   args = function.Args(posargs=(), starargs=starargs)
   f.call(self._ctx.root_node, f, args)
コード例 #17
0
 def test_call_wrong_keywords(self):
   self._ctx.vm.push_frame(frame_state.SimpleFrame())
   x = self.new_var(abstract.Unknown(self._ctx))
   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)
   self.assertRegex(
       str(self._ctx.errorlog), r"foo.*isinstance.*\[wrong-keyword-args\]")
コード例 #18
0
 def test_call_with_multiple_arg_bindings(self):
   f = self._simple_sig([self._ctx.convert.str_type])
   arg = self._ctx.program.NewVariable()
   arg.AddBinding(self._ctx.convert.primitive_class_instances[str], [],
                  self._ctx.root_node)
   arg.AddBinding(self._ctx.convert.primitive_class_instances[int], [],
                  self._ctx.root_node)
   args = function.Args((arg,))
   node, ret = f.call(self._ctx.root_node, f, args)
   self.assertIs(node, self._ctx.root_node)
   self.assertIs(ret.data[0], self._ctx.convert.none)
コード例 #19
0
 def test_call_with_bad_kwargs(self):
   f = self._make_func(
       kwargs_name="kwarg", annotations={"kwarg": self._ctx.convert.str_type})
   kwargs = abstract.Dict(self._ctx)
   kwargs.update(self._ctx.root_node,
                 {"_1": self._ctx.convert.build_int(self._ctx.root_node)})
   kwargs = kwargs.to_variable(self._ctx.root_node)
   args = function.Args(
       posargs=(), namedargs=abstract.Dict(self._ctx), starstarargs=kwargs)
   self.assertRaises(function.WrongArgTypes, f.call, self._ctx.root_node, f,
                     args)
コード例 #20
0
ファイル: special_builtins.py プロジェクト: astroparam/pytype
 def call(self, node, _, args):
     self.match_args(node, args)
     arg, default = self._get_args(args)
     node, fn = self.get_underlying_method(node, arg, "__next__")
     if fn is not None:
         node, ret = function.call_function(self.ctx, node, fn,
                                            function.Args(()))
         ret.PasteVariable(default)
         return node, ret
     else:
         return node, self.ctx.new_unsolvable(node)
コード例 #21
0
 def test_call_type_parameter_instance(self):
   instance = abstract.Instance(self._ctx.convert.list_type, self._ctx)
   instance.merge_instance_type_parameter(
       self._ctx.root_node, abstract_utils.T,
       self._ctx.convert.int_type.to_variable(self._ctx.root_node))
   t = abstract.TypeParameter(abstract_utils.T, self._ctx)
   t_instance = abstract.TypeParameterInstance(t, instance, self._ctx)
   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._ctx.convert.int_type)
コード例 #22
0
 def test_call_with_bad_default(self):
   f = self._make_func(
       param_names=("a", "b"),
       defaults=(self._ctx.convert.build_string(self._ctx.root_node, ""),),
       annotations={
           "a": self._ctx.convert.int_type,
           "b": self._ctx.convert.str_type
       })
   args = function.Args(
       posargs=(self._ctx.convert.build_int(self._ctx.root_node),
                self._ctx.convert.build_int(self._ctx.root_node)))
   self.assertRaises(function.WrongArgTypes, f.call, self._ctx.root_node, f,
                     args)
コード例 #23
0
 def test_call_with_defaults(self):
   f = self._make_func(
       param_names=("a", "b", "c"),
       defaults=(self._ctx.convert.build_int(self._ctx.root_node),),
       annotations={
           "a": self._ctx.convert.int_type,
           "b": self._ctx.convert.int_type,
           "c": self._ctx.convert.int_type
       })
   args = function.Args(
       posargs=(self._ctx.convert.build_int(self._ctx.root_node),
                self._ctx.convert.build_int(self._ctx.root_node)))
   f.call(self._ctx.root_node, f, args)
   args = function.Args(
       posargs=(self._ctx.convert.build_int(self._ctx.root_node),
                self._ctx.convert.build_int(self._ctx.root_node),
                self._ctx.convert.build_int(self._ctx.root_node)))
   f.call(self._ctx.root_node, f, args)
   args = function.Args(
       posargs=(self._ctx.convert.build_int(self._ctx.root_node),))
   self.assertRaises(function.MissingParameter, f.call, self._ctx.root_node, f,
                     args)
コード例 #24
0
 def test_call_with_kwargs(self):
   f = self._make_func(
       kwargs_name="kwarg", annotations={"kwarg": self._ctx.convert.str_type})
   kwargs = abstract.Dict(self._ctx)
   kwargs.update(
       self._ctx.root_node, {
           "_1": self._ctx.convert.build_string(self._ctx.root_node, "1"),
           "_2": self._ctx.convert.build_string(self._ctx.root_node, "2")
       })
   kwargs = kwargs.to_variable(self._ctx.root_node)
   args = function.Args(
       posargs=(), namedargs=abstract.Dict(self._ctx), starstarargs=kwargs)
   f.call(self._ctx.root_node, f, args)
コード例 #25
0
 def test_call_type_parameter_instance_with_wrong_args(self):
   instance = abstract.Instance(self._ctx.convert.list_type, self._ctx)
   instance.merge_instance_type_parameter(
       self._ctx.root_node, abstract_utils.T,
       self._ctx.convert.int_type.to_variable(self._ctx.root_node))
   t = abstract.TypeParameter(abstract_utils.T, self._ctx)
   t_instance = abstract.TypeParameterInstance(t, instance, self._ctx)
   posargs = (self._ctx.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._ctx.errorlog
   self.assertEqual(error.name, "wrong-arg-count")
コード例 #26
0
 def test_call_with_varargs(self):
   f = self._make_func(
       varargs_name="arg",
       annotations={
           "arg": self._ctx.convert.str_type,
           "return": self._ctx.convert.str_type
       })
   starargs = self._ctx.convert.build_tuple(
       self._ctx.root_node,
       (self._ctx.convert.build_string(self._ctx.root_node, ""),))
   args = function.Args(posargs=(), starargs=starargs)
   node, ret = f.call(self._ctx.root_node, f, args)
   self.assertIs(node, self._ctx.root_node)
   self.assertIs(ret.data[0].cls, self._ctx.convert.str_type)
コード例 #27
0
 def call_slot(self, node, *args, **kwargs):
     """Implementation of CallableClass.__call__."""
     if kwargs:
         raise function.WrongKeywordArgs(
             function.Signature.from_callable(self),
             function.Args(posargs=args, namedargs=kwargs), self.ctx,
             kwargs.keys())
     if len(args) != self.num_args:
         raise function.WrongArgCount(
             function.Signature.from_callable(self),
             function.Args(posargs=args), self.ctx)
     formal_args = [(function.argname(i), self.formal_type_parameters[i])
                    for i in range(self.num_args)]
     substs = [datatypes.AliasingDict()]
     bad_param = None
     for view in abstract_utils.get_views(args, node):
         arg_dict = {
             function.argname(i): view[args[i]]
             for i in range(self.num_args)
         }
         subst, bad_param = self.ctx.matcher(node).compute_subst(
             formal_args, arg_dict, view, None)
         if subst is not None:
             substs = [subst]
             break
     else:
         if bad_param:
             raise function.WrongArgTypes(
                 function.Signature.from_callable(self),
                 function.Args(posargs=args),
                 self.ctx,
                 bad_param=bad_param)
     ret = self.ctx.annotation_utils.sub_one_annotation(
         node, self.formal_type_parameters[abstract_utils.RET], substs)
     node, retvar = self.ctx.vm.init_class(node, ret)
     return node, retvar
コード例 #28
0
 def _call_converter_function(self, node, converter_var, args):
   """Run converter and return the input and return types."""
   binding = converter_var.bindings[0]
   fn = binding.data
   sig = self._get_converter_sig(fn, args)
   if sig.param_names and sig.param_names[0] in sig.annotations:
     input_type = sig.annotations[sig.param_names[0]]
   else:
     input_type = self.ctx.convert.unsolvable
   if sig.has_return_annotation:
     return_type = sig.annotations["return"]
   else:
     fn_args = function.Args(posargs=(input_type.instantiate(node),))
     node, ret_var = fn.call(node, binding, fn_args)
     return_type = self.ctx.convert.merge_classes(ret_var.data)
   return input_type, return_type
コード例 #29
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.ctx, "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
コード例 #30
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.sig, args, self.ctx, "default")
   elif "default" in args.namedargs:
     default_var = args.namedargs["default"]
   elif "factory" in args.namedargs:
     mod = self.ctx.vm.import_module("attr", "attr", 0)
     node, attr = self.ctx.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