def test_argspec_for_functools_partial_starargs(self): # pylint: disable=unused-argument def test_function_for_partial2(arg1, arg2, *my_args, **my_kwargs): pass # pylint: enable=unused-argument # Make sure *args, *kwargs is accounted for. expected = tf_inspect.FullArgSpec( args=[], varargs='my_args', varkw='my_kwargs', defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={}) partial = functools.partial(test_function_for_partial2, 0, 1) self.assertEqual(expected, tf_inspect.getfullargspec(partial)) # Make sure *args, *kwargs is accounted for. expected = tf_inspect.FullArgSpec( args=[], varargs='my_args', varkw='my_kwargs', defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={}) partial = functools.partial(test_function_for_partial2, 0, 1, 2, 3, 4, 5) self.assertEqual(expected, tf_inspect.getfullargspec(partial)) # Make sure *args, *kwargs is accounted for. expected = tf_inspect.FullArgSpec( args=['arg1', 'arg2'], varargs='my_args', varkw='my_kwargs', defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={}) partial = functools.partial(test_function_for_partial2, a=1, b=2, c=3) self.assertEqual(expected, tf_inspect.getfullargspec(partial))
def testGetFullArgsSpecForPartial(self): def func(a, b): del a, b partial_function = functools.partial(func, 1) argspec = tf_inspect.FullArgSpec(args=['b'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={}) self.assertEqual(argspec, tf_inspect.getfullargspec(partial_function))
def testGetFullArgSpecOnNewClass(self): class NewClass(object): def __new__(cls, a, b=1, c='hello'): pass argspec = tf_inspect.FullArgSpec(args=['cls', 'a', 'b', 'c'], varargs=None, varkw=None, defaults=(1, 'hello'), kwonlyargs=[], kwonlydefaults=None, annotations={}) self.assertEqual(argspec, tf_inspect.getfullargspec(NewClass))
def testGetFullArgSpecOnCallableObject(self): class Callable(object): def __call__(self, a, b=1, c='hello'): pass argspec = tf_inspect.FullArgSpec(args=['self', 'a', 'b', 'c'], varargs=None, varkw=None, defaults=(1, 'hello'), kwonlyargs=[], kwonlydefaults=None, annotations={}) test_obj = Callable() self.assertEqual(argspec, tf_inspect.getfullargspec(test_obj))
def testGetFullArgSpecOnPartialWithVarargs(self): """Tests getfullargspec on partial function with variable arguments.""" def func(m, *arg): return m + len(arg) partial_func = functools.partial(func, 7, 8) argspec = tf_inspect.FullArgSpec(args=[], varargs='arg', varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={}) self.assertEqual(argspec, tf_inspect.getfullargspec(partial_func))
def testGetFullArgSpecOnPartialNoArgumentsLeft(self): """Tests getfullargspec on partial function that prunes all arguments.""" def func(m, n): return 2 * m + n partial_func = functools.partial(func, 7, 10) argspec = tf_inspect.FullArgSpec(args=[], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={}) self.assertEqual(argspec, tf_inspect.getfullargspec(partial_func))
def testGetFullArgsSpecForPartial(self): def func(a, b): del a, b partial_function = functools.partial(func, 1) argspec = tf_inspect.FullArgSpec( args=['b'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={}) self.assertEqual(argspec, tf_inspect.getfullargspec(partial_function))
def testGetFullArgSpecOnNewClass(self): class NewClass(object): def __new__(cls, a, b=1, c='hello'): pass argspec = tf_inspect.FullArgSpec( args=['cls', 'a', 'b', 'c'], varargs=None, varkw=None, defaults=(1, 'hello'), kwonlyargs=[], kwonlydefaults=None, annotations={}) self.assertEqual(argspec, tf_inspect.getfullargspec(NewClass))
def testGetFullArgSpecOnPartialWithVarargs(self): """Tests getfullargspec on partial function with variable arguments.""" def func(m, *arg): return m + len(arg) partial_func = functools.partial(func, 7, 8) argspec = tf_inspect.FullArgSpec( args=[], varargs='arg', varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={}) self.assertEqual(argspec, tf_inspect.getfullargspec(partial_func))
def testGetFullArgSpecOnPartialNoArgumentsLeft(self): """Tests getfullargspec on partial function that prunes all arguments.""" def func(m, n): return 2 * m + n partial_func = functools.partial(func, 7, 10) argspec = tf_inspect.FullArgSpec( args=[], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={}) self.assertEqual(argspec, tf_inspect.getfullargspec(partial_func))
def testGetFullArgSpecOnCallableObject(self): class Callable(object): def __call__(self, a, b=1, c='hello'): pass argspec = tf_inspect.FullArgSpec( args=['self', 'a', 'b', 'c'], varargs=None, varkw=None, defaults=(1, 'hello'), kwonlyargs=[], kwonlydefaults=None, annotations={}) test_obj = Callable() self.assertEqual(argspec, tf_inspect.getfullargspec(test_obj))
def testGetFullArgSpecOnPartialWithVarkwargs(self): """Tests getfullargspec. Tests on partial function with variable keyword arguments. """ def func(m, n, **kwarg): return m * n + len(kwarg) partial_func = functools.partial(func, 7) argspec = tf_inspect.FullArgSpec(args=['n'], varargs=None, varkw='kwarg', defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={}) self.assertEqual(argspec, tf_inspect.getfullargspec(partial_func))
def testGetArgSpecOnPartialKeywordArgument(self): """Tests getargspec on partial function that prunes some arguments.""" def func(m, n): return 2 * m + n partial_func = functools.partial(func, n=7) argspec = tf_inspect.FullArgSpec(args=['m'], varargs=None, varkw=None, defaults=None, kwonlyargs=['n'], kwonlydefaults={'n': 7}, annotations={}) self.assertEqual(argspec, tf_inspect.getfullargspec(partial_func)) with self.assertRaisesRegexp(ValueError, 'Function has keyword-only.*'): tf_inspect.getargspec(partial_func)
def testGetArgSpecOnPartialKeywordArgument(self): """Tests getargspec on partial function that prunes some arguments.""" def func(m, n): return 2 * m + n partial_func = functools.partial(func, n=7) argspec = tf_inspect.FullArgSpec( args=['m'], varargs=None, varkw=None, defaults=None, kwonlyargs=['n'], kwonlydefaults={'n': 7}, annotations={}) self.assertEqual(argspec, tf_inspect.getfullargspec(partial_func)) with self.assertRaisesRegexp(ValueError, 'Function has keyword-only.*'): tf_inspect.getargspec(partial_func)
def testGetFullArgSpecOnPartialWithVarkwargs(self): """Tests getfullargspec. Tests on partial function with variable keyword arguments. """ def func(m, n, **kwarg): return m * n + len(kwarg) partial_func = functools.partial(func, 7) argspec = tf_inspect.FullArgSpec( args=['n'], varargs=None, varkw='kwarg', defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={}) self.assertEqual(argspec, tf_inspect.getfullargspec(partial_func))
def testGetArgSpecOnPartialValidArgspec(self): """Tests getargspec on partial function with valid argspec.""" def func(m, n, l, k=4): return 2 * m + l + n * k partial_func = functools.partial(func, n=7, l=2) argspec = tf_inspect.FullArgSpec(args=['m'], varargs=None, varkw=None, defaults=None, kwonlyargs=['n', 'l', 'k'], kwonlydefaults={ 'n': 7, 'l': 2, 'k': 4 }, annotations={}) self.assertEqual(argspec, tf_inspect.getfullargspec(partial_func)) with self.assertRaisesRegexp(ValueError, 'Function has keyword-only.*'): tf_inspect.getargspec(partial_func)
def testGetArgSpecOnPartialValidArgspec(self): """Tests getargspec on partial function with valid argspec.""" def func(m, n, l, k=4): return 2 * m + l + n * k partial_func = functools.partial(func, n=7, l=2) argspec = tf_inspect.FullArgSpec( args=['m'], varargs=None, varkw=None, defaults=None, kwonlyargs=['n', 'l', 'k'], kwonlydefaults={ 'n': 7, 'l': 2, 'k': 4 }, annotations={}) self.assertEqual(argspec, tf_inspect.getfullargspec(partial_func)) with self.assertRaisesRegexp(ValueError, 'Function has keyword-only.*'): tf_inspect.getargspec(partial_func)
def test_argspec_for_functools_partial(self): # pylint: disable=unused-argument def test_function_for_partial1(arg1, arg2, kwarg1=1, kwarg2=2): pass # pylint: enable=unused-argument # pylint: disable=protected-access # Make sure everything works for regular functions. expected = tf_inspect.FullArgSpec( args=['arg1', 'arg2', 'kwarg1', 'kwarg2'], varargs=None, varkw=None, defaults=(1, 2), kwonlyargs=[], kwonlydefaults=None, annotations={}) self.assertEqual(expected, tf_inspect.getfullargspec(test_function_for_partial1)) # Make sure doing nothing works. expected = tf_inspect.FullArgSpec( args=['arg1', 'arg2', 'kwarg1', 'kwarg2'], varargs=None, varkw=None, defaults=(1, 2), kwonlyargs=[], kwonlydefaults=None, annotations={}) partial = functools.partial(test_function_for_partial1) self.assertEqual(expected, tf_inspect.getfullargspec(partial)) # Make sure setting args from the front works. expected = tf_inspect.FullArgSpec( args=['arg2', 'kwarg1', 'kwarg2'], varargs=None, varkw=None, defaults=(1, 2), kwonlyargs=[], kwonlydefaults=None, annotations={}) partial = functools.partial(test_function_for_partial1, 1) self.assertEqual(expected, tf_inspect.getfullargspec(partial)) expected = tf_inspect.FullArgSpec( args=['kwarg2'], varargs=None, varkw=None, defaults=(2,), kwonlyargs=[], kwonlydefaults=None, annotations={}) partial = functools.partial(test_function_for_partial1, 1, 2, 3) self.assertEqual(expected, tf_inspect.getfullargspec(partial)) # Make sure setting kwargs works. expected = tf_inspect.FullArgSpec( args=['arg1', 'arg2'], varargs=None, varkw=None, defaults=None, kwonlyargs=['kwarg1', 'kwarg2'], kwonlydefaults={ 'kwarg1': 0, 'kwarg2': 2 }, annotations={}) partial = functools.partial(test_function_for_partial1, kwarg1=0) self.assertEqual(expected, tf_inspect.getfullargspec(partial)) expected = tf_inspect.FullArgSpec( args=['arg1', 'arg2', 'kwarg1'], varargs=None, varkw=None, defaults=(1,), kwonlyargs=['kwarg2'], kwonlydefaults={'kwarg2': 0}, annotations={}) partial = functools.partial(test_function_for_partial1, kwarg2=0) self.assertEqual(expected, tf_inspect.getfullargspec(partial)) expected = tf_inspect.FullArgSpec( args=['arg1'], varargs=None, varkw=None, defaults=None, kwonlyargs=['arg2', 'kwarg1', 'kwarg2'], kwonlydefaults={ 'arg2': 0, 'kwarg1': 0, 'kwarg2': 0 }, annotations={}) partial = functools.partial(test_function_for_partial1, arg2=0, kwarg1=0, kwarg2=0) self.assertEqual(expected, tf_inspect.getfullargspec(partial))
def _generate_signature(func, reverse_index): """Given a function, returns a list of strings representing its args. This function produces a list of strings representing the arguments to a python function. It uses tf_inspect.getfullargspec, which does not generalize well to Python 3.x, which is more flexible in how *args and **kwargs are handled. This is not a problem in TF, since we have to remain compatible to Python 2.7 anyway. This function uses `__name__` for callables if it is available. This can lead to poor results for functools.partial and other callable objects. The returned string is Python code, so if it is included in a Markdown document, it should be typeset as code (using backticks), or escaped. Args: func: A function, method, or functools.partial to extract the signature for. reverse_index: A map from object ids to canonical full names to use. Returns: A list of strings representing the argument signature of `func` as python code. """ args_list = [] argspec = tf_inspect.getfullargspec(func) first_arg_with_default = ( len(argspec.args or []) - len(argspec.defaults or [])) # Python documentation skips `self` when printing method signatures. # Note we cannot test for ismethod here since unbound methods do not register # as methods (in Python 3). first_arg = 1 if 'self' in argspec.args[:1] else 0 # Add all args without defaults. for arg in argspec.args[first_arg:first_arg_with_default]: args_list.append(arg) # Add all args with defaults. if argspec.defaults: try: source = _remove_first_line_indent(tf_inspect.getsource(func)) func_ast = ast.parse(source) ast_defaults = func_ast.body[0].args.defaults except IOError: # If this is a builtin, getsource fails with IOError # If we cannot get the source, assume the AST would be equal to the repr # of the defaults. ast_defaults = [None] * len(argspec.defaults) for arg, default, ast_default in zip( argspec.args[first_arg_with_default:], argspec.defaults, ast_defaults): if id(default) in reverse_index: default_text = reverse_index[id(default)] elif ast_default is not None: default_text = ( astor.to_source(ast_default).rstrip('\n').replace('\t', '\\t') .replace('\n', '\\n').replace('"""', "'")) default_text = PAREN_NUMBER_RE.sub('\\1', default_text) if default_text != repr(default): # This may be an internal name. If so, handle the ones we know about. # TODO(wicke): This should be replaced with a lookup in the index. # TODO(wicke): (replace first ident with tf., check if in index) internal_names = { 'ops.GraphKeys': 'tf.GraphKeys', '_ops.GraphKeys': 'tf.GraphKeys', 'init_ops.zeros_initializer': 'tf.zeros_initializer', 'init_ops.ones_initializer': 'tf.ones_initializer', 'saver_pb2.SaverDef': 'tf.train.SaverDef', } full_name_re = '^%s(.%s)+' % (IDENTIFIER_RE, IDENTIFIER_RE) match = re.match(full_name_re, default_text) if match: lookup_text = default_text for internal_name, public_name in six.iteritems(internal_names): if match.group(0).startswith(internal_name): lookup_text = public_name + default_text[len(internal_name):] break if default_text is lookup_text: logging.warn( 'WARNING: Using default arg, failed lookup: %s, repr: %r', default_text, default) else: default_text = lookup_text else: default_text = repr(default) args_list.append('%s=%s' % (arg, default_text)) # Add *args and *kwargs. if argspec.varargs: args_list.append('*' + argspec.varargs) if argspec.varkw: args_list.append('**' + argspec.varkw) return args_list