예제 #1
0
  def test_get_signature(self):
    # Basic coverage only to make sure function works in Py2 and Py3.
    def fn(a, b=1, *c, **d):
      return a, b, c, d

    s = decorators.get_signature(fn)
    self.assertListEqual(list(s.parameters), ['a', 'b', 'c', 'd'])
예제 #2
0
 def test_get_signature_builtin(self):
   # Tests a builtin function for 3.7+ and fallback result for older versions.
   s = decorators.get_signature(list)
   if sys.version_info < (3, 7):
     self.assertListEqual(
         list(s.parameters),
         ['_', '__unknown__varargs', '__unknown__keywords'])
   else:
     self.assertListEqual(list(s.parameters), ['iterable'])
   self.assertEqual(s.return_annotation, List[Any])
예제 #3
0
def fn_takes_side_inputs(fn):
  try:
    signature = get_signature(fn)
  except TypeError:
    # We can't tell; maybe it does.
    return True

  return (
      len(signature.parameters) > 1 or any(
          p.kind == p.VAR_POSITIONAL or p.kind == p.VAR_KEYWORD
          for p in signature.parameters.values()))
예제 #4
0
 def _run_repeat_test_bad(self, repeat):
     # Various mismatches.
     with self.assertRaises(typehints.TypeCheckError):
         ['a', 'bb', 'c'] | beam.Map(repeat, 'z')
     with self.assertRaises(typehints.TypeCheckError):
         ['a', 'bb', 'c'] | beam.Map(repeat, times='z')
     with self.assertRaises(typehints.TypeCheckError):
         ['a', 'bb', 'c'] | beam.Map(repeat, 3, 4)
     if all(param.default == param.empty
            for param in get_signature(repeat).parameters.values()):
         with self.assertRaisesRegex(typehints.TypeCheckError,
                                     r'(takes exactly|missing a required)'):
             ['a', 'bb', 'c'] | beam.Map(repeat)
예제 #5
0
 def wrapper(*args, **kwargs):
   hints = get_type_hints(f)
   if hints.input_types:  # pylint: disable=too-many-nested-blocks
     input_hints = getcallargs_forhints(
         f, *hints.input_types[0], **hints.input_types[1])
     inputs = get_signature(f).bind(*args, **kwargs).arguments
     for var, hint in input_hints.items():
       value = inputs[var]
       new_value = check_or_interleave(hint, value, var)
       if new_value is not value:
         if var in kwargs:
           kwargs[var] = new_value
         else:
           args = list(args)
           for ix, pvar in enumerate(get_signature(f).parameters):
             if pvar == var:
               args[ix] = new_value
               break
           else:
             raise NotImplementedError('Iterable in nested argument %s' % var)
   res = f(*args, **kwargs)
   return check_or_interleave(hints.simple_output_type('typecheck'), res, None)
예제 #6
0
    def expand(self, pcoll):
        # Since the PTransform will be implemented entirely as a function
        # (once called), we need to pass through any type-hinting information that
        # may have been annotated via the .with_input_types() and
        # .with_output_types() methods.
        kwargs = dict(self._kwargs)
        args = tuple(self._args)

        # TODO(BEAM-5878) Support keyword-only arguments.
        try:
            if 'type_hints' in get_signature(self._fn).parameters:
                args = (self.get_type_hints(), ) + args
        except TypeError:
            # Might not be a function.
            pass
        return self._fn(pcoll, *args, **kwargs)