org.python.core.PySystemState Maven / Gradle / Ivy
// Copyright (c) Corporation for National Research Initiatives // This class implements the standard Python sys module. package org.python.core; import java.io.File; import java.io.FileInputStream; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLDecoder; import java.security.AccessControlException; import java.util.Enumeration; import java.util.Hashtable; import java.util.Properties; import java.util.StringTokenizer; import java.util.jar.JarEntry; import java.util.jar.JarFile; import org.python.core.adapter.ClassicPyObjectAdapter; import org.python.core.adapter.ExtensiblePyObjectAdapter; import org.python.modules.Setup; /** * The "sys" module. */ // xxx this should really be a module! public class PySystemState extends PyObject { public static final String JYTHON_JAR = "jython.jar"; private static final String JAR_URL_PREFIX = "jar:file:"; private static final String JAR_SEPARATOR = "!"; private static final String PYTHON_CACHEDIR = "python.cachedir"; protected static final String PYTHON_CACHEDIR_SKIP = "python.cachedir.skip"; protected static final String CACHEDIR_DEFAULT_NAME = "cachedir"; /** * The current version of Jython. *
if we have a standalone .jar file,* Usually updated by hand.
* Replaced by ant when doing a snapshot build. ** This also applies for the
PY_*
integer values below */ public static String version = "2.2"; private static int PY_MAJOR_VERSION = 2; private static int PY_MINOR_VERSION = 2; private static int PY_MICRO_VERSION = 0; private static int PY_RELEASE_LEVEL = 0x0F; private static int PY_RELEASE_SERIAL = 0; public static int hexversion = ((PY_MAJOR_VERSION << 24) | (PY_MINOR_VERSION << 16) | (PY_MICRO_VERSION << 8) | (PY_RELEASE_LEVEL << 4) | (PY_RELEASE_SERIAL << 0)); public static PyTuple version_info; public static int maxunicode = 65535; /** * The copyright notice for this release. */ // TBD: should we use \u00a9 Unicode c-inside-circle? public static String copyright = "Copyright (c) 2000-2007, Jython Developers\n" + "All rights reserved.\n\n" + "Copyright (c) 2000 BeOpen.com.\n" + "All Rights Reserved.\n\n"+ "Copyright (c) 2000 The Apache Software Foundation. All rights\n" + "reserved.\n\n" + "Copyright (c) 1995-2000 Corporation for National Research "+ "Initiatives.\n" + "All Rights Reserved.\n\n" + "Copyright (c) 1991-1995 Stichting Mathematisch Centrum, " + "Amsterdam.\n" + "All Rights Reserved.\n\n"; /** * The arguments passed to this program on the command line. */ public PyList argv = new PyList(); /** * Exit a Python program with the given status. * * @param status the value to exit with * @exception Py.SystemExit always throws this exception. * When caught at top level the program will exit. */ public static void exit(PyObject status) { throw new PyException(Py.SystemExit, status); } /** * Exit a Python program with the status 0. */ public static void exit() { exit(Py.None); } public PyObject modules; public PyList path; public static PyObject builtins; public PyList meta_path; public PyList path_hooks; public PyObject path_importer_cache; public static String platform = "java"; public static String byteorder = "big"; public PyObject ps1 = new PyString(">>> "); public PyObject ps2 = new PyString("... "); public static int maxint = Integer.MAX_VALUE; public static int minint = Integer.MIN_VALUE; public PyObject executable = Py.None; public static PyList warnoptions; private ClassLoader classLoader = null; public ClassLoader getClassLoader() { return classLoader; } public void setClassLoader(ClassLoader classLoader) { this.classLoader = classLoader; } public static PyTuple exc_info() { PyException exc = Py.getThreadState().exception; if (exc == null) return new PyTuple(new PyObject[] {Py.None,Py.None,Py.None}); return new PyTuple(new PyObject[] {exc.type, exc.value, exc.traceback}); } public static PyFrame _getframe() { return _getframe(-1); } public static PyFrame _getframe(int depth) { PyFrame f = Py.getFrame(); while (depth > 0 && f != null) { f = f.f_back; --depth; } if (f == null) throw Py.ValueError("call stack is not deep enough"); return f; } public PyObject stdout, stderr, stdin; public PyObject __stdout__, __stderr__, __stdin__; public PyObject __displayhook__, __excepthook__; public PyObject last_value = Py.None; public PyObject last_type = Py.None; public PyObject last_traceback = Py.None; // xxx fix this accessors public PyObject __findattr__(String name) { if (name == "exc_value") { PyException exc = Py.getThreadState().exception; if (exc == null) return null; return exc.value; } if (name == "exc_type") { PyException exc = Py.getThreadState().exception; if (exc == null) return null; return exc.type; } if (name == "exc_traceback") { PyException exc = Py.getThreadState().exception; if (exc == null) return null; return exc.traceback; } if (name == "warnoptions") { if (warnoptions == null) warnoptions = new PyList(); return warnoptions; } PyObject ret = super.__findattr__(name); if (ret != null) return ret; return __dict__.__finditem__(name); } public PyObject __dict__; public void __setattr__(String name, PyObject value) { PyType selftype = getType(); if (selftype == null) return; PyObject ret = selftype.lookup(name); // xxx fix fix fix if (ret != null) { ret.jtryset(this, value); return; } if (__dict__ == null) { __dict__ = new PyStringMap(); } __dict__.__setitem__(name, value); //throw Py.AttributeError(name); } public void __delattr__(String name) { if (__dict__ != null) { __dict__.__delitem__(name); return; } throw Py.AttributeError("del '"+name+"'"); } // xxx public void __rawdir__(PyDictionary accum) { accum.update(__dict__); } public String safeRepr() throws PyIgnoreMethodTag { return "module 'sys'"; } public String toString() { return "sys module"; } private int recursionlimit = 1000; public int getrecursionlimit() { return recursionlimit; } public void setrecursionlimit(int recursionlimit) { if(recursionlimit <= 0) { throw Py.ValueError("Recursion limit must be positive"); } this.recursionlimit = recursionlimit; } // xxx fix and polish this public PySystemState() { initialize(); modules = new PyStringMap(); argv = (PyList)defaultArgv.repeat(1); path = (PyList)defaultPath.repeat(1); path.append(Py.newString("__classpath__")); meta_path = new PyList(); meta_path.append(new PrecompiledImporter()); path_hooks = new PyList(); path_hooks.append(new JavaImporter()); path_hooks.append(PyJavaClass.lookup(ZipFileImporter.class)); path_importer_cache = new PyDictionary(); // Set up the initial standard ins and outs __stdout__ = stdout = new PyFile(System.out, ""); __stderr__ = stderr = new PyFile(System.err, " "); __stdin__ = stdin = new PyFile(getSystemIn(), " "); __displayhook__ = new PySystemStateFunctions("displayhook", 10, 1, 1); __excepthook__ = new PySystemStateFunctions("excepthook", 30, 3, 3); // This isn't quite right... if(builtins == null){ builtins = new PyStringMap(); __builtin__.fillWithBuiltins(builtins); } PyModule __builtin__ = new PyModule("__builtin__", builtins); modules.__setitem__("__builtin__", __builtin__); if (getType() != null) { __dict__ = new PyStringMap(); __dict__.invoke("update", getType().getDict()); __dict__.__setitem__("displayhook", __displayhook__); __dict__.__setitem__("excepthook", __excepthook__); } } private static PyList defaultPath; private static PyList defaultArgv; public static Properties registry; // = init_registry(); public static String prefix; public static String exec_prefix=""; private static String findRoot(Properties preProperties, Properties postProperties, String jarFileName) { String root = null; try { if (postProperties != null) root = postProperties.getProperty("python.home"); if (root == null) root = preProperties.getProperty("python.home"); if (root == null) root = preProperties.getProperty("install.root"); String version = preProperties.getProperty("java.version"); if (version == null) version = "???"; String lversion = version.toLowerCase(); if (lversion.startsWith("java")) version = version.substring(4, version.length()); if (lversion.startsWith("jdk") || lversion.startsWith("jre")) { version = version.substring(3, version.length()); } if (version.equals("12")) version = "1.2"; if (version != null) platform = "java"+version; } catch (Exception exc) { return null; } // If install.root is undefined find JYTHON_JAR in class.path if (root == null) { String classpath = preProperties.getProperty("java.class.path"); if (classpath != null) { int jpy = classpath.toLowerCase().indexOf(JYTHON_JAR); if (jpy >= 0) { int start = classpath.lastIndexOf(java.io.File.pathSeparator, jpy) + 1; root = classpath.substring(start, jpy); } else { // in case JYTHON_JAR is referenced from a MANIFEST inside another jar on the classpath root = jarFileName; } } } return root; } private static void initRegistry(Properties preProperties, Properties postProperties, boolean standalone, String jarFileName) { if (registry != null) { Py.writeError("systemState", "trying to reinitialize registry"); return; } registry = preProperties; prefix = exec_prefix = findRoot(preProperties, postProperties, jarFileName); // Load the default registry if (prefix != null) { if (prefix.length() == 0) { prefix = exec_prefix = "."; } try { addRegistryFile(new File(prefix, "registry")); File homeFile = new File(registry.getProperty("user.home"), ".jython"); addRegistryFile(homeFile); } catch (Exception exc) { } } if (postProperties != null) { for (Enumeration e=postProperties.keys(); e.hasMoreElements();) { String key = (String)e.nextElement(); String value = (String)postProperties.get(key); registry.put(key, value); } } if (standalone) { // set default standalone property (if not yet set) if (!registry.containsKey(PYTHON_CACHEDIR_SKIP)) { registry.put(PYTHON_CACHEDIR_SKIP, "true"); } } // Set up options from registry Options.setFromRegistry(); } private static void addRegistryFile(File file) { if (file.exists()) { if (!file.isDirectory()) { registry = new Properties(registry); try { FileInputStream fp = new FileInputStream(file); try { registry.load(fp); } finally { fp.close(); } } catch (IOException e) { System.err.println("couldn't open registry file: " + file.toString()); } } else { System.err.println("warning: " + file.toString() + " is a directory, not a file"); } } } private static boolean initialized = false; public static Properties getBaseProperties(){ try{ return System.getProperties(); }catch(AccessControlException ace){ return new Properties(); } } public static synchronized void initialize() { if (initialized) return; initialize(getBaseProperties(), null, new String[] {""}); } public static synchronized void initialize(Properties preProperties, Properties postProperties, String[] argv) { initialize(preProperties, postProperties, argv, null); } public static synchronized void initialize(Properties preProperties, Properties postProperties, String[] argv, ClassLoader classLoader) { initialize(preProperties, postProperties, argv, classLoader, new ClassicPyObjectAdapter()); } public static synchronized void initialize(Properties preProperties, Properties postProperties, String[] argv, ClassLoader classLoader, ExtensiblePyObjectAdapter adapter) { //System.err.println("initializing system state"); //Thread.currentThread().dumpStack(); if (initialized) { //if (postProperties != null) { // Py.writeError("systemState", // "trying to reinitialize with new " + // "properties"); //} return; } initialized = true; Py.setAdapter(adapter); boolean standalone = false; String jarFileName = getJarFileName(); if (jarFileName != null) { standalone = isStandalone(jarFileName); } // initialize the JPython registry initRegistry(preProperties, postProperties, standalone, jarFileName); // other initializations initBuiltins(registry); initStaticFields(); // Initialize the path (and add system defaults) defaultPath = initPath(registry, standalone, jarFileName); defaultArgv = initArgv(argv); // Set up the known Java packages initPackages(registry); // Finish up standard Python initialization... Py.defaultSystemState = new PySystemState(); Py.setSystemState(Py.defaultSystemState); if (classLoader != null) Py.defaultSystemState.setClassLoader(classLoader); Py.initClassExceptions(PySystemState.builtins); // Make sure that Exception classes have been loaded new PySyntaxError("", 1,1,"", ""); } private static void initStaticFields() { Py.None = new PyNone(); Py.NotImplemented = new PyNotImplemented(); Py.NoKeywords = new String[0]; Py.EmptyObjects = new PyObject[0]; Py.EmptyTuple = new PyTuple(Py.EmptyObjects); Py.NoConversion = new PySingleton("Error"); Py.Ellipsis = new PyEllipsis(); Py.Zero = new PyInteger(0); Py.One = new PyInteger(1); Py.EmptyString = new PyString(""); Py.Newline = new PyString("\n"); Py.Space = new PyString(" "); // Setup standard wrappers for stdout and stderr... Py.stderr = new StderrWrapper(); Py.stdout = new StdoutWrapper(); String s = null; if (PY_RELEASE_LEVEL == 0x0A) s = "alpha"; else if (PY_RELEASE_LEVEL == 0x0B) s = "beta"; else if (PY_RELEASE_LEVEL == 0x0C) s = "candidate"; else if (PY_RELEASE_LEVEL == 0x0F) s = "final"; else if (PY_RELEASE_LEVEL == 0xAA) s = "snapshot"; version_info = new PyTuple(new PyObject[] { Py.newInteger(PY_MAJOR_VERSION), Py.newInteger(PY_MINOR_VERSION), Py.newInteger(PY_MICRO_VERSION), Py.newString(s), Py.newInteger(PY_RELEASE_SERIAL) }); } public static PackageManager packageManager; public static File cachedir; private static void initCacheDirectory(Properties props) { if (Py.frozen) { cachedir = null; return; } String skip = props.getProperty(PYTHON_CACHEDIR_SKIP, "false"); if (skip.equalsIgnoreCase("true")) { cachedir = null; return; } cachedir = new File(props.getProperty(PYTHON_CACHEDIR, CACHEDIR_DEFAULT_NAME)); if (!cachedir.isAbsolute()) { cachedir = new File(PySystemState.prefix, cachedir.getPath()); } } private static void initPackages(Properties props) { initCacheDirectory(props); File pkgdir; if (cachedir != null) { pkgdir = new File(cachedir, "packages"); } else { pkgdir = null; } packageManager = new SysPackageManager(pkgdir, props); } private static PyList initArgv(String[] args) { PyList argv = new PyList(); if (args != null) { for (int i=0; i true false
otherwise. */ private static boolean isStandalone(String jarFileName) { boolean standalone = false; if (jarFileName != null) { JarFile jarFile = null; try { jarFile = new JarFile(jarFileName); JarEntry jarEntry = jarFile.getJarEntry("Lib/javaos.py"); standalone = jarEntry != null; } catch (IOException ioe) { } finally { if (jarFile != null) { try { jarFile.close(); } catch (IOException e) { } } } } return standalone; } /** * @return the full name of the jar file containing this class,null
if not available. */ private static String getJarFileName() { String jarFileName = null; Class thisClass = PySystemState.class; String fullClassName = thisClass.getName(); String className = fullClassName.substring(fullClassName.lastIndexOf(".") + 1); URL url = thisClass.getResource(className + ".class"); // we expect an URL like jar:file:/install_dir/jython.jar!/org/python/core/PySystemState.class if (url != null) { try { String urlString = URLDecoder.decode(url.toString()); int jarSeparatorIndex = urlString.indexOf(JAR_SEPARATOR); if (urlString.startsWith(JAR_URL_PREFIX) && jarSeparatorIndex > 0) { jarFileName = urlString.substring(JAR_URL_PREFIX.length(), jarSeparatorIndex); } } catch (Exception e) { } } return jarFileName; } private static void addPaths(PyList path, String pypath) { StringTokenizer tok = new StringTokenizer(pypath, java.io.File.pathSeparator); while (tok.hasMoreTokens()) path.append(new PyString(tok.nextToken().trim())); } public static PyJavaPackage add_package(String n) { return add_package(n, null); } public static PyJavaPackage add_package(String n, String contents) { return packageManager.makeJavaPackage(n, contents, null); } /** * Add a classpath directory to the list of places that are searched * for java packages. ** Note. Classes found in directory and subdirectory are not * made available to jython by this call. It only makes the java * package found in the directory available. This call is mostly * usefull if jython is embedded in an application that deals with * its own classloaders. A servlet container is a very good example. * Calling add_classdir("
/WEB-INF/classes") makes the java * packages in WEB-INF classes available to jython import. However the * actual classloading is completely handled by the servlet container's * context classloader. */ public static void add_classdir(String directoryPath) { packageManager.addDirectory(new File(directoryPath)); } /** * Add a .jar & .zip directory to the list of places that are searched * for java .jar and .zip files. The .jar and .zip files found will not * be cached. * * Note. Classes in .jar and .zip files found in the directory * are not made available to jython by this call. See the note for * add_classdir(dir) for more details. * * @param directoryPath The name of a directory. * * @see #add_classdir */ public static void add_extdir(String directoryPath) { packageManager.addJarDir(directoryPath, false); } /** * Add a .jar & .zip directory to the list of places that are searched * for java .jar and .zip files. *
* Note. Classes in .jar and .zip files found in the directory * are not made available to jython by this call. See the note for * add_classdir(dir) for more details. * * @param directoryPath The name of a directory. * @param cache Controls if the packages in the zip and jar * file should be cached. * * @see #add_classdir */ public static void add_extdir(String directoryPath, boolean cache) { packageManager.addJarDir(directoryPath, cache); } public TraceFunction tracefunc = null; public TraceFunction profilefunc = null; public void settrace(PyObject tracefunc) { //InterpreterState interp = Py.getThreadState().interp; if (tracefunc == Py.None) { this.tracefunc = null; } else { this.tracefunc = new PythonTraceFunction(tracefunc); } } public void setprofile(PyObject profilefunc) { //InterpreterState interp = Py.getThreadState().interp; if (profilefunc == Py.None) { this.profilefunc = null; } else { this.profilefunc = new PythonTraceFunction(profilefunc); } } private InputStream getSystemIn() { if (Options.pollStandardIn) { return new PollingInputStream(System.in); } else { return System.in; } } public String getdefaultencoding() { return codecs.getDefaultEncoding(); } public void setdefaultencoding(String encoding) { codecs.setDefaultEncoding(encoding); } // Not public by design. We can't rebind the displayhook if // a reflected function is inserted in the class dict. static void displayhook(PyObject o) { /* Print value except if null or None */ /* After printing, also assign to '_' */ /* Before, set '_' to None to avoid recursion */ if (o == Py.None) return; PySystemState sys = Py.getThreadState().systemState; sys.builtins.__setitem__("_", Py.None); Py.stdout.println(o.__repr__()); sys.builtins.__setitem__("_", o); } static void excepthook(PyObject type, PyObject val, PyObject tb) { Py.displayException(type, val, tb, null); } public void callExitFunc() throws PyIgnoreMethodTag { PyObject exitfunc = __findattr__("exitfunc"); if (exitfunc != null) { try { exitfunc.__call__(); } catch (PyException exc) { if (!Py.matchException(exc, Py.SystemExit)) { Py.println(stderr, Py.newString("Error in sys.exitfunc:")); } Py.printException(exc); } } } } // This class is based on a suggestion from Yunho Jeon class PollingInputStream extends FilterInputStream { public PollingInputStream(InputStream s) { super(s); } private void waitForBytes() throws IOException { try { while(available()==0) { //System.err.println("waiting..."); Thread.sleep(100); } } catch (InterruptedException e) { throw new PyException(Py.KeyboardInterrupt, "interrupt waiting on
"); } } public int read() throws IOException { waitForBytes(); return super.read(); } public int read(byte b[], int off, int len) throws IOException { waitForBytes(); return super.read(b, off, len); } } class PySystemStateFunctions extends PyBuiltinFunctionSet { PySystemStateFunctions(String name, int index, int minargs, int maxargs) { super(name, index, minargs, maxargs); } public PyObject __call__(PyObject arg) { switch (index) { case 10: PySystemState.displayhook(arg); return Py.None; default: throw info.unexpectedCall(1, false); } } public PyObject __call__(PyObject arg1, PyObject arg2, PyObject arg3) { switch (index) { case 30: PySystemState.excepthook(arg1, arg2, arg3); return Py.None; default: throw info.unexpectedCall(3, false); } } }