コード例 #1
0
ファイル: analyze.py プロジェクト: yangjianxiang/pytype
    def create_method_arguments(self, node, method):
        """Create arguments for the given method.

    Args:
      node: The current node.
      method: An abstract.InterpreterFunction.

    Returns:
      A tuple of a node and an abstract.FunctionArgs object.
    """
        args = []
        for i in range(method.argcount(node)):
            node, arg = self.create_argument(node, method.signature,
                                             method.signature.param_names[i])
            args.append(arg)
        kws = {}
        for key in method.signature.kwonly_params:
            node, arg = self.create_argument(node, method.signature, key)
            kws[key] = arg
        starargs = self.create_varargs(node) if method.has_varargs() else None
        starstarargs = self.create_kwargs(
            node) if method.has_kwargs() else None
        return node, abstract.FunctionArgs(posargs=tuple(args),
                                           namedargs=kws,
                                           starargs=starargs,
                                           starstarargs=starstarargs)
コード例 #2
0
ファイル: attribute.py プロジェクト: rezeik/pytype
 def _class_getter(self, node, cls, name, valself, valcls, skip=None):
     """Retrieve an attribute by looking at the MRO of this class."""
     attr = self._lookup_from_mro(node, cls, name, valself, valcls, skip)
     if not attr.bindings:
         return node, None
     if isinstance(cls, abstract.InterpreterClass):
         result = self.vm.program.NewVariable()
         nodes = []
         # Deal with descriptors as a potential additional level of indirection.
         for v in attr.bindings:
             value = v.data
             node2, getter = self.get_attribute(node, value, "__get__", v)
             if getter is not None:
                 posargs = []
                 if valself:
                     posargs.append(valself.AssignToNewVariable())
                 if valcls:
                     if not valself:
                         posargs.append(
                             self.vm.convert.none.to_variable(node))
                     posargs.append(valcls.AssignToNewVariable())
                 node2, get_result = self.vm.call_function(
                     node2, getter, abstract.FunctionArgs(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.vm.join_cfg_nodes(nodes), result
     return node, attr
コード例 #3
0
    def create_method_arguments(self, node, method):
        """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.

    Returns:
      A tuple of a node and an abstract.FunctionArgs object.
    """
        args = [
            self.convert.create_new_unknown(node, force=True)
            for _ in range(method.argcount(node))
        ]
        kws = {
            key: self.convert.create_new_unknown(node, force=True)
            for key in method.signature.kwonly_params
        }
        starargs = self.create_varargs(node) if method.has_varargs() else None
        starstarargs = self.create_kwargs(
            node) if method.has_kwargs() else None
        return node, abstract.FunctionArgs(posargs=tuple(args),
                                           namedargs=kws,
                                           starargs=starargs,
                                           starstarargs=starstarargs)
コード例 #4
0
ファイル: abstract_test.py プロジェクト: ashu-22/pytype
    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,
            abstract.FunctionArgs((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)
コード例 #5
0
ファイル: special_builtins.py プロジェクト: wysamuel/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 self.vm.call_function(node, fn, abstract.FunctionArgs(()))
     else:
         return node, self.vm.convert.create_new_unsolvable(node)
コード例 #6
0
ファイル: abstract_test.py プロジェクト: ashu-22/pytype
 def test_call_wrong_argcount(self):
     self._vm.push_frame(frame_state.SimpleFrame())
     node, result = self._is_instance.call(
         self._node, None,
         abstract.FunctionArgs((), self.new_dict(), None, None))
     self.assertEqual(self._node, node)
     self.assertIsInstance(abstract.get_atomic_value(result),
                           abstract.Unsolvable)
     self.assertRegexpMatches(str(self._vm.errorlog), "missing-parameter")
コード例 #7
0
ファイル: abstract_test.py プロジェクト: ashu-22/pytype
 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,
         abstract.FunctionArgs((x, x), self.new_dict(foo=x), None, None))
     self.assertEqual(self._node, node)
     self.assertIsInstance(abstract.get_atomic_value(result),
                           abstract.Unsolvable)
     self.assertRegexpMatches(str(self._vm.errorlog),
                              r"foo.*isinstance.*\[wrong-keyword-args\]")
コード例 #8
0
ファイル: abstract_test.py プロジェクト: gvanrossum/pytype
 def test_call_wrong_argcount(self):
     self._vm.push_frame(FakeFrame())
     node, result = self._is_instance.call(
         self._node, None,
         abstract.FunctionArgs((), self.new_dict(), None, None))
     self.assertEquals(self._node, node)
     self.assertIsInstance(abstract.get_atomic_value(result),
                           abstract.Unsolvable)
     self.assertRegexpMatches(
         str(self._vm.errorlog),
         r"isinstance.*expects 2.*got 0.*\[wrong-arg-count\]")
コード例 #9
0
ファイル: abstract_test.py プロジェクト: yangjianxiang/pytype
 def testCallEmptyTypeParameterInstance(self):
   instance = abstract.Instance(self._vm.convert.list_type, self._vm)
   instance.initialize_type_parameter(
       self._node, abstract.T, self._vm.program.NewVariable())
   t = abstract.TypeParameter(abstract.T, self._vm)
   t_instance = abstract.TypeParameterInstance(t, instance, self._vm)
   node, ret = t_instance.call(self._node, t_instance.to_binding(self._node),
                               abstract.FunctionArgs(posargs=()))
   self.assertIs(node, self._node)
   retval, = ret.data
   self.assertIs(retval, self._vm.convert.empty)
コード例 #10
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, "next")
     if fn is not None:
         node, ret = self.vm.call_function(node, fn,
                                           abstract.FunctionArgs(()))
         ret.PasteVariable(default)
         return node, ret
     else:
         # TODO(kramm): This needs a test case.
         return node, self.vm.convert.create_new_unsolvable(node)
コード例 #11
0
ファイル: abstract_test.py プロジェクト: yangjianxiang/pytype
 def testCallTypeParameterInstance(self):
   instance = abstract.Instance(self._vm.convert.list_type, self._vm)
   instance.initialize_type_parameter(
       self._node, abstract.T,
       self._vm.convert.int_type.to_variable(self._vm.root_cfg_node))
   t = abstract.TypeParameter(abstract.T, self._vm)
   t_instance = abstract.TypeParameterInstance(t, instance, self._vm)
   node, ret = t_instance.call(self._node, t_instance.to_binding(self._node),
                               abstract.FunctionArgs(posargs=()))
   self.assertIs(node, self._node)
   retval, = ret.data
   self.assertListEqual(retval.cls.data, [self._vm.convert.int_type])
コード例 #12
0
ファイル: typing_overlay.py プロジェクト: wysamuel/pytype
    def make_class(self, node, f_locals):
        f_locals = abstract.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.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 = abstract.FunctionArgs(posargs=posargs)
        node, cls_var = self.namedtuple.call(node, None, args)
        cls_val = abstract.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.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.get_atomic_python_constant(fields, tuple)
            fields = [
                abstract.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
コード例 #13
0
 def _get_attribute_computed(self, node, cls, name, valself, compute_function):
   """Call compute_function (if defined) to compute an attribute."""
   assert isinstance(cls, (abstract.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, abstract.FunctionArgs((name_var,)))
   return node, None
コード例 #14
0
ファイル: abstract_test.py プロジェクト: yangjianxiang/pytype
 def testCallTypeParameterInstanceWithWrongArgs(self):
   instance = abstract.Instance(self._vm.convert.list_type, self._vm)
   instance.initialize_type_parameter(
       self._node, abstract.T,
       self._vm.convert.int_type.to_variable(self._vm.root_cfg_node))
   t = abstract.TypeParameter(abstract.T, self._vm)
   t_instance = abstract.TypeParameterInstance(t, instance, self._vm)
   posargs = (self._vm.convert.create_new_unsolvable(self._node),) * 3
   node, ret = t_instance.call(self._node, t_instance.to_binding(self._node),
                               abstract.FunctionArgs(posargs=posargs))
   self.assertIs(node, self._node)
   self.assertTrue(ret.bindings)
   error, = self._vm.errorlog
   self.assertEqual(error.name, "wrong-arg-count")
コード例 #15
0
ファイル: typing_overlay.py プロジェクト: wysamuel/pytype
 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 = abstract.FunctionArgs(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)
コード例 #16
0
ファイル: special_builtins.py プロジェクト: wysamuel/pytype
 def fget_slot(self, node, obj, objtype):
     return self.vm.call_function(node, self.fget,
                                  abstract.FunctionArgs((obj, )))
コード例 #17
0
    def _build_namedtuple(self, name, field_names, field_types, node):
        # Build an InterpreterClass representing the namedtuple.
        if field_types:
            field_types_union = abstract.Union(field_types, self.vm)
        else:
            field_types_union = self.vm.convert.none_type

        members = {
            n: t.instantiate(node)
            for n, t in moves.zip(field_names, field_types)
        }
        # collections.namedtuple has: __dict__, __slots__ and _fields.
        # typing.NamedTuple adds: _field_types, __annotations__ and _field_defaults.
        # __slots__ and _fields are tuples containing the names of the fields.
        slots = tuple(
            self.vm.convert.build_string(node, f) for f in field_names)
        members["__slots__"] = abstract.Tuple(slots, self.vm).to_variable(node)
        members["_fields"] = abstract.Tuple(slots, self.vm).to_variable(node)
        # __dict__ and _field_defaults are both collections.OrderedDicts that map
        # field names (strings) to objects of the field types.
        ordered_dict_cls = self.vm.convert.name_to_value(
            "collections.OrderedDict", ast=self.collections_ast)

        # In Python 2, keys can be `str` or `unicode`; support both.
        # In Python 3, `str_type` and `unicode_type` are the same.
        field_keys_union = abstract.Union(
            [self.vm.convert.str_type, self.vm.convert.unicode_type], self.vm)

        # Normally, we would use abstract.K and abstract.V, but collections.pyi
        # doesn't conform to that standard.
        field_dict_cls = abstract.ParameterizedClass(ordered_dict_cls, {
            "K": field_keys_union,
            "V": field_types_union
        }, self.vm)
        members["__dict__"] = field_dict_cls.instantiate(node)
        members["_field_defaults"] = field_dict_cls.instantiate(node)
        # _field_types and __annotations__ are both collections.OrderedDicts
        # that map field names (strings) to the types of the fields.
        field_types_cls = abstract.ParameterizedClass(
            ordered_dict_cls, {
                "K": field_keys_union,
                "V": self.vm.convert.type_type
            }, self.vm)
        members["_field_types"] = field_types_cls.instantiate(node)
        members["__annotations__"] = field_types_cls.instantiate(node)
        # __new__
        new_annots = {}
        new_lates = {}
        for (n, t) in moves.zip(field_names, field_types):
            # We don't support late annotations yet, but once we do, they'll show up
            # as LateAnnotation objects to be stored in new_lates.
            new_annots[n] = t
        # We set the bound on this TypeParameter later. This gives __new__ the
        # signature: def __new__(cls: Type[_Tname], ...) -> _Tname, i.e. the same
        # signature that visitor.CreateTypeParametersForSignatures would create.
        # This allows subclasses of the NamedTuple to get the correct type from
        # their constructors.
        cls_type_param = abstract.TypeParameter(
            visitors.CreateTypeParametersForSignatures.PREFIX + name,
            self.vm,
            bound=None)
        new_annots["cls"] = abstract.ParameterizedClass(
            self.vm.convert.type_type, {abstract.T: cls_type_param}, self.vm)
        new_annots["return"] = cls_type_param
        members["__new__"] = abstract.SimpleFunction(
            name="__new__",
            param_names=("cls", ) + tuple(field_names),
            varargs_name=None,
            kwonly_params=(),
            kwargs_name=None,
            defaults={},
            annotations=new_annots,
            late_annotations=new_lates,
            vm=self.vm).to_variable(node)
        # __init__
        members["__init__"] = abstract.SimpleFunction(
            name="__init__",
            param_names=("self", ),
            varargs_name="args",
            kwonly_params=(),
            kwargs_name="kwargs",
            defaults={},
            annotations={},
            late_annotations={},
            vm=self.vm).to_variable(node)
        # _make
        # _make is a classmethod, so it needs to be wrapped by
        # specialibuiltins.ClassMethodInstance.
        # Like __new__, it uses the _Tname TypeVar.
        sized_cls = self.vm.convert.name_to_value("typing.Sized")
        iterable_type = abstract.ParameterizedClass(
            self.vm.convert.name_to_value("typing.Iterable"),
            {abstract.T: field_types_union}, self.vm)
        make = abstract.SimpleFunction(
            name="_make",
            param_names=("cls", "iterable", "new", "len"),
            varargs_name=None,
            kwonly_params=(),
            kwargs_name=None,
            defaults={
                "new": self.vm.convert.unsolvable.to_variable(node),
                "len": self.vm.convert.unsolvable.to_variable(node)
            },
            annotations={
                "cls":
                abstract.ParameterizedClass(self.vm.convert.type_type,
                                            {abstract.T: cls_type_param},
                                            self.vm),
                "iterable":
                iterable_type,
                "new":
                self.vm.convert.unsolvable,
                "len":
                abstract.Callable(
                    self.vm.convert.name_to_value("typing.Callable"), {
                        0: sized_cls,
                        abstract.ARGS: sized_cls,
                        abstract.RET: self.vm.convert.int_type
                    }, self.vm),
                "return":
                cls_type_param
            },
            late_annotations={},
            vm=self.vm).to_variable(node)
        make_args = abstract.FunctionArgs(posargs=(make, ))
        _, members["_make"] = self.vm.special_builtins["classmethod"].call(
            node, None, make_args)
        # _replace
        # Like __new__, it uses the _Tname TypeVar. We have to annotate the `self`
        # param to make sure the TypeVar is substituted correctly.
        members["_replace"] = abstract.SimpleFunction(
            name="_replace",
            param_names=("self", ),
            varargs_name=None,
            kwonly_params=(),
            kwargs_name="kwds",
            defaults={},
            annotations={
                "self": cls_type_param,
                "kwds": field_types_union,
                "return": cls_type_param
            },
            late_annotations={},
            vm=self.vm).to_variable(node)
        # __getnewargs__
        getnewargs_tuple_params = dict(
            tuple(enumerate(field_types)) +
            ((abstract.T, field_types_union), ))
        getnewargs_tuple = abstract.TupleClass(self.vm.convert.tuple_type,
                                               getnewargs_tuple_params,
                                               self.vm)
        members["__getnewargs__"] = abstract.SimpleFunction(
            name="__getnewargs__",
            param_names=("self", ),
            varargs_name=None,
            kwonly_params=(),
            kwargs_name=None,
            defaults={},
            annotations={
                "return": getnewargs_tuple
            },
            late_annotations={},
            vm=self.vm).to_variable(node)
        # __getstate__
        members["__getstate__"] = abstract.SimpleFunction(
            name="__getstate__",
            param_names=("self", ),
            varargs_name=None,
            kwonly_params=(),
            kwargs_name=None,
            defaults={},
            annotations={},
            late_annotations={},
            vm=self.vm).to_variable(node)
        # _asdict
        members["_asdict"] = abstract.SimpleFunction(
            name="_asdict",
            param_names=("self", ),
            varargs_name=None,
            kwonly_params=(),
            kwargs_name=None,
            defaults={},
            annotations={
                "return": field_dict_cls
            },
            late_annotations={},
            vm=self.vm).to_variable(node)
        # Finally, make the class.
        abs_membs = abstract.Dict(self.vm)
        abs_membs.update(node, members)
        cls_var = self.vm.make_class(
            node=node,
            name_var=self.vm.convert.build_string(node, name),
            bases=[self.vm.convert.tuple_type.to_variable(node)],
            class_dict_var=abs_membs.to_variable(node),
            cls_var=None)
        # Now that the class has been made, we can complete the TypeParameter used
        # by __new__, _make and _replace.
        cls_type_param.bound = cls_var.data[0]
        return cls_var
コード例 #18
0
ファイル: special_builtins.py プロジェクト: wysamuel/pytype
 def fdelete_slot(self, node, obj):
     return self.vm.call_function(node, self.fdel,
                                  abstract.FunctionArgs((obj, )))
コード例 #19
0
ファイル: abstract_test.py プロジェクト: ashu-22/pytype
 def _call_pytd_function(self, f, args):
     b = f.to_variable(self._vm.root_cfg_node).bindings[0]
     return f.call(self._vm.root_cfg_node, b,
                   abstract.FunctionArgs(posargs=args))
コード例 #20
0
ファイル: special_builtins.py プロジェクト: wysamuel/pytype
 def fset_slot(self, node, obj, value):
     return self.vm.call_function(node, self.fset,
                                  abstract.FunctionArgs((obj, value)))