Example #1
0
def getargs(obj):
    """Get the names and default values of a function's arguments"""
    if inspect.isfunction(obj) or inspect.isbuiltin(obj):
        func_obj = obj
    elif inspect.ismethod(obj):
        func_obj = get_meth_func(obj)
    elif inspect.isclass(obj) and hasattr(obj, '__init__'):
        func_obj = getattr(obj, '__init__')
    else:
        return []
    if not hasattr(func_obj, 'func_code'):
        # Builtin: try to extract info from doc
        args = getargsfromdoc(func_obj)
        if args is not None:
            return args
        else:
            # Example: PyQt4
            return getargsfromdoc(obj)
    args, _, _ = inspect.getargs(func_obj.func_code)
    if not args:
        return getargsfromdoc(obj)
    
    # Supporting tuple arguments in def statement:
    for i_arg, arg in enumerate(args):
        if isinstance(arg, list):
            args[i_arg] = "(%s)" % ", ".join(arg)
            
    defaults = get_func_defaults(func_obj)
    if defaults is not None:
        for index, default in enumerate(defaults):
            args[index+len(args)-len(defaults)] += '='+repr(default)
    if inspect.isclass(obj) or inspect.ismethod(obj):
        if len(args) == 1:
            return None
        if 'self' in args:
            args.remove('self')
    return args
Example #2
0
def getdoc(obj):
    """
    Return text documentation from an object. This comes in a form of
    dictionary with four keys:

    name:
      The name of the inspected object
    argspec:
      It's argspec
    note:
      A phrase describing the type of object (function or method) we are
      inspecting, and the module it belongs to.
    docstring:
      It's docstring
    """
    
    docstring = inspect.getdoc(obj) or inspect.getcomments(obj) or ''
    
    # Most of the time doc will only contain ascii characters, but there are
    # some docstrings that contain non-ascii characters. Not all source files
    # declare their encoding in the first line, so querying for that might not
    # yield anything, either. So assume the most commonly used
    # multi-byte file encoding (which also covers ascii). 
    try:
        docstring = to_text_string(docstring)
    except:
        pass
    
    # Doc dict keys
    doc = {'name': '',
           'argspec': '',
           'note': '',
           'docstring': docstring}
    
    if callable(obj):
        try:
            name = obj.__name__
        except AttributeError:
            doc['docstring'] = docstring
            return doc
        if inspect.ismethod(obj):
            imclass = get_meth_class(obj)
            if get_meth_class_inst(obj) is not None:
                doc['note'] = 'Method of %s instance' \
                              % get_meth_class_inst(obj).__class__.__name__
            else:
                doc['note'] = 'Unbound %s method' % imclass.__name__
            obj = get_meth_func(obj)
        elif hasattr(obj, '__module__'):
            doc['note'] = 'Function of %s module' % obj.__module__
        else:
            doc['note'] = 'Function'
        doc['name'] = obj.__name__
        if inspect.isfunction(obj):
            args, varargs, varkw, defaults = inspect.getargspec(obj)
            doc['argspec'] = inspect.formatargspec(args, varargs, varkw,
                                              defaults,
                                              formatvalue=lambda o:'='+repr(o))
            if name == '<lambda>':
                doc['name'] = name + ' lambda '
                doc['argspec'] = doc['argspec'][1:-1] # remove parentheses
        else:
            argspec = getargspecfromtext(doc['docstring'])
            if argspec:
                doc['argspec'] = argspec
                # Many scipy and numpy docstrings begin with a function
                # signature on the first line. This ends up begin redundant
                # when we are using title and argspec to create the
                # rich text "Definition:" field. We'll carefully remove this
                # redundancy but only under a strict set of conditions:
                # Remove the starting charaters of the 'doc' portion *iff*
                # the non-whitespace characters on the first line 
                # match *exactly* the combined function title 
                # and argspec we determined above.
                signature = doc['name'] + doc['argspec']
                docstring_blocks = doc['docstring'].split("\n\n")
                first_block = docstring_blocks[0].strip()
                if first_block == signature:
                    doc['docstring'] = doc['docstring'].replace(
                                                     signature, '', 1).lstrip()
            else:
                doc['argspec'] = '(...)'
        
        # Remove self from argspec
        argspec = doc['argspec']
        doc['argspec'] = argspec.replace('(self)', '()').replace('(self, ', '(')
        
    return doc