diff --git a/paddle/scripts/paddle_build.sh b/paddle/scripts/paddle_build.sh index 44102f23f097bcb84470843bd8c8053813eb8345..ac13ad5ec8d3ad0dc52e3c740629b0650ccc61db 100755 --- a/paddle/scripts/paddle_build.sh +++ b/paddle/scripts/paddle_build.sh @@ -508,7 +508,7 @@ function generate_api_spec() { source .${spec_kind}_env/bin/activate pip install ${PADDLE_ROOT}/build/python/dist/*whl spec_path=${PADDLE_ROOT}/paddle/fluid/API_${spec_kind}.spec - python ${PADDLE_ROOT}/tools/print_signatures.py paddle.fluid > $spec_path + python ${PADDLE_ROOT}/tools/print_signatures.py paddle > $spec_path # used to log op_register data_type op_type_path=${PADDLE_ROOT}/paddle/fluid/OP_TYPE_${spec_kind}.spec diff --git a/tools/print_signatures.py b/tools/print_signatures.py index 05c4911828a60bbba98af4ebfe961c3be48861ea..2615b4ec23d3265c639fab50dcea07d67937eb36 100644 --- a/tools/print_signatures.py +++ b/tools/print_signatures.py @@ -25,9 +25,13 @@ import collections import sys import pydoc import hashlib +import six +import functools member_dict = collections.OrderedDict() +visited_modules = set() + # APIs that should not be printed into API.spec omitted_list = [ "paddle.fluid.LoDTensor.set", # Do not know why it should be omitted @@ -42,23 +46,45 @@ def md5(doc): return hash.hexdigest() +def get_functools_partial_spec(func): + func_str = func.func.__name__ + args = func.args + keywords = func.keywords + return '{}(args={}, keywords={})'.format(func_str, args, keywords) + + +def format_spec_doc(spec, doc=None): + args = spec.args + varargs = spec.varargs + keywords = spec.keywords + defaults = list(spec.defaults) + for idx, item in enumerate(defaults): + if not isinstance(item, functools.partial): + continue + + defaults[idx] = get_functools_partial_spec(item) + + return 'ArgSpec(args={}, varargs={}, keywords={}, defaults={})'.format( + args, varargs, keywords, tuple(defaults)) + + def queue_dict(member, cur_name): if cur_name in omitted_list: return - doc = ('document', md5(member.__doc__)) + doc_md5 = md5(member.__doc__) if inspect.isclass(member): args = member.__module__ + "." + member.__name__ else: try: - args = inspect.getargspec(member) + args = format_spec_doc(inspect.getargspec(member)) except TypeError: # special for PyBind method args = " ".join([ line.strip() for line in pydoc.render_doc(member).split('\n') if "->" in line ]) - member_dict[cur_name] = (args, doc) + member_dict[cur_name] = "({}, ('document', '{}'))".format(args, doc_md5) def visit_member(parent_name, member): @@ -78,7 +104,31 @@ def visit_member(parent_name, member): format(str(type(member)))) +def is_primitive(instance): + int_types = (int, long) if six.PY2 else (int, ) + pritimitive_types = int_types + (float, str) + if isinstance(instance, pritimitive_types): + return True + elif isinstance(instance, (list, tuple, set)): + for obj in instance: + if not is_primitive(obj): + return False + + return True + else: + return False + + def visit_all_module(mod): + mod_name = mod.__name__ + if mod_name != 'paddle' and not mod_name.startswith('paddle.'): + return + + if mod in visited_modules: + return + + visited_modules.add(mod) + for member_name in ( name for name in (mod.__all__ if hasattr(mod, "__all__") else dir(mod)) @@ -86,6 +136,13 @@ def visit_all_module(mod): instance = getattr(mod, member_name, None) if instance is None: continue + + if is_primitive(instance): + continue + + if not hasattr(instance, "__name__"): + continue + if inspect.ismodule(instance): visit_all_module(instance) else: