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
(func, reverse_index)
| 706 | |
| 707 | |
| 708 | def _generate_signature(func, reverse_index): |
| 709 | """Given a function, returns a list of strings representing its args. |
| 710 | |
| 711 | This function produces a list of strings representing the arguments to a |
| 712 | python function. It uses tf_inspect.getfullargspec, which |
| 713 | does not generalize well to Python 3.x, which is more flexible in how *args |
| 714 | and **kwargs are handled. This is not a problem in TF, since we have to remain |
| 715 | compatible to Python 2.7 anyway. |
| 716 | |
| 717 | This function uses `__name__` for callables if it is available. This can lead |
| 718 | to poor results for functools.partial and other callable objects. |
| 719 | |
| 720 | The returned string is Python code, so if it is included in a Markdown |
| 721 | document, it should be typeset as code (using backticks), or escaped. |
| 722 | |
| 723 | Args: |
| 724 | func: A function, method, or functools.partial to extract the signature for. |
| 725 | reverse_index: A map from object ids to canonical full names to use. |
| 726 | |
| 727 | Returns: |
| 728 | A list of strings representing the argument signature of `func` as python |
| 729 | code. |
| 730 | """ |
| 731 | |
| 732 | args_list = [] |
| 733 | |
| 734 | argspec = _get_arg_spec(func) |
| 735 | first_arg_with_default = ( |
| 736 | len(argspec.args or []) - len(argspec.defaults or [])) |
| 737 | |
| 738 | # Python documentation skips `self` when printing method signatures. |
| 739 | # Note we cannot test for ismethod here since unbound methods do not register |
| 740 | # as methods (in Python 3). |
| 741 | first_arg = 1 if 'self' in argspec.args[:1] else 0 |
| 742 | |
| 743 | # Add all args without defaults. |
| 744 | for arg in argspec.args[first_arg:first_arg_with_default]: |
| 745 | args_list.append(arg) |
| 746 | |
| 747 | # Add all args with defaults. |
| 748 | if argspec.defaults: |
| 749 | try: |
| 750 | source = _remove_first_line_indent(tf_inspect.getsource(func)) |
| 751 | func_ast = ast.parse(source) |
| 752 | ast_defaults = func_ast.body[0].args.defaults |
| 753 | except IOError: # If this is a builtin, getsource fails with IOError |
| 754 | # If we cannot get the source, assume the AST would be equal to the repr |
| 755 | # of the defaults. |
| 756 | ast_defaults = [None] * len(argspec.defaults) |
| 757 | |
| 758 | for arg, default, ast_default in zip( |
| 759 | argspec.args[first_arg_with_default:], argspec.defaults, ast_defaults): |
| 760 | if id(default) in reverse_index: |
| 761 | default_text = reverse_index[id(default)] |
| 762 | elif ast_default is not None: |
| 763 | default_text = ( |
| 764 | astor.to_source(ast_default).rstrip('\n').replace('\t', '\\t') |
| 765 | .replace('\n', '\\n').replace('"""', "'")) |
no test coverage detected