diff -r 3edd2f19bce2 -r e0424e96e3fd py_ext/modules/svgui/pyjs/build.py --- a/py_ext/modules/svgui/pyjs/build.py Wed May 09 00:39:54 2012 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,724 +0,0 @@ -#!/usr/bin/env python - -import sys -import os -import shutil -from copy import copy -from os.path import join, dirname, basename, abspath, split, isfile, isdir -from optparse import OptionParser -import pyjs -from cStringIO import StringIO -try: - # Python 2.5 and above - from hashlib import md5 -except: - import md5 -import re - -usage = """ - usage: %prog [options] - -This is the command line builder for the pyjamas project, which can -be used to build Ajax applications from Python. -For more information, see the website at http://pyjs.org/ -""" - -# GWT1.2 Impl | GWT1.2 Output | Pyjamas 0.2 Platform | Pyjamas 0.2 Output -# -------------+-----------------------+----------------------+---------------------- -# IE6 | ie6 | IE6 | ie6 -# Opera | opera | Opera | opera -# Safari | safari | Safari | safari -# -- | gecko1_8 | Mozilla | mozilla -# -- | gecko | OldMoz | oldmoz -# Standard | all | (default code) | all -# Mozilla | gecko1_8, gecko | -- | -- -# Old | safari, gecko, opera | -- | -- - -version = "%prog pyjamas version 2006-08-19" - -# these names in lowercase need match the strings -# returned by "provider$user.agent" in order to be selected corretly -app_platforms = ['IE6', 'Opera', 'OldMoz', 'Safari', 'Mozilla'] - -# usually defaults to e.g. /usr/share/pyjamas -_data_dir = os.path.join(pyjs.prefix, "share/pyjamas") - - -# .cache.html files produces look like this -CACHE_HTML_PAT=re.compile('^[a-z]*.[0-9a-f]{32}\.cache\.html$') - -# ok these are the three "default" library directories, containing -# the builtins (str, List, Dict, ord, round, len, range etc.) -# the main pyjamas libraries (pyjamas.ui, pyjamas.Window etc.) -# and the contributed addons - -for p in ["library/builtins", - "library", - "addons"]: - p = os.path.join(_data_dir, p) - if os.path.isdir(p): - pyjs.path.append(p) - - -def read_boilerplate(data_dir, filename): - return open(join(data_dir, "builder/boilerplate", filename)).read() - -def copy_boilerplate(data_dir, filename, output_dir): - filename = join(data_dir, "builder/boilerplate", filename) - shutil.copy(filename, output_dir) - - -# taken and modified from python2.4 -def copytree_exists(src, dst, symlinks=False): - if not os.path.exists(src): - return - - names = os.listdir(src) - try: - os.mkdir(dst) - except: - pass - - errors = [] - for name in names: - if name.startswith('CVS'): - continue - if name.startswith('.git'): - continue - if name.startswith('.svn'): - continue - - srcname = os.path.join(src, name) - dstname = os.path.join(dst, name) - try: - if symlinks and os.path.islink(srcname): - linkto = os.readlink(srcname) - os.symlink(linkto, dstname) - elif isdir(srcname): - copytree_exists(srcname, dstname, symlinks) - else: - shutil.copy2(srcname, dstname) - except (IOError, os.error), why: - errors.append((srcname, dstname, why)) - if errors: - print errors - -def check_html_file(source_file, dest_path): - """ Checks if a base HTML-file is available in the PyJamas - output directory. - If the HTML-file isn't available, it will be created. - - If a CSS-file with the same name is available - in the output directory, a reference to this CSS-file - is included. - - If no CSS-file is found, this function will look for a special - CSS-file in the output directory, with the name - "pyjamas_default.css", and if found it will be referenced - in the generated HTML-file. - - [thank you to stef mientki for contributing this function] - """ - - base_html = """\ - - - - - %(css)s - %(title)s - - - - - -""" - - filename = os.path.split ( source_file )[1] - mod_name = os.path.splitext ( filename )[0] - file_name = os.path.join ( dest_path, mod_name + '.html' ) - - # if html file in output directory exists, leave it alone. - if os.path.exists ( file_name ): - return 0 - - if os.path.exists ( - os.path.join ( dest_path, mod_name + '.css' ) ) : - css = "" - elif os.path.exists ( - os.path.join ( dest_path, 'pyjamas_default.css' ) ) : - css = "" - - else: - css = '' - - title = 'PyJamas Auto-Generated HTML file ' + mod_name - - base_html = base_html % {'modulename': mod_name, 'title': title, 'css': css} - - fh = open (file_name, 'w') - fh.write (base_html) - fh.close () - - return 1 - - -def build(app_name, output, js_includes=(), debug=False, dynamic=0, - data_dir=None, cache_buster=False, optimize=False): - - # make sure the output directory is always created in the current working - # directory or at the place given if it is an absolute path. - output = os.path.abspath(output) - msg = "Building '%(app_name)s' to output directory '%(output)s'" % locals() - if debug: - msg += " with debugging statements" - print msg - - # check the output directory - if os.path.exists(output) and not os.path.isdir(output): - print >>sys.stderr, "Output destination %s exists and is not a directory" % output - return - if not os.path.isdir(output): - try: - print "Creating output directory" - os.mkdir(output) - except StandardError, e: - print >>sys.stderr, "Exception creating output directory %s: %s" % (output, e) - - ## public dir - for p in pyjs.path: - pub_dir = join(p, 'public') - if isdir(pub_dir): - print "Copying: public directory of library %r" % p - copytree_exists(pub_dir, output) - - ## AppName.html - can be in current or public directory - html_input_filename = app_name + ".html" - html_output_filename = join(output, basename(html_input_filename)) - if os.path.isfile(html_input_filename): - if not os.path.isfile(html_output_filename) or \ - os.path.getmtime(html_input_filename) > \ - os.path.getmtime(html_output_filename): - try: - shutil.copy(html_input_filename, html_output_filename) - except: - print >>sys.stderr, "Warning: Missing module HTML file %s" % html_input_filename - - print "Copying: %(html_input_filename)s" % locals() - - if check_html_file(html_input_filename, output): - print >>sys.stderr, "Warning: Module HTML file %s has been auto-generated" % html_input_filename - - ## pygwt.js - - print "Copying: pygwt.js" - - pygwt_js_template = read_boilerplate(data_dir, "pygwt.js") - pygwt_js_output = open(join(output, "pygwt.js"), "w") - - print >>pygwt_js_output, pygwt_js_template - - pygwt_js_output.close() - - ## Images - - print "Copying: Images and History" - copy_boilerplate(data_dir, "corner_dialog_topleft_black.png", output) - copy_boilerplate(data_dir, "corner_dialog_topright_black.png", output) - copy_boilerplate(data_dir, "corner_dialog_bottomright_black.png", output) - copy_boilerplate(data_dir, "corner_dialog_bottomleft_black.png", output) - copy_boilerplate(data_dir, "corner_dialog_edge_black.png", output) - copy_boilerplate(data_dir, "corner_dialog_topleft.png", output) - copy_boilerplate(data_dir, "corner_dialog_topright.png", output) - copy_boilerplate(data_dir, "corner_dialog_bottomright.png", output) - copy_boilerplate(data_dir, "corner_dialog_bottomleft.png", output) - copy_boilerplate(data_dir, "corner_dialog_edge.png", output) - copy_boilerplate(data_dir, "tree_closed.gif", output) - copy_boilerplate(data_dir, "tree_open.gif", output) - copy_boilerplate(data_dir, "tree_white.gif", output) - copy_boilerplate(data_dir, "history.html", output) - - - ## all.cache.html - app_files = generateAppFiles(data_dir, js_includes, app_name, debug, - output, dynamic, cache_buster, optimize) - - ## AppName.nocache.html - - print "Creating: %(app_name)s.nocache.html" % locals() - - home_nocache_html_template = read_boilerplate(data_dir, "home.nocache.html") - home_nocache_html_output = open(join(output, app_name + ".nocache.html"), - "w") - - # the selector templ is added to the selectScript function - select_tmpl = """O(["true","%s"],"%s");""" - script_selectors = StringIO() - - for platform, file_prefix in app_files: - print >> script_selectors, select_tmpl % (platform, file_prefix) - - print >>home_nocache_html_output, home_nocache_html_template % dict( - app_name = app_name, - script_selectors = script_selectors.getvalue(), - ) - - home_nocache_html_output.close() - - print "Done. You can run your app by opening '%(html_output_filename)s' in a browser" % locals() - - -def generateAppFiles(data_dir, js_includes, app_name, debug, output, dynamic, - cache_buster, optimize): - - all_cache_html_template = read_boilerplate(data_dir, "all.cache.html") - mod_cache_html_template = read_boilerplate(data_dir, "mod.cache.html") - - # clean out the old ones first - for name in os.listdir(output): - if CACHE_HTML_PAT.match(name): - p = join(output, name) - print "Deleting existing app file %s" % p - os.unlink(p) - - app_files = [] - tmpl = read_boilerplate(data_dir, "all.cache.html") - parser = pyjs.PlatformParser("platform") - app_headers = '' - scripts = [''%script \ - for script in js_includes] - app_body = '\n'.join(scripts) - - mod_code = {} - mod_libs = {} - modules = {} - app_libs = {} - early_app_libs = {} - app_code = {} - overrides = {} - pover = {} - app_modnames = {} - mod_levels = {} - - # First, generate all the code. - # Second, (dynamic only), post-analyse the places where modules - # haven't changed - # Third, write everything out. - - for platform in app_platforms: - - mod_code[platform] = {} - mod_libs[platform] = {} - modules[platform] = [] - pover[platform] = {} - app_libs[platform] = '' - early_app_libs[platform] = '' - app_code[platform] = {} - app_modnames[platform] = {} - - # Application.Platform.cache.html - - parser.setPlatform(platform) - app_translator = pyjs.AppTranslator( - parser=parser, dynamic=dynamic, optimize=optimize) - early_app_libs[platform], appcode = \ - app_translator.translate(None, is_app=False, - debug=debug, - library_modules=['dynamicajax.js', - '_pyjs.js', 'sys', - 'pyjslib']) - pover[platform].update(app_translator.overrides.items()) - for mname, name in app_translator.overrides.items(): - pd = overrides.setdefault(mname, {}) - pd[platform] = name - - print appcode - #mod_code[platform][app_name] = appcode - - # platform.Module.cache.js - - modules_done = ['pyjslib', 'sys', '_pyjs.js'] - #modules_to_do = [app_name] + app_translator.library_modules - modules_to_do = [app_name] + app_translator.library_modules - - dependencies = {} - - deps = map(pyjs.strip_py, modules_to_do) - for d in deps: - sublist = add_subdeps(dependencies, d) - modules_to_do += sublist - deps = uniquify(deps) - #dependencies[app_name] = deps - - modules[platform] = modules_done + modules_to_do - - while modules_to_do: - - #print "modules to do", modules_to_do - - mn = modules_to_do.pop() - mod_name = pyjs.strip_py(mn) - - if mod_name in modules_done: - continue - - modules_done.append(mod_name) - - mod_cache_name = "%s.%s.cache.js" % (platform.lower(), mod_name) - - parser.setPlatform(platform) - mod_translator = pyjs.AppTranslator(parser=parser, optimize=optimize) - mod_libs[platform][mod_name], mod_code[platform][mod_name] = \ - mod_translator.translate(mod_name, - is_app=False, - debug=debug) - pover[platform].update(mod_translator.overrides.items()) - for mname, name in mod_translator.overrides.items(): - pd = overrides.setdefault(mname, {}) - pd[platform] = name - - mods = mod_translator.library_modules - modules_to_do += mods - modules[platform] += mods - - deps = map(pyjs.strip_py, mods) - sd = subdeps(mod_name) - if len(sd) > 1: - deps += sd[:-1] - while mod_name in deps: - deps.remove(mod_name) - - #print - #print - #print "modname preadd:", mod_name, deps - #print - #print - for d in deps: - sublist = add_subdeps(dependencies, d) - modules_to_do += sublist - modules_to_do += add_subdeps(dependencies, mod_name) - #print "modname:", mod_name, deps - deps = uniquify(deps) - #print "modname:", mod_name, deps - dependencies[mod_name] = deps - - # work out the dependency ordering of the modules - - mod_levels[platform] = make_deps(None, dependencies, modules_done) - - # now write everything out - - for platform in app_platforms: - - early_app_libs_ = early_app_libs[platform] - app_libs_ = app_libs[platform] - app_code_ = app_code[platform] - #modules_ = filter_mods(app_name, modules[platform]) - mods = flattenlist(mod_levels[platform]) - mods.reverse() - modules_ = filter_mods(None, mods) - - for mod_name in modules_: - - mod_code_ = mod_code[platform][mod_name] - - mod_name = pyjs.strip_py(mod_name) - - override_name = "%s.%s" % (platform.lower(), mod_name) - if pover[platform].has_key(override_name): - mod_cache_name = "%s.cache.js" % (override_name) - else: - mod_cache_name = "%s.cache.js" % (mod_name) - - print "Creating: " + mod_cache_name - - modlevels = make_deps(None, dependencies, dependencies[mod_name]) - - modnames = [] - - for md in modlevels: - mnames = map(lambda x: "'%s'" % x, md) - mnames = "new pyjslib.List([\n\t\t\t%s])" % ',\n\t\t\t'.join(mnames) - modnames.append(mnames) - - modnames.reverse() - modnames = "new pyjslib.List([\n\t\t%s\n\t])" % ',\n\t\t'.join(modnames) - - # convert the overrides - - overnames = map(lambda x: "'%s': '%s'" % x, pover[platform].items()) - overnames = "new pyjslib.Dict({\n\t\t%s\n\t})" % ',\n\t\t'.join(overnames) - - if dynamic: - mod_cache_html_output = open(join(output, mod_cache_name), "w") - else: - mod_cache_html_output = StringIO() - - print >>mod_cache_html_output, mod_cache_html_template % dict( - mod_name = mod_name, - app_name = app_name, - modnames = modnames, - overrides = overnames, - mod_libs = mod_libs[platform][mod_name], - dynamic = dynamic, - mod_code = mod_code_, - ) - - if dynamic: - mod_cache_html_output.close() - else: - mod_cache_html_output.seek(0) - app_libs_ += mod_cache_html_output.read() - - # write out the dependency ordering of the modules - - app_modnames = [] - - for md in mod_levels[platform]: - mnames = map(lambda x: "'%s'" % x, md) - mnames = "new pyjslib.List([\n\t\t\t%s])" % ',\n\t\t\t'.join(mnames) - app_modnames.append(mnames) - - app_modnames.reverse() - app_modnames = "new pyjslib.List([\n\t\t%s\n\t])" % ',\n\t\t'.join(app_modnames) - - # convert the overrides - - overnames = map(lambda x: "'%s': '%s'" % x, pover[platform].items()) - overnames = "new pyjslib.Dict({\n\t\t%s\n\t})" % ',\n\t\t'.join(overnames) - - #print "platform names", platform, overnames - #print pover - - # now write app.allcache including dependency-ordered list of - # library modules - - file_contents = all_cache_html_template % dict( - app_name = app_name, - early_app_libs = early_app_libs_, - app_libs = app_libs_, - app_code = app_code_, - app_body = app_body, - overrides = overnames, - platform = platform.lower(), - dynamic = dynamic, - app_modnames = app_modnames, - app_headers = app_headers - ) - if cache_buster: - digest = md5.new(file_contents).hexdigest() - file_name = "%s.%s.%s" % (platform.lower(), app_name, digest) - else: - file_name = "%s.%s" % (platform.lower(), app_name) - file_name += ".cache.html" - out_path = join(output, file_name) - out_file = open(out_path, 'w') - out_file.write(file_contents) - out_file.close() - app_files.append((platform.lower(), file_name)) - print "Created app file %s:%s: %s" % ( - app_name, platform, out_path) - - return app_files - -def flattenlist(ll): - res = [] - for l in ll: - res += l - return res - -# creates sub-dependencies e.g. pyjamas.ui.Widget -# creates pyjamas.ui.Widget, pyjamas.ui and pyjamas. -def subdeps(m): - d = [] - m = m.split(".") - for i in range(0, len(m)): - d.append('.'.join(m[:i+1])) - return d - -import time - -def add_subdeps(deps, mod_name): - sd = subdeps(mod_name) - if len(sd) == 1: - return [] - #print "subdeps", mod_name, sd - #print "deps", deps - res = [] - for i in range(0, len(sd)-1): - parent = sd[i] - child = sd[i+1] - l = deps.get(child, []) - l.append(parent) - deps[child] = l - if parent not in res: - res.append(parent) - #print deps - return res - -# makes unique and preserves list order -def uniquify(md): - res = [] - for m in md: - if m not in res: - res.append(m) - return res - -def filter_mods(app_name, md): - while 'sys' in md: - md.remove('sys') - while 'pyjslib' in md: - md.remove('pyjslib') - while app_name in md: - md.remove(app_name) - md = filter(lambda x: not x.endswith('.js'), md) - md = map(pyjs.strip_py, md) - - return uniquify(md) - -def filter_deps(app_name, deps): - - res = {} - for (k, l) in deps.items(): - mods = filter_mods(k, l) - while k in mods: - mods.remove(k) - res[k] = mods - return res - -def has_nodeps(mod, deps): - if not deps.has_key(mod) or not deps[mod]: - return True - return False - -def nodeps_list(mod_list, deps): - res = [] - for mod in mod_list: - if has_nodeps(mod, deps): - res.append(mod) - return res - -# this function takes a dictionary of dependent modules and -# creates a list of lists. the first list will be modules -# that have no dependencies; the second list will be those -# modules that have the first list as dependencies; the -# third will be those modules that have the first and second... -# etc. - - -def make_deps(app_name, deps, mod_list): - print "Calculating Dependencies ..." - mod_list = filter_mods(app_name, mod_list) - deps = filter_deps(app_name, deps) - - if not mod_list: - return [] - - #print mod_list - #print deps - - ordered_deps = [] - last_len = -1 - while deps: - l_deps = len(deps) - #print l_deps - if l_deps==last_len: - for m, dl in deps.items(): - for d in dl: - if m in deps.get(d, []): - raise Exception('Circular Imports found: \n%s %s -> %s %s' - % (m, dl, d, deps[d])) - #raise Exception('Could not calculate dependencies: \n%s' % deps) - break - last_len = l_deps - #print "modlist", mod_list - nodeps = nodeps_list(mod_list, deps) - #print "nodeps", nodeps - mod_list = filter(lambda x: x not in nodeps, mod_list) - newdeps = {} - for k in deps.keys(): - depslist = deps[k] - depslist = filter(lambda x: x not in nodeps, depslist) - if depslist: - newdeps[k] = depslist - #print "newdeps", newdeps - deps = newdeps - ordered_deps.append(nodeps) - #time.sleep(0) - - if mod_list: - ordered_deps.append(mod_list) # last dependencies - usually the app(s) - - ordered_deps.reverse() - - return ordered_deps - -def main(): - global app_platforms - - parser = OptionParser(usage = usage, version = version) - parser.add_option("-o", "--output", dest="output", - help="directory to which the webapp should be written") - parser.add_option("-j", "--include-js", dest="js_includes", action="append", - help="javascripts to load into the same frame as the rest of the script") - parser.add_option("-I", "--library_dir", dest="library_dirs", - action="append", help="additional paths appended to PYJSPATH") - parser.add_option("-D", "--data_dir", dest="data_dir", - help="path for data directory") - parser.add_option("-m", "--dynamic-modules", action="store_true", - dest="dynamic", default=False, - help="Split output into separate dynamically-loaded modules (experimental)") - parser.add_option("-P", "--platforms", dest="platforms", - help="platforms to build for, comma-separated") - parser.add_option("-d", "--debug", action="store_true", dest="debug") - parser.add_option("-O", "--optimize", action="store_true", - dest="optimize", default=False, - help="Optimize generated code (removes all print statements)", - ) - parser.add_option("-c", "--cache_buster", action="store_true", - dest="cache_buster", - help="Enable browser cache-busting (MD5 hash added to output filenames)") - - parser.set_defaults(output = "output", js_includes=[], library_dirs=[], - platforms=(','.join(app_platforms)), - data_dir=os.path.join(sys.prefix, "share/pyjamas"), - dynamic=False, - cache_buster=False, - debug=False) - (options, args) = parser.parse_args() - if len(args) != 1: - parser.error("incorrect number of arguments") - - data_dir = abspath(options.data_dir) - - app_path = args[0] - if app_path.endswith('.py'): - app_path = abspath(app_path) - if not isfile(app_path): - parser.error("Application file not found %r" % app_path) - app_path, app_name = split(app_path) - app_name = app_name[:-3] - pyjs.path.append(app_path) - elif os.path.sep in app_path: - parser.error("Not a valid module declaration %r" % app_path) - else: - app_name = app_path - - for d in options.library_dirs: - pyjs.path.append(abspath(d)) - - if options.platforms: - app_platforms = options.platforms.split(',') - - # this is mostly for getting boilerplate stuff - data_dir = os.path.abspath(options.data_dir) - - build(app_name, options.output, options.js_includes, - options.debug, options.dynamic and 1 or 0, data_dir, - options.cache_buster, options.optimize) - -if __name__ == "__main__": - main() -