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
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__)
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__)
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)
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)
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)