Ejemplo n.º 1
0
def process_routine(rootElt, obj, name, callables):    
    if inspect.isfunction(obj):
        if _gIsPy3:
            argspec = inspect.getfullargspec(obj)
        else:
            argspec = inspect.getargspec(obj)
        sig = name + inspect.formatargspec(*argspec)
    else:
        sig = ''
    doc = getdoc(obj) or None
    call_sig_lines, description_lines = parsePyFuncDoc(doc, [sig])
    if description_lines:
        doc = '\n'.join(parseDocSummary(description_lines))
    if call_sig_lines:
        signature = '\n'.join(call_sig_lines)
    else:
        signature = sig
    if name == '__init__':
        if doc == obj.__init__.__doc__:
            doc = None
        if signature == obj.__init__.__doc__:
            signature = None
    
    funcElt = SubElement(rootElt, "scope", ilk="function", name=name)
    if doc: funcElt.set('doc', doc)
    if signature: funcElt.set('signature', signature)

    callables[name] = funcElt
Ejemplo n.º 2
0
def process_class_using_instance(rootElt, obj, name, callables):
    doc = getsdoc(obj) or None
    classElt = SubElement(rootElt, "scope", ilk="class", name=name)
    if doc: classElt.set('doc', doc)
    callables[name] = classElt
    classElt.set('attributes', '__hidden__')

    for key, value in sorted(inspect.getmembers(obj)):
        if not visiblename(key):
            continue
        if inspect.isbuiltin(value):
            process_routine(classElt, value, key, callables)
        elif (_gIsPy3 and hasattr(value, 'class')) or (
                not _gIsPy3 and isinstance(value, types.InstanceType)):
            klass = value.__class__
            if klass.__module__ == name:
                t = klass.__name__
            else:
                t = "%s.%s" % (klass.__module__, klass.__name__)
            varElt = SubElement(classElt, "variable", name=key, citdl=t)
        elif isdata(value):
            varElt = SubElement(classElt,
                                "variable",
                                name=key,
                                citdl=type(value).__name__)
Ejemplo n.º 3
0
def process_class_using_instance(rootElt, obj, name, callables):
    doc = getsdoc(obj) or None
    classElt = SubElement(rootElt, "scope", ilk="class", name=name)
    if doc: classElt.set('doc', doc)
    callables[name] = classElt
    classElt.set('attributes', '__hidden__')

    for key, value in sorted(inspect.getmembers(obj)):
        if not visiblename(key):
            continue
        if inspect.isbuiltin(value):
            process_routine(classElt, value, key, callables)
        elif (_gIsPy3 and hasattr(value, 'class')) or (not _gIsPy3 and isinstance(value, types.InstanceType)):
            klass = value.__class__
            if klass.__module__ == name:
                t = klass.__name__
            else:
                t = "%s.%s" % (klass.__module__, klass.__name__)
            varElt = SubElement(classElt, "variable", name=key, citdl=t)
        elif isdata(value):
            varElt = SubElement(classElt, "variable", name=key, citdl=type(value).__name__)
Ejemplo n.º 4
0
def process_class(rootElt, obj, name, callables, __hidden__=False):
    doc = getsdoc(obj) or None
    classElt = SubElement(rootElt, "scope", ilk="class", name=name)
    if doc:
        classElt.set('doc', doc)
    callables[name] = classElt
    if __hidden__:
        classElt.set('attributes', '__hidden__')
    classrefs = [base.__name__ for base in obj.__bases__]
    if classrefs:
        classElt.set('classrefs', ' '.join(classrefs))
    # Functions are method descriptors in Python inspect module parlance.

    def attrfilter(attr):
        # Only add methods and attributes of the class to the CIX.
        # - "os._Environ" seems to be a particular problem case in that
        #   some methods defined on it are inspect.ismethod() but not
        #   inspect.ismethoddescriptor(). Not so for other examples in
        #   modules that stdcix.py processes, and adding .ismethod() to this
        #   filter adds unwanted methods on C-defined module exception
        #   classes.
        if not (inspect.isdatadescriptor(attr)
                or inspect.ismethoddescriptor(attr)
                or inspect.ismethod(attr) or
                inspect.isfunction(attr)):
            return False
        # Skip inherited attributes in the CIX.
        try:
            attrname = attr.__name__
            for base in obj.__bases__:
                if hasattr(base, attrname) and getattr(base, attrname) is \
                        getattr(obj, attrname):
                    return False
        except AttributeError:
            # staticmethod and classmethod objects don't have a __name__
            pass
            # print "Couldn't process: %r, assuming ok" % str(attr)
        return True

    # attrs = inspect.getmembers(object, attrfilter) # should I be using
    # getmembers or class attr's?
    attrs = [(name, getattr(
        obj, name)) for name in obj.__dict__ if name not in ('__abstractmethods__')]
    attrs = [(name, attr) for (name, attr) in attrs if attrfilter(attr)]
    for (key, value) in attrs:
        if inspect.isfunction(value) or inspect.ismethod(value) or inspect.ismethoddescriptor(value):
            process_routine(classElt, value, key, callables)
