Exemplo n.º 1
0
    def __init__(self, name, param_names, posonly_count, varargs_name,
                 kwonly_params, kwargs_name, defaults, annotations, ctx):
        """Create a SimpleFunction.

    Args:
      name: Name of the function as a string
      param_names: Tuple of parameter names as strings. This DOES include
        positional-only parameters and does NOT include keyword-only parameters.
      posonly_count: Number of positional-only parameters.
      varargs_name: The "args" in "*args". String or None.
      kwonly_params: Tuple of keyword-only parameters as strings.
      kwargs_name: The "kwargs" in "**kwargs". String or None.
      defaults: Dictionary of string names to values of default arguments.
      annotations: Dictionary of string names to annotations (strings or types).
      ctx: The abstract context for this function.
    """
        annotations = dict(annotations)
        # Every parameter must have an annotation. Defaults to unsolvable.
        for n in itertools.chain(param_names, [varargs_name, kwargs_name],
                                 kwonly_params):
            if n and n not in annotations:
                annotations[n] = ctx.convert.unsolvable
        if not isinstance(defaults, dict):
            defaults = dict(zip(param_names[-len(defaults):], defaults))
        signature = function.Signature(name, param_names, posonly_count,
                                       varargs_name, kwonly_params,
                                       kwargs_name, defaults, annotations)
        super().__init__(signature, ctx)
        self.bound_class = _function_base.BoundFunction
Exemplo n.º 2
0
 def call(self, node, _, args, alias_map=None):
     sig = None
     if isinstance(self.func.__self__, _classes.CallableClass):
         sig = function.Signature.from_callable(self.func.__self__)
     args = args.simplify(node, self.ctx, match_signature=sig)
     posargs = [u.AssignToNewVariable(node) for u in args.posargs]
     namedargs = {
         k: u.AssignToNewVariable(node)
         for k, u in args.namedargs.items()
     }
     try:
         inspect.signature(self.func).bind(node, *posargs, **namedargs)
     except ValueError as e:
         # Happens for, e.g.,
         #   def f((x, y)): pass
         #   f((42,))
         raise NotImplementedError(
             "Wrong number of values to unpack") from e
     except TypeError as e:
         # The possible errors here are:
         #   (1) wrong arg count
         #   (2) duplicate keyword
         #   (3) unexpected keyword
         # The way we constructed namedargs rules out (2).
         if "keyword" in utils.message(e):
             # Happens for, e.g.,
             #   def f(*args): pass
             #   f(x=42)
             raise NotImplementedError("Unexpected keyword") from e
         # The function was passed the wrong number of arguments. The signature is
         # ([self, ]node, ...). The length of "..." tells us how many variables
         # are expected.
         expected_argcount = len(inspect.getfullargspec(self.func).args) - 1
         if inspect.ismethod(self.func) and self.func.__self__ is not None:
             expected_argcount -= 1
         actual_argcount = len(posargs) + len(namedargs)
         if (actual_argcount > expected_argcount
                 or (not args.starargs and not args.starstarargs)):
             # If we have too many arguments, or starargs and starstarargs are both
             # empty, then we can be certain of a WrongArgCount error.
             argnames = tuple("_" + str(i)
                              for i in range(expected_argcount))
             sig = function.Signature(self.name, argnames, 0, None, set(),
                                      None, {}, {}, {})
             raise function.WrongArgCount(sig, args, self.ctx)
         assert actual_argcount < expected_argcount
         # Assume that starargs or starstarargs fills in the missing arguments.
         # Instead of guessing where these arguments should go, overwrite all of
         # the arguments with a list of unsolvables of the correct length, which
         # is guaranteed to give us a correct (but imprecise) analysis.
         posargs = [
             self.ctx.new_unsolvable(node) for _ in range(expected_argcount)
         ]
         namedargs = {}
     return self.func(node, *posargs, **namedargs)
Exemplo n.º 3
0
 def test_signature_del_nonexistent_annotation(self):
   # def f(): ...
   sig = function.Signature(
       name="f",
       param_names=(),
       posonly_count=0,
       varargs_name=None,
       kwonly_params=(),
       kwargs_name=None,
       defaults={},
       annotations={},
   )
   self.assertRaises(KeyError, sig.del_annotation, "rumpelstiltskin")
Exemplo n.º 4
0
 def test_signature_kwonly_param_count(self):
   # def f(*, y=None): ...
   sig = function.Signature(
       name="f",
       param_names=(),
       posonly_count=0,
       varargs_name=None,
       kwonly_params=("y",),
       kwargs_name=None,
       defaults={"y": self._ctx.convert.none_type.to_variable(self._node)},
       annotations={},
   )
   self.assertEqual(repr(sig), "def f(*, y = None) -> Any")
   self.assertEqual(sig.mandatory_param_count(), 0)
   self.assertEqual(sig.maximum_param_count(), 1)
Exemplo n.º 5
0
 def test_signature_kwargs_param_count(self):
   # def f(**kwargs): ...
   sig = function.Signature(
       name="f",
       param_names=(),
       posonly_count=0,
       varargs_name=None,
       kwonly_params=(),
       kwargs_name="kwargs",
       defaults={},
       annotations={},
   )
   self.assertEqual(repr(sig), "def f(**kwargs) -> Any")
   self.assertEqual(sig.mandatory_param_count(), 0)
   self.assertIsNone(sig.maximum_param_count())
Exemplo n.º 6
0
 def test_signature_has_param(self):
   # def f(x, *args, y, **kwargs): ...
   sig = function.Signature(
       name="f",
       param_names=("x",),
       posonly_count=0,
       varargs_name="args",
       kwonly_params={"y"},
       kwargs_name="kwargs",
       defaults={},
       annotations={},
   )
   self.assertEqual(repr(sig), "def f(x, *args, y, **kwargs) -> Any")
   for param in ("x", "args", "y", "kwargs"):
     self.assertTrue(sig.has_param(param))
   self.assertFalse(sig.has_param("rumpelstiltskin"))
Exemplo n.º 7
0
 def test_signature_del_return_annotation(self):
   # def f(x) -> int: ...
   sig = function.Signature(
       name="f",
       param_names=("x",),
       posonly_count=0,
       varargs_name=None,
       kwonly_params=(),
       kwargs_name=None,
       defaults={},
       annotations={
           "x": self._ctx.convert.unsolvable,
           "return": self._ctx.convert.unsolvable
       },
   )
   sig.del_annotation("return")
   self.assertCountEqual(sig.annotations.keys(), {"x"})
   self.assertTrue(sig.has_param_annotations)
   self.assertFalse(sig.has_return_annotation)
Exemplo n.º 8
0
 def test_signature_annotations_existence(self):
   # def f(v: "X") -> "Y"
   sig = function.Signature(
       name="f",
       param_names=("v",),
       posonly_count=0,
       varargs_name=None,
       kwonly_params=(),
       kwargs_name=None,
       defaults={},
       annotations={},
   )
   self.assertFalse(sig.has_param_annotations)
   self.assertFalse(sig.has_return_annotation)
   sig.set_annotation("v", self._ctx.convert.unsolvable)
   self.assertTrue(sig.has_param_annotations)
   self.assertFalse(sig.has_return_annotation)
   sig.set_annotation("return", self._ctx.convert.unsolvable)
   self.assertTrue(sig.has_param_annotations)
   self.assertTrue(sig.has_return_annotation)
Exemplo n.º 9
0
 def _build_signature(self, name, annotations):
     """Build a function.Signature object representing this function."""
     vararg_name = None
     kwarg_name = None
     kwonly = set(
         self.code.co_varnames[self.code.co_argcount:self.nonstararg_count])
     arg_pos = self.nonstararg_count
     if self.has_varargs():
         vararg_name = self.code.co_varnames[arg_pos]
         arg_pos += 1
     if self.has_kwargs():
         kwarg_name = self.code.co_varnames[arg_pos]
         arg_pos += 1
     defaults = dict(
         zip(self.get_positional_names()[-len(self.defaults):],
             self.defaults))
     defaults.update(self.kw_defaults)
     return function.Signature(
         name, tuple(self.code.co_varnames[:self.code.co_argcount]),
         self.posonlyarg_count, vararg_name, tuple(kwonly), kwarg_name,
         defaults, annotations)
Exemplo n.º 10
0
 def test_signature_insert_varargs_and_kwargs(self):
   # def f(x, *args, y, **kwargs): ...
   sig = function.Signature(
       name="f",
       param_names=("x",),
       posonly_count=0,
       varargs_name="args",
       kwonly_params={"y"},
       kwargs_name="kwargs",
       defaults={},
       annotations={},
   )
   # f(1, 2, y=3, z=4)
   int_inst = self._ctx.convert.primitive_class_instances[int]
   int_binding = int_inst.to_binding(self._node)
   arg_dict = {
       "x": int_binding, "_1": int_binding, "y": int_binding, "z": int_binding}
   sig = sig.insert_varargs_and_kwargs(arg_dict)
   self.assertEqual(sig.name, "f")
   self.assertSequenceEqual(sig.param_names, ("x", "_1", "z"))
   self.assertEqual(sig.varargs_name, "args")
   self.assertSetEqual(sig.kwonly_params, {"y"})
   self.assertEqual(sig.kwargs_name, "kwargs")
   self.assertFalse(sig.annotations)