|
@@ -0,0 +1,44 @@
|
|
|
+#!/usr/bin/env python
|
|
|
+
|
|
|
+"""
|
|
|
+Generate an executable Python zip package.
|
|
|
+"""
|
|
|
+
|
|
|
+import os, zipfile, argparse
|
|
|
+
|
|
|
+ap = argparse.ArgumentParser(description = __doc__,
|
|
|
+ formatter_class = argparse.ArgumentDefaultsHelpFormatter)
|
|
|
+ap.add_argument("-o", "--output", required = True, type = argparse.FileType("wb+"))
|
|
|
+ap.add_argument("-m", "--module", default = "main", help = "module within package to run")
|
|
|
+ap.add_argument("-e", "--executable", default = "python", help = "python executable to run")
|
|
|
+ap.add_argument("source")
|
|
|
+args = ap.parse_args()
|
|
|
+
|
|
|
+# PyZipFile.writepy()'s behavior changes when it sees __init__.py
|
|
|
+if os.path.exists(os.path.join(args.source, "__init__.py")):
|
|
|
+ module = "{0.source}.{0.module}".format(args)
|
|
|
+else:
|
|
|
+ module = args.module
|
|
|
+
|
|
|
+# Write executable shim
|
|
|
+args.output.write('''\
|
|
|
+#/bin/sh -
|
|
|
+PYTHONPATH="$0"${{PYTHONPATH+":$PYTHONPATH"}} exec {e} -m {m} ${{1+"$@"}}
|
|
|
+'''.format(m = module, e = args.executable).encode("ascii"))
|
|
|
+
|
|
|
+# Make output executable
|
|
|
+os.fchmod(args.output.fileno(), 0o755)
|
|
|
+
|
|
|
+# Create the zip file and populate it with the code
|
|
|
+z = zipfile.PyZipFile(args.output, "a", zipfile.ZIP_DEFLATED)
|
|
|
+z.writepy(args.source)
|
|
|
+
|
|
|
+# Add data files, if any
|
|
|
+if os.path.isdir(args.source):
|
|
|
+ for root, dirs, files in os.walk(args.source):
|
|
|
+ for fn in files:
|
|
|
+ if not any(fn.endswith(fn2) for fn2 in (".py", ".pyc", ".pyo")):
|
|
|
+ z.write(os.path.join(root, fn))
|
|
|
+
|
|
|
+# Test the zip file we just generated out of paranoia
|
|
|
+z.testzip()
|