Ejemplo n.º 5
0
def get_var_cix(cix_node, var_type, **attrs):
    var_cix_node = SubElement(cix_node, 'variable', **attrs)
    if var_type:
        var_cix_node.set('citdl', var_type)
Ejemplo n.º 6
0
def docmodule(modname, root, force=False, usefile=False, dir=None):
    name = modname
    modulename = modname
    if modname == '*':
        if _gIsPy3:
            modname = 'builtins'
        else:
            modname = '__builtin__'

    if dir:
        modinfo = imp.find_module(modname, [dir])
        try:
            obj = imp.load_module(modname, *modinfo)
        except ImportError:
            ex = sys.exc_info()[1]
            cixfile = SubElement(root, "file",
                                 lang="Python",
                                 mtime=str(int(time.time())),
                                 path=os.path.basename(modinfo[1]),
                                 error=str(ex))
            return
    else:
        # no dir is given, try to load from python path
        try:
            obj, modulename = pydoc.resolve(modname)
        except Exception:
            print(sys.exc_info()[1])
            return

    result = ''
    try:
        all = obj.__all__
    except AttributeError:
        all = None

    try:
        filename = inspect.getabsfile(obj)
    except TypeError:
        filename = '(built-in)'
    if usefile:
        cixfile = SubElement(root, "file",
                             lang="Python",
                             mtime=str(int(time.time())),
                             path=os.path.basename(filename))
    else:
        cixfile = root
    module = obj
    doc = getsdoc(obj) or None
    moduleElt = SubElement(cixfile, "scope", ilk="blob", name=name, lang="Python")
    if doc: moduleElt.set('doc', doc)
    skips = module_skips.get(name, [])
    callables = {}
    for key, value in sorted(inspect.getmembers(obj)):
        if key in skips:
            continue
        if inspect.ismodule(value):
            process_module(moduleElt, value, key, callables, modname)
            continue
        if not visiblename(key): # forget about __all__ 
            continue
        if (inspect.isfunction(value) or
            inspect.ismethod(value) or
            inspect.ismethoddescriptor(value) or
            inspect.isroutine(value) or
            inspect.isbuiltin(value)):
            process_routine(moduleElt, value, key, callables)
        elif inspect.isclass(value) or (not _gIsPy3 and isinstance(value, types.TypeType)):
            process_class(moduleElt, value, key, callables)
        elif (_gIsPy3 and hasattr(value, 'class')) or (not _gIsPy3 and isinstance(value, types.InstanceType)):
            klass = value.__class__
            if klass.__module__ == name:
                t = klass.__name__
            else:
                t = "%s.%s" % (klass.__module__, klass.__name__)
            varElt = SubElement(moduleElt, "variable", name=key, citdl=t)
            # make sure we also process the type of instances
            process_class(moduleElt, klass, klass.__name__, callables)
        elif isdata(value):
            varElt = SubElement(moduleElt, "variable", name=key, citdl=type(value).__name__)
        else:
            log.warn("unexpected element in module '%s': '%s' is %r",
                     modulename, name, type(value))

    helpername = os.path.join("helpers", modname + '_helper.py')
    namespace = {}
    if os.path.exists(helpername):
        sys.stderr.write("Found helper module: %r\n" % helpername)
        if _gIsPy3:
            exec(compile(open(helpername).read(), os.path.basename(helpername), 'exec'), namespace, namespace)
        else:
            execfile(helpername, namespace, namespace)
        # look in helpername for analyze_retval_exprs, which is a list of (callable_string, *args)
        # and which corresponds to callables which when called w/ the specified args, will return
        # variables which should be used to specify the <return> subelement of the callable.
        analyze_retval_exprs = namespace.get('analyze_retval_exprs', [])
        signatures = namespace.get('signatures', {})
        for retval_expr in analyze_retval_exprs:
            name, args = retval_expr
            if name in callables:
                callableElt = callables[name]
                if name in signatures:
                    sig = signatures[name]
                    callableElt.set('signature', sig) # XXX???
                playarea = module.__dict__
                var = eval(name, playarea)(*args)
                # find out what type that is
                callableElt.set("returns", type(var).__name__)
            else:
                print("Don't know about: %r" % expr)
                
        hidden_classes_exprs = namespace.get('hidden_classes_exprs', [])
        for expr in hidden_classes_exprs:
            playarea = module.__dict__
            var = eval(expr, playarea)
            name = type(var).__name__
            process_class_using_instance(moduleElt, var, name, callables)

        function_overrides = namespace.get('function_overrides')
        if function_overrides is not None:
            for name in function_overrides:
                namesplit = name.split(".")
                callableElt = callables[namesplit[0]]
                for subname in namesplit[1:]:
                    for childElt in callableElt:
                        if childElt.get("name") == subname:
                            callableElt = childElt
                            break
                    else:
                        callableElt = None
                        break
                if callableElt is None:
                    print("  couldn't find elem with name: %r" % (name, ))
                    continue
                overrides = function_overrides[name]
                for setting, value in overrides.items():
                    print("  overriding %s.%s %s attribute from %r to %r" % (modname, name, setting, callableElt.get(setting), value))
                    callableElt.set(setting, value)