From: <zy...@us...> - 2010-06-26 04:03:29
|
Revision: 7071 http://jython.svn.sourceforge.net/jython/?rev=7071&view=rev Author: zyasoft Date: 2010-06-26 04:03:22 +0000 (Sat, 26 Jun 2010) Log Message: ----------- Added test code to verify that proxies are not leaked by hard refs in PyType#class_to_test. This will cause the regrtest to fail until the patch in issue 1522 is also applied (other issues apply in its integration unfortunately). Modified Paths: -------------- trunk/jython/Lib/test/test_jy_internals.py trunk/jython/tests/java/javatests/TestSupport.java Modified: trunk/jython/Lib/test/test_jy_internals.py =================================================================== --- trunk/jython/Lib/test/test_jy_internals.py 2010-06-25 14:22:08 UTC (rev 7070) +++ trunk/jython/Lib/test/test_jy_internals.py 2010-06-26 04:03:22 UTC (rev 7071) @@ -1,6 +1,7 @@ """ test some jython internals """ +import gc import unittest import time from test.test_support import run_suite @@ -9,10 +10,59 @@ import jarray from org.python.core import Py +from org.python.util import PythonInterpreter +from javatests.TestSupport import getField from java.sql import Date, Time, Timestamp import datetime +class MemoryLeakTests(unittest.TestCase): + + def test_class_to_test_weakness(self): + # regrtest for bug 1522, adapted from test code submitted by Matt Brinkley + + # work around the fact that we can't look at PyType directly + # by using this helper function that reflects on PyType (and + # demonstrates here that it's the same as the builtin function + # `type`!) + class_to_type_map = getField(type, 'class_to_type').get(None) + + def make_clean(): + # gc a few times just to be really sure, since in this + # case we don't really care if it takes a few cycles of GC + # for the garbage to be reached + gc.collect() + time.sleep(0.1) + gc.collect() + time.sleep(0.5) + gc.collect() + + def create_proxies(): + pi = PythonInterpreter() + pi.exec(""" +from java.lang import Comparable + +class Dog(Comparable): + def compareTo(self, o): + return 0 + def bark(self): + return 'woof woof' + +Dog().bark() +""") + pi.cleanup(); + make_clean() + + # get to steady state first, then verify we don't create new proxies + for i in xrange(2): + create_proxies() + start_size = class_to_type_map.size() + for i in xrange(5): + create_proxies() + make_clean() + self.assertEqual(start_size, class_to_type_map.size()) + + class WeakIdentityMapTests(unittest.TestCase): def test_functionality(self): @@ -249,6 +299,7 @@ suite_add(IdTest) suite_add(FrameTest) suite_add(ModuleTest) + suite_add(MemoryLeakTests) run_suite(test_suite) if __name__ == "__main__": Modified: trunk/jython/tests/java/javatests/TestSupport.java =================================================================== --- trunk/jython/tests/java/javatests/TestSupport.java 2010-06-25 14:22:08 UTC (rev 7070) +++ trunk/jython/tests/java/javatests/TestSupport.java 2010-06-26 04:03:22 UTC (rev 7071) @@ -1,6 +1,9 @@ //Copyright (c) Corporation for National Research Initiatives package javatests; +import java.lang.reflect.Field; +import java.lang.NoSuchFieldException; + /** * @author updikca1 */ @@ -46,5 +49,16 @@ assertThat( !a.equals(b), message + "[not a.equals(b) failed]"); assertThat( !b.equals(a), message + "[not b.equals(a) failed]"); } + + public static Field getField(Class cls, String name) { + try { + Field f = cls.getDeclaredField(name); + f.setAccessible(true); + return f; + } catch (NoSuchFieldException ex) { + throw new RuntimeException(ex); + } + } + } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-06-26 06:04:07
|
Revision: 7072 http://jython.svn.sourceforge.net/jython/?rev=7072&view=rev Author: zyasoft Date: 2010-06-26 06:04:00 +0000 (Sat, 26 Jun 2010) Log Message: ----------- Fixed #1522 by weakening references in class_to_type map (both key and value). However, in certain cases our code expects that these refs are in fact hard, so make all exposed types hard and also by default PyType#fromClass will add a hard ref. In contrast, types imported in that proxy Java classes should now be weak. Added Guava R05 (which includes google collections), to support the desired map. We may wish to strip this down, however, it could be useful in the future too. Modified Paths: -------------- trunk/jython/build.xml trunk/jython/src/org/python/core/PyJavaType.java trunk/jython/src/org/python/core/PyObject.java trunk/jython/src/org/python/core/PyType.java trunk/jython/src/org/python/core/adapter/ClassicPyObjectAdapter.java trunk/jython/src/org/python/core/imp.java trunk/jython/src/org/python/modules/zipimport/zipimporter.java trunk/jython/src/org/python/util/Generic.java Added Paths: ----------- trunk/jython/extlibs/guava-r05.jar Modified: trunk/jython/build.xml =================================================================== --- trunk/jython/build.xml 2010-06-26 04:03:22 UTC (rev 7071) +++ trunk/jython/build.xml 2010-06-26 06:04:00 UTC (rev 7072) @@ -188,6 +188,7 @@ <pathelement path="${extlibs.dir}/asm-3.1.jar" /> <pathelement path="${extlibs.dir}/asm-commons-3.1.jar" /> <pathelement path="${extlibs.dir}/constantine.jar" /> + <pathelement path="${extlibs.dir}/guava-r05.jar" /> <pathelement path="${extlibs.dir}/jaffl.jar"/> <pathelement path="${extlibs.dir}/jffi-Darwin.jar"/> <pathelement path="${extlibs.dir}/jffi-i386-FreeBSD.jar"/> @@ -584,6 +585,8 @@ <zipfileset src="extlibs/asm-commons-3.1.jar"/> <zipfileset src="extlibs/asm-util-3.1.jar"/> <rule pattern="org.objectweb.asm.**" result="org.python.objectweb.asm.@1"/> + <zipfileset src="extlibs/guava-r05.jar"/> + <rule pattern="com.google.**" result="org.python.google.@1"/> <zipfileset src="extlibs/jaffl.jar"/> <zipfileset src="extlibs/jffi-Darwin.jar"/> <zipfileset src="extlibs/jffi-i386-FreeBSD.jar"/> Added: trunk/jython/extlibs/guava-r05.jar =================================================================== (Binary files differ) Property changes on: trunk/jython/extlibs/guava-r05.jar ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Modified: trunk/jython/src/org/python/core/PyJavaType.java =================================================================== --- trunk/jython/src/org/python/core/PyJavaType.java 2010-06-26 04:03:22 UTC (rev 7071) +++ trunk/jython/src/org/python/core/PyJavaType.java 2010-06-26 06:04:00 UTC (rev 7072) @@ -59,7 +59,7 @@ private Set<String> modified; public static PyObject wrapJavaObject(Object o) { - PyObject obj = new PyObjectDerived(PyType.fromClass(o.getClass())); + PyObject obj = new PyObjectDerived(PyType.fromClass(o.getClass(), false)); obj.javaProxy = o; return obj; } Modified: trunk/jython/src/org/python/core/PyObject.java =================================================================== --- trunk/jython/src/org/python/core/PyObject.java 2010-06-26 04:03:22 UTC (rev 7071) +++ trunk/jython/src/org/python/core/PyObject.java 2010-06-26 06:04:00 UTC (rev 7072) @@ -63,7 +63,7 @@ * field to correspond to the specific subclass of <code>PyObject</code> being instantiated. **/ public PyObject() { - objtype = PyType.fromClass(getClass()); + objtype = PyType.fromClass(getClass(), false); } /** Modified: trunk/jython/src/org/python/core/PyType.java =================================================================== --- trunk/jython/src/org/python/core/PyType.java 2010-06-26 04:03:22 UTC (rev 7071) +++ trunk/jython/src/org/python/core/PyType.java 2010-06-26 06:04:00 UTC (rev 7072) @@ -22,6 +22,8 @@ import org.python.modules._weakref.WeakrefModule; import org.python.util.Generic; +import com.google.common.collect.MapMaker; + /** * The Python Type object implementation. */ @@ -97,7 +99,8 @@ /** Mapping of Java classes to their PyTypes. */ private static Map<Class<?>, PyType> class_to_type; - + private static Set<PyType> exposedTypes; + /** Mapping of Java classes to their TypeBuilders. */ private static Map<Class<?>, TypeBuilder> classToBuilder; @@ -121,7 +124,15 @@ PyObject[] args, String[] keywords) { // Special case: type(x) should return x.getType() if (args.length == 1 && keywords.length == 0) { - return args[0].getType(); + PyObject obj = args[0]; + PyType objType = obj.getType(); + + // special case for PyStringMap so that it types as a dict + PyType psmType = PyType.fromClass(PyStringMap.class); + if (objType == psmType) { + return PyDictionary.TYPE; + } + return objType; } // If that didn't trigger, we need 3 arguments. but ArgParser below may give a msg // saying type() needs exactly 3. @@ -517,7 +528,7 @@ * followed by the mro of baseClass. */ protected void computeLinearMro(Class<?> baseClass) { - base = PyType.fromClass(baseClass); + base = PyType.fromClass(baseClass, false); mro = new PyType[base.mro.length + 1]; System.arraycopy(base.mro, 0, mro, 1, base.mro.length); mro[0] = this; @@ -622,7 +633,7 @@ dict); javaProxy = proxyClass; - PyType proxyType = PyType.fromClass(proxyClass); + PyType proxyType = PyType.fromClass(proxyClass, false); List<PyObject> cleanedBases = Generic.list(); boolean addedProxyType = false; for (PyObject base : bases) { @@ -908,7 +919,7 @@ PyObject[] computeMro(MROMergeState[] toMerge, List<PyObject> mro) { boolean addedProxy = false; - PyType proxyAsType = javaProxy == null ? null : PyType.fromClass(((Class<?>)javaProxy)); + PyType proxyAsType = javaProxy == null ? null : PyType.fromClass(((Class<?>)javaProxy), false); scan : for (int i = 0; i < toMerge.length; i++) { if (toMerge[i].isMerged()) { continue scan; @@ -1164,7 +1175,7 @@ return null; } - public static void addBuilder(Class<?> forClass, TypeBuilder builder) { + public synchronized static void addBuilder(Class<?> forClass, TypeBuilder builder) { if (classToBuilder == null) { classToBuilder = Generic.map(); } @@ -1181,9 +1192,9 @@ } } - private static PyType addFromClass(Class<?> c, Set<PyJavaType> needsInners) { + private synchronized static PyType addFromClass(Class<?> c, Set<PyJavaType> needsInners) { if (ExposeAsSuperclass.class.isAssignableFrom(c)) { - PyType exposedAs = fromClass(c.getSuperclass()); + PyType exposedAs = fromClass(c.getSuperclass(), false); class_to_type.put(c, exposedAs); return exposedAs; } @@ -1227,7 +1238,7 @@ return builder; } - private static PyType createType(Class<?> c, Set<PyJavaType> needsInners) { + private synchronized static PyType createType(Class<?> c, Set<PyJavaType> needsInners) { PyType newtype; if (c == PyType.class) { newtype = new PyType(false); @@ -1251,18 +1262,25 @@ return newtype; } - // XXX what's the proper scope of this synchronization? given module import lock, might be - // ok to omit this sync here... + // re the synchronization used here: this result is cached in each type obj, + // so we just need to prevent data races. all public methods that access class_to_type + // are themselves synchronized. However, if we use Google Collections/Guava, + // MapMaker only uses ConcurrentMap anyway + public static synchronized PyType fromClass(Class<?> c) { + return fromClass(c, true); + } + + public static synchronized PyType fromClass(Class<?> c, boolean hardRef) { if (class_to_type == null) { - class_to_type = Generic.synchronizedWeakHashMap(); + class_to_type = new MapMaker().weakKeys().weakValues().makeMap(); addFromClass(PyType.class, null); } PyType type = class_to_type.get(c); if (type != null) { return type; } - // We haven't seen this class before, so it's type needs to be created. If it's being + // We haven't seen this class before, so its type needs to be created. If it's being // exposed as a Java class, defer processing its inner types until it's completely // created in case the inner class references a class that references this class. Set<PyJavaType> needsInners = Generic.set(); @@ -1284,10 +1302,17 @@ || ExposeAsSuperclass.class.isAssignableFrom(inner)) { Py.BOOTSTRAP_TYPES.add(inner); } - javaType.dict.__setitem__(inner.getSimpleName(), PyType.fromClass(inner)); + javaType.dict.__setitem__(inner.getSimpleName(), PyType.fromClass(inner, hardRef)); } } } + if (hardRef && result != null) { + if (exposedTypes == null) { + exposedTypes = Generic.set(); + } + exposedTypes.add(result) ; + } + return result; } @@ -1757,7 +1782,7 @@ private Object readResolve() { if (underlying_class != null) { - return PyType.fromClass(underlying_class); + return PyType.fromClass(underlying_class, false); } PyObject mod = imp.importName(module.intern(), false); PyObject pytyp = mod.__getattr__(name.intern()); Modified: trunk/jython/src/org/python/core/adapter/ClassicPyObjectAdapter.java =================================================================== --- trunk/jython/src/org/python/core/adapter/ClassicPyObjectAdapter.java 2010-06-26 04:03:22 UTC (rev 7071) +++ trunk/jython/src/org/python/core/adapter/ClassicPyObjectAdapter.java 2010-06-26 06:04:00 UTC (rev 7072) @@ -73,7 +73,7 @@ add(new ClassAdapter(Class.class) { public PyObject adapt(Object o) { - return PyType.fromClass((Class<?>)o); + return PyType.fromClass((Class<?>)o, false); } }); Modified: trunk/jython/src/org/python/core/imp.java =================================================================== --- trunk/jython/src/org/python/core/imp.java 2010-06-26 04:03:22 UTC (rev 7071) +++ trunk/jython/src/org/python/core/imp.java 2010-06-26 06:04:00 UTC (rev 7072) @@ -399,7 +399,7 @@ throw Py.JavaError(e); } } - return PyType.fromClass(c); // xxx? + return PyType.fromClass(c, false); // xxx? } static PyObject getPathImporter(PyObject cache, PyList hooks, PyObject p) { Modified: trunk/jython/src/org/python/modules/zipimport/zipimporter.java =================================================================== --- trunk/jython/src/org/python/modules/zipimport/zipimporter.java 2010-06-26 04:03:22 UTC (rev 7071) +++ trunk/jython/src/org/python/modules/zipimport/zipimporter.java 2010-06-26 06:04:00 UTC (rev 7072) @@ -117,7 +117,7 @@ zipimport._zip_directory_cache.__setitem__(archive, files); } } else { - throw zipimport.ZipImportError("not a Zip file"); + throw zipimport.ZipImportError("not a Zip file: " + path); } if (prefix != "" && !prefix.endsWith(File.separator)) { Modified: trunk/jython/src/org/python/util/Generic.java =================================================================== --- trunk/jython/src/org/python/util/Generic.java 2010-06-26 04:03:22 UTC (rev 7071) +++ trunk/jython/src/org/python/util/Generic.java 2010-06-26 06:04:00 UTC (rev 7072) @@ -58,11 +58,6 @@ return new HashMap<K, V>(); } - public static <K, V> Map<K, V> synchronizedWeakHashMap() { - return Collections.synchronizedMap(new WeakHashMap<K, V>()); - } - - /** * Makes a ConcurrentMap using generic types inferred from whatever this is being * assigned to. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <otm...@us...> - 2010-06-27 04:51:35
|
Revision: 7074 http://jython.svn.sourceforge.net/jython/?rev=7074&view=rev Author: otmarhumbel Date: 2010-06-27 04:51:29 +0000 (Sun, 27 Jun 2010) Log Message: ----------- prepare for 2.5.2b1 Modified Paths: -------------- trunk/jython/NEWS trunk/jython/README.txt trunk/jython/build.xml Modified: trunk/jython/NEWS =================================================================== --- trunk/jython/NEWS 2010-06-26 06:26:04 UTC (rev 7073) +++ trunk/jython/NEWS 2010-06-27 04:51:29 UTC (rev 7074) @@ -1,6 +1,6 @@ Jython NEWS -Jython 2.5.2a1 +Jython 2.5.2b1 Bugs Fixed - [ 1614 ] minidom chunks the character input on multi-line values - [ 1615 ] Can't invoke Java method that takes a variable number of arguments with zero arguments @@ -52,6 +52,7 @@ - [ 1594 ] Glob patterns like *.txt processed incorrectly on startup - [ 1356 ] [Windows] test_subprocess test_communicate_pipe_buf fails - [ 1595 ] [patch] CachedJarsPackageManager cannot write cache for packages in jar over 64k + - [ 1522 ] repeated execution of external python scripts causing PermGen out of memory exception - Fix runtime issues during exitfuncs triggered via SystemRestart (such as during Django or Pylons development mode reloading) - Fix pickling of collections.defaultdict objects Modified: trunk/jython/README.txt =================================================================== --- trunk/jython/README.txt 2010-06-26 06:26:04 UTC (rev 7073) +++ trunk/jython/README.txt 2010-06-27 04:51:29 UTC (rev 7074) @@ -6,6 +6,6 @@ bugs, a number of Python compatibility bugs, and more. See the NEWS file for more details. -The release was compiled on Windows XP with JDK 6 and requires JDK 5 to run. +The release was compiled on Mac OS X with JDK 5 and requires JDK 5 to run. Please try this out and report any bugs at http://bugs.jython.org. Modified: trunk/jython/build.xml =================================================================== --- trunk/jython/build.xml 2010-06-26 06:26:04 UTC (rev 7073) +++ trunk/jython/build.xml 2010-06-27 04:51:29 UTC (rev 7074) @@ -122,13 +122,13 @@ <property name="PY_RELEASE_LEVEL_SNAPSHOT" value="170"/> <!-- 0xAA --> <!-- The current version info --> - <property name="jython.version" value="2.5.1+"/> - <property name="jython.version.noplus" value="2.5.1"/> + <property name="jython.version" value="2.5.2b1"/> + <property name="jython.version.noplus" value="2.5.2b1"/> <property name="jython.major_version" value="2"/> <property name="jython.minor_version" value="5"/> - <property name="jython.micro_version" value="1"/> - <property name="jython.release_level" value="${PY_RELEASE_LEVEL_FINAL}"/> - <property name="jython.release_serial" value="0"/> + <property name="jython.micro_version" value="2"/> + <property name="jython.release_level" value="${PY_RELEASE_LEVEL_BETA}"/> + <property name="jython.release_serial" value="1"/> <condition property="do.snapshot.build"> <isset property="snapshot.revision" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-07-14 05:12:26
|
Revision: 7078 http://jython.svn.sourceforge.net/jython/?rev=7078&view=rev Author: zyasoft Date: 2010-07-14 05:12:19 +0000 (Wed, 14 Jul 2010) Log Message: ----------- Added specific support of threading.Thread.__tojava__, which enables the underlying Java thread to be accessed. Also restored concurrency of the canonical maps by switching to Google Guava to support them with MapMaker. Fixes #1630. Modified Paths: -------------- trunk/jython/Lib/test/test_threading_jy.py trunk/jython/Lib/threading.py trunk/jython/NEWS trunk/jython/src/org/python/modules/_threading/_threading.java Modified: trunk/jython/Lib/test/test_threading_jy.py =================================================================== --- trunk/jython/Lib/test/test_threading_jy.py 2010-07-14 04:18:08 UTC (rev 7077) +++ trunk/jython/Lib/test/test_threading_jy.py 2010-07-14 05:12:19 UTC (rev 7078) @@ -2,13 +2,17 @@ Made for Jython. """ +from __future__ import with_statement + import unittest from test import test_support import threading import time import random -from threading import Thread +from threading import Condition, Lock, Thread +from java.lang import Thread as JThread, InterruptedException + class ThreadingTestCase(unittest.TestCase): def test_str_name(self): @@ -42,8 +46,46 @@ self.assertEqual(threading.Lock, threading._Lock) self.assertEqual(threading.RLock, threading._RLock) + +class JavaIntegrationTestCase(unittest.TestCase): + """Verifies that Thread.__tojava__ correctly gets the underlying Java thread""" + + def test_interruptible(self): + + def wait_until_interrupted(cv): + name = threading.currentThread().getName() + with cv: + while not JThread.currentThread().isInterrupted(): + try: + cv.wait() + except InterruptedException, e: + break + + num_threads = 5 + unfair_condition = Condition() + threads = [ + Thread( + name="thread #%d" % i, + target=wait_until_interrupted, + args=(unfair_condition,)) + for i in xrange(num_threads)] + + for thread in threads: + thread.start() + time.sleep(0.1) + + for thread in threads: + JThread.interrupt(thread) + + joined_threads = 0 + for thread in threads: + thread.join(1.) # timeout just in case so we don't stall regrtest + joined_threads += 1 + self.assertEqual(joined_threads, num_threads) + + def test_main(): - test_support.run_unittest(ThreadingTestCase, TwistedTestCase) + test_support.run_unittest(JavaIntegrationTestCase, ThreadingTestCase, TwistedTestCase) if __name__ == "__main__": Modified: trunk/jython/Lib/threading.py =================================================================== --- trunk/jython/Lib/threading.py 2010-07-14 04:18:08 UTC (rev 7077) +++ trunk/jython/Lib/threading.py 2010-07-14 05:12:19 UTC (rev 7078) @@ -3,12 +3,11 @@ from java.util.concurrent import Semaphore, CyclicBarrier from java.util.concurrent.locks import ReentrantLock from org.python.util import jython +from org.python.core import Py from thread import _newFunctionThread from thread import _local as local -from _threading import Lock, RLock, Condition, _Lock, _RLock +from _threading import Lock, RLock, Condition, _Lock, _RLock, _threads, _active, _jthread_to_pythread, _register_thread, _unregister_thread import java.lang.Thread -import weakref - import sys as _sys from traceback import print_exc as _print_exc @@ -93,8 +92,7 @@ class JavaThread(object): def __init__(self, thread): self._thread = thread - _jthread_to_pythread[thread] = self - _threads[thread.getId()] = self + _register_thread(thread, self) def __repr__(self): _thread = self._thread @@ -141,11 +139,14 @@ def setDaemon(self, daemonic): self._thread.setDaemon(bool(daemonic)) -# relies on the fact that this is a CHM -_threads = weakref.WeakValueDictionary() -_active = _threads -_jthread_to_pythread = Collections.synchronizedMap(WeakHashMap()) + def __tojava__(self, c): + if isinstance(self._thread, c): + return self._thread + if isinstance(self, c): + return self + return Py.NoConversion + class Thread(JavaThread): def __init__(self, group=None, target=None, name=None, args=None, kwargs=None): assert group is None, "group argument must be None for now" @@ -225,7 +226,7 @@ pass def __delete(self): - del _threads[self._thread.getId()] + _unregister_thread(self._thread) class _MainThread(Thread): @@ -241,7 +242,7 @@ return False def __exitfunc(self): - del _threads[self._thread.getId()] + _unregister_thread(self._thread) t = _pickSomeNonDaemonThread() while t: t.join() Modified: trunk/jython/NEWS =================================================================== --- trunk/jython/NEWS 2010-07-14 04:18:08 UTC (rev 7077) +++ trunk/jython/NEWS 2010-07-14 05:12:19 UTC (rev 7078) @@ -1,8 +1,8 @@ Jython NEWS -Jython 2.5.2a1 +Jython 2.5.2b2 Bugs Fixed - - [ ] + - [ 1630 ] threading.Thread lacks __tojava__ method Jython 2.5.2b1 Bugs Fixed Modified: trunk/jython/src/org/python/modules/_threading/_threading.java =================================================================== --- trunk/jython/src/org/python/modules/_threading/_threading.java 2010-07-14 04:18:08 UTC (rev 7077) +++ trunk/jython/src/org/python/modules/_threading/_threading.java 2010-07-14 05:12:19 UTC (rev 7078) @@ -3,6 +3,8 @@ import org.python.core.ClassDictInit; import org.python.core.Py; import org.python.core.PyObject; +import com.google.common.collect.MapMaker; +import java.util.Map; public class _threading implements ClassDictInit { @@ -13,5 +15,21 @@ dict.__setitem__("_Lock", Lock.TYPE); dict.__setitem__("_RLock", Lock.TYPE); dict.__setitem__("Condition", Condition.TYPE); +// dict.__setitem__("JavaThread", JavaThread.TYPE); } + + // internals to support threading.py, test_threading.py + public static Map<Long, PyObject> _threads = new MapMaker().weakValues().makeMap(); + public static Map<Thread, PyObject> _jthread_to_pythread = new MapMaker().weakKeys().makeMap(); + public static Map<Long, PyObject> _active = _threads; + + public static void _register_thread(Thread jthread, PyObject pythread) { + _threads.put(jthread.getId(), pythread); + _jthread_to_pythread.put(jthread, pythread); + } + + public static void _unregister_thread(Thread jthread) { + _threads.remove(jthread.getId()); + } + } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-07-20 03:50:57
|
Revision: 7079 http://jython.svn.sourceforge.net/jython/?rev=7079&view=rev Author: zyasoft Date: 2010-07-20 03:50:50 +0000 (Tue, 20 Jul 2010) Log Message: ----------- Fixed magic comments for source encoding so that it only looks at actual comments (first two lines), not other source text. Resolves #1506 Modified Paths: -------------- trunk/jython/Lib/test/test_grammar_jy.py trunk/jython/NEWS trunk/jython/src/org/python/core/ParserFacade.java Modified: trunk/jython/Lib/test/test_grammar_jy.py =================================================================== --- trunk/jython/Lib/test/test_grammar_jy.py 2010-07-14 05:12:19 UTC (rev 7078) +++ trunk/jython/Lib/test/test_grammar_jy.py 2010-07-20 03:50:50 UTC (rev 7079) @@ -2,6 +2,7 @@ """ from test import test_support +import sys import unittest class GrammarTest(unittest.TestCase): @@ -32,8 +33,21 @@ self.assertEquals(7, foo(1, 7)) self.assertEquals(10, foo(b=10)) -def test_main(): + +pep263 = """ + # verify that PEP263 encoding is only set by magic comments, not + # by other similar looking input; seen in issue 1506 + >>> line = '"Content-Transfer-Encoding: 8bit"' + >>> print line + "Content-Transfer-Encoding: 8bit" + """ + +__test__ = dict(pep263=pep263) + + +def test_main(verbose=None): test_support.run_unittest(GrammarTest) + test_support.run_doctest(sys.modules[__name__], verbose) if __name__ == '__main__': - test_main() + test_main(verbose=True) Modified: trunk/jython/NEWS =================================================================== --- trunk/jython/NEWS 2010-07-14 05:12:19 UTC (rev 7078) +++ trunk/jython/NEWS 2010-07-20 03:50:50 UTC (rev 7079) @@ -2,6 +2,7 @@ Jython 2.5.2b2 Bugs Fixed + - [ 1506 ] Jython applies PEP263 pattern for determining source-code encoding on noncomments - [ 1630 ] threading.Thread lacks __tojava__ method Jython 2.5.2b1 Modified: trunk/jython/src/org/python/core/ParserFacade.java =================================================================== --- trunk/jython/src/org/python/core/ParserFacade.java 2010-07-14 05:12:19 UTC (rev 7078) +++ trunk/jython/src/org/python/core/ParserFacade.java 2010-07-20 03:50:50 UTC (rev 7079) @@ -344,9 +344,9 @@ } private static ExpectedEncodingBufferedReader prepBufReader(String string, - CompilerFlags cflags, - String filename) - throws IOException { + CompilerFlags cflags, + String filename) + throws IOException { if (cflags.source_is_utf8) return prepBufReader(new StringReader(string), cflags, filename); @@ -429,10 +429,10 @@ return encoding; } + private static final Pattern pep263EncodingPattern = Pattern.compile("#.*coding[:=]\\s*([-\\w.]+)"); + private static String matchEncoding(String inputStr) { - String patternStr = "coding[:=]\\s*([-\\w.]+)"; - Pattern pattern = Pattern.compile(patternStr); - Matcher matcher = pattern.matcher(inputStr); + Matcher matcher = pep263EncodingPattern.matcher(inputStr); boolean matchFound = matcher.find(); if (matchFound && matcher.groupCount() == 1) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-07-20 04:29:05
|
Revision: 7080 http://jython.svn.sourceforge.net/jython/?rev=7080&view=rev Author: zyasoft Date: 2010-07-20 04:28:59 +0000 (Tue, 20 Jul 2010) Log Message: ----------- Fixes SyspathJavaLoader so that packages added to sys.path work with Java's standard resource loading (getResource, getResourceAsStream) methods. Resolves #1373. Thanks Justin Deoliveira and Costantino Cerbo for contributing this patch. Modified Paths: -------------- trunk/jython/ACKNOWLEDGMENTS trunk/jython/Lib/test/test_sys_jy.py trunk/jython/NEWS trunk/jython/src/org/python/core/SyspathJavaLoader.java Added Paths: ----------- trunk/jython/Lib/test/bug1373.jar Modified: trunk/jython/ACKNOWLEDGMENTS =================================================================== --- trunk/jython/ACKNOWLEDGMENTS 2010-07-20 03:50:50 UTC (rev 7079) +++ trunk/jython/ACKNOWLEDGMENTS 2010-07-20 04:28:59 UTC (rev 7080) @@ -88,6 +88,8 @@ Leonardo Soto James Robinson Jonathan Feinberg + Justin Deoliveira + Costantino Cerbo Local Variables: mode: indented-text Added: trunk/jython/Lib/test/bug1373.jar =================================================================== (Binary files differ) Property changes on: trunk/jython/Lib/test/bug1373.jar ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Modified: trunk/jython/Lib/test/test_sys_jy.py =================================================================== --- trunk/jython/Lib/test/test_sys_jy.py 2010-07-20 03:50:50 UTC (rev 7079) +++ trunk/jython/Lib/test/test_sys_jy.py 2010-07-20 04:28:59 UTC (rev 7080) @@ -129,8 +129,25 @@ self.assertTrue('sys_jy_test_module' not in sys.modules, "sys.modules should be per PySystemState instance") +class SyspathResourceTest(unittest.TestCase): + def setUp(self): + self.orig_path = sys.path + sys.path.insert(0, test.test_support.findfile("bug1373.jar")) + + def tearDown(self): + sys.path = self.orig_path + + def test_resource_stream_from_syspath(self): + from pck import Main + self.assert_(Main.getResourceAsStream('Main.txt')) + + def test_resource_url_from_syspath(self): + from pck import Main + self.assert_(Main.getResource('Main.txt')) + + def test_main(): - test.test_support.run_unittest(SysTest, ShadowingTest) + test.test_support.run_unittest(SysTest, ShadowingTest, SyspathResourceTest) if __name__ == "__main__": test_main() Modified: trunk/jython/NEWS =================================================================== --- trunk/jython/NEWS 2010-07-20 03:50:50 UTC (rev 7079) +++ trunk/jython/NEWS 2010-07-20 04:28:59 UTC (rev 7080) @@ -2,6 +2,7 @@ Jython 2.5.2b2 Bugs Fixed + - [ 1373 ] Jython ClassLoader getResource does not work - [ 1506 ] Jython applies PEP263 pattern for determining source-code encoding on noncomments - [ 1630 ] threading.Thread lacks __tojava__ method Modified: trunk/jython/src/org/python/core/SyspathJavaLoader.java =================================================================== --- trunk/jython/src/org/python/core/SyspathJavaLoader.java 2010-07-20 03:50:50 UTC (rev 7079) +++ trunk/jython/src/org/python/core/SyspathJavaLoader.java 2010-07-20 04:28:59 UTC (rev 7080) @@ -134,7 +134,7 @@ ZipEntry ze = archive.getEntry(entryRes); if (ze != null) { try { - return new URL("jar:" + entry.__str__().toString() + "!/" + entryRes); + return new URL("jar:file:" + entry.__str__().toString() + "!/" + entryRes); } catch (MalformedURLException e) { throw new RuntimeException(e); } @@ -143,7 +143,11 @@ } String dir = sys.getPath(entry.__str__().toString()); try { - return new File(dir, res).toURI().toURL(); + File resource = new File(dir, res); + if (!resource.exists()) { + continue; + } + return resource.toURI().toURL(); } catch (MalformedURLException e) { throw new RuntimeException(e); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-07-20 05:20:18
|
Revision: 7081 http://jython.svn.sourceforge.net/jython/?rev=7081&view=rev Author: zyasoft Date: 2010-07-20 05:20:12 +0000 (Tue, 20 Jul 2010) Log Message: ----------- Added test to verify that single method interface support does not break java.lang.Object methods like toString. (This was actually fixed by Tobias in r6982.) Modified Paths: -------------- trunk/jython/Lib/test/test_func_jy.py trunk/jython/NEWS Modified: trunk/jython/Lib/test/test_func_jy.py =================================================================== --- trunk/jython/Lib/test/test_func_jy.py 2010-07-20 04:28:59 UTC (rev 7080) +++ trunk/jython/Lib/test/test_func_jy.py 2010-07-20 05:20:12 UTC (rev 7081) @@ -4,6 +4,7 @@ """ import types import unittest +from java.lang import Object from test import test_support xyz = 123 @@ -48,9 +49,25 @@ self.assertNotEqual(hash(foo.bar), hash(Foo().bar)) +class SingleMethodInterfaceTestCase(unittest.TestCase): + + def test_java_lang_object_methods(self): + # Passing a PyFunction to Object.toString, .hashCode, etc + # should not result in the function itself being called + + def return42(): + return 42 + s = Object.toString(return42) + self.assertNotEqual(s, 42) + self.assert_(s.startswith('<function return42')) + + + + def test_main(): test_support.run_unittest(FunctionTypeTestCase, - MethodHashCodeTestCase) + MethodHashCodeTestCase, + SingleMethodInterfaceTestCase) if __name__ == '__main__': test_main() Modified: trunk/jython/NEWS =================================================================== --- trunk/jython/NEWS 2010-07-20 04:28:59 UTC (rev 7080) +++ trunk/jython/NEWS 2010-07-20 05:20:12 UTC (rev 7081) @@ -5,6 +5,7 @@ - [ 1373 ] Jython ClassLoader getResource does not work - [ 1506 ] Jython applies PEP263 pattern for determining source-code encoding on noncomments - [ 1630 ] threading.Thread lacks __tojava__ method + - [ 1558 ] PyFunction to single method interface wrapping does not handle java.lang.Object methods Jython 2.5.2b1 Bugs Fixed @@ -98,6 +99,8 @@ - Fix pickling of collections.defaultdict objects - Fix the cmath module to accept objects implementing the __float__ method - Add google indexer (by Yin Wang and Steve Yegge) + - Python functions can be directly passed to Java methods that + take a single method interface (such as Callable or Runnable) Jython 2.5.1rc3 Bugs Fixed This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2010-07-27 23:44:58
|
Revision: 7082 http://jython.svn.sourceforge.net/jython/?rev=7082&view=rev Author: pjenvey Date: 2010-07-27 23:44:47 +0000 (Tue, 27 Jul 2010) Log Message: ----------- fix array breaking __radd__ fallbacks fixes #1622 Modified Paths: -------------- trunk/jython/Lib/test/test_array.py trunk/jython/Lib/test/test_array_jy.py trunk/jython/NEWS trunk/jython/src/org/python/core/PyArray.java Modified: trunk/jython/Lib/test/test_array.py =================================================================== --- trunk/jython/Lib/test/test_array.py 2010-07-20 05:20:12 UTC (rev 7081) +++ trunk/jython/Lib/test/test_array.py 2010-07-27 23:44:47 UTC (rev 7082) @@ -291,10 +291,13 @@ ) b = array.array(self.badtypecode()) - self.assertRaises(TypeError, a.__add__, b) + if test_support.is_jython: + self.assertRaises(TypeError, operator.add, a, b) + self.assertRaises(TypeError, operator.add, a, "bad") + else: + self.assertRaises(TypeError, a.__add__, b) + self.assertRaises(TypeError, a.__add__, "bad") - self.assertRaises(TypeError, a.__add__, "bad") - def test_iadd(self): a = array.array(self.typecode, self.example[::-1]) b = a @@ -306,10 +309,13 @@ ) b = array.array(self.badtypecode()) - self.assertRaises(TypeError, a.__add__, b) + if test_support.is_jython: + self.assertRaises(TypeError, operator.add, a, b) + self.assertRaises(TypeError, operator.iadd, a, "bad") + else: + self.assertRaises(TypeError, a.__add__, b) + self.assertRaises(TypeError, a.__iadd__, "bad") - self.assertRaises(TypeError, a.__iadd__, "bad") - def test_mul(self): a = 5*array.array(self.typecode, self.example) self.assertEqual( Modified: trunk/jython/Lib/test/test_array_jy.py =================================================================== --- trunk/jython/Lib/test/test_array_jy.py 2010-07-20 05:20:12 UTC (rev 7081) +++ trunk/jython/Lib/test/test_array_jy.py 2010-07-27 23:44:47 UTC (rev 7082) @@ -4,10 +4,7 @@ import os import unittest from test import test_support -from array import array, zeros -from java.lang import String -from java.lang.reflect import Array -from java.util import Arrays +from array import array class ArrayJyTestCase(unittest.TestCase): @@ -15,12 +12,17 @@ # While jarray is still being phased out, just flex the initializers. # The rest of the test for array will catch all the big problems. import jarray + from java.lang import String jarray.array(range(5), 'i') jarray.array([String("a"), String("b"), String("c")], String) jarray.zeros(5, 'i') jarray.zeros(5, String) def test_java_object_arrays(self): + from array import zeros + from java.lang import String + from java.lang.reflect import Array + from java.util import Arrays jStringArr = array(String, [String("a"), String("b"), String("c")]) self.assert_( Arrays.equals(jStringArr.typecode, 'java.lang.String'), @@ -32,6 +34,7 @@ self.assertEqual(jStringArr, eval(str(jStringArr))) def test_java_compat(self): + from array import zeros from java.awt import Color hsb = Color.RGBtoHSB(0,255,255, None) self.assertEqual(hsb, array('f', [0.5,1,1]), @@ -68,9 +71,24 @@ self.assertEqual(x, array('i', range(5) * 4)) +class ArrayOpsTestCase(unittest.TestCase): + + def test_ops(self): + # http://bugs.jython.org/issue1622 + class Foo(object): + def __radd__(self, that): + return '__radd__' + ar = array('i', range(5)) + self.assertEqual('__radd__', ar + Foo()) + ar += Foo() + self.assertEqual('__radd__', ar) + + def test_main(): - test_support.run_unittest(ArrayJyTestCase, - ToFromfileTestCase) + tests = [ToFromfileTestCase, ArrayOpsTestCase] + if test_support.is_jython: + tests.extend([ArrayJyTestCase]) + test_support.run_unittest(*tests) if __name__ == "__main__": Modified: trunk/jython/NEWS =================================================================== --- trunk/jython/NEWS 2010-07-20 05:20:12 UTC (rev 7081) +++ trunk/jython/NEWS 2010-07-27 23:44:47 UTC (rev 7082) @@ -6,6 +6,7 @@ - [ 1506 ] Jython applies PEP263 pattern for determining source-code encoding on noncomments - [ 1630 ] threading.Thread lacks __tojava__ method - [ 1558 ] PyFunction to single method interface wrapping does not handle java.lang.Object methods + - [ 1622 ] array type prevents __radd__ fallback Jython 2.5.2b1 Bugs Fixed Modified: trunk/jython/src/org/python/core/PyArray.java =================================================================== --- trunk/jython/src/org/python/core/PyArray.java 2010-07-20 05:20:12 UTC (rev 7081) +++ trunk/jython/src/org/python/core/PyArray.java 2010-07-27 23:44:47 UTC (rev 7082) @@ -304,17 +304,16 @@ return array___iadd__(other); } - @ExposedMethod + @ExposedMethod(type = MethodType.BINARY) final PyObject array___iadd__(PyObject other) { - PyArray otherArr = null; if (!(other instanceof PyArray)) { - throw Py.TypeError(String.format("can only append array (not \"%.200s\") to array", - other.getType().fastGetName())); + return null; } - otherArr = (PyArray)other; + + PyArray otherArr = (PyArray)other; if (!otherArr.typecode.equals(this.typecode)) { - throw Py.TypeError("can only append arrays of the same type, " - + "expected '" + this.type + ", found " + otherArr.type); + throw Py.TypeError("can only append arrays of the same type, expected '" + + this.type + ", found " + otherArr.type); } delegate.appendArray(otherArr.delegate.copyArray()); return this; @@ -332,16 +331,16 @@ * a PyArray to be added to the instance * @return the result of the addition as a new PyArray instance */ - @ExposedMethod + @ExposedMethod(type = MethodType.BINARY) final PyObject array___add__(PyObject other) { - PyArray otherArr = null; - if(!(other instanceof PyArray)) { - throw Py.TypeError("can only append another array to an array"); + if (!(other instanceof PyArray)) { + return null; } - otherArr = (PyArray)other; - if(!otherArr.typecode.equals(this.typecode)) { - throw Py.TypeError("can only append arrays of the same type, " - + "expected '" + this.type + ", found " + otherArr.type); + + PyArray otherArr = (PyArray)other; + if (!otherArr.typecode.equals(this.typecode)) { + throw Py.TypeError("can only append arrays of the same type, expected '" + this.type + + ", found " + otherArr.type); } PyArray ret = new PyArray(this); ret.delegate.appendArray(otherArr.delegate.copyArray()); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-08-04 17:22:19
|
Revision: 7084 http://jython.svn.sourceforge.net/jython/?rev=7084&view=rev Author: zyasoft Date: 2010-08-04 17:22:13 +0000 (Wed, 04 Aug 2010) Log Message: ----------- Enabled ListTest#test_indexOf, this closes out issue #1395 Modified Paths: -------------- trunk/jython/NEWS trunk/jython/tests/java/javatests/ListTest.java Modified: trunk/jython/NEWS =================================================================== --- trunk/jython/NEWS 2010-08-01 12:48:48 UTC (rev 7083) +++ trunk/jython/NEWS 2010-08-04 17:22:13 UTC (rev 7084) @@ -2,6 +2,7 @@ Jython 2.5.2b2 Bugs Fixed + - [ 1395 ] PyList.indexOf() and PyTuple.indexOf() do not function properly - [ 1373 ] Jython ClassLoader getResource does not work - [ 1506 ] Jython applies PEP263 pattern for determining source-code encoding on noncomments - [ 1630 ] threading.Thread lacks __tojava__ method Modified: trunk/jython/tests/java/javatests/ListTest.java =================================================================== --- trunk/jython/tests/java/javatests/ListTest.java 2010-08-01 12:48:48 UTC (rev 7083) +++ trunk/jython/tests/java/javatests/ListTest.java 2010-08-04 17:22:13 UTC (rev 7084) @@ -124,6 +124,7 @@ // skip unhashable types } test_subList(); + test_indexOf(); test_lastIndexOf(); test_listIterator(); test_toArray(); @@ -243,7 +244,7 @@ } /** Tests indexOf(Object o) */ - public void indexOf() { + public void test_indexOf() { TestSupport.assertThat(defaultList().indexOf(3) == 3, "indexOf(3) did not return 3"); TestSupport.assertThat(defaultList().indexOf(42) == -1, "indexOf() non-existing entry did not return -1"); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-08-09 20:56:18
|
Revision: 7086 http://jython.svn.sourceforge.net/jython/?rev=7086&view=rev Author: zyasoft Date: 2010-08-09 20:56:10 +0000 (Mon, 09 Aug 2010) Log Message: ----------- Java classes that do not implement Cloneable and/or Serializable will now get null __copy__ and __deepcopy__ methods. We still need to add support of copying immutable Java objects (which do not support Cloneable, but makes sense in Python) to reasonably complete work on issue #1551. Modified Paths: -------------- trunk/jython/Lib/test/test_java_integration.py trunk/jython/src/org/python/core/PyJavaType.java Modified: trunk/jython/Lib/test/test_java_integration.py =================================================================== --- trunk/jython/Lib/test/test_java_integration.py 2010-08-06 14:11:47 UTC (rev 7085) +++ trunk/jython/Lib/test/test_java_integration.py 2010-08-09 20:56:10 UTC (rev 7086) @@ -25,7 +25,9 @@ from org.python.tests import (BeanImplementation, Child, Child2, CustomizableMapHolder, Listenable, ToUnicode) from org.python.tests.mro import (ConfusedOnGetitemAdd, FirstPredefinedGetitem, GetitemAdder) +from javatests.ProxyTests import Person + class InstantiationTest(unittest.TestCase): def test_cant_instantiate_abstract(self): self.assertRaises(TypeError, Component) @@ -541,7 +543,25 @@ self.assertNotEqual(id(items[0]), id(items_copy[0])) self.assertNotEqual(id(items[1]), id(items_copy[1])) + def test_copy_when_not_cloneable(self): + bdfl = Person("Guido", "von Rossum") + self.assertRaises(TypeError, copy.copy, bdfl) + # monkeypatching in a __copy__ should now work + Person.__copy__ = lambda p: Person(p.firstName, p.lastName) + copy_bdfl = copy.copy(bdfl) + self.assertEqual(str(bdfl), str(copy_bdfl)) + + def test_copy_when_not_serializable(self): + bdfl = Person("Guido", "von Rossum") + self.assertRaises(TypeError, copy.deepcopy, bdfl) + + # monkeypatching in a __deepcopy__ should now work + Person.__deepcopy__ = lambda p, memo: Person(p.firstName, p.lastName) + copy_bdfl = copy.deepcopy(bdfl) + self.assertEqual(str(bdfl), str(copy_bdfl)) + + class UnicodeTest(unittest.TestCase): def test_unicode_conversion(self): Modified: trunk/jython/src/org/python/core/PyJavaType.java =================================================================== --- trunk/jython/src/org/python/core/PyJavaType.java 2010-08-06 14:11:47 UTC (rev 7085) +++ trunk/jython/src/org/python/core/PyJavaType.java 2010-08-09 20:56:10 UTC (rev 7086) @@ -528,7 +528,23 @@ || getDescrMethod(forClass, "_dodel", PyObject.class) != null; } if (forClass == Object.class) { - // Pass __eq__ and __repr__ through to subclasses of Object + + addMethod(new PyBuiltinMethodNarrow("__copy__") { + @Override + public PyObject __call__() { + throw Py.TypeError("Could not copy Java object because it is not Cloneable or known to be immutable. " + + "Consider monkeypatching __copy__ for " + self.getType().fastGetName()); + } + }); + + addMethod(new PyBuiltinMethodNarrow("__deepcopy__") { + @Override + public PyObject __call__(PyObject memo) { + throw Py.TypeError("Could not deepcopy Java object because it is not Serializable. " + + "Consider monkeypatching __deepcopy__ for " + self.getType().fastGetName()); + } + }); + addMethod(new PyBuiltinMethodNarrow("__eq__", 1) { @Override public PyObject __call__(PyObject o) { @@ -592,7 +608,7 @@ } // TODO consider adding support for __copy__ of immutable Java objects - // (__deepcopy__ should just work since it uses serialization) + // (__deepcopy__ just works for these objects since it uses serialization instead) if(forClass == Cloneable.class) { addMethod(new PyBuiltinMethodNarrow("__copy__") { @@ -600,13 +616,13 @@ public PyObject __call__() { Object obj = self.getJavaProxy(); Method clone; - // we could specialize so that for well known objects like collections, - // we don't use reflection to get around the fact that Object#clone is protected (but most subclasses are not); - // also we can potentially cache the method handle in the proxy instead of looking it up each time + // TODO we could specialize so that for well known objects like collections. This would avoid needing to use reflection + // in the general case, because Object#clone is protected (but most subclasses are not). + // + // Lastly we can potentially cache the method handle in the proxy instead of looking it up each time try { clone = obj.getClass().getMethod("clone"); - Object copy; - copy = clone.invoke(obj); + Object copy = clone.invoke(obj); return Py.java2py(copy); } catch (Exception ex) { throw Py.TypeError("Could not copy Java object"); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-08-09 21:24:28
|
Revision: 7088 http://jython.svn.sourceforge.net/jython/?rev=7088&view=rev Author: zyasoft Date: 2010-08-09 21:24:20 +0000 (Mon, 09 Aug 2010) Log Message: ----------- Added support for find_global in cPickle. This fixes #1632. Thanks Alex Gr?\195?\182nholm for the patch! Modified Paths: -------------- trunk/jython/ACKNOWLEDGMENTS trunk/jython/Lib/test/test_cpickle_jy.py trunk/jython/NEWS trunk/jython/src/org/python/modules/cPickle.java Modified: trunk/jython/ACKNOWLEDGMENTS =================================================================== --- trunk/jython/ACKNOWLEDGMENTS 2010-08-09 20:58:24 UTC (rev 7087) +++ trunk/jython/ACKNOWLEDGMENTS 2010-08-09 21:24:20 UTC (rev 7088) @@ -90,6 +90,7 @@ Jonathan Feinberg Justin Deoliveira Costantino Cerbo + Alex Gr\xF6nholm Local Variables: mode: indented-text Modified: trunk/jython/Lib/test/test_cpickle_jy.py =================================================================== --- trunk/jython/Lib/test/test_cpickle_jy.py 2010-08-09 20:58:24 UTC (rev 7087) +++ trunk/jython/Lib/test/test_cpickle_jy.py 2010-08-09 21:24:20 UTC (rev 7088) @@ -5,6 +5,7 @@ import cPickle import pickle import unittest +from StringIO import StringIO from test import test_support class MyClass(object): @@ -34,7 +35,41 @@ m4 = iter(m3.foo).next() self.assertEqual(m4.foo, s2) + def test_find_global(self): + class A(object): + def __init__(self, x, y): + self.x = x + self.y = y + + def __eq__(self, other): + if isinstance(other, A) and self.x == other.x and self.y == other.y: + return True + return False + + class B(object): + def __init__(self, x, y): + self.x = x + self.y = y + + def restrictive_find_global(module, clsname): + if clsname == 'A': + return A + else: + raise pickle.UnpicklingError("Cannot load class", module, clsname) + + a = A("python", "C") + a_pickled = cPickle.dumps(a, 2) + a_unpickler = cPickle.Unpickler(StringIO(a_pickled)) + a_unpickler.find_global = restrictive_find_global + self.assertEqual(a_unpickler.load(), a) + + b_pickled = cPickle.dumps(B("jython", "java"), 2) + b_unpickler = cPickle.Unpickler(StringIO(b_pickled)) + b_unpickler.find_global = restrictive_find_global + self.assertRaises(pickle.UnpicklingError, b_unpickler.load) + + def test_main(): test_support.run_unittest(CPickleTestCase) Modified: trunk/jython/NEWS =================================================================== --- trunk/jython/NEWS 2010-08-09 20:58:24 UTC (rev 7087) +++ trunk/jython/NEWS 2010-08-09 21:24:20 UTC (rev 7088) @@ -2,6 +2,7 @@ Jython 2.5.2b2 Bugs Fixed + - [ 1632 ] cPickle.Unpickler does not allow assignment of find_global - [ 1395 ] PyList.indexOf() and PyTuple.indexOf() do not function properly - [ 1373 ] Jython ClassLoader getResource does not work - [ 1506 ] Jython applies PEP263 pattern for determining source-code encoding on noncomments Modified: trunk/jython/src/org/python/modules/cPickle.java =================================================================== --- trunk/jython/src/org/python/modules/cPickle.java 2010-08-09 20:58:24 UTC (rev 7087) +++ trunk/jython/src/org/python/modules/cPickle.java 2010-08-09 21:24:20 UTC (rev 7088) @@ -1573,6 +1573,7 @@ * persistent_load(). */ public PyObject persistent_load = null; + public PyObject find_global = null; private PyObject mark = new PyString("spam"); @@ -1982,12 +1983,11 @@ final private PyObject find_class(String module, String name) { - PyObject fc = dict.__finditem__("find_global"); - if (fc != null) { - if (fc == Py.None) + if (find_global != null) { + if (find_global == Py.None) throw new PyException(UnpicklingError, "Global and instance pickles are not supported."); - return fc.__call__(new PyString(module), new PyString(name)); + return find_global.__call__(new PyString(module), new PyString(name)); } PyObject modules = Py.getSystemState().modules; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-08-10 02:53:26
|
Revision: 7089 http://jython.svn.sourceforge.net/jython/?rev=7089&view=rev Author: zyasoft Date: 2010-08-10 02:53:20 +0000 (Tue, 10 Aug 2010) Log Message: ----------- Support copy.copy (through __copy__) of well-known immutable Java types (drawn from java.lang, java.net, java.util). This better matches the copy semantics of Python than Object#clone/Cloneable. Modified Paths: -------------- trunk/jython/Lib/test/test_java_integration.py trunk/jython/src/org/python/core/PyJavaType.java Modified: trunk/jython/Lib/test/test_java_integration.py =================================================================== --- trunk/jython/Lib/test/test_java_integration.py 2010-08-09 21:24:20 UTC (rev 7088) +++ trunk/jython/Lib/test/test_java_integration.py 2010-08-10 02:53:20 UTC (rev 7089) @@ -561,7 +561,17 @@ copy_bdfl = copy.deepcopy(bdfl) self.assertEqual(str(bdfl), str(copy_bdfl)) + def test_immutable(self): + abc = String("abc") + abc_copy = copy.copy(abc) + self.assertEqual(id(abc), id(abc_copy)) + + fruits = ArrayList([String("apple"), String("banana")]) + fruits_copy = copy.copy(fruits) + self.assertEqual(fruits, fruits_copy) + self.assertNotEqual(id(fruits), id(fruits_copy)) + class UnicodeTest(unittest.TestCase): def test_unicode_conversion(self): Modified: trunk/jython/src/org/python/core/PyJavaType.java =================================================================== --- trunk/jython/src/org/python/core/PyJavaType.java 2010-08-09 21:24:20 UTC (rev 7088) +++ trunk/jython/src/org/python/core/PyJavaType.java 2010-08-10 02:53:20 UTC (rev 7089) @@ -43,6 +43,29 @@ "bounds", "enable"); + + // Add well-known immutable classes from standard packages of + // java.lang, java.net, java.util that are not marked Cloneable. + // This was found by hand, there are likely more! + private final static Set<Class<?>> immutableClasses = Generic.set( + Boolean.class, + Byte.class, + Character.class, + Class.class, + Double.class, + Float.class, + Integer.class, + Long.class, + Short.class, + String.class, + java.net.InetAddress.class, + java.net.Inet4Address.class, + java.net.Inet6Address.class, + java.net.InetSocketAddress.class, + java.net.Proxy.class, + java.net.URI.class, + java.util.concurrent.TimeUnit.class); + private static Map<Class<?>, PyBuiltinMethod[]> collectionProxies; /** @@ -143,15 +166,15 @@ } Set<String> allModified = Generic.set(); - PyJavaType[] conflicted = inConflict.toArray(new PyJavaType[inConflict.size()]); - for (PyJavaType type : conflicted) { + PyJavaType[] conflictedAttributes = inConflict.toArray(new PyJavaType[inConflict.size()]); + for (PyJavaType type : conflictedAttributes) { if (type.modified == null) { continue; } for (String method : type.modified) { if (!allModified.add(method)) { // Another type in conflict has this method, fail PyList types = new PyList(); - for (PyJavaType othertype : conflicted) { + for (PyJavaType othertype : conflictedAttributes) { if (othertype.modified != null && othertype.modified.contains(method)) { types.add(othertype); } @@ -164,7 +187,7 @@ // We can keep trucking, there aren't any existing method name conflicts. Mark the // conflicts in all the classes so further method additions can check for trouble - for (PyJavaType type : conflicted) { + for (PyJavaType type : conflictedAttributes) { for (PyJavaType otherType : inConflict) { if (otherType != type) { if (type.conflicted == null) { @@ -306,23 +329,23 @@ } // Now check if it's a bean property accessor - String name = null; + String beanPropertyName = null; boolean get = true; if (methname.startsWith("get") && methname.length() > 3 && n == 0) { - name = methname.substring(3); + beanPropertyName = methname.substring(3); } else if (methname.startsWith("is") && methname.length() > 2 && n == 0 && meth.getReturnType() == Boolean.TYPE) { - name = methname.substring(2); + beanPropertyName = methname.substring(2); } else if (methname.startsWith("set") && methname.length() > 3 && n == 1) { - name = methname.substring(3); + beanPropertyName = methname.substring(3); get = false; } - if (name != null) { - name = normalize(StringUtil.decapitalize(name)); - PyBeanProperty prop = props.get(name); + if (beanPropertyName != null) { + beanPropertyName = normalize(StringUtil.decapitalize(beanPropertyName)); + PyBeanProperty prop = props.get(beanPropertyName); if (prop == null) { - prop = new PyBeanProperty(name, null, null, null); - props.put(name, prop); + prop = new PyBeanProperty(beanPropertyName, null, null, null); + props.put(beanPropertyName, prop); } if (get) { prop.getMethod = meth; @@ -405,11 +428,11 @@ } for (Method meth : ev.eventClass.getMethods()) { - String name = meth.getName().intern(); - if (dict.__finditem__(name) != null) { + String methodName = meth.getName().intern(); + if (dict.__finditem__(methodName) != null) { continue; } - dict.__setitem__(name, new PyBeanEventProperty(name, + dict.__setitem__(methodName, new PyBeanEventProperty(methodName, ev.eventClass, ev.addMethod, meth)); @@ -607,9 +630,19 @@ }); } - // TODO consider adding support for __copy__ of immutable Java objects - // (__deepcopy__ just works for these objects since it uses serialization instead) + if (immutableClasses.contains(forClass)) { + + // __deepcopy__ just works for these objects since it uses serialization instead + + addMethod(new PyBuiltinMethodNarrow("__copy__") { + @Override + public PyObject __call__() { + return self; + } + }); + } + if(forClass == Cloneable.class) { addMethod(new PyBuiltinMethodNarrow("__copy__") { @Override @@ -881,6 +914,7 @@ collectionProxies = Generic.map(); PyBuiltinMethodNarrow iterableProxy = new PyBuiltinMethodNarrow("__iter__") { + @Override public PyObject __call__() { return new IteratorIter(((Iterable)self.getJavaProxy())); } @@ -906,6 +940,7 @@ containsProxy}); PyBuiltinMethodNarrow iteratorProxy = new PyBuiltinMethodNarrow("__iter__") { + @Override public PyObject __call__() { return new IteratorIter(((Iterator)self.getJavaProxy())); } @@ -913,6 +948,7 @@ collectionProxies.put(Iterator.class, new PyBuiltinMethod[] {iteratorProxy}); PyBuiltinMethodNarrow enumerationProxy = new PyBuiltinMethodNarrow("__iter__") { + @Override public PyObject __call__() { return new EnumerationIter(((Enumeration)self.getJavaProxy())); } @@ -933,6 +969,7 @@ } }; PyBuiltinMethodNarrow mapContainsProxy = new MapMethod("__contains__", 1) { + @Override public PyObject __call__(PyObject obj) { Object other = obj.__tojava__(Object.class); return asMap().containsKey(other) ? Py.True : Py.False; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-08-14 17:17:27
|
Revision: 7090 http://jython.svn.sourceforge.net/jython/?rev=7090&view=rev Author: zyasoft Date: 2010-08-14 17:17:21 +0000 (Sat, 14 Aug 2010) Log Message: ----------- Our JSR223 engine factory now publishes a list of sort-of well known MIME types (as authoritative as these things ever get). Fixes #1555. Modified Paths: -------------- trunk/jython/NEWS trunk/jython/src/org/python/jsr223/PyScriptEngineFactory.java Added Paths: ----------- trunk/jython/Lib/test/test_jsr223.py Added: trunk/jython/Lib/test/test_jsr223.py =================================================================== --- trunk/jython/Lib/test/test_jsr223.py (rev 0) +++ trunk/jython/Lib/test/test_jsr223.py 2010-08-14 17:17:21 UTC (rev 7090) @@ -0,0 +1,55 @@ +# test for ScriptEngine, otherwise we are not in Java 6/JSR223 support added + +# test each feature + +import sys +import unittest +from javax.script import ScriptEngine, ScriptEngineManager +from test import test_support + + +class JSR223TestCase(unittest.TestCase): + def setUp(self): + self.engine = ScriptEngineManager().getEngineByName("python") + + def test_eval(self): + engine = self.engine + engine.put("a", 42) + engine.eval("b = a/6") + self.assertEqual(engine.get("b"), 7) + + def test_factory(self): + f = self.engine.factory + language_version = ".".join(str(comp) for comp in sys.version_info[0:2]) # such as "2.5" + impl_version = ".".join(str(comp) for comp in sys.version_info[0:3]) # such as "2.5.2" + + self.assertNotEqual(f.scriptEngine, self.engine) # we don't pool engines + + self.assertEqual(f.engineName, "jython") + self.assertEqual(f.engineVersion, impl_version) + self.assertEqual(set(f.extensions), set(['py'])) + self.assertEqual(f.languageName, "python") + self.assertEqual(f.languageVersion, language_version) + self.assertEqual(set(f.names), set(["python", "jython"])) + self.assertEqual(set(f.mimeTypes), set(["text/python", "application/python", "text/x-python", "application/x-python"])) + + # variants + self.assertEqual(f.getParameter(ScriptEngine.ENGINE), "jython") + self.assertEqual(f.getParameter(ScriptEngine.ENGINE_VERSION), impl_version) + self.assertEqual(f.getParameter(ScriptEngine.NAME), "jython") + self.assertEqual(f.getParameter(ScriptEngine.LANGUAGE), "python") + self.assertEqual(f.getParameter(ScriptEngine.LANGUAGE_VERSION), language_version) + + self.assertEqual(f.getOutputStatement("abc"), "print u'abc'") + self.assertEqual(f.getProgram("x = 42", "y = 'abc'"), "x = 42\ny = 'abc'\n") + + + + +def test_main(): + test_support.run_unittest( + JSR223TestCase) + + +if __name__ == "__main__": + test_main() Modified: trunk/jython/NEWS =================================================================== --- trunk/jython/NEWS 2010-08-10 02:53:20 UTC (rev 7089) +++ trunk/jython/NEWS 2010-08-14 17:17:21 UTC (rev 7090) @@ -2,6 +2,7 @@ Jython 2.5.2b2 Bugs Fixed + - [ 1555 ] Jython does not publish MIME types via JSR 223 (ScriptEngine.getFactory().getMimeTypes() is empty). - [ 1632 ] cPickle.Unpickler does not allow assignment of find_global - [ 1395 ] PyList.indexOf() and PyTuple.indexOf() do not function properly - [ 1373 ] Jython ClassLoader getResource does not work Modified: trunk/jython/src/org/python/jsr223/PyScriptEngineFactory.java =================================================================== --- trunk/jython/src/org/python/jsr223/PyScriptEngineFactory.java 2010-08-10 02:53:20 UTC (rev 7089) +++ trunk/jython/src/org/python/jsr223/PyScriptEngineFactory.java 2010-08-14 17:17:21 UTC (rev 7090) @@ -85,9 +85,9 @@ return new PyScriptEngine(this); } - @SuppressWarnings("unchecked") public List<String> getMimeTypes() { - return Collections.EMPTY_LIST; + return Collections.unmodifiableList(Arrays.asList( + "text/python", "application/python", "text/x-python", "application/x-python")); } public List<String> getNames() { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-08-15 14:09:17
|
Revision: 7094 http://jython.svn.sourceforge.net/jython/?rev=7094&view=rev Author: zyasoft Date: 2010-08-15 14:09:10 +0000 (Sun, 15 Aug 2010) Log Message: ----------- Define the package name for a class dynamically loaded from sys.path. Fixes #1455. Thanks to "stan" for the patch! Modified Paths: -------------- trunk/jython/Lib/test/test_zipimport_jy.py trunk/jython/src/org/python/core/SyspathJavaLoader.java Modified: trunk/jython/Lib/test/test_zipimport_jy.py =================================================================== --- trunk/jython/Lib/test/test_zipimport_jy.py 2010-08-14 21:00:19 UTC (rev 7093) +++ trunk/jython/Lib/test/test_zipimport_jy.py 2010-08-15 14:09:10 UTC (rev 7094) @@ -1,5 +1,6 @@ import unittest import sys +import java.lang.Package from test import test_support @@ -8,6 +9,8 @@ self.orig_path = sys.path sys.path.insert(0, test_support.findfile("syspath_import.jar")) + # TODO confirm that package is unloaded via a phantom ref or something like that + def tearDown(self): sys.path = self.orig_path @@ -15,6 +18,12 @@ from syspathonly import Syspath self.assertEquals(Syspath.staticCall(), "result") + def test_package_defined(self): + from syspathonly import Syspath + package = Syspath().class.package + self.assert_(isinstance(package, java.lang.Package)) + self.assertEquals(package.name, 'syspathonly') + def test_load_pkg_from_syspath(self): import syspathpkg self.assertEquals(syspathpkg.__name__, 'syspathpkg') Modified: trunk/jython/src/org/python/core/SyspathJavaLoader.java =================================================================== --- trunk/jython/src/org/python/core/SyspathJavaLoader.java 2010-08-14 21:00:19 UTC (rev 7093) +++ trunk/jython/src/org/python/core/SyspathJavaLoader.java 2010-08-15 14:09:10 UTC (rev 7094) @@ -84,6 +84,19 @@ return null; } } + + protected Package definePackageForClass(String name) { + int lastDotIndex = name.lastIndexOf('.'); + if (lastDotIndex < 0) { + return null; + } + String pkgname = name.substring(0, lastDotIndex); + Package pkg = getPackage(pkgname); + if (pkg == null) { + pkg = definePackage(pkgname, null, null, null, null, null, null, null); + } + return pkg; + } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { @@ -106,6 +119,7 @@ buffer = getBytesFromDir(dir, name); } if (buffer != null) { + definePackageForClass(name); return defineClass(name, buffer, 0, buffer.length); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-08-16 16:45:36
|
Revision: 7096 http://jython.svn.sourceforge.net/jython/?rev=7096&view=rev Author: zyasoft Date: 2010-08-16 16:45:29 +0000 (Mon, 16 Aug 2010) Log Message: ----------- Removed Tools directory, including jythonc. It was not being copied, and even though there's potentially useful code in there, we don't want what are effectively sandbox directories like this cluttering trunk and confusing users on what is being supported. Fixes #1643. Modified Paths: -------------- trunk/jython/NEWS Removed Paths: ------------- trunk/jython/Tools/ Modified: trunk/jython/NEWS =================================================================== --- trunk/jython/NEWS 2010-08-15 14:14:05 UTC (rev 7095) +++ trunk/jython/NEWS 2010-08-16 16:45:29 UTC (rev 7096) @@ -2,6 +2,7 @@ Jython 2.5.2b2 Bugs Fixed + - [ 1643 ] Tools subdirectory still exists in trunk - [ 1455 ] Classes loaded dynamically from sys.path do not have their package defined - [ 1555 ] Jython does not publish MIME types via JSR 223 (ScriptEngine.getFactory().getMimeTypes() is empty). - [ 1632 ] cPickle.Unpickler does not allow assignment of find_global This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-08-21 03:30:47
|
Revision: 7098 http://jython.svn.sourceforge.net/jython/?rev=7098&view=rev Author: zyasoft Date: 2010-08-21 03:30:41 +0000 (Sat, 21 Aug 2010) Log Message: ----------- Expose the Python interpreter to sys, along with its associated JLine Reader (if available from JLineConsole). This enables a (so far) partial implemnentation of readline semantics suitable for completion support. See #1133. Modified Paths: -------------- trunk/jython/Lib/readline.py trunk/jython/src/org/python/util/JLineConsole.java trunk/jython/src/org/python/util/jython.java Modified: trunk/jython/Lib/readline.py =================================================================== --- trunk/jython/Lib/readline.py 2010-08-17 19:23:22 UTC (rev 7097) +++ trunk/jython/Lib/readline.py 2010-08-21 03:30:41 UTC (rev 7098) @@ -5,80 +5,121 @@ """ -try: - from org.gnu.readline import Readline, ReadlineCompleter -except ImportError, msg: - raise ImportError, '%s. The readline module requires that java-readline from http://java-readline.sourceforge.net/ be on the classpath' % msg +from __future__ import with_statement +import os.path +import sys -__all__ = ["readline"] +# XXX move to _jline_readline.py, just like our _gnu_readline.py (which is orphaned) +# then simply try successive imports to see what is installed -def parse_and_bind (bindings): - """Parse and execute single line of a readline init file.\ - - """ - Readline.parseAndBind(bindings) +# XXX what's oru character encoding issues here, if any? +try: + reader = sys._jy_interpreter.reader + #from JLine import Completor +except AttributeError: + raise ImportError("Cannot access JLineConsole") + +def parse_and_bind(string): + # XXX this should probably reinitialize the reader, if possible + # with any desired settings; this will require some more work to implement + + # most importantly, need to support + # readline.parse_and_bind("tab: complete") + # but it's possible we can readily support other aspects of a readline file + pass + def get_line_buffer(): - """Return the current contents of the line buffer. - - """ - return Readline.getLineBuffer() + return str(reader.cursorBuffer.buffer) # or use toString to get unicode? -def read_init_file(filename): - """Parse a readline initialization file. - The default filename is the last filename used. +def insert_text(string): + reader.putString(string) + +def read_init_file(filename=None): + pass - """ - Readline.readInitFile(filename) +def read_history_file(filename="~/.history"): + expanded = os.path.expanduser(filename) + new_history = reader.getHistory().getClass()() + with open(expanded) as f: + for line in f: + new_history.addToHistory(line) + reader.history = new_history -def read_history_file(filename): - """Load a readline history file. - The default filename is '~/.history'. +def write_history_file(filename="~/.history"): + expanded = os.path.expanduser(filename) + with open(expanded, 'w') as f: + for line in reader.history.historyList: + f.write(line) - """ - Readline.readHistoryFile(filename) +def clear_history(): + reader.history.clear() -def write_history_file(filename): - """Save a readline history file. - The default filename is '~/.history'. +def get_history_length(): + return reader.history.maxSize - """ - Readline.writeHistoryFile(filename) +def set_history_length(length): + reader.history.maxSize = length -def set_completer(completionfunction = None): - """Set or remove the completer instance. If an instance of ReadlineCompleter is specified, - it will be used as the new completer; if omitted or None, any completer already installed is removed. +def get_current_history_length(): + return len(reader.history.historyList) - The completer method is called as completerclass.completer(text, state), for state in 0, 1, 2, ..., - until it returns a non-string value. It should return the next possible completion starting with text. +def get_history_item(index): + return reader.history.historyList[index] - """ - class DerivedCompleter (ReadlineCompleter): - def __init__ (self, method): - self.method = method +def remove_history_item(pos): + raise Exception("not implemented") - def completer (self, text, state): - return self.method(text, state) +def redisplay(): + reader.drawLine() # XXX not certain - Readline.setCompleter(DerivedCompleter(completionfunction)) +def set_startup_hook(function=None): + pass +def set_pre_input_hook(function=None): + pass + + +_completion_function = None + +def set_completer(function=None): + # XXX single method interface, http://jline.sourceforge.net/apidocs/jline/Completor.html + # just need to figure out what's necessary to adapt to Python's convention, + # but it should be fine :) + + """The completer method is called as completerclass.completer(text, state), for state in 0, 1, 2, ..., + until it returns a non-string value. It should return the next possible completion starting with text.""" + + _completion_function = function + + def complete_handler(buffer, cursor, candidates): + for state in xrange(100): + completion = function(buffer[:cursor], state) + if completion: + candidates.add(completion) + else: + break + return 0 + + reader.addCompletor(complete_handler) + + def get_completer(): - """Get the current completer instance.""" - return Readline.getCompleter() + return _completion_function -def set_completer_delims(delimiters): - """Set the readline word delimiters for tab-completion.""" - Readline.setWordBreakCharacters(delimiters) +def get_begidx(): + pass +def get_endidx(): + pass + +def set_completer_delims(string): + pass + def get_completer_delims(): - """Get the readline word delimiters for tab-completion.""" - return Readline.getWordBreakCharacters() + pass def add_history(line): - """Append a line to the history buffer, as if it was the last line typed.""" - Readline.addToHistory(line) + reader.addToHistory(line) -def get_current_history_length(): - """Get the number of lines currently available in history.""" - return Readline.getHistorySize() Modified: trunk/jython/src/org/python/util/JLineConsole.java =================================================================== --- trunk/jython/src/org/python/util/JLineConsole.java 2010-08-17 19:23:22 UTC (rev 7097) +++ trunk/jython/src/org/python/util/JLineConsole.java 2010-08-21 03:30:41 UTC (rev 7098) @@ -156,4 +156,11 @@ private boolean isEOF(String line) { return line == null || (windows && CTRL_Z.equals(line)); } + + /** + * @return the JLine console reader associated with this interpreter + */ + public ConsoleReader getReader() { + return reader; + } } Modified: trunk/jython/src/org/python/util/jython.java =================================================================== --- trunk/jython/src/org/python/util/jython.java 2010-08-17 19:23:22 UTC (rev 7097) +++ trunk/jython/src/org/python/util/jython.java 2010-08-21 03:30:41 UTC (rev 7098) @@ -155,17 +155,19 @@ } Py.getSystemState().setWarnoptions(warnoptions); + PySystemState systemState = Py.getSystemState(); // Decide if stdin is interactive if (!opts.fixInteractive && opts.interactive) { opts.interactive = ((PyFile)Py.defaultSystemState.stdin).isatty(); if (!opts.interactive) { - PySystemState systemState = Py.getSystemState(); + systemState.ps1 = systemState.ps2 = Py.EmptyString; } } // Now create an interpreter InteractiveConsole interp = newInterpreter(opts.interactive); + systemState.__setattr__("_jy_interpreter", Py.java2py(interp)); // Print banner and copyright information (or not) if (opts.interactive && opts.notice && !opts.runModule) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-08-21 03:56:27
|
Revision: 7100 http://jython.svn.sourceforge.net/jython/?rev=7100&view=rev Author: zyasoft Date: 2010-08-21 03:56:21 +0000 (Sat, 21 Aug 2010) Log Message: ----------- Minor changes to PyLong, PyFloat that were missed by NetBean's accessor refactoring support. Added tests of how our subclasses of our types can now be abused to have treatable as the original type, but mutable. Use such dangerous functionality with care! See #1645 for further discussion of this issue, including rationale. Implemented to help support efforts like processing.py. Thanks Jonathan Feinberg for this patch set. Modified Paths: -------------- trunk/jython/ACKNOWLEDGMENTS trunk/jython/src/org/python/core/PyFloat.java trunk/jython/src/org/python/core/PyLong.java Added Paths: ----------- trunk/jython/tests/java/org/python/core/WrappedBooleanTest.java trunk/jython/tests/java/org/python/core/WrappedFloatTest.java trunk/jython/tests/java/org/python/core/WrappedIntegerTest.java trunk/jython/tests/java/org/python/core/WrappedLongTest.java Modified: trunk/jython/ACKNOWLEDGMENTS =================================================================== --- trunk/jython/ACKNOWLEDGMENTS 2010-08-21 03:42:48 UTC (rev 7099) +++ trunk/jython/ACKNOWLEDGMENTS 2010-08-21 03:56:21 UTC (rev 7100) @@ -90,7 +90,8 @@ Jonathan Feinberg Justin Deoliveira Costantino Cerbo - Alex Gr\xF6nholm + Alex Gr\xF6nholm + Jonathan Feinberg Local Variables: mode: indented-text Modified: trunk/jython/src/org/python/core/PyFloat.java =================================================================== --- trunk/jython/src/org/python/core/PyFloat.java 2010-08-21 03:42:48 UTC (rev 7099) +++ trunk/jython/src/org/python/core/PyFloat.java 2010-08-21 03:56:21 UTC (rev 7100) @@ -82,7 +82,7 @@ * Determine if this float is not infinity, nor NaN. */ public boolean isFinite() { - return !Double.isInfinite(value) && !Double.isNaN(value); + return !Double.isInfinite(getValue()) && !Double.isNaN(getValue()); } @Override Modified: trunk/jython/src/org/python/core/PyLong.java =================================================================== --- trunk/jython/src/org/python/core/PyLong.java 2010-08-21 03:42:48 UTC (rev 7099) +++ trunk/jython/src/org/python/core/PyLong.java 2010-08-21 03:56:21 UTC (rev 7100) @@ -151,7 +151,7 @@ @Override public boolean __nonzero__() { - return !value.equals(BigInteger.valueOf(0)); + return !getValue().equals(BigInteger.ZERO); } @ExposedMethod(doc = BuiltinDocs.long___nonzero___doc) Added: trunk/jython/tests/java/org/python/core/WrappedBooleanTest.java =================================================================== --- trunk/jython/tests/java/org/python/core/WrappedBooleanTest.java (rev 0) +++ trunk/jython/tests/java/org/python/core/WrappedBooleanTest.java 2010-08-21 03:56:21 UTC (rev 7100) @@ -0,0 +1,59 @@ +package org.python.core; + +import junit.framework.TestCase; + +import org.python.util.PythonInterpreter; + +public class WrappedBooleanTest extends TestCase { + + // Simulate the use case where you want to expose some (possibly mutable) + // java boolean field to an interpreter without having to set the value to a + // new PyBoolean each time it changes. + @SuppressWarnings("serial") + static class WrappedBoolean extends PyBoolean { + public WrappedBoolean() { + super(true); + } + + private boolean mutableValue; + + @Override + public boolean getBooleanValue() { + return mutableValue; + } + + public void setMutableValue(final boolean newValue) { + mutableValue = newValue; + } + } + + private PythonInterpreter interp; + private WrappedBoolean a, b; + + @Override + protected void setUp() throws Exception { + interp = new PythonInterpreter(new PyStringMap(), new PySystemState()); + a = new WrappedBoolean(); + b = new WrappedBoolean(); + a.setMutableValue(true); + b.setMutableValue(false); + interp.set("a", a); + interp.set("b", b); + } + + public void testAnd() { + interp.exec("c = a and b"); + assertEquals(new PyBoolean(false), interp.get("c")); + b.setMutableValue(true); + interp.exec("c = a and b"); + assertEquals(new PyBoolean(true), interp.get("c")); + } + + public void testOr() { + interp.exec("c = a or b"); + assertEquals(new PyBoolean(true), interp.get("c")); + a.setMutableValue(false); + interp.exec("c = a or b"); + assertEquals(new PyBoolean(false), interp.get("c")); + } +} Added: trunk/jython/tests/java/org/python/core/WrappedFloatTest.java =================================================================== --- trunk/jython/tests/java/org/python/core/WrappedFloatTest.java (rev 0) +++ trunk/jython/tests/java/org/python/core/WrappedFloatTest.java 2010-08-21 03:56:21 UTC (rev 7100) @@ -0,0 +1,61 @@ +package org.python.core; + +import junit.framework.TestCase; + +import org.python.util.PythonInterpreter; + +public class WrappedFloatTest extends TestCase { + + // Simulate the use case where you want to expose some (possibly mutable) + // java float field to an interpreter without having to set the value to a new + // PyFloat each time it changes. + @SuppressWarnings("serial") + static class WrappedFloat extends PyFloat { + public WrappedFloat() { + super(0); + } + + private double mutableValue; + + @Override + public double getValue() { + return mutableValue; + } + + public void setMutableValue(final double newValue) { + mutableValue = newValue; + } + } + + private PythonInterpreter interp; + private WrappedFloat a, b; + + @Override + protected void setUp() throws Exception { + interp = new PythonInterpreter(new PyStringMap(), new PySystemState()); + a = new WrappedFloat(); + b = new WrappedFloat(); + a.setMutableValue(13.0); + b.setMutableValue(17.0); + interp.set("a", a); + interp.set("b", b); + } + + public void testAdd() { + interp.exec("c = a + b"); + assertEquals(new PyFloat(30), interp.get("c")); + b.setMutableValue(18.0); + interp.exec("c = a + b"); + assertEquals(new PyFloat(31), interp.get("c")); + } + + public void testDiv() { + interp.exec("c = a / b"); + assertEquals(new PyFloat(13 / 17.), interp.get("c")); + } + + public void testMod() { + interp.exec("c = b % a"); + assertEquals(new PyFloat(4), interp.get("c")); + } +} Added: trunk/jython/tests/java/org/python/core/WrappedIntegerTest.java =================================================================== --- trunk/jython/tests/java/org/python/core/WrappedIntegerTest.java (rev 0) +++ trunk/jython/tests/java/org/python/core/WrappedIntegerTest.java 2010-08-21 03:56:21 UTC (rev 7100) @@ -0,0 +1,61 @@ +package org.python.core; + +import junit.framework.TestCase; + +import org.python.util.PythonInterpreter; + +public class WrappedIntegerTest extends TestCase { + + // Simulate the use case where you want to expose some (possibly mutable) + // java int field to an interpreter without having to set the value to a new + // PyInteger each time it changes. + @SuppressWarnings("serial") + static class WrappedInteger extends PyInteger { + public WrappedInteger() { + super(0); + } + + private int mutableValue; + + @Override + public int getValue() { + return mutableValue; + } + + public void setMutableValue(final int newValue) { + mutableValue = newValue; + } + } + + private PythonInterpreter interp; + private WrappedInteger a, b; + + @Override + protected void setUp() throws Exception { + interp = new PythonInterpreter(new PyStringMap(), new PySystemState()); + a = new WrappedInteger(); + b = new WrappedInteger(); + a.setMutableValue(13); + b.setMutableValue(17); + interp.set("a", a); + interp.set("b", b); + } + + public void testAdd() { + interp.exec("c = a + b"); + assertEquals(new PyInteger(30), interp.get("c")); + b.setMutableValue(18); + interp.exec("c = a + b"); + assertEquals(new PyInteger(31), interp.get("c")); + } + + public void testDiv() { + interp.exec("c = a / float(b)"); + assertEquals(new PyFloat(13 / 17.), interp.get("c")); + } + + public void testMod() { + interp.exec("c = b % a"); + assertEquals(new PyInteger(4), interp.get("c")); + } +} Added: trunk/jython/tests/java/org/python/core/WrappedLongTest.java =================================================================== --- trunk/jython/tests/java/org/python/core/WrappedLongTest.java (rev 0) +++ trunk/jython/tests/java/org/python/core/WrappedLongTest.java 2010-08-21 03:56:21 UTC (rev 7100) @@ -0,0 +1,58 @@ +package org.python.core; + +import java.math.BigInteger; + +import junit.framework.TestCase; + +import org.python.util.PythonInterpreter; + +public class WrappedLongTest extends TestCase { + + // Simulate the use case where you want to expose some (possibly mutable) + // java long field to an interpreter without having to set the value to a + // new PyLong each time it changes. + @SuppressWarnings("serial") + static class WrappedLong extends PyLong { + public WrappedLong() { + super(0); + } + + private long mutableValue; + + @Override + public BigInteger getValue() { + return BigInteger.valueOf(mutableValue); + } + + public void setMutableValue(final long newValue) { + mutableValue = newValue; + } + } + + private PythonInterpreter interp; + private WrappedLong a, b; + + @Override + protected void setUp() throws Exception { + interp = new PythonInterpreter(new PyStringMap(), new PySystemState()); + a = new WrappedLong(); + b = new WrappedLong(); + a.setMutableValue(13000000000L); + b.setMutableValue(17000000000L); + interp.set("a", a); + interp.set("b", b); + } + + public void testAdd() { + interp.exec("c = a + b"); + assertEquals(new PyLong(30000000000L), interp.get("c")); + b.setMutableValue(18000000000L); + interp.exec("c = a + b"); + assertEquals(new PyLong(31000000000L), interp.get("c")); + } + + public void testMod() { + interp.exec("c = b % a"); + assertEquals(new PyLong(4000000000L), interp.get("c")); + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-08-22 06:39:28
|
Revision: 7101 http://jython.svn.sourceforge.net/jython/?rev=7101&view=rev Author: zyasoft Date: 2010-08-22 06:39:22 +0000 (Sun, 22 Aug 2010) Log Message: ----------- Module#addConstants incorrectly set the accessbility of the 'self' constant in the generated module bytecode to be final, but it can in fact be modified outside of the class initializer. Verified the regrtest passes with -Xcomp (except for test_jy_internals, but this looks like standard issues of working with GC in tests). Bumped bytecode magic. Thanks Ian Rogers for your analysis! Modified Paths: -------------- trunk/jython/NEWS trunk/jython/src/org/python/compiler/Module.java trunk/jython/src/org/python/core/imp.java Modified: trunk/jython/NEWS =================================================================== --- trunk/jython/NEWS 2010-08-21 03:56:21 UTC (rev 7100) +++ trunk/jython/NEWS 2010-08-22 06:39:22 UTC (rev 7101) @@ -2,6 +2,7 @@ Jython 2.5.2b2 Bugs Fixed + - [ 1611 ] Jython bytecode violated JLS, causing NPE on Sun's JVM when using -Xcomp option - [ 1643 ] Tools subdirectory still exists in trunk - [ 1455 ] Classes loaded dynamically from sys.path do not have their package defined - [ 1555 ] Jython does not publish MIME types via JSR 223 (ScriptEngine.getFactory().getMimeTypes() is empty). Modified: trunk/jython/src/org/python/compiler/Module.java =================================================================== --- trunk/jython/src/org/python/compiler/Module.java 2010-08-21 03:56:21 UTC (rev 7100) +++ trunk/jython/src/org/python/compiler/Module.java 2010-08-22 06:39:22 UTC (rev 7101) @@ -550,7 +550,7 @@ } void addConstants(Code c) throws IOException { - classfile.addField("self", "L" + classfile.name + ";", ACC_STATIC | ACC_FINAL); + classfile.addField("self", "L" + classfile.name + ";", ACC_STATIC); c.aload(0); c.putstatic(classfile.name, "self", "L" + classfile.name + ";"); Enumeration e = constants.elements(); Modified: trunk/jython/src/org/python/core/imp.java =================================================================== --- trunk/jython/src/org/python/core/imp.java 2010-08-21 03:56:21 UTC (rev 7100) +++ trunk/jython/src/org/python/core/imp.java 2010-08-22 06:39:22 UTC (rev 7101) @@ -21,7 +21,7 @@ private static final String UNKNOWN_SOURCEFILE = "<unknown>"; - private static final int APIVersion = 30; + private static final int APIVersion = 31; public static final int NO_MTIME = -1; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-08-24 13:14:30
|
Revision: 7102 http://jython.svn.sourceforge.net/jython/?rev=7102&view=rev Author: zyasoft Date: 2010-08-24 13:14:24 +0000 (Tue, 24 Aug 2010) Log Message: ----------- Fixes incomplete implementation of relative imports for PEP328, which could cause a NPE. Thanks Anselm Kruis! Modified Paths: -------------- trunk/jython/ACKNOWLEDGMENTS trunk/jython/NEWS trunk/jython/src/org/python/antlr/GrammarActions.java trunk/jython/src/org/python/compiler/CodeCompiler.java trunk/jython/src/org/python/core/__builtin__.java trunk/jython/src/org/python/core/imp.java Modified: trunk/jython/ACKNOWLEDGMENTS =================================================================== --- trunk/jython/ACKNOWLEDGMENTS 2010-08-22 06:39:22 UTC (rev 7101) +++ trunk/jython/ACKNOWLEDGMENTS 2010-08-24 13:14:24 UTC (rev 7102) @@ -92,6 +92,7 @@ Costantino Cerbo Alex Gr\xF6nholm Jonathan Feinberg + Anselm Kruis Local Variables: mode: indented-text Modified: trunk/jython/NEWS =================================================================== --- trunk/jython/NEWS 2010-08-22 06:39:22 UTC (rev 7101) +++ trunk/jython/NEWS 2010-08-24 13:14:24 UTC (rev 7102) @@ -2,6 +2,7 @@ Jython 2.5.2b2 Bugs Fixed + - [ 1648 ] Incomplete implementation of pep328 for relative imports - [ 1611 ] Jython bytecode violated JLS, causing NPE on Sun's JVM when using -Xcomp option - [ 1643 ] Tools subdirectory still exists in trunk - [ 1455 ] Classes loaded dynamically from sys.path do not have their package defined Modified: trunk/jython/src/org/python/antlr/GrammarActions.java =================================================================== --- trunk/jython/src/org/python/antlr/GrammarActions.java 2010-08-22 06:39:22 UTC (rev 7101) +++ trunk/jython/src/org/python/antlr/GrammarActions.java 2010-08-24 13:14:24 UTC (rev 7102) @@ -63,11 +63,6 @@ String makeFromText(List dots, List<Name> names) { StringBuilder d = new StringBuilder(); - if (dots != null) { - for (int i=0;i<dots.size();i++) { - d.append("."); - } - } d.append(PythonTree.dottedNameListToString(names)); return d.toString(); } @@ -80,7 +75,9 @@ result.add(new Name(tok, tok.getText(), expr_contextType.Load)); } } - result.addAll(names); + if (null != names) { + result.addAll(names); + } return result; } Modified: trunk/jython/src/org/python/compiler/CodeCompiler.java =================================================================== --- trunk/jython/src/org/python/compiler/CodeCompiler.java 2010-08-22 06:39:22 UTC (rev 7101) +++ trunk/jython/src/org/python/compiler/CodeCompiler.java 2010-08-24 13:14:24 UTC (rev 7102) @@ -896,6 +896,18 @@ return Exit; } + /** + * Push the import level <code>0</code> or <code>-1</code>. + */ + private void defaultImportLevel() { + // already prepared for a future change of DEFAULT_LEVEL + if (module.getFutures().isAbsoluteImportOn() || imp.DEFAULT_LEVEL == 0) { + code.iconst_0(); + } else { + code.iconst_m1(); + } + } + @Override public Object visitImport(Import node) throws Exception { setline(node); @@ -906,8 +918,9 @@ asname = a.getInternalAsname(); code.ldc(name); loadFrame(); + defaultImportLevel(); code.invokestatic(p(imp.class), "importOneAs", sig(PyObject.class, String.class, - PyFrame.class)); + PyFrame.class, Integer.TYPE)); } else { String name = a.getInternalName(); asname = name; @@ -916,8 +929,9 @@ } code.ldc(name); loadFrame(); + defaultImportLevel(); code.invokestatic(p(imp.class), "importOne", sig(PyObject.class, String.class, - PyFrame.class)); + PyFrame.class, Integer.TYPE)); } set(new Name(a, asname, expr_contextType.Store)); } @@ -954,8 +968,9 @@ } loadFrame(); + defaultImportLevel(); code.invokestatic(p(imp.class), "importAll", sig(Void.TYPE, String.class, - PyFrame.class)); + PyFrame.class, Integer.TYPE)); } else { java.util.List<String> fromNames = new ArrayList<String>();//[names.size()]; java.util.List<String> asnames = new ArrayList<String>();//[names.size()]; @@ -973,11 +988,7 @@ loadFrame(); if (node.getInternalLevel() == 0) { - if (module.getFutures().isAbsoluteImportOn()) { - code.iconst_0(); - } else { - code.iconst_m1(); - } + defaultImportLevel(); } else { code.iconst(node.getInternalLevel()); } Modified: trunk/jython/src/org/python/core/__builtin__.java =================================================================== --- trunk/jython/src/org/python/core/__builtin__.java 2010-08-22 06:39:22 UTC (rev 7101) +++ trunk/jython/src/org/python/core/__builtin__.java 2010-08-24 13:14:24 UTC (rev 7102) @@ -1161,8 +1161,16 @@ return null; } - PyObject module = __import__.__call__(new PyObject[] {Py.newString(name), globals, locals, - fromlist, Py.newInteger(level)}); + PyObject[] args; + if (level < 0) { + // for backward compatibility provide only 4 arguments + args = new PyObject[] {Py.newString(name), globals, locals, + fromlist}; + } else { + args = new PyObject[] {Py.newString(name), globals, locals, + fromlist, Py.newInteger(level)}; + } + PyObject module = __import__.__call__(args); return module; } Modified: trunk/jython/src/org/python/core/imp.java =================================================================== --- trunk/jython/src/org/python/core/imp.java 2010-08-22 06:39:22 UTC (rev 7101) +++ trunk/jython/src/org/python/core/imp.java 2010-08-24 13:14:24 UTC (rev 7102) @@ -21,7 +21,7 @@ private static final String UNKNOWN_SOURCEFILE = "<unknown>"; - private static final int APIVersion = 31; + private static final int APIVersion = 32; public static final int NO_MTIME = -1; @@ -621,22 +621,33 @@ return import_first(name, new StringBuilder()); } - /** - * Find the parent module name for a module. If __name__ does not exist in - * the module then the parent is null. If __name__ does exist then the - * __path__ is checked for the parent module. For example, the __name__ - * 'a.b.c' would return 'a.b'. - * - * @param dict the __dict__ of a loaded module - * @param level used for relative and absolute imports. -1 means try both, - * 0 means absolute only, positive ints represent the level to - * look upward for a relative path. See PEP 328 at - * http://www.python.org/dev/peps/pep-0328/ - * - * @return the parent name for a module - */ + /** + * Find the parent package name for a module. + * + * If __name__ does not exist in the module or if level is <code>0</code>, + * then the parent is <code>null</code>. If __name__ does exist and is not a + * package name, the containing package is located. If no such package + * exists and level is <code>-1</code>, the parent is <code>null</code>. If + * level is <code>-1</code>, the parent is the current name. Otherwise, + * <code>level-1</code> doted parts are stripped from the current name. For + * example, the __name__ <code>"a.b.c"</code> and level <code>2</code> would + * return <code>"a.b"</code>, if <code>c</code> is a package and would + * return <code>"a"</code>, if <code>c</code> is not a package. + * + * @param dict + * the __dict__ of a loaded module + * @param level + * used for relative and absolute imports. -1 means try both, 0 + * means absolute only, positive ints represent the level to look + * upward for a relative path (1 means current package, 2 means + * one level up). See PEP 328 at + * http://www.python.org/dev/peps/pep-0328/ + * + * @return the parent name for a module + */ private static String getParent(PyObject dict, int level) { if (dict == null || level == 0) { + // try an absolute import return null; } PyObject tmp = dict.__finditem__("__name__"); @@ -645,20 +656,25 @@ } String name = tmp.toString(); + // locate the current package tmp = dict.__finditem__("__path__"); - if (tmp != null && tmp instanceof PyList) { - return name.intern(); - } - int dot = name.lastIndexOf('.'); - if (dot == -1) { - if (level > 0) { - throw Py.ValueError("Attempted relative import in non-package"); + if (! (tmp instanceof PyList)) { + // __name__ is not a package name, try one level upwards. + int dot = name.lastIndexOf('.'); + if (dot == -1) { + if (level <= -1) { + // there is no package, perform an absolute search + return null; + } + throw Py.ValueError("Attempted relative import in non-package"); } - return null; + // name should be the package name. + name = name.substring(0, dot); } - name = name.substring(0, dot); - while (--level > 0) { - dot = name.lastIndexOf('.'); + + // walk upwards if required (level >= 2) + while (level-- > 1) { + int dot = name.lastIndexOf('.'); if (dot == -1) { throw Py.ValueError("Attempted relative import beyond toplevel package"); } @@ -779,7 +795,7 @@ */ private static PyObject import_name(String name, boolean top, PyObject modDict, PyObject fromlist, int level) { - if (name.length() == 0) { + if (name.length() == 0 && level <= 0) { throw Py.ValueError("Empty module name"); } PyObject modules = Py.getSystemState().modules; @@ -870,9 +886,17 @@ * Called from jython generated code when a statement like "import spam" is * executed. */ + @Deprecated public static PyObject importOne(String mod, PyFrame frame) { + return importOne(mod, frame, imp.DEFAULT_LEVEL); + } + /** + * Called from jython generated code when a statement like "import spam" is + * executed. + */ + public static PyObject importOne(String mod, PyFrame frame, int level) { PyObject module = __builtin__.__import__(mod, frame.f_globals, frame - .getLocals(), Py.None); + .getLocals(), Py.None, level); return module; } @@ -880,9 +904,17 @@ * Called from jython generated code when a statement like "import spam as * foo" is executed. */ + @Deprecated public static PyObject importOneAs(String mod, PyFrame frame) { + return importOneAs(mod, frame, imp.DEFAULT_LEVEL); + } + /** + * Called from jython generated code when a statement like "import spam as + * foo" is executed. + */ + public static PyObject importOneAs(String mod, PyFrame frame, int level) { PyObject module = __builtin__.__import__(mod, frame.f_globals, frame - .getLocals(), Py.None); + .getLocals(), Py.None, level); int dot = mod.indexOf('.'); while (dot != -1) { int dot2 = mod.indexOf('.', dot + 1); @@ -957,26 +989,17 @@ * Called from jython generated code when a statement like "from spam.eggs * import *" is executed. */ - public static void importAll(String mod, PyFrame frame) { + public static void importAll(String mod, PyFrame frame, int level) { PyObject module = __builtin__.__import__(mod, frame.f_globals, frame - .getLocals(), all); - PyObject names; - boolean filter = true; - if (module instanceof PyJavaPackage) { - names = ((PyJavaPackage) module).fillDir(); - } else { - PyObject __all__ = module.__findattr__("__all__"); - if (__all__ != null) { - names = __all__; - filter = false; - } else { - names = module.__dir__(); - } - } - - loadNames(names, module, frame.getLocals(), filter); + .getLocals(), all, level); + importAll(module, frame); } + @Deprecated + public static void importAll(String mod, PyFrame frame) { + importAll(mod, frame, DEFAULT_LEVEL); + } + public static void importAll(PyObject module, PyFrame frame) { PyObject names; boolean filter = true; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-09-08 06:27:21
|
Revision: 7112 http://jython.svn.sourceforge.net/jython/?rev=7112&view=rev Author: zyasoft Date: 2010-09-08 06:27:14 +0000 (Wed, 08 Sep 2010) Log Message: ----------- To address #1327 - removed use of Guava's FinalizableReferenceQueue and now does a passive cleanup of PySystemState-related data, so that classloaders will hopefully GC under a range of setups. Also de-registers the shutdown hook. Modified Paths: -------------- trunk/jython/Lib/test/test_jy_internals.py trunk/jython/Lib/test/test_weakref.py trunk/jython/src/org/python/core/Py.java trunk/jython/src/org/python/core/PySystemState.java trunk/jython/src/org/python/util/PythonInterpreter.java Modified: trunk/jython/Lib/test/test_jy_internals.py =================================================================== --- trunk/jython/Lib/test/test_jy_internals.py 2010-09-07 20:49:59 UTC (rev 7111) +++ trunk/jython/Lib/test/test_jy_internals.py 2010-09-08 06:27:14 UTC (rev 7112) @@ -50,7 +50,6 @@ Dog().bark() """) - pi.cleanup(); make_clean() # get to steady state first, then verify we don't create new proxies Modified: trunk/jython/Lib/test/test_weakref.py =================================================================== --- trunk/jython/Lib/test/test_weakref.py 2010-09-07 20:49:59 UTC (rev 7111) +++ trunk/jython/Lib/test/test_weakref.py 2010-09-08 06:27:14 UTC (rev 7112) @@ -12,8 +12,9 @@ def extra_collect(): """Kick Java's GC into gear""" gc.collect() - time.sleep(0.1) + time.sleep(0.2) gc.collect() + time.sleep(0.2) gc.collect() else: def extra_collect(): Modified: trunk/jython/src/org/python/core/Py.java =================================================================== --- trunk/jython/src/org/python/core/Py.java 2010-09-07 20:49:59 UTC (rev 7111) +++ trunk/jython/src/org/python/core/Py.java 2010-09-08 06:27:14 UTC (rev 7112) @@ -773,7 +773,7 @@ // memory error. Fix for bug #1654484 PyType.fromClass(OutOfMemoryError.class); } - public static PySystemState defaultSystemState; + public static volatile PySystemState defaultSystemState; // This is a hack to get initializations to work in proper order public static synchronized boolean initPython() { PySystemState.initialize(); Modified: trunk/jython/src/org/python/core/PySystemState.java =================================================================== --- trunk/jython/src/org/python/core/PySystemState.java 2010-09-07 20:49:59 UTC (rev 7111) +++ trunk/jython/src/org/python/core/PySystemState.java 2010-09-08 06:27:14 UTC (rev 7112) @@ -7,6 +7,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.net.URL; import java.net.URLDecoder; @@ -21,11 +23,11 @@ import java.util.Properties; import java.util.Set; import java.util.StringTokenizer; +import java.util.concurrent.ConcurrentMap; import java.util.jar.JarEntry; import java.util.jar.JarFile; -import com.google.common.base.FinalizablePhantomReference; -import com.google.common.base.FinalizableReferenceQueue; +import com.google.common.collect.MapMaker; import org.jruby.ext.posix.util.Platform; import org.python.Version; import org.python.core.adapter.ClassicPyObjectAdapter; @@ -153,9 +155,12 @@ // Automatically close resources associated with a PySystemState when they get GCed private final PySystemStateCloser closer; - private static final FinalizableReferenceQueue systemStateQueue = new FinalizableReferenceQueue(); + private static final ReferenceQueue systemStateQueue = new ReferenceQueue<PySystemState>(); + private static final ConcurrentMap<WeakReference<PySystemState>, PySystemStateCloser> sysClosers = Generic.concurrentMap(); +// static { +// startCleanupThread(); +// } - public PySystemState() { initialize(); closer = new PySystemStateCloser(this); @@ -1251,36 +1256,60 @@ return closer.unregisterCloser(resourceCloser); } - public void shutdown() { - closer.shutdown(); + public void cleanup() { + closer.cleanup(); } + private static void startCleanupThread() { + Thread cleanupThread = new Thread(new Runnable() { + public void run() { + while (true) { + try { + Reference<PySystemStateCloser> ref = systemStateQueue.remove(); + PySystemStateCloser closer = sysClosers.get(ref); + closer.cleanup(); + sysClosers.remove(ref); + } catch (InterruptedException ex) { + break; + } + } + } + }); + cleanupThread.setDaemon(true); + cleanupThread.start(); + } private static class PySystemStateCloser { private final ArrayList<WeakReference<ThreadState[]>> threadStateList = new ArrayList<WeakReference<ThreadState[]>>(); private final Set<Callable> resourceClosers = new LinkedHashSet<Callable>(); - private final FinalizablePhantomReference<PySystemState> sys; - private volatile boolean isShutdown = false; + private volatile boolean isCleanup = false; + private final Thread shutdownHook; private PySystemStateCloser(PySystemState sys) { - this.sys = new FinalizablePhantomReference<PySystemState>(sys, systemStateQueue) { - public void finalizeReferent() { - shutdown(); - } - }; - initShutdownCloser(); + shutdownHook = initShutdownCloser(); + WeakReference<PySystemState> ref = new WeakReference(sys, systemStateQueue); + sysClosers.put(ref, this); + cleanupOtherClosers(); } + private static void cleanupOtherClosers() { + Reference<PySystemStateCloser> ref; + while ((ref = systemStateQueue.poll()) != null) { + PySystemStateCloser closer = sysClosers.get(ref); + closer.cleanup(); + } + } + private synchronized void registerThreadState(ThreadState[] threadLocal, ThreadState ts) { - if (!isShutdown) { // is this really necessary? + if (!isCleanup) { threadLocal[0] = ts; threadStateList.add(new WeakReference<ThreadState[]>(threadLocal)); } } private synchronized void registerCloser(Callable closer) { - if (!isShutdown) { + if (!isCleanup) { resourceClosers.add(closer); } } @@ -1289,12 +1318,17 @@ return resourceClosers.remove(closer); } - private synchronized void shutdown() { - if (isShutdown) { + private synchronized void cleanup() { + if (isCleanup) { return; } - isShutdown = true; + isCleanup = true; + // close this thread so we can unload any associated classloaders in cycle with this instance + if (shutdownHook != null) { + Runtime.getRuntime().removeShutdownHook(shutdownHook); + } + // clear out existing ThreadStates so that they can be GCed - this resolves ClassLoader issues for (WeakReference<ThreadState[]> ref : threadStateList) { ThreadState[] o = ref.get(); @@ -1308,18 +1342,21 @@ try { callable.call(); } catch (Exception e) { - // just continue + // just continue, nothing we can do } } resourceClosers.clear(); } - // Python scripts expect that files are closed upon an orderly shutdown of the VM. - private void initShutdownCloser() { + // Python scripts expect that files are closed upon an orderly cleanup of the VM. + private Thread initShutdownCloser() { try { - Runtime.getRuntime().addShutdownHook(new ShutdownCloser()); + Thread shutdownHook = new ShutdownCloser(); + Runtime.getRuntime().addShutdownHook(shutdownHook); + return shutdownHook; } catch (SecurityException se) { - Py.writeDebug("PySystemState", "Can't register shutdown closer hook"); + Py.writeDebug("PySystemState", "Can't register cleanup closer hook"); + return null; } } Modified: trunk/jython/src/org/python/util/PythonInterpreter.java =================================================================== --- trunk/jython/src/org/python/util/PythonInterpreter.java 2010-09-07 20:49:59 UTC (rev 7111) +++ trunk/jython/src/org/python/util/PythonInterpreter.java 2010-09-08 06:27:14 UTC (rev 7112) @@ -340,16 +340,18 @@ public void cleanup() { setSystemState(); - Py.getSystemState().callExitFunc(); + PySystemState sys = Py.getSystemState(); + sys.callExitFunc(); try { - Py.getSystemState().stdout.invoke("flush"); + sys.stdout.invoke("flush"); } catch (PyException pye) { // fall through } try { - Py.getSystemState().stderr.invoke("flush"); + sys.stderr.invoke("flush"); } catch (PyException pye) { // fall through } + sys.cleanup(); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-09-08 07:18:55
|
Revision: 7113 http://jython.svn.sourceforge.net/jython/?rev=7113&view=rev Author: zyasoft Date: 2010-09-08 07:18:48 +0000 (Wed, 08 Sep 2010) Log Message: ----------- Fixed #1503, Java constructors should take keyword arguments. Thanks Geoffrey French! Modified Paths: -------------- trunk/jython/NEWS trunk/jython/src/org/python/core/PyReflectedConstructor.java Modified: trunk/jython/NEWS =================================================================== --- trunk/jython/NEWS 2010-09-08 06:27:14 UTC (rev 7112) +++ trunk/jython/NEWS 2010-09-08 07:18:48 UTC (rev 7113) @@ -2,6 +2,7 @@ Jython 2.5.2b2 Bugs Fixed + - [ 1503 ] Java constructors should take keyword arguments - [ 1648 ] Incomplete implementation of pep328 for relative imports - [ 1611 ] Jython bytecode violated JLS, causing NPE on Sun's JVM when using -Xcomp option - [ 1643 ] Tools subdirectory still exists in trunk Modified: trunk/jython/src/org/python/core/PyReflectedConstructor.java =================================================================== --- trunk/jython/src/org/python/core/PyReflectedConstructor.java 2010-09-08 06:27:14 UTC (rev 7112) +++ trunk/jython/src/org/python/core/PyReflectedConstructor.java 2010-09-08 07:18:48 UTC (rev 7113) @@ -115,32 +115,77 @@ } ReflectedCallData callData = new ReflectedCallData(); Object method = null; - // Remove keyword args + + // If we have keyword args, there are two ways this can be handled; + // a) we find a constructor that takes keyword args, and use it. + // b) we don't, in which case we strip the keyword args, and pass the + // non-keyword args, and then use the keyword args to set bean properties + // If we don't have keyword args; just look for a constructor that + // takes the right number of args. int nkeywords = keywords.length; + ReflectedArgs rargs = null; PyObject[] allArgs = args; + boolean usingKeywordArgsCtor = false; if (nkeywords > 0) { - args = new PyObject[allArgs.length - nkeywords]; - System.arraycopy(allArgs, 0, args, 0, args.length); - } - // Check for a matching constructor to call - int n = nargs; - for (int i = 0; i < n; i++) { - ReflectedArgs rargs = argslist[i]; - if (rargs.matches(null, args, Py.NoKeywords, callData)) { - method = rargs.data; - break; + // We have keyword args. + + // Look for a constructor; the ReflectedArgs#matches() method exits early in the case + // where keyword args are used + int n = nargs; + for (int i = 0; i < n; i++) { + rargs = argslist[i]; + if (rargs.matches(null, args, keywords, callData)) { + method = rargs.data; + break; + } } - } + + if (method != null) { + // Constructor found that will accept the keyword args + usingKeywordArgsCtor = true; + } else { + // No constructor found that will take keyword args + + // Remove the keyword args + args = new PyObject[allArgs.length - nkeywords]; + System.arraycopy(allArgs, 0, args, 0, args.length); + + // Look for a constructor with no keyword args + for (int i = 0; i < n; i++) { + rargs = argslist[i]; + if (rargs.matches(null, args, Py.NoKeywords, callData)) { + method = rargs.data; + break; + } + } + } + } else { + // Just look for a constructor with no keyword args + int n = nargs; + for (int i = 0; i < n; i++) { + rargs = argslist[i]; + if (rargs.matches(null, args, Py.NoKeywords, callData)) { + method = rargs.data; + break; + } + } + } + // Throw an error if no valid set of arguments if (method == null) { throwError(callData.errArg, args.length, false, false); } // Do the actual constructor call constructProxy(self, (Constructor<?>)method, callData.getArgsArray(), javaClass); - // Do setattr's for keyword args - int offset = args.length; - for (int i = 0; i < nkeywords; i++) { - self.__setattr__(keywords[i], allArgs[i + offset]); + // Do setattr's for keyword args. This convenience allows Java bean properties to be set in + // by a Python constructor call. + // However, this is not done if the Java constructor accepts (PyObject[], String[]) as its arguments, + // in which case the intention is that the Java constructor will handle the keyword arguments itself. + if (!usingKeywordArgsCtor) { + int offset = args.length; + for (int i = 0; i < nkeywords; i++) { + self.__setattr__(keywords[i], allArgs[i + offset]); + } } return Py.None; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-09-08 20:36:22
|
Revision: 7115 http://jython.svn.sourceforge.net/jython/?rev=7115&view=rev Author: zyasoft Date: 2010-09-08 20:36:15 +0000 (Wed, 08 Sep 2010) Log Message: ----------- Fixed PyJavaType#setSlice so it properly works with Python objects that are subclasses of Java classes implementing List. Resolves #1397. Thanks Geoffrey French for the patch! Modified Paths: -------------- trunk/jython/Lib/test/test_java_list_delegate.py trunk/jython/NEWS trunk/jython/src/org/python/core/PyJavaType.java trunk/jython/src/org/python/core/PyList.java Modified: trunk/jython/Lib/test/test_java_list_delegate.py =================================================================== --- trunk/jython/Lib/test/test_java_list_delegate.py 2010-09-08 11:37:00 UTC (rev 7114) +++ trunk/jython/Lib/test/test_java_list_delegate.py 2010-09-08 20:36:15 UTC (rev 7115) @@ -21,17 +21,25 @@ except Exception, e: return type(e) - def check_list(self, control, results, initial): - for result in results: + def _arraylist_of(self, xs): + """ + Converts a python list to a java.util.ArrayList + """ + a = ArrayList() + a.addAll( xs ) + return a + + def check_list(self, control, results, list_type_names, initial, test_name): + for result, type_name in zip(results, list_type_names): try: len(result) except: print result - self.assertEquals(len(control), len(result), "%s is wrong for %s" % (type(result), initial)) - for pvalue, jvalue in zip(control, result): - self.assertEquals(pvalue, jvalue) + self.assertEquals(len(control), len(result), "%s: length for %s does not match that of list" % (test_name, type_name)) + for control_value, result_value in zip(control, result): + self.assertEquals(control_value, result_value, "%s: values from %s do not match those from list" % (test_name, type_name)) - def _list_op_test(self, initial_value, op_func, check_value): + def _list_op_test(self, initial_value, op_func, test_name): """ Tests a list operation @@ -39,24 +47,33 @@ - a python list - a java.util.List instance - givens the same result in both cases + gives the same result in both cases """ lists = [list(initial_value), ArrayList(initial_value), Vector(initial_value)] + list_type_names = ['list', 'ArrayList', 'Vector'] results = [self._perform_op(l, op_func) for l in lists] - self.check_list(lists[0], lists[1:], initial_value) - if check_value or not isinstance(results[0], list): - for r in results[1:]: - self.assertEquals(results[0], r) + self.check_list(lists[0], lists[1:], list_type_names[1:], initial_value, test_name) + if not isinstance(results[0], list): + for r,n in zip(results[1:], list_type_names[1:]): + self.assertEquals(results[0], r, '%s: result for list does not match result for java type %s' % (test_name,n) ) else: - self.check_list(results[0], results[1:], initial_value) + self.check_list(results[0], results[1:], list_type_names[1:], initial_value, test_name) def test_get_integer(self): initial_value = range(0, 5) for i in xrange(-7, 7): - self._list_op_test(initial_value, lambda xs: xs[i], True) + self._list_op_test(initial_value, lambda xs: xs[i], 'get_integer [%d]' % (i,)) + def test_get_slice(self): + initial_value = range(0, 5) + + for i in [None] + range(-7, 7): + for j in [None] + range(-7, 7): + for k in [None] + range(-7, 7): + self._list_op_test(initial_value, lambda xs: xs[i:j:k], 'get_slice [%s:%s:%s]' % (i,j,k)) + def test_set_integer(self): initial_value = range(0, 5) @@ -66,24 +83,27 @@ return _f for i in xrange(-7, 7): - self._list_op_test(initial_value, make_op_func(i), True) + self._list_op_test(initial_value, make_op_func(i), 'set_integer [%d]' % (i,)) def test_set_slice(self): - initial_value = range(0, 10) + initial_value = range(0, 5) def make_op_func(i, j, k, v): def _f(xs): xs[i:j:k] = v return _f + + for i in [None] + range(-7, 7): + for j in [None] + range(-7, 7): + for k in [None] + range(-7, 7): + self._list_op_test(initial_value, make_op_func(i, j, k, []), 'set_slice [%s:%s:%s]=[]' % (i,j,k)) + self._list_op_test(initial_value, make_op_func(i, j, k, range(0,2)), 'set_slice [%s:%s:%s]=range(0,2)' % (i,j,k)) + self._list_op_test(initial_value, make_op_func(i, j, k, range(0,4)), 'set_slice [%s:%s:%s]=range(0,4)' % (i,j,k)) + self._list_op_test(initial_value, make_op_func(i, j, k, xrange(0,2)), 'set_slice [%s:%s:%s]=xrange(0,2)' % (i,j,k)) + self._list_op_test(initial_value, make_op_func(i, j, k, self._arraylist_of(range(0,2))), 'set_slice [%s:%s:%s]=ArrayList(range(0,2))' % (i,j,k)) + + self._list_op_test([1,2,3,4,5], make_op_func(1, None, None, [1,2,3,4,5]), 'set_slice [1:]=[1,2,3,4,5]') - for i in xrange(-12, 12): - for j in xrange(-12, 12): - for k in xrange(-12, 12): - self._list_op_test(initial_value, make_op_func(i, j, k, []), True) - self._list_op_test(initial_value, make_op_func(i, j, k, range(0,2)), True) - self._list_op_test(initial_value, make_op_func(i, j, k, range(0,4)), True) - self._list_op_test(initial_value, make_op_func(i, j, k, xrange(0,2)), True) - def test_del_integer(self): initial_value = range(0,5) @@ -93,20 +113,20 @@ return _f for i in xrange(-7, 7): - self._list_op_test(initial_value, make_op_func(i), True) + self._list_op_test(initial_value, make_op_func(i), 'del_integer [%d]' % (i,)) def test_del_slice(self): - initial_value = range(0,10) + initial_value = range(0,5) def make_op_func(i, j, k): def _f(xs): del xs[i:j:k] return _f - for i in xrange(-12, 12): - for j in xrange(-12, 12): - for k in xrange(-12, 12): - self._list_op_test(initial_value, make_op_func(i, j, k), True) + for i in [None] + range(-7, 7): + for j in [None] + range(-7, 7): + for k in [None] + range(-7, 7): + self._list_op_test(initial_value, make_op_func(i, j, k), 'del_slice [%s:%s:%s]' % (i,j,k)) def test_len(self): jlist = ArrayList() @@ -174,6 +194,43 @@ self.assert_(m.size() == 11) self.assert_(m.get(10) == 84) + + + def test_set_slice_from_input_types(self): + """ + Tests the slice setting functionality of Python lists + Ensures that the results are all the same, whether the source list is a Python list, a java.util.List or an iterator + """ + initial_value = range(0, 5) + + def make_op_func(i, j, k, v): + def _f(xs): + xs[i:j:k] = v + return _f + + for i in [None] + range(-7, 7): + for j in [None] + range(-7, 7): + for k in [None] + range(-7, 7): + destPy = copy(initial_value) + destJUL = copy(initial_value) + destIter = copy(initial_value) + + sourcePy = range(0, 2) + sourceJUL = self._arraylist_of(range(0, 2)) + sourceIter = xrange(0, 2) + + resultPy = self._perform_op(destPy, make_op_func(i, j, k, sourcePy)) + resultJUL = self._perform_op(destJUL, make_op_func(i, j, k, sourceJUL)) + resultIter = self._perform_op(destIter, make_op_func(i, j, k, sourceIter)) + + self.assertEquals(resultPy, resultJUL) + self.assertEquals(resultPy, resultIter) + + self.assertEquals(destPy, destJUL) + self.assertEquals(destPy, destIter) + + + def test_main(): test.test_support.run_unittest(CollectionProxyTest) Modified: trunk/jython/NEWS =================================================================== --- trunk/jython/NEWS 2010-09-08 11:37:00 UTC (rev 7114) +++ trunk/jython/NEWS 2010-09-08 20:36:15 UTC (rev 7115) @@ -2,6 +2,7 @@ Jython 2.5.2b2 Bugs Fixed + - [ 1397 ] Bugs in PyList and PyJavaType.ListIndexDelegate slice setting - [ 1503 ] Java constructors should take keyword arguments - [ 1648 ] Incomplete implementation of pep328 for relative imports - [ 1611 ] Jython bytecode violated JLS, causing NPE on Sun's JVM when using -Xcomp option Modified: trunk/jython/src/org/python/core/PyJavaType.java =================================================================== --- trunk/jython/src/org/python/core/PyJavaType.java 2010-09-08 11:37:00 UTC (rev 7114) +++ trunk/jython/src/org/python/core/PyJavaType.java 2010-09-08 20:36:15 UTC (rev 7115) @@ -1079,26 +1079,94 @@ public void setItem(int idx, PyObject value) { list.set(idx, value.__tojava__(Object.class)); } - + @Override public void setSlice(int start, int stop, int step, PyObject value) { - if (step == 0) { - return; + if (stop < start) { + stop = start; } - if (value.javaProxy == this) { - List newseq = new ArrayList(len()); - for (Object object : ((List)value.javaProxy)) { - newseq.add(object); + if (value.javaProxy == this.list) { + List<Object> xs = Generic.list(); + xs.addAll(this.list); + setsliceList(start, stop, step, xs); + } else if (value instanceof PyList) { + setslicePyList(start, stop, step, (PyList)value); + } else { + Object valueList = value.__tojava__(List.class); + if (valueList != null && valueList != Py.NoConversion) { + setsliceList(start, stop, step, (List)valueList); + } else { + setsliceIterator(start, stop, step, value.asIterable().iterator()); } - value = Py.java2py(newseq); } - int j = start; - for (PyObject obj : value.asIterable()) { - setItem(j, obj); - j += step; + } + + + + final private void setsliceList(int start, int stop, int step, List<Object> value) { + if (step == 1) { + list.subList(start, stop).clear(); + list.addAll(start, value); + } else { + int size = list.size(); + Iterator<Object> iter = value.listIterator(); + for (int j = start; iter.hasNext(); j += step) { + Object item =iter.next(); + if (j >= size) { + list.add(item); + } else { + list.set(j, item); + } + } } } + final private void setsliceIterator(int start, int stop, int step, Iterator<PyObject> iter) { + if (step == 1) { + List<Object> insertion = new ArrayList<Object>(); + if (iter != null) { + while (iter.hasNext()) { + insertion.add(iter.next().__tojava__(Object.class)); + } + } + list.subList(start, stop).clear(); + list.addAll(start, insertion); + } else { + int size = list.size(); + for (int j = start; iter.hasNext(); j += step) { + Object item = iter.next().__tojava__(Object.class); + if (j >= size) { + list.add(item); + } else { + list.set(j, item); + } + } + } + } + + final private void setslicePyList(int start, int stop, int step, PyList value) { + if (step == 1) { + list.subList(start, stop).clear(); + int n = value.getList().size(); + for (int i=0, j=start; i<n; i++, j++) { + Object item = value.getList().get(i).__tojava__(Object.class); + list.add(j, item); + } + } else { + int size = list.size(); + Iterator<PyObject> iter = value.getList().listIterator(); + for (int j = start; iter.hasNext(); j += step) { + Object item = iter.next().__tojava__(Object.class); + if (j >= size) { + list.add(item); + } else { + list.set(j, item); + } + } + } + } + + @Override public void delItems(int start, int stop) { int n = stop - start; Modified: trunk/jython/src/org/python/core/PyList.java =================================================================== --- trunk/jython/src/org/python/core/PyList.java 2010-09-08 11:37:00 UTC (rev 7114) +++ trunk/jython/src/org/python/core/PyList.java 2010-09-08 20:36:15 UTC (rev 7115) @@ -147,26 +147,38 @@ setslicePyList(start, stop, step, (PyList) value); } else if (value instanceof PySequence) { setsliceIterator(start, stop, step, value.asIterable().iterator()); - } else if (value != null && !(value instanceof List)) { - value = new PyList(value); - setsliceIterator(start, stop, step, value.asIterable().iterator()); + } else if (value instanceof List) { + setsliceList(start, stop, step, (List)value); } else { - List valueList = (List) value.__tojava__(List.class); + Object valueList = value.__tojava__(List.class); if (valueList != null && valueList != Py.NoConversion) { - setsliceList(start, stop, step, valueList); + setsliceList(start, stop, step, (List)valueList); + } else { + value = new PyList(value); + setsliceIterator(start, stop, step, value.asIterable().iterator()); } } } final private void setsliceList(int start, int stop, int step, List value) { - int n = sliceLength(start, stop, step); - if (list instanceof ArrayList) { - ((ArrayList) list).ensureCapacity(start + n); + if (step == 1) { + list.subList(start, stop).clear(); + int n = value.size(); + for (int i=0, j=start; i<n; i++, j++) { + list.add(j, Py.java2py(value.get(i))); + } + } else { + int size = list.size(); + Iterator<Object> iter = value.listIterator(); + for (int j = start; iter.hasNext(); j += step) { + PyObject item = Py.java2py(iter.next()); + if (j >= size) { + list.add(item); + } else { + list.set(j, item); + } + } } - ListIterator src = value.listIterator(); - for (int j = start; src.hasNext(); j += step) { - set(j, src.next()); - } } final private void setsliceIterator(int start, int stop, int step, Iterator<PyObject> iter) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-09-12 23:08:25
|
Revision: 7120 http://jython.svn.sourceforge.net/jython/?rev=7120&view=rev Author: zyasoft Date: 2010-09-12 23:08:19 +0000 (Sun, 12 Sep 2010) Log Message: ----------- Backed out support for nulling out ThreadState support. We need a better solution that doesn't introduce synchronization issues and a backwards breaking API change. See the discussion in #1327. Modified Paths: -------------- trunk/jython/src/org/python/core/PySystemState.java trunk/jython/src/org/python/core/ThreadStateMapping.java trunk/jython/tests/java/org/python/core/WrappedBooleanTest.java trunk/jython/tests/java/org/python/core/WrappedFloatTest.java trunk/jython/tests/java/org/python/core/WrappedIntegerTest.java trunk/jython/tests/java/org/python/core/WrappedLongTest.java trunk/jython/tests/java/org/python/tests/ExceptionTest.java trunk/jython/tests/java/org/python/tests/SerializationTest.java trunk/jython/tests/java/org/python/tests/props/BeanPropertyTest.java Modified: trunk/jython/src/org/python/core/PySystemState.java =================================================================== --- trunk/jython/src/org/python/core/PySystemState.java 2010-09-12 23:04:58 UTC (rev 7119) +++ trunk/jython/src/org/python/core/PySystemState.java 2010-09-12 23:08:19 UTC (rev 7120) @@ -1244,10 +1244,6 @@ return f; } - public void registerThreadState(ThreadState[] threadLocal, ThreadState ts) { - closer.registerThreadState(threadLocal, ts); - } - public void registerCloser(Callable resourceCloser) { closer.registerCloser(resourceCloser); } @@ -1281,7 +1277,6 @@ private static class PySystemStateCloser { - private final ArrayList<WeakReference<ThreadState[]>> threadStateList = new ArrayList<WeakReference<ThreadState[]>>(); private final Set<Callable> resourceClosers = new LinkedHashSet<Callable>(); private volatile boolean isCleanup = false; private final Thread shutdownHook; @@ -1301,13 +1296,6 @@ } } - private synchronized void registerThreadState(ThreadState[] threadLocal, ThreadState ts) { - if (!isCleanup) { - threadLocal[0] = ts; - threadStateList.add(new WeakReference<ThreadState[]>(threadLocal)); - } - } - private synchronized void registerCloser(Callable closer) { if (!isCleanup) { resourceClosers.add(closer); @@ -1329,15 +1317,6 @@ Runtime.getRuntime().removeShutdownHook(shutdownHook); } - // clear out existing ThreadStates so that they can be GCed - this resolves ClassLoader issues - for (WeakReference<ThreadState[]> ref : threadStateList) { - ThreadState[] o = ref.get(); - if (o != null) { - o[0] = null; - } - } - threadStateList.clear(); - for (Callable callable : resourceClosers) { try { callable.call(); Modified: trunk/jython/src/org/python/core/ThreadStateMapping.java =================================================================== --- trunk/jython/src/org/python/core/ThreadStateMapping.java 2010-09-12 23:04:58 UTC (rev 7119) +++ trunk/jython/src/org/python/core/ThreadStateMapping.java 2010-09-12 23:08:19 UTC (rev 7120) @@ -1,19 +1,15 @@ package org.python.core; class ThreadStateMapping { - private static final ThreadLocal<ThreadState[]> cachedThreadState = - new ThreadLocal<ThreadState[]>() { - @Override - protected ThreadState[] initialValue() { - return new ThreadState[1]; - } - }; + private static final ThreadLocal<ThreadState> cachedThreadState = new ThreadLocal<ThreadState>(); - public synchronized ThreadState getThreadState(PySystemState newSystemState) { - ThreadState[] threadLocal = cachedThreadState.get(); - if (threadLocal[0] != null) - return threadLocal[0]; + public ThreadState getThreadState(PySystemState newSystemState) { + ThreadState ts = cachedThreadState.get(); + if (ts != null) { + return ts; + } + Thread t = Thread.currentThread(); if (newSystemState == null) { Py.writeDebug("threadstate", "no current system state"); @@ -23,8 +19,8 @@ newSystemState = Py.defaultSystemState; } - ThreadState ts = new ThreadState(t, newSystemState); - newSystemState.registerThreadState(threadLocal, ts); + ts = new ThreadState(t, newSystemState); + cachedThreadState.set(ts); return ts; } } Modified: trunk/jython/tests/java/org/python/core/WrappedBooleanTest.java =================================================================== --- trunk/jython/tests/java/org/python/core/WrappedBooleanTest.java 2010-09-12 23:04:58 UTC (rev 7119) +++ trunk/jython/tests/java/org/python/core/WrappedBooleanTest.java 2010-09-12 23:08:19 UTC (rev 7120) @@ -32,7 +32,6 @@ @Override protected void setUp() throws Exception { - PythonInterpreter.initialize(null, null, null); interp = new PythonInterpreter(new PyStringMap(), new PySystemState()); a = new WrappedBoolean(); b = new WrappedBoolean(); Modified: trunk/jython/tests/java/org/python/core/WrappedFloatTest.java =================================================================== --- trunk/jython/tests/java/org/python/core/WrappedFloatTest.java 2010-09-12 23:04:58 UTC (rev 7119) +++ trunk/jython/tests/java/org/python/core/WrappedFloatTest.java 2010-09-12 23:08:19 UTC (rev 7120) @@ -32,7 +32,6 @@ @Override protected void setUp() throws Exception { - PythonInterpreter.initialize(null, null, null); interp = new PythonInterpreter(new PyStringMap(), new PySystemState()); a = new WrappedFloat(); b = new WrappedFloat(); Modified: trunk/jython/tests/java/org/python/core/WrappedIntegerTest.java =================================================================== --- trunk/jython/tests/java/org/python/core/WrappedIntegerTest.java 2010-09-12 23:04:58 UTC (rev 7119) +++ trunk/jython/tests/java/org/python/core/WrappedIntegerTest.java 2010-09-12 23:08:19 UTC (rev 7120) @@ -32,7 +32,6 @@ @Override protected void setUp() throws Exception { - PythonInterpreter.initialize(null, null, null); interp = new PythonInterpreter(new PyStringMap(), new PySystemState()); a = new WrappedInteger(); b = new WrappedInteger(); Modified: trunk/jython/tests/java/org/python/core/WrappedLongTest.java =================================================================== --- trunk/jython/tests/java/org/python/core/WrappedLongTest.java 2010-09-12 23:04:58 UTC (rev 7119) +++ trunk/jython/tests/java/org/python/core/WrappedLongTest.java 2010-09-12 23:08:19 UTC (rev 7120) @@ -34,7 +34,6 @@ @Override protected void setUp() throws Exception { - PythonInterpreter.initialize(null, null, null); interp = new PythonInterpreter(new PyStringMap(), new PySystemState()); a = new WrappedLong(); b = new WrappedLong(); Modified: trunk/jython/tests/java/org/python/tests/ExceptionTest.java =================================================================== --- trunk/jython/tests/java/org/python/tests/ExceptionTest.java 2010-09-12 23:04:58 UTC (rev 7119) +++ trunk/jython/tests/java/org/python/tests/ExceptionTest.java 2010-09-12 23:08:19 UTC (rev 7120) @@ -28,7 +28,6 @@ " else:\n" + " raise Throwable()\n" + "r = Raiser()"; - PythonInterpreter.initialize(null, null, null); PythonInterpreter interp = new PythonInterpreter(); interp.exec(raiser); t = Py.tojava(interp.get("r"), Thrower.class); Modified: trunk/jython/tests/java/org/python/tests/SerializationTest.java =================================================================== --- trunk/jython/tests/java/org/python/tests/SerializationTest.java 2010-09-12 23:04:58 UTC (rev 7119) +++ trunk/jython/tests/java/org/python/tests/SerializationTest.java 2010-09-12 23:08:19 UTC (rev 7120) @@ -18,7 +18,6 @@ @Override protected void setUp() throws Exception { - PythonInterpreter.initialize(null, null, null); interp = new PythonInterpreter(new PyStringMap(), new PySystemState()); interp.exec("from java.io import Serializable"); interp.exec("class Test(Serializable): pass"); Modified: trunk/jython/tests/java/org/python/tests/props/BeanPropertyTest.java =================================================================== --- trunk/jython/tests/java/org/python/tests/props/BeanPropertyTest.java 2010-09-12 23:04:58 UTC (rev 7119) +++ trunk/jython/tests/java/org/python/tests/props/BeanPropertyTest.java 2010-09-12 23:08:19 UTC (rev 7120) @@ -12,7 +12,6 @@ @Override protected void setUp() throws Exception { - PythonInterpreter.initialize(null, null, null); interp = new PythonInterpreter(new PyStringMap(), new PySystemState()); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <otm...@us...> - 2010-09-13 13:44:39
|
Revision: 7121 http://jython.svn.sourceforge.net/jython/?rev=7121&view=rev Author: otmarhumbel Date: 2010-09-13 13:44:33 +0000 (Mon, 13 Sep 2010) Log Message: ----------- prepare for 2.5.2b2 Modified Paths: -------------- trunk/jython/README.txt trunk/jython/build.xml Modified: trunk/jython/README.txt =================================================================== --- trunk/jython/README.txt 2010-09-12 23:08:19 UTC (rev 7120) +++ trunk/jython/README.txt 2010-09-13 13:44:33 UTC (rev 7121) @@ -1,11 +1,13 @@ -Welcome to Jython 2.5.2 Beta1 +Welcome to Jython 2.5.2 Beta2 ============================= -This is the first beta release of the 2.5.2 version of Jython. This release -fixes a number of bugs, including some Java integration problems, several modjy -bugs, a number of Python compatibility bugs, and more. See the NEWS file for +This is the second beta release of the 2.5.2 version of Jython. This release +fixes a number of bugs and addresses memory and threading issues. See the NEWS file for more details. The release was compiled on Mac OS X with JDK 5 and requires JDK 5 to run. -Please try this out and report any bugs at http://bugs.jython.org. +Please try it out and report any bugs at http://bugs.jython.org. + +And - last but not least - please help spread the word: +If companies still are using Jython 2.2.1, they really should start testing against 2.5.2 now. Modified: trunk/jython/build.xml =================================================================== --- trunk/jython/build.xml 2010-09-12 23:08:19 UTC (rev 7120) +++ trunk/jython/build.xml 2010-09-13 13:44:33 UTC (rev 7121) @@ -123,13 +123,13 @@ <property name="PY_RELEASE_LEVEL_SNAPSHOT" value="170"/> <!-- 0xAA --> <!-- The current version info --> - <property name="jython.version" value="2.5.2b1"/> - <property name="jython.version.noplus" value="2.5.2b1"/> + <property name="jython.version" value="2.5.2b2"/> + <property name="jython.version.noplus" value="2.5.2b2"/> <property name="jython.major_version" value="2"/> <property name="jython.minor_version" value="5"/> <property name="jython.micro_version" value="2"/> <property name="jython.release_level" value="${PY_RELEASE_LEVEL_BETA}"/> - <property name="jython.release_serial" value="1"/> + <property name="jython.release_serial" value="2"/> <condition property="do.snapshot.build"> <isset property="snapshot.revision" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-09-13 17:53:12
|
Revision: 7122 http://jython.svn.sourceforge.net/jython/?rev=7122&view=rev Author: zyasoft Date: 2010-09-13 17:53:05 +0000 (Mon, 13 Sep 2010) Log Message: ----------- Updated NEWS and README.txt in prep of 2.5.2b2 Modified Paths: -------------- trunk/jython/NEWS trunk/jython/README.txt Modified: trunk/jython/NEWS =================================================================== --- trunk/jython/NEWS 2010-09-13 13:44:33 UTC (rev 7121) +++ trunk/jython/NEWS 2010-09-13 17:53:05 UTC (rev 7122) @@ -2,6 +2,7 @@ Jython 2.5.2b2 Bugs Fixed + - [ 1327 ] Classloaders cannot GC, which exhausts permgen (partial bug fix) - [ 1604 ] PyBuiltinCallable.Info should be serializable - [ 1397 ] Bugs in PyList and PyJavaType.ListIndexDelegate slice setting - [ 1503 ] Java constructors should take keyword arguments Modified: trunk/jython/README.txt =================================================================== --- trunk/jython/README.txt 2010-09-13 13:44:33 UTC (rev 7121) +++ trunk/jython/README.txt 2010-09-13 17:53:05 UTC (rev 7122) @@ -1,13 +1,43 @@ Welcome to Jython 2.5.2 Beta2 ============================= -This is the second beta release of the 2.5.2 version of Jython. This release -fixes a number of bugs and addresses memory and threading issues. See the NEWS file for -more details. +This is the second beta release of the 2.5.2 version of Jython. Our +current plans is that this will be the last beta of 2.5.2, but this +will depend on bug report. -The release was compiled on Mac OS X with JDK 5 and requires JDK 5 to run. +This release fixes bugs related to resource leaks, Java integration, +and a number of other issues. See the NEWS file for more details. In +particular, we did not completely fix #1327, "Classloaders cannot GC, +which exhausts permgen." Jython uses instances of ThreadLocal-managed +class, ThreadState, to manage its execution state, including frames, +exceptions, and the global namespace. The ThreadState also indirectly +refers to the ClassLoaders used by Jython. Such usage can cause +resource leaks when a Jython application is restarted under certain +app containers, because the ThreadState often may not cleaned up by +the app server's thread pool. -Please try it out and report any bugs at http://bugs.jython.org. +Fixing this problem without a breakwards breaking API change appears +to be difficult. Therefore we recommend exploring workarounds, such as +the one published in this blog post, +http://weblogs.java.net/blog/jjviana/archive/2010/06/09/dealing-glassfish-301-memory-leak-or-threadlocal-thread-pool-bad-ide -And - last but not least - please help spread the word: -If companies still are using Jython 2.2.1, they really should start testing against 2.5.2 now. +Jython 2.6 will introduce limited backwards breaking API changes, so +it will be possible to fully resolve this bug, and related issues, in +that version instead. + +And -- last but not least -- please help spread the word: + +Organizations using Jython 2.2.1, or earlier, should test their code +against 2.5.2 beta 2 now so that bug fixes and/or workarounds may be +identified. In particular, please note the following: + + * No additional work is anticipated on Jython 2.2. + + * Jython 2.5.2 is the last release in Jython 2.5.x series that will + address non-severe issues, including Java integration issues. + + * Jython 2.6 development will begin immediately following the 2.5.2 + release. Jython 2.6 will require the use of JDK 6. + +The release was compiled on Mac OS X with JDK 5 and requires JDK 5 to +run. Please try it out and report any bugs at http://bugs.jython.org. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |