public void append_json_repr(StringBuffer buf, PyObject py_obj) throws JSONEncodeError { if (py_obj instanceof PyString) append_json_string_repr(buf, ((PyString) py_obj).toString()); // Must test for PyBoolean before PyInteger because former is a subclass of latter. else if (py_obj instanceof PyBoolean) buf.append(((PyBoolean) py_obj).getBooleanValue() ? "true" : "false"); else if (py_obj instanceof PyInteger) buf.append(Integer.toString(((PyInteger) py_obj).getValue())); else if (py_obj instanceof PyLong) { String repr = ((PyLong) py_obj).__repr__().toString(); buf.append(repr.substring(0, repr.length() - 1)); } else if (py_obj instanceof PyFloat) buf.append(Double.toString(((PyFloat) py_obj).getValue())); else if (py_obj instanceof PyStringMap) append_json_string_map_repr(buf, (PyStringMap) py_obj); else if (py_obj instanceof PyDictionary) append_json_dictionary_repr(buf, (PyDictionary) py_obj); else if (py_obj instanceof PySequence) append_json_sequence_repr(buf, (PySequence) py_obj); else if (py_obj instanceof PyNone) buf.append("null"); else if (py_obj.__findattr__("__json__") != null && py_obj.__findattr__("__json__").isCallable()) buf.append(((PyMethod) py_obj.__findattr__("__json__")).__call__().toString()); else throw new JSONEncodeError( "Python '" + ((PyType) py_obj.fastGetClass()).fastGetName() + "' object '" + py_obj.__repr__() + "' is not encodable in JSON"); }
/** * Ensure that if the test runner has a {@code __del__} attribute, it is called when the thread * is shutdown. Normally Jython defers this to the Java garbage collector, so we might have done * something like * * <blockquote> * * <pre> * m_testRunner = null; * Runtime.getRuntime().gc(); * </pre> * * </blockquote> * * instead. However this would have a number of problems: * * <ol> * <li>Some JVM's may chose not to finalise the test runner in response to {@code gc()}. * <li>{@code __del__} would be called by a GC thread. * <li>The standard Jython finalizer wrapping around {@code __del__} logs to {@code stderr}. * </ol> * * <p>Instead, we call any {@code __del__} ourselves. After calling this method, the {@code * PyObject} that underlies this class is made invalid. */ @Override public void shutdown() throws ScriptExecutionException { final PyObject del = m_testRunner.__findattr__("__del__"); if (del != null) { try { del.__call__(); } catch (final PyException e) { throw new JythonScriptExecutionException("deleting TestRunner instance", e); } finally { // To avoid the (pretty small) chance of the test runner being // finalised and __del__ being run twice, we disable it. // Unfortunately, Jython caches the __del__ attribute and makes // it impossible to turn it off at a class level. Instead we do // this: m_testRunner.__setattr__("__class__", m_dieQuietly); } } }
/** * Retrieves <code>name</code> from the PyObject in <code>proxy</code> if it's defined in Python. * This is a specialized helper function for internal PyProxy use. */ public static PyObject findPython(PyProxy proxy, String name) { PyObject o = proxy._getPyInstance(); if (o == null) { proxy.__initProxy__(new Object[0]); o = proxy._getPyInstance(); } PyObject ret = o.__findattr__(name); if (ret instanceof PyMethod) { PyMethod meth = ((PyMethod) ret); if (meth.__func__ instanceof PyReflectedFunction) { PyReflectedFunction func = (PyReflectedFunction) meth.__func__; if (func.nargs > 0 && proxy.getClass() == func.argslist[0].declaringClass) { // This function is the default return for the proxy type if the Python instance // hasn't returned something of its own from __findattr__, so do the standard // Java call on this return null; } } } Py.setSystemState(proxy._getPySystemState()); return ret; }