From: <zy...@us...> - 2009-01-29 14:24:38
|
Revision: 5999 http://jython.svn.sourceforge.net/jython/?rev=5999&view=rev Author: zyasoft Date: 2009-01-29 14:24:33 +0000 (Thu, 29 Jan 2009) Log Message: ----------- Extract script now processes most/all of the test.test_* modules with a test_main and importable by CPython. May want to consider generalizing support for instance methods and closure setup with respect to new.function (= PyFunction), but this seems purely a testing nicety for top-level defs. Modified Paths: -------------- branches/pbcvm/Tools/pbcvm/extract.py Modified: branches/pbcvm/Tools/pbcvm/extract.py =================================================================== --- branches/pbcvm/Tools/pbcvm/extract.py 2009-01-29 03:44:58 UTC (rev 5998) +++ branches/pbcvm/Tools/pbcvm/extract.py 2009-01-29 14:24:33 UTC (rev 5999) @@ -4,6 +4,7 @@ Jython the desired PBC. """ +from __future__ import with_statement import inspect import networkx # add dependency to a setup script? probably overkill import sys @@ -13,97 +14,128 @@ argcount nlocals stacksize flags code consts names varnames filename name firstlineno lnotab -""".split()] # add freevars cellvars? + freevars cellvars +""".split()] # add -# this has to be instantiated per module! so simply move into a class -_codeobjs = {} -_codeobjs_names = {} -counters = defaultdict(int) -depend = networkx.DiGraph() -root = "root" +ROOT = object() -def extract(mod): - functionobjs = candidate_functions(mod) - for name, f in functionobjs: - #print >> sys.stderr, "Extracting", f - extract_code_obj(f) - codes = {} - for code, definition in _codeobjs.iteritems(): - codes[_codeobjs_names[code]] = definition - print "from %s import *" % mod.__name__ - print "from org.python.core import PyBytecode" - print - print "_codeobjs = {}" - print +class Extract(object): - objs = networkx.topological_sort(depend) - for obj in objs: - if not inspect.iscode(obj): - continue - name = _codeobjs_names[obj] - print "_codeobjs[%r] = %s" % (name, _codeobjs[obj]) - print - for name, f in functionobjs: - print "%s.func_code = _codeobjs[%r]" % (name, _codeobjs_names[f.func_code]) + def __init__(self, mod, writer): + self.mod = mod + self.writer = writer + self.codeobjs = {} + self.codeobjs_names = {} + self.counters = defaultdict(int) + self.depend = networkx.DiGraph() + + def extract(self): + mod = self.mod + writer = self.writer + functionobjs = self.candidate_functions() + for name, f in functionobjs: + self.extract_code_obj(f) + + print >> writer, "from %s import *" % mod.__name__ + print >> writer, "from org.python.core import PyBytecode" + print >> writer + print >> writer, "_codeobjs = {}" + print >> writer + + objs = networkx.topological_sort(self.depend) + for obj in objs: + if not inspect.iscode(obj): + continue + name = self.codeobjs_names[obj] + print >> writer, "_codeobjs[%r] = %s" % (name, self.codeobjs[obj]) + print >> writer + for name, f in functionobjs: + # this may be a Jython diff, need to determine further; need to check if im_func or not on the object + print >> writer, "try: %s.func_code = _codeobjs[%r]" % (name, self.codeobjs_names[f.func_code]) + print >> writer, "except (AttributeError, ValueError): pass" # ignore setting cells, im_func, etc... %s.im_func.func_code = _codeobjs[%r]" % (name, self.codeobjs_names[f.func_code]) - print - print 'if __name__ == "__main__":' - print ' test_main()' + print >> writer + print >> writer, 'if __name__ == "__main__":' + print >> writer, ' test_main()' + def candidate_functions(self): + """functions and methods we will retrieve code objects""" + + mod = self.mod + functions = inspect.getmembers(mod, inspect.isfunction) + functions = [(name, f) for (name, f) in functions if not inspect.isbuiltin(f) and name != "test_main"] -def candidate_functions(mod): - """functions and methods we will retrieve code objects""" + classes = inspect.getmembers(mod, inspect.isclass) + for classname, cls in classes: + for methodname, method in inspect.getmembers(cls, inspect.ismethod): + if inspect.getmodule(method) == mod: + functions.append(("%s.%s" % (classname, methodname), method)) + return functions - functions = inspect.getmembers(mod, inspect.isfunction) - functions = [(name, f) for (name, f) in functions if not inspect.isbuiltin(f)] + def extract_code_obj(self, f_or_code): + if inspect.iscode(f_or_code): + code = f_or_code + else: + code = f_or_code.func_code + self.extract_def(code) - classes = inspect.getmembers(mod, inspect.isclass) - for classname, cls in classes: - #print >> sys.stderr, "Extracting from", cls - for methodname, method in inspect.getmembers(cls, inspect.ismethod): - #print >> sys.stderr, "Extracting method", method - if inspect.getmodule(method) == mod: - functions.append(("%s.%s" % (classname, methodname), method)) - return functions + def extract_def(self, code): + if code in self.codeobjs_names: + #print >> sys.stderr, "Already seen", code + return "_codeobjs[%r]" % (self.codeobjs_names[code],) -def extract_code_obj(f_or_code): - if inspect.iscode(f_or_code): - code = f_or_code - else: - code = f_or_code.func_code - extract_def(code) + co_name = code.co_name + #print >> sys.stderr, "Processing", code + name = co_name + "." + str(self.counters[co_name]) + self.counters[co_name] += 1 + self.codeobjs_names[code] = name + values = [] + self.depend.add_edge(code, ROOT) + for attr in attrs: + # treat co_consts specially - maybe also need to use pickling in case repr is not suitable + if attr == 'co_consts': + co_consts = [] + for const in getattr(code, attr): + if inspect.iscode(const): + #print >> sys.stderr, "Extracting code const " + str(const) + co_consts.append(self.extract_def(const)) + self.depend.add_edge(const, code) + else: + co_consts.append(repr(const)) + values.append((attr, "["+', '.join(co_consts)+"]")) + else: + values.append((attr, repr(getattr(code, attr)))) + self.codeobjs[code] = "PyBytecode(\n" + '\n'.join([' '* 4 + v + ', # ' + attr for (attr, v) in values])+"\n )" + return "_codeobjs[%r]" % (name,) -def extract_def(code): - if code in _codeobjs_names: - print >> sys.stderr, "Already seen", code - return "_codeobjs[%r]" % (_codeobjs_names[code],) - co_name = code.co_name - print >> sys.stderr, "Processing", code - name = co_name + "." + str(counters[co_name]) - counters[co_name] += 1 - _codeobjs_names[code] = name - # need to treat co_consts specially - maybe use pickling if repr is not suitable? - values = [] - depend.add_edge(code, root) - for attr in attrs: - if attr == 'co_consts': - co_consts = [] - for const in getattr(code, attr): - if inspect.iscode(const): - print >> sys.stderr, "Extracting code const " + str(const) - co_consts.append(extract_def(const)) - depend.add_edge(const, code) - else: - co_consts.append(repr(const)) - values.append((attr, "["+', '.join(co_consts)+"]")) - else: - values.append((attr, repr(getattr(code, attr)))) - _codeobjs[code] = "PyBytecode(\n" + '\n'.join([' '* 4 + v + ', # ' + attr for (attr, v) in values])+"\n )" - return "_codeobjs[%r]" % (name,) +# for now, just use the cwd +def import_modules(path): + import glob + import os.path + sys.path.insert(0, path) + for name in sorted(glob.iglob("test/test_*.py")): + modname = os.path.splitext(os.path.basename(name))[0] + qualified_name = "test." + modname + print "Trying", qualified_name + try: + topmod = __import__(qualified_name) + except Exception, e: + print "Could not import", qualified_name, ":", repr(e) + continue + mod = getattr(topmod, modname) + try: + mod.test_main + except AttributeError, e: + print "No test_main in", qualified_name + continue + output_name = "test/" + modname + "_pbc.py" + with open(output_name, "w") as f: + print "Extracting", name, "to", output_name + Extract(mod, f).extract() + if __name__ == '__main__': - modname = sys.argv[1] - mod = __import__(modname) - extract(mod) + path = modname = sys.argv[1] + import_modules(path) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |