src.shell.jython.py Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jython Show documentation
Show all versions of jython Show documentation
Jython is an implementation of the high-level, dynamic, object-oriented
language Python written in 100% Pure Java, and seamlessly integrated with
the Java platform. It thus allows you to run Python on any Java platform.
#!/usr/bin/env python2.7 -E
# -*- coding: utf-8 -*-
# bin/jython.py
# Launch script for Jython, generally to be compiled by tools like py2exe.
# However it is an alternative to the bin/jython bash script.
#
# Designed to be executed by CPython 2.7, although it may make sense for some
# scenarios to be executed by Jython instead - inside a jar for example.
#
# FIXME consider how to use this to support standalone jython jar
import argparse
import glob
import inspect
import os
import os.path
import pipes
import subprocess
import sys
from collections import OrderedDict
is_windows = os.name == "nt" or (os.name == "java" and os._name == "nt")
def make_parser():
parser = argparse.ArgumentParser(description="Jython", add_help=False)
parser.add_argument("-D", dest="properties", action="append")
parser.add_argument("-J", dest="java", action="append")
parser.add_argument("--boot", action="store_true")
parser.add_argument("--jdb", action="store_true")
parser.add_argument("--help", "-h", action="store_true")
parser.add_argument("--print", dest="print_requested", action="store_true")
parser.add_argument("--profile", action="store_true")
args, remainder = parser.parse_known_args()
items = args.java or []
args.java = []
for item in items:
if item.startswith("-Xmx"):
args.mem = item
elif item.startswith("-Xss"):
args.stack = item
else:
args.java.append(item)
# need to account for the fact that -c and -cp/-classpath are ambiguous options as far
# as argparse is concerned, so parse separately
args.classpath = []
r = iter(remainder)
r2 = []
while True:
try:
arg = next(r)
except StopIteration:
break
if arg == "-cp" or arg == "-classpath":
args.classpath = next(r)
else:
r2.append(arg)
remainder = r2
if args.properties is None:
args.properties = []
props = OrderedDict()
for kv in args.properties:
k, v = kv.split("=")
props[k] = v
args.properties = props
args.encoding = args.properties.get("file.encoding", None)
return parser, args, remainder
class JythonCommand(object):
def __init__(self, parser, args, jython_args):
self.parser = parser
self.args = args
self.jython_args = jython_args
@property
def uname(self):
if hasattr(self, "_uname"):
return self._uname
if is_windows:
self._uname = "windows"
else:
uname = subprocess.check_output(["uname"]).strip().lower()
if uname.startswith("cygwin"):
self._uname = "cygwin"
else:
self._uname = uname
return self._uname
@property
def java_home(self):
if not hasattr(self, "_java_home"):
self.setup_java_command()
return self._java_home
@property
def java_command(self):
if not hasattr(self, "_java_command"):
self.setup_java_command()
return self._java_command
def setup_java_command(self):
if "JAVA_HOME" not in os.environ:
self._java_home = None
self._java_command = "jdb" if self.args.jdb else "java"
else:
self._java_home = os.environ["JAVA_HOME"]
#if self.uname == "cygwin":
# self._java_home = subprocess.check_output(["cygpath", "--windows", self._java_home]).strip()
if self.uname == "cygwin":
self._java_command = "jdb" if self.args.jdb else "java"
else:
self._java_command = os.path.join(
self.java_home, "bin",
"jdb" if self.args.jdb else "java")
@property
def executable(self):
"""Path to executable"""
if hasattr(self, "_executable"):
return self._executable
# Modified from
# http://stackoverflow.com/questions/3718657/how-to-properly-determine-current-script-directory-in-python/22881871#22881871
if getattr(sys, "frozen", False): # py2exe, PyInstaller, cx_Freeze
path = os.path.abspath(sys.executable)
else:
def inspect_this(): pass
path = inspect.getabsfile(inspect_this)
self._executable = os.path.realpath(path)
return self._executable
@property
def jython_home(self):
if hasattr(self, "_jython_home"):
return self._jython_home
if "JYTHON_HOME" in os.environ:
self._jython_home = os.environ["JYTHON_HOME"]
else:
self._jython_home = os.path.dirname(os.path.dirname(self.executable))
if self.uname == "cygwin":
self._jython_home = subprocess.check_output(["cygpath", "--windows", self._jython_home]).strip()
return self._jython_home
@property
def jython_opts():
return os.environ.get("JYTHON_OPTS", "")
@property
def classpath_delimiter(self):
return ";" if (is_windows or self.uname == "cygwin") else ":"
@property
def classpath(self):
if hasattr(self, "_classpath"):
return self._classpath
if os.path.exists(os.path.join(self.jython_home, "jython-dev.jar")):
jars = [os.path.join(self.jython_home, "jython-dev.jar")]
jars.append(os.path.join(self.jython_home, "javalib", "*"))
elif not os.path.exists(os.path.join(self.jython_home, "jython.jar")):
self.parser.error(
"""{executable}:
{jython_home} contains neither jython-dev.jar nor jython.jar.
Try running this script from the 'bin' directory of an installed Jython or
setting {envvar_specifier}JYTHON_HOME.""".\
format(
executable=self.executable,
jython_home=self.jython_home,
envvar_specifier="%" if self.uname == "windows" else "$"))
else:
jars = [os.path.join(self.jython_home, "jython.jar")]
self._classpath = self.classpath_delimiter.join(jars)
if self.args.classpath and not self.args.boot:
self._classpath += self.classpath_delimiter + self.args.classpath
return self._classpath
@property
def java_mem(self):
if hasattr(self.args.java, "mem"):
return self.args.java.mem
else:
return os.environ.get("JAVA_MEM", "-Xmx512m")
@property
def java_stack(self):
if hasattr(self.args.java, "stack"):
return self.args.java.mem
else:
return os.environ.get("JAVA_STACK", "-Xss1024k")
@property
def java_opts(self):
if "JAVA_OPTS" in os.environ:
options = os.environ["JAVA_OPTS"].split()
else:
options = []
options.extend([self.java_mem, self.java_stack])
return options
@property
def java_profile_agent(self):
return os.path.join(self.jython_home, "javalib", "profile.jar")
def set_encoding(self):
if "JAVA_ENCODING" not in os.environ and self.uname == "darwin" and "file.encoding" not in self.args.properties:
self.args.properties["file.encoding"] = "UTF-8"
def convert(self, arg):
if sys.stdout.encoding:
return arg.encode(sys.stdout.encoding)
else:
return arg
def convert_path(self, arg):
if self.uname == "cygwin":
if not arg.startswith("/cygdrive/"):
new_path = self.convert(arg).replace("/", "\\")
else:
new_path = subprocess.check_output(["cygpath", "-pw", self.convert(arg)]).strip()
return new_path
else:
return self.convert(arg)
@property
def command(self):
self.set_encoding()
args = [self.java_command]
args.extend(self.java_opts)
args.extend(self.args.java)
if self.args.boot:
args.append("-Xbootclasspath/a:%s" % self.convert_path(self.classpath))
if self.args.classpath:
args.extend(["-classpath", self.convert_path(self.args.classpath)])
else:
args.extend(["-classpath", self.convert_path(self.classpath)])
if "python.home" not in self.args.properties:
args.append("-Dpython.home=%s" % self.convert_path(self.jython_home))
if "python.executable" not in self.args.properties:
args.append("-Dpython.executable=%s" % self.convert_path(self.executable))
if "python.launcher.uname" not in self.args.properties:
args.append("-Dpython.launcher.uname=%s" % self.uname)
# determine if is-a-tty for the benefit of running on cygwin - mintty doesn't behave like
# a standard windows tty and so JNR posix doesn't detect it properly
if "python.launcher.tty" not in self.args.properties:
args.append("-Dpython.launcher.tty=%s" % str(os.isatty(sys.stdin.fileno())).lower())
if self.uname == "cygwin" and "python.console" not in self.args.properties:
args.append("-Dpython.console=org.python.core.PlainConsole")
if self.args.profile:
args.append("-XX:-UseSplitVerifier")
args.append("-javaagent:%s" % self.convert_path(self.java_profile_agent))
for k, v in self.args.properties.iteritems():
args.append("-D%s=%s" % (self.convert(k), self.convert(v)))
args.append("org.python.util.jython")
if self.args.help:
args.append("--help")
args.extend(self.jython_args)
return args
def print_help():
print >> sys.stderr, """
Jython launcher options:
-Jarg : pass argument through to Java VM (e.g. -J-Xmx512m)
--jdb : run under JDB
--print : print the Java command instead of executing it
--profile: run with the Java Interactive Profiler (http://jiprof.sf.net)
--boot : put jython on the boot classpath (disables the bytecode verifier)
-- : pass remaining arguments through to Jython
Jython launcher environment variables:
JAVA_HOME : Java installation directory
JYTHON_HOME: Jython installation directory
JYTHON_OPTS: default command line arguments
"""
def main():
if sys.stdout.encoding:
if sys.stdout.encoding.lower() == "cp65001":
sys.exit("""Jython does not support code page 65001 (CP_UTF8).
Please try another code page by setting it with the chcp command.""")
sys.argv = [arg.decode(sys.stdout.encoding) for arg in sys.argv]
parser, args, jython_args = make_parser()
jython_command = JythonCommand(parser, args, jython_args)
command = jython_command.command
if args.profile:
try:
os.unlink("profile.txt")
except OSError:
pass
if args.print_requested:
if jython_command.uname == "windows":
print subprocess.list2cmdline(jython_command.command)
else:
print " ".join(pipes.quote(arg) for arg in jython_command.command)
else:
if not (is_windows or not hasattr(os, "execvp") or args.help or jython_command.uname == "cygwin"):
# Replace this process with the java process.
#
# NB such replacements actually do not work under Windows,
# but if tried, they also fail very badly by hanging.
# So don't even try!
os.execvp(command[0], command[1:])
else:
result = 1
try:
result = subprocess.call(command)
if args.help:
print_help()
except KeyboardInterrupt:
pass
sys.exit(result)
if __name__ == "__main__":
main()