--- a/svgui/pyjs/build.py Fri Oct 01 15:36:09 2021 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,774 +0,0 @@
-#!/usr/bin/env python
-
-
-from __future__ import absolute_import
-from __future__ import print_function
-import sys
-import shutil
-import re
-import os
-from os.path import join, basename, abspath, split, isfile, isdir
-from hashlib import md5
-from optparse import OptionParser
-from six.moves import cStringIO
-
-from svgui.pyjs import pyjs
-
-
-usage = """
- usage: %prog [options] <application module name or path>
-
-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(r'^[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 Exception:
- 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) as 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 = """\
-<html>
- <!-- auto-generated html - you should consider editing and
- adapting this to suit your requirements
- -->
- <head>
- <meta name="pygwt:module" content="%(modulename)s">
- %(css)s
- <title>%(title)s</title>
- </head>
- <body bgcolor="white">
- <script language="javascript" src="pygwt.js"></script>
- </body>
-</html>
-"""
-
- 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 = "<link rel='stylesheet' href='" + mod_name + ".css'>"
- elif os.path.exists(os.path.join(dest_path, 'pyjamas_default.css')):
- css = "<link rel='stylesheet' href='pyjamas_default.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("Output destination %s exists and is not a directory" % output, file=sys.stderr)
- return
- if not os.path.isdir(output):
- try:
- print("Creating output directory")
- os.mkdir(output)
- except OSError as e:
- print("Exception creating output directory %s: %s" % (output, e), file=sys.stderr)
-
- # 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 Exception:
- print("Warning: Missing module HTML file %s" % html_input_filename, file=sys.stderr)
-
- print("Copying: %(html_input_filename)s" % locals())
-
- if check_html_file(html_input_filename, output):
- print("Warning: Module HTML file %s has been auto-generated" % html_input_filename, file=sys.stderr)
-
- # 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_template, file=pygwt_js_output)
-
- 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 = cStringIO()
-
- for platform, file_prefix in app_files:
- print(select_tmpl % (platform, file_prefix), file=script_selectors)
-
- print(
- home_nocache_html_template % dict(
- app_name=app_name,
- script_selectors=script_selectors.getvalue(),
- ), file=home_nocache_html_output)
-
- 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 = []
- parser = pyjs.PlatformParser("platform")
- app_headers = ''
- scripts = ['<script type="text/javascript" src="%s"></script>' %
- 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 override_name in pover[platform]:
- 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 = cStringIO()
-
- print(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_,
- ), file=mod_cache_html_output)
-
- 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
-
-
-def subdeps(m):
- """
- creates sub-dependencies e.g. pyjamas.ui.Widget
- creates pyjamas.ui.Widget, pyjamas.ui and pyjamas.
- """
- d = []
- m = m.split(".")
- for i in range(0, len(m)):
- d.append('.'.join(m[:i+1]))
- return d
-
-
-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]
- k = deps.get(child, [])
- k.append(parent)
- deps[child] = k
- if parent not in res:
- res.append(parent)
- # print deps
- return res
-
-
-def uniquify(md):
- """
- makes unique and preserves list order
- """
- 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 mod not in deps 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()