PyObject to an instance of a Java class.
Identical to o.__tojava__(c) except that it will
raise a TypeError if the conversion fails.
@param o the PyObject to convert.
@param c the class to convert it to.
**/
@SuppressWarnings("unchecked")
public static String, if it can be represented as
* US-ASCII, and a {@link PyUnicode} otherwise.
*
* @param s string content
* @return PyString or PyUnicode according to content of
* s.
*/
public static PyString newStringOrUnicode(String s) {
return newStringOrUnicode(Py.EmptyString, s);
}
/**
* Return a {@link PyString} for the given Java String, if it can be represented as
* US-ASCII and if a preceding object is not a PyUnicode, and a {@link PyUnicode}
* otherwise. In some contexts, we want the result to be a PyUnicode if some
* preceding result is a PyUnicode.
*
* @param precedent string of which the type sets a precedent
* @param s string content
* @return PyString or PyUnicode according to content of
* s.
*/
public static PyString newStringOrUnicode(PyObject precedent, String s) {
if (!(precedent instanceof PyUnicode) && PyString.charsFitWidth(s, 7)) {
return Py.newBytes(s);
} else {
return Py.newUnicode(s);
}
}
public static PyString newStringUTF8(String s) {
if (PyString.charsFitWidth(s, 7)) {
// ascii of course is a subset of UTF-8
return Py.newBytes(s);
} else {
return Py.newBytes(codecs.PyUnicode_EncodeUTF8(s, null));
}
}
/**
* Return a file name or path as Unicode (Java UTF-16 String), decoded if necessary
* from a Python bytes object, using the file system encoding. In Jython, this
* encoding is UTF-8, irrespective of the OS platform. This method is comparable with Python 3
* os.fsdecode, but for Java use, in places such as the os module. If
* the argument is not a PyUnicode, it will be decoded using the nominal Jython
* file system encoding. If the argument is a PyUnicode, its
* String is returned.
*
* @param filename as bytes to decode, or already as unicode
* @return unicode version of path
*/
public static String fileSystemDecode(PyString filename) {
String s = filename.getString();
if (filename instanceof PyUnicode || PyString.charsFitWidth(s, 7)) {
// Already decoded or bytes usable as ASCII
return s;
} else {
// It's bytes, so must decode properly
assert "utf-8".equals(PySystemState.FILE_SYSTEM_ENCODING.toString());
return codecs.PyUnicode_DecodeUTF8(s, null);
}
}
/**
* As {@link #fileSystemDecode(PyString)} but raising ValueError if not a
* str or unicode.
*
* @param filename as bytes to decode, or already as unicode
* @return unicode version of the file name
*/
public static String fileSystemDecode(PyObject filename) {
if (filename instanceof PyString) {
return fileSystemDecode((PyString)filename);
} else {
throw Py.TypeError(String.format("coercing to Unicode: need string, %s type found",
filename.getType().fastGetName()));
}
}
/**
* Return a PyString object we can use as a file name or file path in places where Python
* expects a bytes (that is a str) object in the file system encoding.
* In Jython, this encoding is UTF-8, irrespective of the OS platform.
*
* This is subtly different from CPython's use of "file system encoding", which tracks the
* platform's choice so that OS services may be called that have a bytes interface. Jython's
* interaction with the OS occurs via Java using String arguments representing Unicode values,
* so we have no need to match the encoding actually chosen by the platform (e.g. 'mbcs' on
* Windows). Rather we need a nominal Jython file system encoding, for use where the standard
* library forces byte paths on us (in Python 2). There is no reason for this choice to vary
* with OS platform. Methods receiving paths as bytes will
* {@link #fileSystemDecode(PyString)} them again for Java.
*
* @param filename as unicode to encode, or already as bytes
* @return encoded bytes version of path
*/
public static PyString fileSystemEncode(String filename) {
if (PyString.charsFitWidth(filename, 7)) {
// Just wrap it as US-ASCII is a subset of the file system encoding
return Py.newBytes(filename);
} else {
// It's non just US-ASCII, so must encode properly
assert "utf-8".equals(PySystemState.FILE_SYSTEM_ENCODING.toString());
return Py.newBytes(codecs.PyUnicode_EncodeUTF8(filename, null));
}
}
/**
* Return a PyString object we can use as a file name or file path in places where Python
* expects a bytes (that is, str) object in the file system encoding.
* In Jython, this encoding is UTF-8, irrespective of the OS platform. This method is comparable
* with Python 3 os.fsencode. If the argument is a PyString, it is returned
* unchanged. If the argument is a PyUnicode, it is converted to a bytes using the
* nominal Jython file system encoding.
*
* @param filename as unicode to encode, or already as bytes
* @return encoded bytes version of path
*/
public static PyString fileSystemEncode(PyString filename) {
return (filename instanceof PyUnicode) ? fileSystemEncode(filename.getString()) : filename;
}
/**
* Convert a PyList path to a list of Java String objects decoded from
* the path elements to strings guaranteed usable in the Java API.
*
* @param path a Python search path
* @return equivalent Java list
*/
private static ListdefaultValue.
*/
public static PyString getenv(PyString name, PyString defaultValue) {
try {
PyObject value = getEnvironment().__finditem__(name);
if (value == null) {
return defaultValue;
} else {
return value.__str__();
}
} catch (PyException e) {
// Something is fishy about os.environ, so the name is not defined.
return defaultValue;
}
}
/** The same as {@code getenv(name, null)}. See {@link #getenv(String, String)}. */
public static String getenv(String name) {
return getenv(name, null);
}
/**
* Get the value of the environment variable named from {@code os.environ} or return the given
* default value. This is a convenience wrapper on {@link #getenv(PyString, PyString)} which
* takes care of the fact that environment variables are FS-encoded.
*
* @param name to access in the environment.
* @param defaultValue to return if {@code key} is not defined.
* @return the corresponding value or defaultValue.
*/
public static String getenv(String name, String defaultValue) {
PyString value = getenv(newUnicode(name), null);
if (value == null) {
return defaultValue;
} else {
// Environment variables are FS-encoded byte strings
return fileSystemDecode(value);
}
}
public static PyStringMap newStringMap() {
return new PyStringMap();
}
/**
* Return a not-necessarily new {@link PyUnicode} from a Java {@code char}. Some low index chars
* (ASCII) return a re-used {@code PyUnicode}. This method does not assume the character is
* basic-plane.
*
* @param c to convert to a {@code PyUnicode}.
* @return a new or re-used {@code PyUnicode}
*/
public static PyUnicode newUnicode(char c) {
return PyUnicode.from(c);
}
/**
* Return a not-necessarily new {@link PyUnicode} from a Java {@code String}. Empty and some
* single-character strings return a re-used {@code PyUnicode}. This method does not assume the
* character codes are basic-plane, but scans the string to find out. (See
* {@link #newUnicode(String, boolean)} for one that allows the caller to assert that it is.
*
* @param s to wrap as a {@code PyUnicode}.
* @return a new or re-used {@code PyUnicode}
*/
public static PyUnicode newUnicode(String s) {
return PyUnicode.fromString(s, false);
}
public static PyUnicode newUnicode(String s, boolean isBasic) {
return PyUnicode.fromString(s, isBasic);
}
public static PyBoolean newBoolean(boolean t) {
return t ? Py.True : Py.False;
}
public static PyObject newDate(Date date) {
if (date == null) {
return Py.None;
}
PyObject datetimeModule = __builtin__.__import__("datetime");
PyObject dateClass = datetimeModule.__getattr__("date");
Calendar cal = Calendar.getInstance();
cal.setTime(date);
return dateClass.__call__(newInteger(cal.get(Calendar.YEAR)),
newInteger(cal.get(Calendar.MONTH) + 1),
newInteger(cal.get(Calendar.DAY_OF_MONTH)));
}
public static PyObject newTime(Time time) {
if (time == null) {
return Py.None;
}
PyObject datetimeModule = __builtin__.__import__("datetime");
PyObject timeClass = datetimeModule.__getattr__("time");
Calendar cal = Calendar.getInstance();
cal.setTime(time);
return timeClass.__call__(newInteger(cal.get(Calendar.HOUR_OF_DAY)),
newInteger(cal.get(Calendar.MINUTE)),
newInteger(cal.get(Calendar.SECOND)),
newInteger(cal.get(Calendar.MILLISECOND) *
1000));
}
public static PyObject newDatetime(Timestamp timestamp) {
if (timestamp == null) {
return Py.None;
}
PyObject datetimeModule = __builtin__.__import__("datetime");
PyObject datetimeClass = datetimeModule.__getattr__("datetime");
Calendar cal = Calendar.getInstance();
cal.setTime(timestamp);
return datetimeClass.__call__(new PyObject[] {
newInteger(cal.get(Calendar.YEAR)),
newInteger(cal.get(Calendar.MONTH) + 1),
newInteger(cal.get(Calendar.DAY_OF_MONTH)),
newInteger(cal.get(Calendar.HOUR_OF_DAY)),
newInteger(cal.get(Calendar.MINUTE)),
newInteger(cal.get(Calendar.SECOND)),
newInteger(timestamp.getNanos() / 1000)});
}
public static PyObject newDecimal(String decimal) {
if (decimal == null) {
return Py.None;
}
PyObject decimalModule = __builtin__.__import__("decimal");
PyObject decimalClass = decimalModule.__getattr__("Decimal");
return decimalClass.__call__(newString(decimal));
}
public static PyCode newCode(int argcount, String varnames[],
String filename, String name,
boolean args, boolean keywords,
PyFunctionTable funcs, int func_id,
String[] cellvars, String[] freevars,
int npurecell, int moreflags) {
return new PyTableCode(argcount, varnames,
filename, name, 0, args, keywords, funcs,
func_id, cellvars, freevars, npurecell,
moreflags);
}
public static PyCode newCode(int argcount, String varnames[],
String filename, String name,
int firstlineno,
boolean args, boolean keywords,
PyFunctionTable funcs, int func_id,
String[] cellvars, String[] freevars,
int npurecell, int moreflags) {
return new PyTableCode(argcount, varnames,
filename, name, firstlineno, args, keywords,
funcs, func_id, cellvars, freevars, npurecell,
moreflags);
}
// --
public static PyCode newCode(int argcount, String varnames[],
String filename, String name,
boolean args, boolean keywords,
PyFunctionTable funcs, int func_id) {
return new PyTableCode(argcount, varnames,
filename, name, 0, args, keywords, funcs,
func_id);
}
public static PyCode newCode(int argcount, String varnames[],
String filename, String name,
int firstlineno,
boolean args, boolean keywords,
PyFunctionTable funcs, int func_id) {
return new PyTableCode(argcount, varnames,
filename, name, firstlineno, args, keywords,
funcs, func_id);
}
public static PyCode newJavaCode(Class cls, String name) {
return new JavaCode(newJavaFunc(cls, name));
}
public static PyObject newJavaFunc(Class cls, String name) {
try {
Method m = cls.getMethod(name, new Class[]{PyObject[].class, String[].class});
return new JavaFunc(m);
} catch (NoSuchMethodException e) {
throw Py.JavaError(e);
}
}
private static PyObject initExc(String name, PyObject exceptions,
PyObject dict) {
PyObject tmp = exceptions.__getattr__(name);
dict.__setitem__(name, tmp);
return tmp;
}
static void initClassExceptions(PyObject dict) {
PyObject exc = imp.load("exceptions");
BaseException = initExc("BaseException", exc, dict);
Exception = initExc("Exception", exc, dict);
SystemExit = initExc("SystemExit", exc, dict);
StopIteration = initExc("StopIteration", exc, dict);
GeneratorExit = initExc("GeneratorExit", exc, dict);
StandardError = initExc("StandardError", exc, dict);
KeyboardInterrupt = initExc("KeyboardInterrupt", exc, dict);
ImportError = initExc("ImportError", exc, dict);
EnvironmentError = initExc("EnvironmentError", exc, dict);
IOError = initExc("IOError", exc, dict);
OSError = initExc("OSError", exc, dict);
EOFError = initExc("EOFError", exc, dict);
RuntimeError = initExc("RuntimeError", exc, dict);
NotImplementedError = initExc("NotImplementedError", exc, dict);
NameError = initExc("NameError", exc, dict);
UnboundLocalError = initExc("UnboundLocalError", exc, dict);
AttributeError = initExc("AttributeError", exc, dict);
SyntaxError = initExc("SyntaxError", exc, dict);
IndentationError = initExc("IndentationError", exc, dict);
TabError = initExc("TabError", exc, dict);
TypeError = initExc("TypeError", exc, dict);
AssertionError = initExc("AssertionError", exc, dict);
LookupError = initExc("LookupError", exc, dict);
IndexError = initExc("IndexError", exc, dict);
KeyError = initExc("KeyError", exc, dict);
ArithmeticError = initExc("ArithmeticError", exc, dict);
OverflowError = initExc("OverflowError", exc, dict);
ZeroDivisionError = initExc("ZeroDivisionError", exc, dict);
FloatingPointError = initExc("FloatingPointError", exc, dict);
ValueError = initExc("ValueError", exc, dict);
UnicodeError = initExc("UnicodeError", exc, dict);
UnicodeEncodeError = initExc("UnicodeEncodeError", exc, dict);
UnicodeDecodeError = initExc("UnicodeDecodeError", exc, dict);
UnicodeTranslateError = initExc("UnicodeTranslateError", exc, dict);
ReferenceError = initExc("ReferenceError", exc, dict);
SystemError = initExc("SystemError", exc, dict);
MemoryError = initExc("MemoryError", exc, dict);
BufferError = initExc("BufferError", exc, dict);
Warning = initExc("Warning", exc, dict);
UserWarning = initExc("UserWarning", exc, dict);
DeprecationWarning = initExc("DeprecationWarning", exc, dict);
PendingDeprecationWarning = initExc("PendingDeprecationWarning", exc, dict);
SyntaxWarning = initExc("SyntaxWarning", exc, dict);
RuntimeWarning = initExc("RuntimeWarning", exc, dict);
FutureWarning = initExc("FutureWarning", exc, dict);
ImportWarning = initExc("ImportWarning", exc, dict);
UnicodeWarning = initExc("UnicodeWarning", exc, dict);
BytesWarning = initExc("BytesWarning", exc, dict);
// Pre-initialize the PyJavaClass for OutOfMemoryError so when we need
// it it creating the pieces for it won't cause an additional out of
// memory error. Fix for bug #1654484
PyType.fromClass(OutOfMemoryError.class);
}
public static volatile PySystemState defaultSystemState;
// This is a hack to get initializations to work in proper order
public static synchronized boolean initPython() {
PySystemState.initialize();
return true;
}
private static boolean syspathJavaLoaderRestricted = false;
/**
* Common code for {@link #findClass(String)} and {@link #findClassEx(String, String)}.
*
* @param name of the Java class to load and initialise
* @param reason to be given in debug output (or {@code null} to suppress debug output.
* @return the loaded class
* @throws ClassNotFoundException if the class wasn't found by the class loader
*/
private static Class findClassInternal(String name, String reason)
throws ClassNotFoundException {
ClassLoader classLoader = Py.getSystemState().getClassLoader();
if (classLoader != null) {
findClassTrying(name, reason, classLoader, "sys.classLoader");
return loadAndInitClass(name, classLoader);
}
if (!syspathJavaLoaderRestricted) {
try {
classLoader = imp.getSyspathJavaLoader();
findClassTrying(name, reason, classLoader, "SysPathJavaLoader");
} catch (SecurityException e) {
syspathJavaLoaderRestricted = true;
}
}
if (syspathJavaLoaderRestricted) {
classLoader = imp.getParentClassLoader();
findClassTrying(name, reason, classLoader, "Jython's parent class loader");
}
if (classLoader != null) {
try {
return loadAndInitClass(name, classLoader);
} catch (ClassNotFoundException cnfe) {
// let the default classloader try
/*
* XXX: by trying another classloader that may not be on a parent/child relationship
* with the Jython's parent classsloader we are risking some nasty class loading
* problems (such as having two incompatible copies for the same class that is
* itself a dependency of two classes loaded from these two different class
* loaders).
*/
}
}
classLoader = Thread.currentThread().getContextClassLoader();
findClassTrying(name, reason, classLoader,
"context class loader, for backwards compatibility");
return loadAndInitClass(name, classLoader);
}
private static void findClassTrying(String name, String reason, ClassLoader cl, String place) {
if (cl != null && reason != null && importLogger.isLoggable(Level.FINE)) {
importLogger.log(Level.FINE, "# trying {0} as {1} in {2}",
new Object[] {name, reason, place});
}
}
/**
* Find and load a Java class by name.
*
* @param name of the Java class.
* @return the class, or {@code null} if it wasn't found or something went wrong
*/
public static Class findClass(String name) {
try {
return findClassInternal(name, null);
} catch (ClassNotFoundException | IllegalArgumentException | NoClassDefFoundError e) {
// e.printStackTrace();
return null;
}
}
/**
* Find and load a Java class by name.
*
* @param name Name of the Java class.
* @param reason for finding the class. Used in debugging messages.
* @return the class, or {@code null} if it simply wasn't found
* @throws PyException {@code JavaError} wrapping errors occurring when the class is found but
* cannot be loaded.
*/
public static Class findClassEx(String name, String reason) throws PyException {
try {
return findClassInternal(name, reason);
} catch (ClassNotFoundException e) {
return null;
} catch (IllegalArgumentException | LinkageError e) {
throw JavaError(e);
}
}
// An alias to express intent (since boolean flags aren't exactly obvious).
// We *need* to initialize classes on findClass/findClassEx, so that import
// statements can trigger static initializers
private static Class loadAndInitClass(String name, ClassLoader loader)
throws ClassNotFoundException {
return Class.forName(name, true, loader);
}
public static void initProxy(PyProxy proxy, String module, String pyclass, Object[] args)
{
if (proxy._getPyInstance() != null) {
return;
}
PyObject instance = (PyObject)(ThreadContext.initializingProxy.get()[0]);
ThreadState ts = Py.getThreadState();
if (instance != null) {
if (JyAttribute.hasAttr(instance, JyAttribute.JAVA_PROXY_ATTR)) {
throw Py.TypeError("Proxy instance reused");
}
JyAttribute.setAttr(instance, JyAttribute.JAVA_PROXY_ATTR, proxy);
proxy._setPyInstance(instance);
proxy._setPySystemState(ts.getSystemState());
return;
}
// Ensure site-packages are available before attempting to import module.
// This step enables supporting modern Python apps when using proxies
// directly from Java (eg through clamp).
importSiteIfSelected();
PyObject mod = imp.importName(module.intern(), false);
PyType pyc = (PyType)mod.__getattr__(pyclass.intern());
PyObject[] pargs;
if (args == null || args.length == 0) {
pargs = Py.EmptyObjects;
} else {
pargs = Py.javas2pys(args);
}
instance = pyc.__call__(pargs);
JyAttribute.setAttr(instance, JyAttribute.JAVA_PROXY_ATTR, proxy);
proxy._setPyInstance(instance);
proxy._setPySystemState(ts.getSystemState());
}
/**
* Initializes a default PythonInterpreter and runs the code from
* {@link PyRunnable#getMain} as __main__
*
* Called by the code generated in {@link org.python.compiler.Module#addMain()}
*/
public static void runMain(PyRunnable main, String[] args) throws Exception {
runMain(new PyRunnableBootstrap(main), args);
}
/**
* Initializes a default PythonInterpreter and runs the code loaded from the
* {@link CodeBootstrap} as __main__ Called by the code generated in
* {@link org.python.compiler.Module#addMain()}
*/
public static void runMain(CodeBootstrap main, String[] args)
throws Exception {
PySystemState.initialize(null, null, args, main.getClass().getClassLoader());
try {
imp.createFromCode("__main__", CodeLoader.loadCode(main));
} catch (PyException e) {
Py.getSystemState().callExitFunc();
if (e.match(Py.SystemExit)) {
return;
}
throw e;
}
Py.getSystemState().callExitFunc();
}
//XXX: this needs review to make sure we are cutting out all of the Java exceptions.
private static String getStackTrace(Throwable javaError) {
CharArrayWriter buf = new CharArrayWriter();
javaError.printStackTrace(new PrintWriter(buf));
String str = buf.toString();
int index = -1;
if (index == -1) {
index = str.indexOf(
"at org.python.core.PyReflectedConstructor.__call__");
}
if (index == -1) {
index = str.indexOf("at org.python.core.PyReflectedFunction.__call__");
}
if (index == -1) {
index = str.indexOf(
"at org/python/core/PyReflectedConstructor.__call__");
}
if (index == -1) {
index = str.indexOf("at org/python/core/PyReflectedFunction.__call__");
}
if (index != -1) {
index = str.lastIndexOf("\n", index);
}
int index0 = str.indexOf("\n");
if (index >= index0) {
str = str.substring(index0 + 1, index + 1);
}
return str;
}
/**
* Display an exception and stack trace through
* {@link #printException(Throwable, PyFrame, PyObject)}.
*
* @param t to display
*/
public static void printException(Throwable t) {
printException(t, null, null);
}
/**
* Display an exception and stack trace through
* {@link #printException(Throwable, PyFrame, PyObject)}.
*
* @param t to display
* @param f frame at which to start the stack trace
*/
public static void printException(Throwable t, PyFrame f) {
printException(t, f, null);
}
/**
* Display an exception and stack trace. If the exception was {@link Py#SystemExit} and
* {@link Options#inspect}{@code ==false}, this will exit the JVM.
*
* @param t to display
* @param f frame at which to start the stack trace
* @param file output onto this stream or {@link Py#stderr} if {@code null}
*/
public static synchronized void printException(Throwable t, PyFrame f,
PyObject file) {
StdoutWrapper stderr = Py.stderr;
if (file != null) {
stderr = new FixedFileWrapper(file);
}
if (Options.showJavaExceptions) {
stderr.println("Java Traceback:");
java.io.CharArrayWriter buf = new java.io.CharArrayWriter();
if (t instanceof PyException) {
((PyException)t).super__printStackTrace(new java.io.PrintWriter(buf));
} else {
t.printStackTrace(new java.io.PrintWriter(buf));
}
stderr.print(buf.toString());
}
PyException exc = Py.JavaError(t);
// Act on SystemExit here.
maybeSystemExit(exc);
setException(exc, f);
ThreadState ts = getThreadState();
PySystemState sys = ts.getSystemState();
sys.last_value = exc.value;
sys.last_type = exc.type;
sys.last_traceback = exc.traceback;
PyObject exceptHook = sys.__findattr__("excepthook");
if (exceptHook != null) {
try {
exceptHook.__call__(exc.type, exc.value, exc.traceback);
} catch (PyException exc2) {
exc2.normalize();
flushLine();
stderr.println("Error in sys.excepthook:");
displayException(exc2.type, exc2.value, exc2.traceback, file);
stderr.println();
stderr.println("Original exception was:");
displayException(exc.type, exc.value, exc.traceback, file);
}
} else {
stderr.println("sys.excepthook is missing");
displayException(exc.type, exc.value, exc.traceback, file);
}
ts.exception = null;
}
/**
* Print the description of an exception as a big string. The arguments are closely equivalent
* to the tuple returned by Python sys.exc_info, on standard error or a given
* byte-oriented file. Compare with Python traceback.print_exception.
*
* @param type of exception
* @param value the exception parameter (second argument to raise)
* @param tb traceback of the call stack where the exception originally occurred
* @param file to print encoded string to, or null meaning standard error
*/
public static void displayException(PyObject type, PyObject value, PyObject tb, PyObject file) {
// Output is to standard error, unless a file object has been given.
StdoutWrapper stderr = Py.stderr;
// As we format the exception in Unicode, we deal with encoding in this method
String encoding, errors = codecs.REPLACE;
if (file != null) {
// Ostensibly writing to a file: assume file content encoding (file.encoding)
stderr = new FixedFileWrapper(file);
encoding = codecs.getDefaultEncoding();
} else {
// Not a file, assume we should encode for the console
encoding = getAttr(Py.getSystemState().__stderr__, "encoding", null);
}
// But if the stream can tell us directly, of course we use that answer.
encoding = getAttr(stderr.myFile(), "encoding", encoding);
errors = getAttr(stderr.myFile(), "errors", errors);
flushLine();
// The creation of the report operates entirely in Java String (to support Unicode).
try {
// Be prepared for formatting or printing to fail
PyString bytes = exceptionToBytes(type, value, tb, encoding, errors);
stderr.print(bytes);
} catch (Exception ex) {
// Looks like that exception just won't convert or print
value = Py.newString("sys.exc_info. Compare with Python
* traceback.format_exception.
*
* @param type of exception
* @param value the exception parameter (second argument to raise)
* @param tb traceback of the call stack where the exception originally occurred
* @return string representation of the traceback and exception
*/
static String exceptionToString(PyObject type, PyObject value, PyObject tb) {
// Compose the stack dump, syntax error, and actual exception in this buffer:
StringBuilder buf;
if (tb instanceof PyTraceback) {
buf = new StringBuilder(((PyTraceback)tb).dumpStack());
} else {
buf = new StringBuilder();
}
if (__builtin__.isinstance(value, Py.SyntaxError)) {
// The value part of the exception is a syntax error: first emit that.
appendSyntaxError(buf, value);
// Now supersede it with just the syntax error message for the next phase.
value = value.__findattr__("msg");
if (value == null) {
value = Py.None;
}
}
if (value.getJavaProxy() != null) {
Object javaError = value.__tojava__(Throwable.class);
if (javaError != null && javaError != Py.NoConversion) {
// The value is some Java Throwable: append that too
buf.append(getStackTrace((Throwable)javaError));
}
}
// Formatting the value may raise UnicodeEncodeError: client must deal
buf.append(formatException(type, value)).append('\n');
return buf.toString();
}
/**
* Helper to {@link #tracebackToString(PyObject, PyObject)} when the value in an exception turns
* out to be a syntax error.
*/
private static void appendSyntaxError(StringBuilder buf, PyObject value) {
PyObject filename = value.__findattr__("filename");
PyObject text = value.__findattr__("text");
PyObject lineno = value.__findattr__("lineno");
buf.append(" File \"");
buf.append(filename == Py.None || filename == null ? "input(), raw_input(), etc.) as
* constructed and set by {@link PySystemState} initialization.
*
* @return the Jython Console
*/
public static Console getConsole() {
if (console == null) {
// We really shouldn't ask for a console before PySystemState initialization but ...
try {
// ... something foolproof that we can supersede.
installConsole(new PlainConsole("ascii"));
} catch (Exception e) {
// This really, really shouldn't happen
throw Py.RuntimeError("Could not create fall-back PlainConsole: " + e);
}
}
return console;
}
/**
* Install the provided Console, first uninstalling any current one. The Jython Console is used
* for raw_input() etc., and may provide line-editing and history recall at the
* prompt. A Console may replace System.in with its line-editing input method.
*
* @param console The new Console object
* @throws UnsupportedOperationException if some prior Console refuses to uninstall
* @throws IOException if {@link Console#install()} raises it
*/
public static void installConsole(Console console) throws UnsupportedOperationException,
IOException {
if (Py.console != null) {
// Some Console class already installed: may be able to uninstall
Py.console.uninstall();
Py.console = null;
}
// Install the specified Console
console.install();
Py.console = console;
// Cause sys (if it exists) to export the console handler that was installed
if (Py.defaultSystemState != null) {
Py.defaultSystemState.__setattr__("_jy_console", Py.java2py(console));
}
}
private static final String IMPORT_SITE_ERROR = ""
+ "Cannot import site module and its dependencies: %s\n"
+ "Determine if the following attributes are correct:\n" //
+ " * sys.path: %s\n"
+ " This attribute might be including the wrong directories, such as from CPython\n"
+ " * sys.prefix: %s\n"
+ " This attribute is set by the system property python.home, although it can\n"
+ " be often automatically determined by the location of the Jython jar file\n\n"
+ "You can use the -S option or python.import.site=false to not import the site module";
public static boolean importSiteIfSelected() {
// Ensure sys.flags.no_site actually reflects what happened. (See docs of these two.)
Options.no_site = !Options.importSite;
if (Options.importSite) {
try {
// Ensure site-packages are available
imp.load("site");
return true;
} catch (PyException pye) {
if (pye.match(Py.ImportError)) {
PySystemState sys = Py.getSystemState();
String value = pye.value.__getattr__("args").__getitem__(0).toString();
Listobjects into an array of PyObjects.
*
* @see ClassicPyObjectAdapter - default PyObjectAdapter type
*/
public static PyObject[] javas2pys(Object... objects) {
PyObject[] objs = new PyObject[objects.length];
for (int i = 0; i < objs.length; i++) {
objs[i] = java2py(objects[i]);
}
return objs;
}
/**
* @return the ExtensiblePyObjectAdapter used by java2py.
*/
public static ExtensiblePyObjectAdapter getAdapter() {
if (adapter == null) {
adapter = new ClassicPyObjectAdapter();
}
return adapter;
}
/**
* Set the ExtensiblePyObjectAdapter used by java2py.
*
* @param adapter The new ExtensiblePyObjectAdapter
*/
protected static void setAdapter(ExtensiblePyObjectAdapter adapter) {
Py.adapter = adapter;
}
/**
* Handles wrapping Java objects in PyObject to expose them to jython.
*/
private static ExtensiblePyObjectAdapter adapter;
// XXX: The following two makeClass overrides are *only* for the
// old compiler, they should be removed when the newcompiler hits
public static PyObject makeClass(String name, PyObject[] bases, PyCode code) {
return makeClass(name, bases, code, null);
}
public static PyObject makeClass(String name, PyObject[] bases, PyCode code,
PyObject[] closure_cells) {
ThreadState state = getThreadState();
PyObject dict = code.call(state, Py.EmptyObjects, Py.NoKeywords,
state.frame.f_globals, Py.EmptyObjects, new PyTuple(closure_cells));
return makeClass(name, bases, dict);
}
public static PyObject makeClass(String name, PyObject base, PyObject dict) {
PyObject[] bases = base == null ? EmptyObjects : new PyObject[] {base};
return makeClass(name, bases, dict);
}
/**
* Create a new Python class.
*
* @param name the String name of the class
* @param bases an array of PyObject base classes
* @param dict the class's namespace, containing the class body
* definition
* @return a new Python Class PyObject
*/
public static PyObject makeClass(String name, PyObject[] bases, PyObject dict) {
PyObject metaclass = dict.__finditem__("__metaclass__");
if (metaclass == null) {
if (bases.length != 0) {
PyObject base = bases[0];
metaclass = base.__findattr__("__class__");
if (metaclass == null) {
metaclass = base.getType();
}
} else {
PyObject globals = getFrame().f_globals;
if (globals != null) {
metaclass = globals.__finditem__("__metaclass__");
}
if (metaclass == null) {
metaclass = PyClass.TYPE;
}
}
}
try {
return metaclass.__call__(new PyString(name), new PyTuple(bases), dict);
} catch (PyException pye) {
if (!pye.match(TypeError)) {
throw pye;
}
pye.value = Py.newString(String.format("Error when calling the metaclass bases\n "
+ "%s", pye.value.__str__().toString()));
throw pye;
}
}
private static int nameindex = 0;
public static synchronized String getName() {
String name = "org.python.pycode._pyx" + nameindex;
nameindex += 1;
return name;
}
public static CompilerFlags getCompilerFlags() {
return CompilerFlags.getCompilerFlags();
}
public static CompilerFlags getCompilerFlags(int flags, boolean dont_inherit) {
final PyFrame frame;
if (dont_inherit) {
frame = null;
} else {
frame = Py.getFrame();
}
return CompilerFlags.getCompilerFlags(flags, frame);
}
public static CompilerFlags getCompilerFlags(CompilerFlags flags, boolean dont_inherit) {
final PyFrame frame;
if (dont_inherit) {
frame = null;
} else {
frame = Py.getFrame();
}
return CompilerFlags.getCompilerFlags(flags, frame);
}
// w/o compiler-flags
public static PyCode compile(InputStream istream, String filename, CompileMode kind) {
return compile_flags(istream, filename, kind, new CompilerFlags());
}
/**
* Entry point for compiling modules.
*
* @param node Module node, coming from the parsing process
* @param name Internal name for the compiled code. Typically generated by
* calling {@link #getName()}.
* @param filename Source file name
* @param linenumbers True to track source line numbers on the generated
* code
* @param printResults True to call the sys.displayhook on the result of
* the code
* @param cflags Compiler flags
* @return Code object for the compiled module
*/
public static PyCode compile_flags(mod node, String name, String filename,
boolean linenumbers, boolean printResults,
CompilerFlags cflags) {
return CompilerFacade.compile(node, name, filename, linenumbers, printResults, cflags);
}
public static PyCode compile_flags(mod node, String filename,
CompileMode kind, CompilerFlags cflags) {
return Py.compile_flags(node, getName(), filename, true,
kind == CompileMode.single, cflags);
}
/**
* Compiles python source code coming from a file or another external stream
*/
public static PyCode compile_flags(InputStream istream, String filename,
CompileMode kind, CompilerFlags cflags) {
mod node = ParserFacade.parse(istream, kind, filename, cflags);
return Py.compile_flags(node, filename, kind, cflags);
}
/**
* Compiles python source code coming from String (raw bytes) data.
*
* If the String is properly decoded (from PyUnicode) the PyCF_SOURCE_IS_UTF8 flag
* should be specified.
*/
public static PyCode compile_flags(String data, String filename,
CompileMode kind, CompilerFlags cflags) {
if (data.contains("\0")) {
throw Py.TypeError("compile() expected string without null bytes");
}
if (cflags != null && cflags.dont_imply_dedent) {
data += "\n";
} else {
data += "\n\n";
}
mod node = ParserFacade.parse(data, kind, filename, cflags);
return Py.compile_flags(node, filename, kind, cflags);
}
public static PyObject compile_command_flags(String string, String filename,
CompileMode kind, CompilerFlags cflags, boolean stdprompt) {
mod node = ParserFacade.partialParse(string + "\n", kind, filename,
cflags, stdprompt);
if (node == null) {
return Py.None;
}
return Py.compile_flags(node, Py.getName(), filename, true, true, cflags);
}
public static PyObject[] unpackSequence(PyObject obj, int length) {
if (obj instanceof PyTuple && obj.__len__() == length) {
// optimization
return ((PyTuple)obj).getArray();
}
PyObject[] ret = new PyObject[length];
PyObject iter = obj.__iter__();
for (int i = 0; i < length; i++) {
PyObject tmp = iter.__iternext__();
if (tmp == null) {
throw Py.ValueError(String.format("need more than %d value%s to unpack", i,
i == 1 ? "" : "s"));
}
ret[i] = tmp;
}
if (iter.__iternext__() != null) {
throw Py.ValueError("too many values to unpack");
}
return ret;
}
public static PyObject iter(PyObject seq, String message) {
try {
return seq.__iter__();
} catch (PyException exc) {
if (exc.match(Py.TypeError)) {
throw Py.TypeError(message);
}
throw exc;
}
}
private static IdImpl idimpl = new IdImpl();
public static long id(PyObject o) {
return idimpl.id(o);
}
public static String idstr(PyObject o) {
return idimpl.idstr(o);
}
public static long java_obj_id(Object o) {
return idimpl.java_obj_id(o);
}
public static void printResult(PyObject ret) {
Py.getThreadState().getSystemState().invoke("displayhook", ret);
}
public static void saveClassFile(String name, ByteArrayOutputStream bytestream) {
String dirname = Options.proxyDebugDirectory;
if (dirname == null) {
return;
}
byte[] bytes = bytestream.toByteArray();
File dir = new File(dirname);
File file = makeFilename(name, dir);
new File(file.getParent()).mkdirs();
try {
FileOutputStream o = new FileOutputStream(file);
o.write(bytes);
o.close();
} catch (Throwable t) {
t.printStackTrace();
}
}
private static File makeFilename(String name, File dir) {
int index = name.indexOf(".");
if (index == -1) {
return new File(dir, name + ".class");
}
return makeFilename(name.substring(index + 1, name.length()),
new File(dir, name.substring(0, index)));
}
public static boolean isInstance(PyObject inst, PyObject cls) {
// Quick test for an exact match
if (inst.getType() == cls) {
return true;
}
if (cls instanceof PyTuple) {
for (PyObject item : cls.asIterable()) {
if (isInstance(inst, item)) {
return true;
}
}
return false;
}
PyObject checkerResult;
if ((checkerResult = dispatchToChecker(inst, cls, "__instancecheck__")) != null) {
return checkerResult.__nonzero__();
}
return recursiveIsInstance(inst, cls);
}
static boolean recursiveIsInstance(PyObject inst, PyObject cls) {
if (cls instanceof PyClass && inst instanceof PyInstance) {
PyClass inClass = ((PyInstance) inst).fastGetClass();
return inClass.isSubClass((PyClass) cls);
}
if (cls instanceof PyType) {
PyType type = (PyType)cls;
//Special case PyStringMap to compare as an instance type dict.
if (inst instanceof PyStringMap &&
type.equals(PyDictionary.TYPE)) {
return true;
}
PyType instType = inst.getType();
// equiv. to PyObject_TypeCheck
if (instType == type || instType.isSubType(type)) {
return true;
}
PyObject instCls = inst.__findattr__("__class__");
if (instCls != null && instCls != instType && instCls instanceof PyType) {
return ((PyType) instCls).isSubType(type);
}
return false;
}
checkClass(cls, "isinstance() arg 2 must be a class, type, or tuple of classes and types");
PyObject instCls = inst.__findattr__("__class__");
if (instCls == null) {
return false;
}
return abstractIsSubClass(instCls, cls);
}
public static boolean isSubClass(PyObject derived, PyObject cls) {
if (cls instanceof PyTuple) {
for (PyObject item : cls.asIterable()) {
if (isSubClass(derived, item)) {
return true;
}
}
return false;
}
PyObject checkerResult;
if ((checkerResult = dispatchToChecker(derived, cls, "__subclasscheck__")) != null) {
return checkerResult.__nonzero__();
}
return recursiveIsSubClass(derived, cls);
}
static boolean recursiveIsSubClass(PyObject derived, PyObject cls) {
if (derived instanceof PyType && cls instanceof PyType) {
if (derived == cls) {
return true;
}
PyType type = (PyType)cls;
PyType subtype = (PyType)derived;
// Special case PyStringMap to compare as a subclass of
// PyDictionary. Note that we don't need to check for stringmap
// subclasses, since stringmap can't be subclassed. PyStringMap's
// TYPE is computed lazily, so we have to use PyType.fromClass :(
if (type == PyDictionary.TYPE &&
subtype == PyType.fromClass(PyStringMap.class)) {
return true;
}
return subtype.isSubType(type);
}
if (derived instanceof PyClass && cls instanceof PyClass) {
return ((PyClass) derived).isSubClass((PyClass) cls);
}
checkClass(derived, "issubclass() arg 1 must be a class");
checkClass(cls, "issubclass() arg 2 must be a class or tuple of classes");
return abstractIsSubClass(derived, cls);
}
private static boolean abstractIsSubClass(PyObject derived, PyObject cls) {
while (true) {
if (derived == cls) {
return true;
}
PyTuple bases = abstractGetBases(derived);
if (bases == null) {
return false;
}
int basesSize = bases.size();
if (basesSize == 0) {
return false;
}
if (basesSize == 1) {
// Avoid recursivity in the single inheritance case
derived = bases.pyget(0);
continue;
}
for (PyObject base : bases.asIterable()) {
if (abstractIsSubClass(base, cls)) {
return true;
}
}
return false;
}
}
/**
* Attempt to dispatch an isinstance/issubclass call to cls's associated
* __instancecheck__/__subclasscheck__.
*
* @param checkerArg the argument to call the checker with
* @param cls a Python class
* @param checkerName the checker name
* @return null if cls provides no checker, otherwise the result of calling the
* checker
*/
private static PyObject dispatchToChecker(PyObject checkerArg, PyObject cls,
String checkerName) {
//Ignore old style classes.
if (cls instanceof PyClass) {
return null;
}
/* Here we would actually like to call cls.__findattr__("__metaclass__")
* rather than cls.getType(). However there are circumstances where the
* metaclass doesn't show up as __metaclass__. On the other hand we need
* to avoid that checker refers to builtin type___subclasscheck__ or
* type___instancecheck__. Filtering out checker-instances of
* PyBuiltinMethodNarrow does the trick. We also filter out PyMethodDescr
* to shortcut some unnecessary looping.
*/
PyObject checker = cls.getType().__findattr__(checkerName);
if (checker == null || checker instanceof PyMethodDescr ||
checker instanceof PyBuiltinMethodNarrow) {
return null;
}
return checker.__call__(cls, checkerArg);
}
/**
* Return the __bases__ of cls. Returns null if no valid __bases__ are found.
*/
private static PyTuple abstractGetBases(PyObject cls) {
PyObject bases = cls.__findattr__("__bases__");
return bases instanceof PyTuple ? (PyTuple) bases : null;
}
/**
* Throw a TypeError with the specified message if cls does not appear to be a Python
* class.
*/
private static void checkClass(PyObject cls, String message) {
if (abstractGetBases(cls) == null) {
throw Py.TypeError(message);
}
}
/**
* Turn any Python iterable into an array of its elements.
*
* @param iterable to evaluate
* @return array of elements from iterable
*/
static PyObject[] make_array(PyObject iterable) {
// Special-case the common tuple and list cases, for efficiency
if (iterable instanceof PySequenceList) {
return ((PySequenceList) iterable).getArray();
} else {
int n = 10;
if (!(iterable instanceof PyGenerator)) {
try {
n = iterable.__len__(); // may be available, otherwise ...
} catch (PyException pye) { /* ... leave n at 0 */ }
}
List
* It automatically converts {@code args} to {@link org.python.core.PyObject}s.
* For keyword-support use {@link #newJ(PyObject, Class, String[], Object...)}.
*
* @see #newJ(PyObject, Class, PyObject[], String[])
* @see #newJ(PyObject, Class, String[], Object...)
* @see #newJ(PyModule, Class, Object...)
* @see #newJ(PyModule, Class, String[], Object...)
* @see PyModule#newJ(Class, Object...)
* @see PyModule#newJ(Class, String[], Object...)
*
* @param cls - the class to be instanciated
* @param jcls - the Java-type to be returned
* @param args are automatically converted to Jython-PyObjects
* @return an instance of cls in form of the interface jcls
*/
@SuppressWarnings("unchecked")
public static
* {@code keywordss} are applied to the last {@code args} in the list.
*
* @see #newJ(PyObject, Class, Object...)
* @see #newJ(PyObject, Class, String[], Object...)
* @see #newJ(PyModule, Class, Object...)
* @see #newJ(PyModule, Class, String[], Object...)
* @see PyModule#newJ(Class, Object...)
* @see PyModule#newJ(Class, String[], Object...)
*
* @param cls - the class to be instanciated
* @param jcls - the Java-type to be returned
* @param keywords are applied to the last args
* @param args for the Python-class constructor
* @return an instance of cls in form of the interface jcls
*/
@SuppressWarnings("unchecked")
public static
* It automatically converts {@code args} to {@link org.python.core.PyObject}s.
* {@code keywordss} are applied to the last {@code args} in the list.
*
* @see #newJ(PyObject, Class, PyObject[], String[])
* @see #newJ(PyObject, Class, Object...)
* @see #newJ(PyModule, Class, Object...)
* @see #newJ(PyModule, Class, String[], Object...)
* @see PyModule#newJ(Class, Object...)
* @see PyModule#newJ(Class, String[], Object...)
*
* @param cls - the class to be instanciated
* @param jcls - the Java-type to be returned
* @param keywords are applied to the last args
* @param args are automatically converted to Jython-PyObjects
* @return an instance of cls in form of the interface jcls
*/
@SuppressWarnings("unchecked")
public static
* For keywords-support use {@link #newJ(PyModule, Class, String[], Object...)}.
*
* @see #newJ(PyModule, Class, String[], Object...)
* @see #newJ(PyObject, Class, PyObject[], String[])
* @see #newJ(PyObject, Class, Object...)
* @see #newJ(PyObject, Class, String[], Object...)
* @see PyModule#newJ(Class, Object...)
* @see PyModule#newJ(Class, String[], Object...)
*
* @param module the module containing the desired class
* @param jcls Java-type of the desired clas, must have the same name
* @param args constructor-arguments
* @return a new instance of the desired class
*/
public static
* {@code keywordss} are applied to the last {@code args} in the list.
*
* @see #newJ(PyModule, Class, Object...)
* @see #newJ(PyObject, Class, PyObject[], String[])
* @see #newJ(PyObject, Class, Object...)
* @see #newJ(PyObject, Class, String[], Object...)
* @see PyModule#newJ(Class, Object...)
* @see PyModule#newJ(Class, String[], Object...)
*
* @param module the module containing the desired class
* @param jcls Java-type of the desired class, must have the same name
* @param keywords are applied to the last {@code args} in the list
* @param args constructor-arguments
* @return a new instance of the desired class
*/
public static