You can subscribe to this list here.
2000 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(1) |
Nov
(107) |
Dec
(67) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2001 |
Jan
(76) |
Feb
(125) |
Mar
(72) |
Apr
(13) |
May
(18) |
Jun
(12) |
Jul
(129) |
Aug
(47) |
Sep
(1) |
Oct
(36) |
Nov
(128) |
Dec
(124) |
2002 |
Jan
(59) |
Feb
|
Mar
(14) |
Apr
(14) |
May
(72) |
Jun
(9) |
Jul
(3) |
Aug
(5) |
Sep
(18) |
Oct
(65) |
Nov
(28) |
Dec
(12) |
2003 |
Jan
(10) |
Feb
(2) |
Mar
(4) |
Apr
(33) |
May
(21) |
Jun
(9) |
Jul
(29) |
Aug
(34) |
Sep
(4) |
Oct
(8) |
Nov
(15) |
Dec
(4) |
2004 |
Jan
(26) |
Feb
(12) |
Mar
(11) |
Apr
(9) |
May
(7) |
Jun
|
Jul
(5) |
Aug
|
Sep
(3) |
Oct
(7) |
Nov
(1) |
Dec
(10) |
2005 |
Jan
(2) |
Feb
(72) |
Mar
(16) |
Apr
(39) |
May
(48) |
Jun
(97) |
Jul
(57) |
Aug
(13) |
Sep
(16) |
Oct
(24) |
Nov
(100) |
Dec
(24) |
2006 |
Jan
(15) |
Feb
(34) |
Mar
(33) |
Apr
(31) |
May
(79) |
Jun
(64) |
Jul
(41) |
Aug
(64) |
Sep
(31) |
Oct
(46) |
Nov
(55) |
Dec
(37) |
2007 |
Jan
(32) |
Feb
(61) |
Mar
(11) |
Apr
(58) |
May
(46) |
Jun
(30) |
Jul
(94) |
Aug
(93) |
Sep
(86) |
Oct
(69) |
Nov
(125) |
Dec
(177) |
2008 |
Jan
(169) |
Feb
(97) |
Mar
(74) |
Apr
(113) |
May
(120) |
Jun
(334) |
Jul
(215) |
Aug
(237) |
Sep
(72) |
Oct
(189) |
Nov
(126) |
Dec
(160) |
2009 |
Jan
(180) |
Feb
(45) |
Mar
(98) |
Apr
(140) |
May
(151) |
Jun
(71) |
Jul
(107) |
Aug
(119) |
Sep
(73) |
Oct
(121) |
Nov
(14) |
Dec
(6) |
2010 |
Jan
(13) |
Feb
(9) |
Mar
(10) |
Apr
(64) |
May
(3) |
Jun
(16) |
Jul
(7) |
Aug
(23) |
Sep
(17) |
Oct
(37) |
Nov
(5) |
Dec
(8) |
2011 |
Jan
(10) |
Feb
(11) |
Mar
(77) |
Apr
(11) |
May
(2) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
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: <otm...@us...> - 2010-09-07 20:50:05
|
Revision: 7111 http://jython.svn.sourceforge.net/jython/?rev=7111&view=rev Author: otmarhumbel Date: 2010-09-07 20:49:59 +0000 (Tue, 07 Sep 2010) Log Message: ----------- fix the java tests by initializing the interpreter in setUp() Modified 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 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/tests/java/org/python/core/WrappedBooleanTest.java =================================================================== --- trunk/jython/tests/java/org/python/core/WrappedBooleanTest.java 2010-09-04 02:43:03 UTC (rev 7110) +++ trunk/jython/tests/java/org/python/core/WrappedBooleanTest.java 2010-09-07 20:49:59 UTC (rev 7111) @@ -32,6 +32,7 @@ @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-04 02:43:03 UTC (rev 7110) +++ trunk/jython/tests/java/org/python/core/WrappedFloatTest.java 2010-09-07 20:49:59 UTC (rev 7111) @@ -32,6 +32,7 @@ @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-04 02:43:03 UTC (rev 7110) +++ trunk/jython/tests/java/org/python/core/WrappedIntegerTest.java 2010-09-07 20:49:59 UTC (rev 7111) @@ -32,6 +32,7 @@ @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-04 02:43:03 UTC (rev 7110) +++ trunk/jython/tests/java/org/python/core/WrappedLongTest.java 2010-09-07 20:49:59 UTC (rev 7111) @@ -34,6 +34,7 @@ @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-04 02:43:03 UTC (rev 7110) +++ trunk/jython/tests/java/org/python/tests/ExceptionTest.java 2010-09-07 20:49:59 UTC (rev 7111) @@ -28,6 +28,7 @@ " 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-04 02:43:03 UTC (rev 7110) +++ trunk/jython/tests/java/org/python/tests/SerializationTest.java 2010-09-07 20:49:59 UTC (rev 7111) @@ -18,6 +18,7 @@ @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-04 02:43:03 UTC (rev 7110) +++ trunk/jython/tests/java/org/python/tests/props/BeanPropertyTest.java 2010-09-07 20:49:59 UTC (rev 7111) @@ -12,6 +12,7 @@ @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: <zy...@us...> - 2010-09-04 02:43:10
|
Revision: 7110 http://jython.svn.sourceforge.net/jython/?rev=7110&view=rev Author: zyasoft Date: 2010-09-04 02:43:03 +0000 (Sat, 04 Sep 2010) Log Message: ----------- Doc cleanup Modified Paths: -------------- trunk/jython/src/org/python/core/imp.java Modified: trunk/jython/src/org/python/core/imp.java =================================================================== --- trunk/jython/src/org/python/core/imp.java 2010-08-28 03:52:43 UTC (rev 7109) +++ trunk/jython/src/org/python/core/imp.java 2010-09-04 02:43:03 UTC (rev 7110) @@ -48,22 +48,24 @@ } /** - * <p> - * Selects the parent class loader for Jython, used for dinamically load classes and resources + * Selects the parent class loader for Jython, to be used for + * dynamically loaded classes and resources. Chooses between the + * current and context classloader based on the following + * criteria: + * + * <ul> + * <li>If both are the same classloader, return that classloader. + * <li>If either is null, then the non-null one is selected. + * <li>If both are not null, and a parent/child relationship can + * be determined, then the child is selected. + * <li>If both are not null and not on a parent/child + * relationship, then the current class loader is returned (since + * it is likely for the context class loader to <b>not</b> see the + * Jython classes) + * </ul> * - * <p> - * The current implementation chooses between the current and context - * classloader based on the following criteria:<ul> - * - * <li>If both are the same, that one is returned. - * <li>If either is null, the non-null one is selected. - * <li>If both are not null, and a parent/child relationship can be determined, - * the child is selected. - * <li>If both are not null and not on a parent/child relationship, the - * current class loader is returned (since it is likely for the - * context class loader to <b>not</b> see the Jython classes) - * - * @return the parent class loader for Jython or null if both the current and context classloaders are null; + * @return the parent class loader for Jython or null if both the + * current and context classloaders are null. */ public static ClassLoader getParentClassLoader() { ClassLoader current = imp.class.getClassLoader(); @@ -252,14 +254,15 @@ /** * Stores the bytes in compiledSource in compiledFilename. * - * If compiledFilename is null it's set to the results of - * makeCompiledFilename(sourcefileName) + * If compiledFilename is null, it's set to the results of + * makeCompiledFilename(sourcefileName). * - * If sourceFilename is null or set to UNKNOWN_SOURCEFILE null is returned + * If sourceFilename is null or set to UNKNOWN_SOURCEFILE, then + * null is returned. * - * @return the compiledFilename eventually used or null if a - * compiledFilename couldn't be determined of if an error was thrown - * while writing to the cache file. + * @return the compiledFilename eventually used; or null if a + * compiledFilename couldn't be determined or if an error + * was thrown while writing to the cache file. */ public static String cacheCompiledSource(String sourceFilename, String compiledFilename, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-08-28 03:52:49
|
Revision: 7109 http://jython.svn.sourceforge.net/jython/?rev=7109&view=rev Author: zyasoft Date: 2010-08-28 03:52:43 +0000 (Sat, 28 Aug 2010) Log Message: ----------- Use Guava's FinalizableReferenceQueue and a new PySystemStateCloser class to manage the closing of those resources that prevent classloader GC (because they have hard refs to classes) after a PySystemState itself is GCed. This refactoring also moved the closing of user-unclosed files associated with a PyFile to the holding PySystemState, instead of having to wait for JVM shutdown. Now the JVM shutdown hook does this closing of resources through the PySystemStateCloser. Modified Paths: -------------- trunk/jython/src/org/python/core/PyFile.java trunk/jython/src/org/python/core/PySystemState.java trunk/jython/src/org/python/core/PyType.java trunk/jython/src/org/python/core/ThreadStateMapping.java Modified: trunk/jython/src/org/python/core/PyFile.java =================================================================== --- trunk/jython/src/org/python/core/PyFile.java 2010-08-27 13:20:44 UTC (rev 7108) +++ trunk/jython/src/org/python/core/PyFile.java 2010-08-28 03:52:43 UTC (rev 7109) @@ -6,7 +6,7 @@ import java.io.InputStream; import java.io.OutputStream; -import java.util.LinkedList; +import java.util.concurrent.Callable; import org.python.core.io.BinaryIOWrapper; import org.python.core.io.BufferedIOBase; @@ -78,13 +78,6 @@ * shutdown */ private Closer closer; - /** All PyFiles' closers */ - private static LinkedList<Closer> closers = new LinkedList<Closer>(); - - static { - initCloser(); - } - public PyFile() {} public PyFile(PyType subType) { @@ -155,7 +148,7 @@ String mode = ap.getString(1, "r"); int bufsize = ap.getInt(2, -1); file___init__(new FileIO(name.toString(), parseMode(mode)), name, mode, bufsize); - closer = new Closer(file); + closer = new Closer(file, Py.getSystemState()); } private void file___init__(RawIOBase raw, String name, String mode, int bufsize) { @@ -569,16 +562,9 @@ } } - private static void initCloser() { - try { - Runtime.getRuntime().addShutdownHook(new PyFileCloser()); - } catch (SecurityException se) { - Py.writeDebug("PyFile", "Can't register file closer hook"); - } - } - + /** - * A mechanism to make sure PyFiles are closed on exit. On creation Closer adds itself + * XXX update docs - A mechanism to make sure PyFiles are closed on exit. On creation Closer adds itself * to a list of Closers that will be run by PyFileCloser on JVM shutdown. When a * PyFile's close or finalize methods are called, PyFile calls its Closer.close which * clears Closer out of the shutdown queue. @@ -588,55 +574,39 @@ * be called during shutdown, so we can't use it. It's vital that this Closer has no * reference to the PyFile it's closing so the PyFile remains garbage collectable. */ - private static class Closer { + private static class Closer implements Callable { - /** The underlying file */ - private TextIOBase file; + /** + * The underlying file + */ + private final TextIOBase file; + private PySystemState sys; - public Closer(TextIOBase file) { + public Closer(TextIOBase file, PySystemState sys) { this.file = file; - // Add ourselves to the queue of Closers to be run on shutdown - synchronized (closers) { - closers.add(this); - } + this.sys = sys; + sys.registerCloser(this); } + // For closing directly + public void close() { - synchronized (closers) { - if (!closers.remove(this)) { - return; - } + if (sys.unregisterCloser(this)) { + file.close(); } - doClose(); + sys = null; } - public void doClose() { + // For closing as part of a shutdown process + + public Object call() { file.close(); + sys = null; + return null; } + } - private static class PyFileCloser extends Thread { - public PyFileCloser() { - super("Jython Shutdown File Closer"); - } - @Override - public void run() { - if (closers == null) { - // closers can be null in some strange cases - return; - } - synchronized (closers) { - while (closers.size() > 0) { - try { - closers.removeFirst().doClose(); - } catch (PyException e) { - // continue - } - } - } - } - } - } Modified: trunk/jython/src/org/python/core/PySystemState.java =================================================================== --- trunk/jython/src/org/python/core/PySystemState.java 2010-08-27 13:20:44 UTC (rev 7108) +++ trunk/jython/src/org/python/core/PySystemState.java 2010-08-28 03:52:43 UTC (rev 7109) @@ -7,18 +7,25 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.lang.ref.WeakReference; import java.net.URL; import java.net.URLDecoder; import java.nio.charset.Charset; import java.nio.charset.UnsupportedCharsetException; import java.security.AccessControlException; +import java.util.concurrent.Callable; +import java.util.ArrayList; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; +import java.util.Set; import java.util.StringTokenizer; import java.util.jar.JarEntry; import java.util.jar.JarFile; +import com.google.common.base.FinalizablePhantomReference; +import com.google.common.base.FinalizableReferenceQueue; import org.jruby.ext.posix.util.Platform; import org.python.Version; import org.python.core.adapter.ClassicPyObjectAdapter; @@ -144,8 +151,14 @@ /** true when a SystemRestart is triggered. */ public boolean _systemRestart = false; + // Automatically close resources associated with a PySystemState when they get GCed + private final PySystemStateCloser closer; + private static final FinalizableReferenceQueue systemStateQueue = new FinalizableReferenceQueue(); + + public PySystemState() { initialize(); + closer = new PySystemStateCloser(this); modules = new PyStringMap(); argv = (PyList)defaultArgv.repeat(1); @@ -1225,8 +1238,118 @@ throw Py.ValueError("call stack is not deep enough"); return f; } + + public void registerThreadState(ThreadState[] threadLocal, ThreadState ts) { + closer.registerThreadState(threadLocal, ts); + } + + public void registerCloser(Callable resourceCloser) { + closer.registerCloser(resourceCloser); + } + + public synchronized boolean unregisterCloser(Callable resourceCloser) { + return closer.unregisterCloser(resourceCloser); + } + + public void shutdown() { + closer.shutdown(); + } + + + 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 PySystemStateCloser(PySystemState sys) { + this.sys = new FinalizablePhantomReference<PySystemState>(sys, systemStateQueue) { + public void finalizeReferent() { + shutdown(); + } + }; + initShutdownCloser(); + } + + private synchronized void registerThreadState(ThreadState[] threadLocal, ThreadState ts) { + if (!isShutdown) { // is this really necessary? + threadLocal[0] = ts; + threadStateList.add(new WeakReference<ThreadState[]>(threadLocal)); + } + } + + private synchronized void registerCloser(Callable closer) { + if (!isShutdown) { + resourceClosers.add(closer); + } + } + + private synchronized boolean unregisterCloser(Callable closer) { + return resourceClosers.remove(closer); + } + + private synchronized void shutdown() { + if (isShutdown) { + return; + } + isShutdown = true; + + // 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(); + } catch (Exception e) { + // just continue + } + } + resourceClosers.clear(); + } + + // Python scripts expect that files are closed upon an orderly shutdown of the VM. + private void initShutdownCloser() { + try { + Runtime.getRuntime().addShutdownHook(new ShutdownCloser()); + } catch (SecurityException se) { + Py.writeDebug("PySystemState", "Can't register shutdown closer hook"); + } + } + + private class ShutdownCloser extends Thread { + + private ShutdownCloser() { + super("Jython Shutdown Closer"); + } + + @Override + public synchronized void run() { + if (resourceClosers == null) { + // resourceClosers can be null in some strange cases + return; + } + for (Callable callable : resourceClosers) { + try { + callable.call(); // side effect of being removed from this set + } catch (Exception e) { + // continue - nothing we can do now! + } + } + resourceClosers.clear(); + } + } + + } } + class PySystemStateFunctions extends PyBuiltinFunctionSet { PySystemStateFunctions(String name, int index, int minargs, int maxargs) { Modified: trunk/jython/src/org/python/core/PyType.java =================================================================== --- trunk/jython/src/org/python/core/PyType.java 2010-08-27 13:20:44 UTC (rev 7108) +++ trunk/jython/src/org/python/core/PyType.java 2010-08-28 03:52:43 UTC (rev 7109) @@ -91,7 +91,7 @@ /** The number of __slots__ defined. */ private int numSlots; - private ReferenceQueue<PyType> subclasses_refq = new ReferenceQueue<PyType>(); + private transient ReferenceQueue<PyType> subclasses_refq = new ReferenceQueue<PyType>(); private Set<WeakReference<PyType>> subclasses = Generic.set(); /** Global mro cache. */ Modified: trunk/jython/src/org/python/core/ThreadStateMapping.java =================================================================== --- trunk/jython/src/org/python/core/ThreadStateMapping.java 2010-08-27 13:20:44 UTC (rev 7108) +++ trunk/jython/src/org/python/core/ThreadStateMapping.java 2010-08-28 03:52:43 UTC (rev 7109) @@ -1,26 +1,41 @@ package org.python.core; class ThreadStateMapping { - private static final ThreadLocal<ThreadState> cachedThreadState = new ThreadLocal<ThreadState>(); + private static final ThreadLocal<ThreadState[]> cachedThreadState = + new ThreadLocal<ThreadState[]>() { + @Override + protected ThreadState[] initialValue() { + return new ThreadState[1]; + } + }; public ThreadState getThreadState(PySystemState newSystemState) { - ThreadState ts = cachedThreadState.get(); + + // usual double checked locking pattern + ThreadState ts = cachedThreadState.get()[0]; + if (ts != null) { return ts; } + synchronized(this) { + ThreadState[] threadLocal = cachedThreadState.get(); + if(threadLocal[0] != null) + return (ThreadState)threadLocal[0]; - Thread t = Thread.currentThread(); - if (newSystemState == null) { - Py.writeDebug("threadstate", "no current system state"); - if (Py.defaultSystemState == null) { - PySystemState.initialize(); + Thread t = Thread.currentThread(); + if (newSystemState == null) { + Py.writeDebug("threadstate", "no current system state"); + if (Py.defaultSystemState == null) { + PySystemState.initialize(); + } + newSystemState = Py.defaultSystemState; } - newSystemState = Py.defaultSystemState; + + ts = new ThreadState(t, newSystemState); + + newSystemState.registerThreadState(threadLocal, ts); + return ts; } - - ts = new ThreadState(t, newSystemState); - cachedThreadState.set(ts); - return ts; } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-08-25 01:40:52
|
Revision: 7104 http://jython.svn.sourceforge.net/jython/?rev=7104&view=rev Author: zyasoft Date: 2010-08-25 01:40:46 +0000 (Wed, 25 Aug 2010) Log Message: ----------- Now test that defaultdict's __missing__/default_factory is computed atomically. Modified Paths: -------------- trunk/jython/Lib/test/test_defaultdict_jy.py Modified: trunk/jython/Lib/test/test_defaultdict_jy.py =================================================================== --- trunk/jython/Lib/test/test_defaultdict_jy.py 2010-08-25 01:38:26 UTC (rev 7103) +++ trunk/jython/Lib/test/test_defaultdict_jy.py 2010-08-25 01:40:46 UTC (rev 7104) @@ -3,10 +3,15 @@ Made for Jython. """ import pickle +import time +import threading import unittest from collections import defaultdict from test import test_support +from random import randint +from java.util.concurrent.atomic import AtomicInteger + class PickleTestCase(unittest.TestCase): def test_pickle(self): @@ -15,8 +20,63 @@ self.assertEqual(pickle.loads(pickle.dumps(d, proto)), d) +# TODO push into test_support or some other common module - run_threads +# is originally from test_list_jy.py + +class ThreadSafetyTestCase(unittest.TestCase): + + def run_threads(self, f, num=10): + threads = [] + for i in xrange(num): + t = threading.Thread(target=f) + t.start() + threads.append(t) + timeout = 10. # be especially generous + for t in threads: + t.join(timeout) + timeout = 0. + for t in threads: + self.assertFalse(t.isAlive()) + + def test_inc_dec(self): + + class Counter(object): + def __init__(self): + self.atomic = AtomicInteger() + # waiting is important here to ensure that + # defaultdict factories can step on each other + time.sleep(0.001) + + def decrementAndGet(self): + return self.atomic.decrementAndGet() + + def incrementAndGet(self): + return self.atomic.incrementAndGet() + + def get(self): + return self.atomic.get() + + def __repr__(self): + return "Counter<%s>" % (self.atomic.get()) + + counters = defaultdict(Counter) + size = 17 + + def tester(): + for i in xrange(1000): + j = (i + randint(0, size)) % size + counters[j].decrementAndGet() + time.sleep(0.0001) + counters[j].incrementAndGet() + + self.run_threads(tester, 20) + + for i in xrange(size): + self.assertEqual(counters[i].get(), 0, counters) + + def test_main(): - test_support.run_unittest(PickleTestCase) + test_support.run_unittest(PickleTestCase, ThreadSafetyTestCase) if __name__ == '__main__': This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-08-25 01:38:34
|
Revision: 7103 http://jython.svn.sourceforge.net/jython/?rev=7103&view=rev Author: zyasoft Date: 2010-08-25 01:38:26 +0000 (Wed, 25 Aug 2010) Log Message: ----------- Missing file (test of pep328 support) from r7102 Added Paths: ----------- trunk/jython/Lib/test/test_import_pep328.py Added: trunk/jython/Lib/test/test_import_pep328.py =================================================================== --- trunk/jython/Lib/test/test_import_pep328.py (rev 0) +++ trunk/jython/Lib/test/test_import_pep328.py 2010-08-25 01:38:26 UTC (rev 7103) @@ -0,0 +1,419 @@ +# test_import_pep328 - Test various aspects of import +# +# Copyright (c) 2010 by science+computing ag +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at# +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Licensed to PSF under a Contributor Agreement. +# See http://www.python.org/2.4/license for licensing details. + +''' +Import related tests: + +- Test how 'import ...' and 'from ... import ...' invoke the + '__import__' function. +- Test the module name resolution of the '__import__'-function. + +The reference is C-python. +''' +import unittest +import exceptions +import imp +import __builtin__ +import sys +import types + +origImport = __import__ + +class TestImportStatementError(exceptions.ImportError): + def __init__(self, args): + names = ['name', 'globals', 'locals', 'fromlist', 'level'] + self.len = len(args) + for a in args: + n = names.pop(0) + setattr(self, n, a) + for n in names: + setattr(self, n, None) + + +class TestImportStatement(unittest.TestCase): + """Test the 'import' and 'from ... import' statements + + This class tests, how the compiler calls the + '__import__'-function for various forms of the + 'import' and 'from ... import' statements. + """ + + AI = "from __future__ import absolute_import ;" + + def importFunction(*args): + if args[0] == '__future__': + return origImport(*args) + raise TestImportStatementError(args) + importFunction = staticmethod(importFunction) + + def setUp(self): + __builtin__.__import__ = self.importFunction + + def tearDown(self): + __builtin__.__import__ = origImport + + def runImport(self, statement): + l = {} + g = {} + try: + exec statement in g, l + except TestImportStatementError,e: + self.assert_(e.globals is g, "globals is changed") + self.assert_(e.locals is l, "locals is changed") + return e + self.fail("Expected a TestImportStatementError") + + def testFromDotsOnly(self): + dots = '' + for i in range(1,10): + dots += '.' + a = self.runImport("from %s import (A,B)" % (dots,)) + self.assertEqual(a.len, 5) + self.assertEqual(a.name, "") + self.assertEqual(a.level, i) + self.assertEqual(a.fromlist, ('A', 'B')) + + def testFromDotsOnlyAs(self): + dots = '' + for i in range(1,10): + dots += '.' + a = self.runImport("from %s import A as B" % (dots,)) + self.assertEqual(a.len, 5) + self.assertEqual(a.name, "") + self.assertEqual(a.fromlist, ('A',)) + self.assertEqual(a.level, i) + + def testFromDotsAndName(self): + dots = '' + for i in range(1,10): + dots += '.' + a = self.runImport("from %sX import A" % (dots,)) + self.assertEqual(a.len, 5) + self.assertEqual(a.name, "X") + self.assertEqual(a.fromlist, ('A',)) + self.assertEqual(a.level, i) + + def testFromDotsAndDotedName(self): + dots = '' + for i in range(1,10): + dots += '.' + a = self.runImport("from %sX.Y import A" % (dots,)) + self.assertEqual(a.len, 5) + self.assertEqual(a.name, "X.Y") + self.assertEqual(a.fromlist, ('A',)) + self.assertEqual(a.level, i) + + def testAbsoluteFromDotedNameAs(self): + a = self.runImport(self.AI + "from X.Y import A as B") + self.assertEqual(a.len, 5) + self.assertEqual(a.name, "X.Y") + self.assertEqual(a.fromlist, ('A',)) + self.assertEqual(a.level, 0) + + def testRelativeOrAbsoluteFromDotedNameAs(self): + a = self.runImport("from X.Y import A as B") + self.assertEqual(a.name, "X.Y") + self.assertEqual(a.fromlist, ('A',)) + self.assertEqual(a.len, 4) + + def testAbsoluteFromDotedNameAll(self): + a = self.runImport(self.AI + "from X.Y import *") + self.assertEqual(a.len, 5) + self.assertEqual(a.name, "X.Y") + self.assertEqual(a.fromlist, ('*',)) + self.assertEqual(a.level, 0) + + def testRelativeOrAbsoluteFromDotedNameAll(self): + a = self.runImport("from X.Y import *") + self.assertEqual(a.name, "X.Y") + self.assertEqual(a.fromlist, ('*',)) + self.assertEqual(a.len, 4) + + def testAbsoluteImportName(self): + a = self.runImport(self.AI + "import X") + self.assertEqual(a.len, 5) + self.assertEqual(a.name, "X") + self.assertEqual(a.fromlist, None) + self.assertEqual(a.level, 0) + + def testAbsoluteImportDotedName(self): + a = self.runImport(self.AI + "import X.Y") + self.assertEqual(a.len, 5) + self.assertEqual(a.name, "X.Y") + self.assertEqual(a.fromlist, None) + self.assertEqual(a.level, 0) + + def testRelativeOrAbsoluteImportName(self): + a = self.runImport("import X") + self.assertEqual(a.name, "X") + self.assertEqual(a.fromlist, None) + self.assertEqual(a.len, 4) + + def testRelativeOrAbsoluteImportDotedName(self): + a = self.runImport("import X.Y") + self.assertEqual(a.name, "X.Y") + self.assertEqual(a.fromlist, None) + self.assertEqual(a.len, 4) + + def testAbsoluteImportDotedNameAs(self): + a = self.runImport(self.AI + "import X.Y as Z") + self.assertEqual(a.len, 5) + self.assertEqual(a.name, "X.Y") + self.assertEqual(a.fromlist, None) + self.assertEqual(a.level, 0) + + +class TestImportFunctionError(exceptions.ImportError): + pass + +class TestImportFunction(unittest.TestCase): + """Test the '__import__' function + + This class tests, how the '__import__'-function + resolves module names. It uses the 'meta_path' hook, + to intercept the actual module loading. + + Module Structure: + + Top + \---- X package + | \-- Y package + | | \-- Z1 module + | | \-- Z2 module + | \-- Y2 package + \---- X2 module + + """ + + nameX = "TestImportFunctionX" + + + def setUp(self): + self.modX = imp.new_module(self.nameX) + self.modX.__path__ = ['X'] + + self.modX2 = imp.new_module(self.nameX+"2") + self.modY = imp.new_module(self.nameX+".Y") + self.modY.__path__ = ['X/Y'] + self.modY2 = imp.new_module(self.nameX+".Y2") + self.modY2.__path__ = ['X/Y'] + self.modZ1 = imp.new_module(self.nameX+".Y.Z1") + self.modZ2 = imp.new_module(self.nameX+".Y.Z2") + + self.expected = "something_completely_different" + sys.meta_path.insert(0, self) + + def tearDown(self): + try: + sys.meta_path.remove(self) + except ValueError: + pass + for k in sys.modules.keys(): + if k.startswith(self.nameX): + del sys.modules[k] + + def importX(self): + sys.modules[self.modX.__name__] = self.modX + def importX2(self): + sys.modules[self.modX2.__name__] = self.modX2 + def importY(self): + self.importX() + sys.modules[self.modY.__name__] = self.modY + self.modX.Y = self.modY + def importY2(self): + self.importX() + sys.modules[self.modY2.__name__] = self.modY2 + self.modX.Y2 = self.modY2 + def importZ1(self): + self.importY() + sys.modules[self.modZ1.__name__] = self.modZ1 + self.modY.Z1 = self.modZ1 + def top(self): + if sys.modules.has_key("__main__"): + return sys.modules["__main__"].__dict__ + return globals() + + + def find_module(self, fullname, path=None): + if self.expected and self.expected != fullname: + return None + self.fullname = fullname + self.path = path + return self + + def load_module(self, fullname): + self.assertEqual(fullname, self.fullname) + raise TestImportFunctionError() + + def runImport(self, expected, name, globals, fromlist=None, level=None): + self.expected = expected + if isinstance(globals, types.ModuleType): + globals = globals.__dict__ + try: + if level is not None: + __import__(name, globals, None, fromlist, level) + else: + __import__(name, globals, None, fromlist) + except TestImportFunctionError: + return + self.fail("Expected a TestImportFunctionError") + + def testRelativeOrAbsolute_top_X2_1(self): + self.runImport(None, self.modX2.__name__, self.top()) + self.assertEqual(self.fullname, self.modX2.__name__) + self.assertEqual(self.path, None) + + def testRelativeOrAbsolute_top_X2_2(self): + self.runImport(None, self.modX2.__name__, self.top(), None, -1) + self.assertEqual(self.fullname, self.modX2.__name__) + self.assertEqual(self.path, None) + + + def testRelativeOrAbsolute_top_Y_1(self): + self.importX() + self.runImport(None, self.modY.__name__, self.top()) + self.assertEqual(self.fullname, self.modY.__name__) + self.assertEqual(self.path, ['X']) + + def testRelativeOrAbsolute_top_Y_2(self): + self.importX() + self.runImport(None, self.modY.__name__, self.top(), None, -1) + self.assertEqual(self.fullname, self.modY.__name__) + self.assertEqual(self.path, ['X']) + + + def testAbsolute_top_X2(self): + self.runImport(None, self.modX2.__name__, globals(), None, 0) + self.assertEqual(self.fullname, self.modX2.__name__) + self.assertEqual(self.path, None) + + def testAbsolute_top_Y(self): + self.importX() + self.runImport(None, self.modY.__name__, globals(), None, 0) + self.assertEqual(self.fullname, self.modY.__name__) + self.assertEqual(self.path, ['X']) + + # Relative case + def testRelativeOrAbsolute_X_X2_rel1(self): + self.importX() + self.runImport(None, self.modX2.__name__, self.modX) + self.assertEqual(self.fullname, self.nameX + "." + self.modX2.__name__) + self.assertEqual(self.path, ['X']) + + def testRelativeOrAbsolute_X_X2_rel2(self): + self.importX() + self.runImport(None, self.modX2.__name__, self.modX, None, -1) + self.assertEqual(self.path, ['X']) + self.assertEqual(self.fullname, self.nameX + "." + self.modX2.__name__) + + # Absolute case + def testRelativeOrAbsolute_X_X2_abs1(self): + self.importX() + self.runImport(self.modX2.__name__, self.modX2.__name__, self.modX) + self.assertEqual(self.fullname, self.modX2.__name__) + self.assertEqual(self.path, None) + + def testRelativeOrAbsolute_X_X2_abs2(self): + self.importX() + self.runImport(self.modX2.__name__, self.modX2.__name__, self.modX, None, -1) + self.assertEqual(self.path, None) + self.assertEqual(self.fullname, self.modX2.__name__) + + def testAbsolute_X_X2(self): + self.importX() + self.runImport(None, self.modX2.__name__, self.modX, None, 0) + self.assertEqual(self.fullname, self.modX2.__name__) + self.assertEqual(self.path, None) + + def testAbsolute_X_Y(self): + self.importX() + self.runImport(None, self.modY.__name__, self.modX, None, 0) + self.assertEqual(self.fullname, self.modY.__name__) + self.assertEqual(self.path, ['X']) + + def testRelative_Z1_Z2(self): + self.importZ1() + self.runImport(None, "", self.modZ1, ['Z2'], 1) + self.assertEqual(self.fullname, self.modZ2.__name__) + self.assertEqual(self.path, ['X/Y']) + + def testRelative_Z1_Y2(self): + self.importZ1() + self.runImport(None, "", self.modZ1, ["Y2"], 2) + self.assertEqual(self.fullname, self.modX.__name__+".Y2") + self.assertEqual(self.path, ['X']) + + def testRelative_Z1_X2(self): + # """beyond top level""" + self.importZ1() + self.assertRaises(ValueError, self.runImport, None, "", self.modZ1, [self.modX2.__name__], 3) + + def testRelative_X2_X(self): + # """not a package""" + self.importX2() + self.assertRaises(ValueError, self.runImport, None, "", self.modX2, [self.modX.__name__], 1) + + def testRelative_X2_Y(self): + # """not a package""" + self.importX2() + self.importX() + self.assertRaises(ValueError, self.runImport, None, self.modX.__name__, self.modX2, ["Y"], 1) + + def testRelative_X_Z1_1(self): + self.importX() + self.runImport(None, "Y", self.modX, ['Z1'], 1) + self.assertEqual(self.fullname, self.modY.__name__) + self.assertEqual(self.path, ['X']) + + def testRelative_X_Z1_2(self): + self.importY() + self.runImport(None, "Y", self.modX, ['Z1'], 1) + self.assertEqual(self.fullname, self.modZ1.__name__) + self.assertEqual(self.path, ['X/Y']) + + def testRelative_Y_Z1(self): + self.importY() + self.runImport(None, "Z1", self.modY, ['A', 'B'], 1) + self.assertEqual(self.fullname, self.modZ1.__name__) + self.assertEqual(self.path, ['X/Y']) + + def testRelative_Y2_Z1_1(self): + self.importY2() + self.runImport(None, "Y", self.modY2, ['Z1'], 2) + self.assertEqual(self.fullname, self.modY.__name__) + self.assertEqual(self.path, ['X']) + + def testRelative_Y2_Z1_2(self): + self.importY2() + self.importY() + self.runImport(None, "Y", self.modY2, ['Z1'], 2) + self.assertEqual(self.fullname, self.modZ1.__name__) + self.assertEqual(self.path, ['X/Y']) + +try: + from test import test_support +except ImportError: + test_main = unittest.main +else: + def test_main(): + test_support.run_unittest(TestImportStatement, + TestImportFunction) + +if __name__ == '__main__': + test_main() 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-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-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-21 03:42:56
|
Revision: 7099 http://jython.svn.sourceforge.net/jython/?rev=7099&view=rev Author: zyasoft Date: 2010-08-21 03:42:48 +0000 (Sat, 21 Aug 2010) Log Message: ----------- Standard refactoring of some core Python types so that their implementation (including subclasses) do not access the underlying backing field, but uses an accessor. More fixes for #1645. In addition, there's support for defaultdict providing atomic construction of values for associated keys, using Guava MapMaker's makeComputingMap. This is a rather cool example of the additional abstraction provided by the refactoring (namely PyDictionary#getMap). Some tests are needed to demo how sweet this really is :) Note that we cannot, given our constructors calling super in a chain, readily remove extraneous fields that are not used, either through the use of abstract classes to share implementation; or violate safe publication by calling it later, outside the constructor. (There are in fact tests that fail without safe publication.) But this is a minor concern. Modified Paths: -------------- trunk/jython/src/org/python/core/FilelikeInputStream.java trunk/jython/src/org/python/core/JavaImportHelper.java trunk/jython/src/org/python/core/PyDictionary.java trunk/jython/src/org/python/core/PyFile.java trunk/jython/src/org/python/core/PyFileReader.java trunk/jython/src/org/python/core/PyFileWriter.java trunk/jython/src/org/python/core/PyFloat.java trunk/jython/src/org/python/core/PyInteger.java trunk/jython/src/org/python/core/PyObject.java trunk/jython/src/org/python/core/PyString.java trunk/jython/src/org/python/core/PyUnicode.java trunk/jython/src/org/python/core/StdoutWrapper.java trunk/jython/src/org/python/core/__builtin__.java trunk/jython/src/org/python/core/codecs.java trunk/jython/src/org/python/modules/_collections/PyDefaultDict.java Modified: trunk/jython/src/org/python/core/FilelikeInputStream.java =================================================================== --- trunk/jython/src/org/python/core/FilelikeInputStream.java 2010-08-21 03:30:41 UTC (rev 7098) +++ trunk/jython/src/org/python/core/FilelikeInputStream.java 2010-08-21 03:42:48 UTC (rev 7099) @@ -31,8 +31,8 @@ } else if(len == 0) { return 0; } - String result = ((PyString)filelike.__getattr__("read") - .__call__(new PyInteger(len))).string; + String result = ((PyString) filelike.__getattr__("read") + .__call__(new PyInteger(len))).getString(); if(result.length() == 0) { return -1; } Modified: trunk/jython/src/org/python/core/JavaImportHelper.java =================================================================== --- trunk/jython/src/org/python/core/JavaImportHelper.java 2010-08-21 03:30:41 UTC (rev 7098) +++ trunk/jython/src/org/python/core/JavaImportHelper.java 2010-08-21 03:42:48 UTC (rev 7099) @@ -117,7 +117,7 @@ while (iterator.hasNext()) { Object obj = iterator.next(); if (obj instanceof PyString) { - obj = ((PyString)obj).string; + obj = ((PyString) obj).getString(); } if (obj instanceof String) { String fromName = (String) obj; Modified: trunk/jython/src/org/python/core/PyDictionary.java =================================================================== --- trunk/jython/src/org/python/core/PyDictionary.java 2010-08-21 03:30:41 UTC (rev 7098) +++ trunk/jython/src/org/python/core/PyDictionary.java 2010-08-21 03:42:48 UTC (rev 7099) @@ -31,8 +31,12 @@ public static final PyType TYPE = PyType.fromClass(PyDictionary.class); - protected final ConcurrentMap<PyObject, PyObject> table; + private final ConcurrentMap<PyObject, PyObject> map; + public ConcurrentMap<PyObject, PyObject> getMap() { + return map; + } + /** * Create an empty dictionary. */ @@ -45,7 +49,7 @@ */ public PyDictionary(PyType type, int capacity) { super(type); - table = new ConcurrentHashMap<PyObject, PyObject>(capacity, Generic.CHM_LOAD_FACTOR, + map = new ConcurrentHashMap<PyObject, PyObject>(capacity, Generic.CHM_LOAD_FACTOR, Generic.CHM_CONCURRENCY_LEVEL); } @@ -54,7 +58,7 @@ */ public PyDictionary(PyType type) { super(type); - table = Generic.concurrentMap(); + map = Generic.concurrentMap(); } /** @@ -65,14 +69,27 @@ } /** - * Create a new derived dictionary which is based on the given map. + * Create a new dictionary which is populated with entries the given map. */ public PyDictionary(PyType type, Map<PyObject, PyObject> map) { this(type, Math.max((int) (map.size() / Generic.CHM_LOAD_FACTOR) + 1, Generic.CHM_INITIAL_CAPACITY)); - table.putAll(map); + this.map.putAll(map); } + /** + * Create a new dictionary without initializing table. Used for dictionary + * factories, with different backing maps, at the cost that it prevents us from making table be final. + */ + // TODO we may want to revisit this API, but our chain calling of super makes this tough + protected PyDictionary(PyType type, boolean initializeBacking) { + super(type); + if (initializeBacking) { + map = Generic.concurrentMap(); + } else { + map = null; // for later initialization + } + } /** * Create a new dictionary with the element as content. @@ -84,7 +101,7 @@ public PyDictionary(PyObject elements[]) { this(); for (int i = 0; i < elements.length; i += 2) { - table.put(elements[i], elements[i + 1]); + map.put(elements[i], elements[i + 1]); } } @@ -103,7 +120,7 @@ } @ExposedClassMethod(defaults = "Py.None", doc = BuiltinDocs.dict_fromkeys_doc) - final static PyObject dict_fromkeys(PyType type, PyObject keys, PyObject value) { + static PyObject dict_fromkeys(PyType type, PyObject keys, PyObject value) { PyObject d = type.__call__(); for (PyObject o : keys.asIterable()) { d.__setitem__(o, value); @@ -118,12 +135,12 @@ @ExposedMethod(doc = BuiltinDocs.dict___len___doc) final int dict___len__() { - return table.size(); + return getMap().size(); } @Override public boolean __nonzero__() { - return table.size() != 0; + return getMap().size() != 0; } @Override @@ -133,12 +150,12 @@ @Override public PyObject __finditem__(PyObject key) { - return table.get(key); + return getMap().get(key); } @ExposedMethod(doc = BuiltinDocs.dict___getitem___doc) protected final PyObject dict___getitem__(PyObject key) { - PyObject result = table.get(key); + PyObject result = getMap().get(key); if (result != null) { return result; } @@ -161,7 +178,7 @@ @ExposedMethod(doc = BuiltinDocs.dict___setitem___doc) final void dict___setitem__(PyObject key, PyObject value) { - table.put(key, value); + getMap().put(key, value); } @Override @@ -171,7 +188,7 @@ @ExposedMethod(doc = BuiltinDocs.dict___delitem___doc) final void dict___delitem__(PyObject key) { - Object ret = table.remove(key); + Object ret = getMap().remove(key); if (ret == null) { throw Py.KeyError(key.toString()); } @@ -200,7 +217,7 @@ } StringBuilder buf = new StringBuilder("{"); - for (Entry<PyObject, PyObject> entry : table.entrySet()) { + for (Entry<PyObject, PyObject> entry : getMap().entrySet()) { buf.append((entry.getKey()).__repr__().toString()); buf.append(": "); buf.append((entry.getValue()).__repr__().toString()); @@ -229,8 +246,8 @@ return null; } PyDictionary other = (PyDictionary)otherObj; - int an = table.size(); - int bn = other.table.size(); + int an = getMap().size(); + int bn = other.getMap().size(); if (an != bn) { return Py.False; } @@ -314,8 +331,8 @@ return -2; } PyDictionary other = (PyDictionary)otherObj; - int an = table.size(); - int bn = other.table.size(); + int an = getMap().size(); + int bn = other.getMap().size(); if (an < bn) { return -1; } @@ -364,7 +381,7 @@ @ExposedMethod(doc = BuiltinDocs.dict_has_key_doc) final boolean dict_has_key(PyObject key) { - return table.containsKey(key); + return getMap().containsKey(key); } @Override @@ -390,7 +407,7 @@ @ExposedMethod(defaults = "Py.None", doc = BuiltinDocs.dict_get_doc) final PyObject dict_get(PyObject key, PyObject defaultObj) { - PyObject o = table.get(key); + PyObject o = getMap().get(key); return o == null ? defaultObj : o; } @@ -413,7 +430,7 @@ @ExposedMethod(doc = BuiltinDocs.dict_copy_doc) final PyDictionary dict_copy() { - return new PyDictionary(table); // no need to clone() + return new PyDictionary(getMap()); // no need to clone() } /** @@ -425,7 +442,7 @@ @ExposedMethod(doc = BuiltinDocs.dict_clear_doc) final void dict_clear() { - table.clear(); + getMap().clear(); } /** @@ -479,7 +496,7 @@ */ private void merge(PyObject other) { if (other instanceof PyDictionary) { - table.putAll(((PyDictionary)other).table); + getMap().putAll(((PyDictionary) other).getMap()); } else if (other instanceof PyStringMap) { mergeFromKeys(other, ((PyStringMap)other).keys()); } else { @@ -552,14 +569,14 @@ @ExposedMethod(defaults = "Py.None", doc = BuiltinDocs.dict_setdefault_doc) final PyObject dict_setdefault(PyObject key, PyObject failobj) { - PyObject oldValue = table.putIfAbsent(key, failobj); + PyObject oldValue = getMap().putIfAbsent(key, failobj); return oldValue == null ? failobj : oldValue; } // XXX: needs __doc__ but CPython does not define setifabsent @ExposedMethod(defaults = "Py.None") final PyObject dict_setifabsent(PyObject key, PyObject failobj) { - PyObject oldValue = table.putIfAbsent(key, failobj); + PyObject oldValue = getMap().putIfAbsent(key, failobj); return oldValue == null ? Py.None : oldValue; } @@ -582,13 +599,13 @@ @ExposedMethod(defaults = "null", doc = BuiltinDocs.dict_pop_doc) final PyObject dict_pop(PyObject key, PyObject defaultValue) { - if (!table.containsKey(key)) { + if (!map.containsKey(key)) { if (defaultValue == null) { throw Py.KeyError("popitem(): dictionary is empty"); } return defaultValue; } - return table.remove(key); + return getMap().remove(key); } @@ -602,7 +619,7 @@ @ExposedMethod(doc = BuiltinDocs.dict_popitem_doc) final PyObject dict_popitem() { - Iterator<Entry<PyObject, PyObject>> it = table.entrySet().iterator(); + Iterator<Entry<PyObject, PyObject>> it = getMap().entrySet().iterator(); if (!it.hasNext()) { throw Py.KeyError("popitem(): dictionary is empty"); } @@ -622,8 +639,8 @@ @ExposedMethod(doc = BuiltinDocs.dict_items_doc) final PyList dict_items() { - List<PyObject> list = new ArrayList<PyObject>(table.size()); - for (Entry<PyObject, PyObject> entry : table.entrySet()) { + List<PyObject> list = new ArrayList<PyObject>(getMap().size()); + for (Entry<PyObject, PyObject> entry : getMap().entrySet()) { list.add(new PyTuple(entry.getKey(), entry.getValue())); } return PyList.fromList(list); @@ -638,12 +655,12 @@ @ExposedMethod(doc = BuiltinDocs.dict_keys_doc) final PyList dict_keys() { - return PyList.fromList(new ArrayList<PyObject>(table.keySet())); + return PyList.fromList(new ArrayList<PyObject>(getMap().keySet())); } @ExposedMethod(doc = BuiltinDocs.dict_values_doc) final PyList dict_values() { - return PyList.fromList(new ArrayList<PyObject>(table.values())); + return PyList.fromList(new ArrayList<PyObject>(getMap().values())); } /** @@ -655,7 +672,7 @@ @ExposedMethod(doc = BuiltinDocs.dict_iteritems_doc) final PyObject dict_iteritems() { - return new ItemsIter(table.entrySet()); + return new ItemsIter(getMap().entrySet()); } /** @@ -667,7 +684,7 @@ @ExposedMethod(doc = BuiltinDocs.dict_iterkeys_doc) final PyObject dict_iterkeys() { - return new ValuesIter(table.keySet()); + return new ValuesIter(getMap().keySet()); } /** @@ -679,7 +696,7 @@ @ExposedMethod(doc = BuiltinDocs.dict_itervalues_doc) final PyObject dict_itervalues() { - return new ValuesIter(table.values()); + return new ValuesIter(getMap().values()); } @Override @@ -687,6 +704,21 @@ return dict___hash__(); } + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final PyDictionary other = (PyDictionary) obj; + if (this.map != other.map && (this.map == null || !this.map.equals(other.map))) { + return false; + } + return true; + } + @ExposedMethod(doc = BuiltinDocs.dict___hash___doc) final int dict___hash__() { throw Py.TypeError(String.format("unhashable type: '%.200s'", getType().fastGetName())); @@ -715,7 +747,7 @@ @Override public PyObject __iternext__() { - if (table.size() != size) { + if (getMap().size() != size) { throw Py.RuntimeError("dictionary changed size during iteration"); } if (!iterator.hasNext()) { @@ -738,7 +770,7 @@ @Override public PyObject __iternext__() { - if (table.size() != size) { + if (getMap().size() != size) { throw Py.RuntimeError("dictionary changed size during iteration"); } if (!iterator.hasNext()) { @@ -757,81 +789,81 @@ */ /** @see java.util.Map#entrySet() */ public Set entrySet() { - return new PyMapEntrySet(table.entrySet()); + return new PyMapEntrySet(getMap().entrySet()); } /** @see java.util.Map#keySet() */ public Set keySet() { - return new PyMapKeyValSet(table.keySet()); + return new PyMapKeyValSet(getMap().keySet()); } /** @see java.util.Map#values() */ public Collection values() { - return new PyMapKeyValSet(table.values()); + return new PyMapKeyValSet(getMap().values()); } /** @see java.util.Map#putAll(Map map) */ public void putAll(Map map) { for (Object o : map.entrySet()) { Entry entry = (Entry)o; - table.put(Py.java2py(entry.getKey()), Py.java2py(entry.getValue())); + getMap().put(Py.java2py(entry.getKey()), Py.java2py(entry.getValue())); } } /** @see java.util.Map#remove(Object key) */ public Object remove(Object key) { - return tojava(table.remove(Py.java2py(key))); + return tojava(getMap().remove(Py.java2py(key))); } /** @see java.util.Map#put(Object key, Object value) */ public Object put(Object key, Object value) { - return tojava(table.put(Py.java2py(key), Py.java2py(value))); + return tojava(getMap().put(Py.java2py(key), Py.java2py(value))); } /** @see java.util.Map#get(Object key) */ public Object get(Object key) { - return tojava(table.get(Py.java2py(key))); + return tojava(getMap().get(Py.java2py(key))); } /** @see java.util.Map#containsValue(Object key) */ public boolean containsValue(Object value) { - return table.containsValue(Py.java2py(value)); + return getMap().containsValue(Py.java2py(value)); } /** @see java.util.Map#containsValue(Object key) */ public boolean containsKey(Object key) { - return table.containsKey(Py.java2py(key)); + return getMap().containsKey(Py.java2py(key)); } /** @see java.util.Map#isEmpty() */ public boolean isEmpty() { - return table.isEmpty(); + return getMap().isEmpty(); } /** @see java.util.Map#size() */ public int size() { - return table.size(); + return getMap().size(); } /** Convert return values to java objects */ - final static Object tojava(Object val) { + static Object tojava(Object val) { return val == null ? null : ((PyObject)val).__tojava__(Object.class); } public Object putIfAbsent(Object key, Object value) { - return tojava(table.putIfAbsent(Py.java2py(key), Py.java2py(value))); + return tojava(getMap().putIfAbsent(Py.java2py(key), Py.java2py(value))); } public boolean remove(Object key, Object value) { - return table.remove(Py.java2py(key), Py.java2py(value)); + return getMap().remove(Py.java2py(key), Py.java2py(value)); } public boolean replace(Object key, Object oldValue, Object newValue) { - return table.replace(Py.java2py(key), Py.java2py(oldValue), Py.java2py(newValue)); + return getMap().replace(Py.java2py(key), Py.java2py(oldValue), Py.java2py(newValue)); } public Object replace(Object key, Object value) { - return tojava(table.replace(Py.java2py(key), Py.java2py(value))); + return tojava(getMap().replace(Py.java2py(key), Py.java2py(value))); } } @@ -926,6 +958,11 @@ return new SimpleEntry(key, value); } + @Override + public int hashCode() { + return ((key == null) ? 0 : key.hashCode()) ^ ((value == null) ? 0 : value.hashCode()); + } + } /** Modified: trunk/jython/src/org/python/core/PyFile.java =================================================================== --- trunk/jython/src/org/python/core/PyFile.java 2010-08-21 03:30:41 UTC (rev 7098) +++ trunk/jython/src/org/python/core/PyFile.java 2010-08-21 03:42:48 UTC (rev 7099) @@ -389,7 +389,7 @@ if (obj instanceof PyUnicode) { return ((PyUnicode)obj).encode(); } else if (obj instanceof PyString) { - return ((PyString)obj).string; + return ((PyString) obj).getString(); } else if (binary && obj instanceof PyArray) { return ((PyArray)obj).tostring(); } Modified: trunk/jython/src/org/python/core/PyFileReader.java =================================================================== --- trunk/jython/src/org/python/core/PyFileReader.java 2010-08-21 03:30:41 UTC (rev 7098) +++ trunk/jython/src/org/python/core/PyFileReader.java 2010-08-21 03:42:48 UTC (rev 7099) @@ -155,7 +155,7 @@ int size = 0; do { final PyString line = readline(-1); - int len = line.string.length(); + int len = line.getString().length(); if (len == 0) { // EOF break; Modified: trunk/jython/src/org/python/core/PyFileWriter.java =================================================================== --- trunk/jython/src/org/python/core/PyFileWriter.java 2010-08-21 03:30:41 UTC (rev 7098) +++ trunk/jython/src/org/python/core/PyFileWriter.java 2010-08-21 03:42:48 UTC (rev 7099) @@ -51,9 +51,9 @@ public void write(PyObject o) { if (o instanceof PyUnicode) { - write(((PyUnicode) o).string); + write(((PyUnicode) o).getString()); } else if (o instanceof PyString) { - write(((PyString) o).string); + write(((PyString) o).getString()); } else { throw Py.TypeError("write requires a string as its argument"); } Modified: trunk/jython/src/org/python/core/PyFloat.java =================================================================== --- trunk/jython/src/org/python/core/PyFloat.java 2010-08-21 03:30:41 UTC (rev 7098) +++ trunk/jython/src/org/python/core/PyFloat.java 2010-08-21 03:42:48 UTC (rev 7099) @@ -268,11 +268,11 @@ } } - private static final boolean canCoerce(PyObject other) { + private static boolean canCoerce(PyObject other) { return other instanceof PyFloat || other instanceof PyInteger || other instanceof PyLong; } - private static final double coerce(PyObject other) { + private static double coerce(PyObject other) { if (other instanceof PyFloat) { return ((PyFloat) other).getValue(); } else if (other instanceof PyInteger) { Modified: trunk/jython/src/org/python/core/PyInteger.java =================================================================== --- trunk/jython/src/org/python/core/PyInteger.java 2010-08-21 03:30:41 UTC (rev 7098) +++ trunk/jython/src/org/python/core/PyInteger.java 2010-08-21 03:42:48 UTC (rev 7099) @@ -33,7 +33,7 @@ @Deprecated public static final BigInteger maxInt = MAX_INT; - private int value; + private final int value; public PyInteger(PyType subType, int v) { super(subType); Modified: trunk/jython/src/org/python/core/PyObject.java =================================================================== --- trunk/jython/src/org/python/core/PyObject.java 2010-08-21 03:30:41 UTC (rev 7098) +++ trunk/jython/src/org/python/core/PyObject.java 2010-08-21 03:42:48 UTC (rev 7099) @@ -26,7 +26,7 @@ public static final PyType TYPE = PyType.fromClass(PyObject.class); /** The type of this object. */ - PyType objtype; + protected PyType objtype; /** * An underlying Java instance that this object is wrapping or is a subclass Modified: trunk/jython/src/org/python/core/PyString.java =================================================================== --- trunk/jython/src/org/python/core/PyString.java 2010-08-21 03:30:41 UTC (rev 7098) +++ trunk/jython/src/org/python/core/PyString.java 2010-08-21 03:42:48 UTC (rev 7099) @@ -17,9 +17,13 @@ public class PyString extends PyBaseString { public static final PyType TYPE = PyType.fromClass(PyString.class); - protected String string; + protected String string; // cannot make final because of Python intern support protected transient boolean interned=false; + public String getString() { + return string; + } + // for PyJavaClass.init() public PyString() { this(TYPE, ""); @@ -57,7 +61,7 @@ } @ExposedNew - final static PyObject str_new(PyNewWrapper new_, boolean init, PyType subtype, + static PyObject str_new(PyNewWrapper new_, boolean init, PyType subtype, PyObject[] args, String[] keywords) { ArgParser ap = new ArgParser("str", args, keywords, new String[] { "object" }, 0); PyObject S = ap.getPyObject(0, null); @@ -75,18 +79,19 @@ } public int[] toCodePoints() { - int n = string.length(); + int n = getString().length(); int[] codePoints = new int[n]; for (int i = 0; i < n; i++) { - codePoints[i] = string.charAt(i); + codePoints[i] = getString().charAt(i); } return codePoints; } public String substring(int start, int end) { - return string.substring(start, end); + return getString().substring(start, end); } + @Override public PyString __str__() { return str___str__(); } @@ -96,43 +101,47 @@ if (getClass() == PyString.class) { return this; } - return new PyString(string); + return new PyString(getString()); } + @Override public PyUnicode __unicode__() { return new PyUnicode(this); } + @Override public int __len__() { return str___len__(); } @ExposedMethod(doc = BuiltinDocs.str___len___doc) final int str___len__() { - return string.length(); + return getString().length(); } + @Override public String toString() { - return string; + return getString(); } public String internedString() { if (interned) - return string; + return getString(); else { - string = string.intern(); + string = getString().intern(); interned = true; - return string; + return getString(); } } + @Override public PyString __repr__() { return str___repr__(); } @ExposedMethod(doc = BuiltinDocs.str___repr___doc) final PyString str___repr__() { - return new PyString(encode_UnicodeEscape(string, true)); + return new PyString(encode_UnicodeEscape(getString(), true)); } private static char[] hexdigit = "0123456789abcdef".toCharArray(); @@ -475,6 +484,7 @@ return seq___getslice__(start, stop, step); } + @Override public int __cmp__(PyObject other) { return str___cmp__(other); } @@ -484,10 +494,11 @@ if (!(other instanceof PyString)) return -2; - int c = string.compareTo(((PyString)other).string); + int c = getString().compareTo(((PyString) other).getString()); return c < 0 ? -1 : c > 0 ? 1 : 0; } + @Override public PyObject __eq__(PyObject other) { return str___eq__(other); } @@ -497,9 +508,10 @@ String s = coerce(other); if (s == null) return null; - return string.equals(s) ? Py.True : Py.False; + return getString().equals(s) ? Py.True : Py.False; } + @Override public PyObject __ne__(PyObject other) { return str___ne__(other); } @@ -509,9 +521,10 @@ String s = coerce(other); if (s == null) return null; - return string.equals(s) ? Py.False : Py.True; + return getString().equals(s) ? Py.False : Py.True; } + @Override public PyObject __lt__(PyObject other) { return str___lt__(other); } @@ -521,9 +534,10 @@ String s = coerce(other); if (s == null) return null; - return string.compareTo(s) < 0 ? Py.True : Py.False; + return getString().compareTo(s) < 0 ? Py.True : Py.False; } + @Override public PyObject __le__(PyObject other) { return str___le__(other); } @@ -533,9 +547,10 @@ String s = coerce(other); if (s == null) return null; - return string.compareTo(s) <= 0 ? Py.True : Py.False; + return getString().compareTo(s) <= 0 ? Py.True : Py.False; } + @Override public PyObject __gt__(PyObject other) { return str___gt__(other); } @@ -545,9 +560,10 @@ String s = coerce(other); if (s == null) return null; - return string.compareTo(s) > 0 ? Py.True : Py.False; + return getString().compareTo(s) > 0 ? Py.True : Py.False; } + @Override public PyObject __ge__(PyObject other) { return str___ge__(other); } @@ -557,7 +573,7 @@ String s = coerce(other); if (s == null) return null; - return string.compareTo(s) >= 0 ? Py.True : Py.False; + return getString().compareTo(s) >= 0 ? Py.True : Py.False; } private static String coerce(PyObject o) { @@ -566,13 +582,29 @@ return null; } + @Override public int hashCode() { return str___hash__(); } +// @Override +// public boolean equals(Object obj) { +// if (obj == null) { +// return false; +// } +// if (getClass() != obj.getClass()) { +// return false; +// } +// final PyString other = (PyString) obj; +// if ((this.string == null) ? (other.string != null) : !this.string.equals(other.string)) { +// return false; +// } +// return true; +// } + @ExposedMethod(doc = BuiltinDocs.str___hash___doc) final int str___hash__() { - return string.hashCode(); + return getString().hashCode(); } /** @@ -581,23 +613,24 @@ * corresponding char. */ public byte[] toBytes() { - return StringUtil.toBytes(string); + return StringUtil.toBytes(getString()); } + @Override public Object __tojava__(Class<?> c) { if (c.isAssignableFrom(String.class)) { - return string; + return getString(); } if (c == Character.TYPE || c == Character.class) - if (string.length() == 1) - return new Character(string.charAt(0)); + if (getString().length() == 1) + return new Character(getString().charAt(0)); if (c.isArray()) { if (c.getComponentType() == Byte.TYPE) return toBytes(); if (c.getComponentType() == Character.TYPE) - return string.toCharArray(); + return getString().toCharArray(); } if (c.isInstance(this)) @@ -607,7 +640,7 @@ } protected PyObject pyget(int i) { - return Py.newString(string.charAt(i)); + return Py.newString(getString().charAt(i)); } protected PyObject getslice(int start, int stop, int step) { @@ -620,7 +653,7 @@ char new_chars[] = new char[n]; int j = 0; for (int i=start; j<n; i+=step) - new_chars[j++] = string.charAt(i); + new_chars[j++] = getString().charAt(i); return createInstance(new String(new_chars), true); } @@ -635,6 +668,7 @@ return new PyString(str); } + @Override public boolean __contains__(PyObject o) { return str___contains__(o); } @@ -644,14 +678,14 @@ if (!(o instanceof PyString)) throw Py.TypeError("'in <string>' requires string as left operand"); PyString other = (PyString) o; - return string.indexOf(other.string) >= 0; + return getString().indexOf(other.getString()) >= 0; } protected PyObject repeat(int count) { if(count < 0) { count = 0; } - int s = string.length(); + int s = getString().length(); if((long)s * count > Integer.MAX_VALUE) { // Since Strings store their data in an array, we can't make one // longer than Integer.MAX_VALUE. Without this check we get @@ -661,7 +695,7 @@ } char new_chars[] = new char[s * count]; for(int i = 0; i < count; i++) { - string.getChars(0, s, new_chars, i * s); + getString().getChars(0, s, new_chars, i * s); } return createInstance(new String(new_chars)); } @@ -692,6 +726,7 @@ return repeat(o.asIndex(Py.OverflowError)); } + @Override public PyObject __add__(PyObject other) { return str___add__(other); } @@ -703,30 +738,33 @@ } if (other instanceof PyString) { PyString otherStr = (PyString)other; - return new PyString(string.concat(otherStr.string)); + return new PyString(getString().concat(otherStr.getString())); } return null; } @ExposedMethod(doc = BuiltinDocs.str___getnewargs___doc) final PyTuple str___getnewargs__() { - return new PyTuple(new PyString(this.string)); + return new PyTuple(new PyString(this.getString())); } + @Override public PyTuple __getnewargs__() { return str___getnewargs__(); } + @Override public PyObject __mod__(PyObject other) { return str___mod__(other); } @ExposedMethod(doc = BuiltinDocs.str___mod___doc) public PyObject str___mod__(PyObject other){ - StringFormatter fmt = new StringFormatter(string, false); + StringFormatter fmt = new StringFormatter(getString(), false); return fmt.format(other); } + @Override public PyObject __int__() { try { @@ -739,27 +777,33 @@ } } + @Override public PyObject __long__() { return atol(10); } + @Override public PyFloat __float__() { return new PyFloat(atof()); } + @Override public PyObject __pos__() { throw Py.TypeError("bad operand type for unary +"); } + @Override public PyObject __neg__() { throw Py.TypeError("bad operand type for unary -"); } + @Override public PyObject __invert__() { throw Py.TypeError("bad operand type for unary ~"); } @SuppressWarnings("fallthrough") + @Override public PyComplex __complex__() { boolean got_re = false; boolean got_im = false; @@ -767,8 +811,8 @@ boolean sw_error = false; int s = 0; - int n = string.length(); - while (s < n && Character.isSpaceChar(string.charAt(s))) + int n = getString().length(); + while (s < n && Character.isSpaceChar(getString().charAt(s))) s++; if (s == n) { @@ -781,7 +825,7 @@ int sign = 1; do { - char c = string.charAt(s); + char c = getString().charAt(s); switch (c) { case '-': sign = -1; @@ -793,7 +837,7 @@ } // a character is guaranteed, but it better be a digit // or J or j - c = string.charAt(++s); // eat the sign character + c = getString().charAt(++s); // eat the sign character // and check the next if (!Character.isDigit(c) && c!='J' && c!='j') sw_error = true; @@ -817,7 +861,7 @@ break; case ' ': - while (s < n && Character.isSpaceChar(string.charAt(s))) + while (s < n && Character.isSpaceChar(getString().charAt(s))) s++; if (s != n) sw_error = true; @@ -829,15 +873,15 @@ sw_error = true; break; } - int end = endDouble(string, s); - z = Double.valueOf(string.substring(s, end)).doubleValue(); + int end = endDouble(getString(),s); + z = Double.valueOf(getString().substring(s, end)).doubleValue(); if (z == Double.POSITIVE_INFINITY) { - throw Py.ValueError(String.format("float() out of range: %.150s", string)); + throw Py.ValueError(String.format("float() out of range: %.150s", getString())); } s=end; if (s < n) { - c = string.charAt(s); + c = getString().charAt(s); if (c == 'J' || c == 'j') { break; } @@ -861,7 +905,7 @@ if (sw_error) { throw Py.ValueError("malformed string for complex() " + - string.substring(s)); + getString().substring(s)); } return new PyComplex(x,y); @@ -895,7 +939,7 @@ @ExposedMethod(doc = BuiltinDocs.str_lower_doc) final String str_lower() { - return string.toLowerCase(); + return getString().toLowerCase(); } public String upper() { @@ -904,7 +948,7 @@ @ExposedMethod(doc = BuiltinDocs.str_upper_doc) final String str_upper() { - return string.toUpperCase(); + return getString().toUpperCase(); } public String title() { @@ -913,7 +957,7 @@ @ExposedMethod(doc = BuiltinDocs.str_title_doc) final String str_title() { - char[] chars = string.toCharArray(); + char[] chars = getString().toCharArray(); int n = chars.length; boolean previous_is_cased = false; @@ -940,7 +984,7 @@ @ExposedMethod(doc = BuiltinDocs.str_swapcase_doc) final String str_swapcase() { - char[] chars = string.toCharArray(); + char[] chars = getString().toCharArray(); int n=chars.length; for (int i=0; i<n; i++) { char c = chars[i]; @@ -964,7 +1008,7 @@ @ExposedMethod(defaults = "null", doc = BuiltinDocs.str_strip_doc) final String str_strip(String sep) { - char[] chars = string.toCharArray(); + char[] chars = getString().toCharArray(); int n=chars.length; int start=0; if (sep == null) @@ -984,7 +1028,7 @@ if (end >= start) { return (end < n-1 || start > 0) - ? string.substring(start, end+1) : string; + ? getString().substring(start, end+1) : getString(); } else { return ""; } @@ -1000,7 +1044,7 @@ @ExposedMethod(defaults = "null", doc = BuiltinDocs.str_lstrip_doc) final String str_lstrip(String sep) { - char[] chars = string.toCharArray(); + char[] chars = getString().toCharArray(); int n=chars.length; int start=0; if (sep == null) @@ -1010,7 +1054,7 @@ while (start < n && sep.indexOf(chars[start]) >= 0) start++; - return (start > 0) ? string.substring(start, n) : string; + return (start > 0) ? getString().substring(start, n) : getString(); } public String rstrip(String sep) { @@ -1019,7 +1063,7 @@ @ExposedMethod(defaults = "null", doc = BuiltinDocs.str_rstrip_doc) final String str_rstrip(String sep) { - char[] chars = string.toCharArray(); + char[] chars = getString().toCharArray(); int n=chars.length; int end=n-1; if (sep == null) @@ -1029,7 +1073,7 @@ while (end >= 0 && sep.indexOf(chars[end]) >= 0) end--; - return (end < n-1) ? string.substring(0, end+1) : string; + return (end < n-1) ? getString().substring(0, end+1) : getString(); } @@ -1056,7 +1100,7 @@ PyList list = new PyList(); - char[] chars = string.toCharArray(); + char[] chars = getString().toCharArray(); int n=chars.length; if (maxsplit < 0) @@ -1108,7 +1152,7 @@ } PyList list = new PyList(); - char[] chars = string.toCharArray(); + char[] chars = getString().toCharArray(); if (maxsplit < 0) { maxsplit = chars.length; @@ -1165,7 +1209,7 @@ if (sepObj instanceof PyUnicode) { return unicodePartition(sepObj); } else if (sepObj instanceof PyString) { - sep = ((PyString)sepObj).string; + sep = ((PyString) sepObj).getString(); } else { throw Py.TypeError("expected a character buffer object"); } @@ -1174,10 +1218,10 @@ throw Py.ValueError("empty separator"); } - int index = string.indexOf(sep); + int index = getString().indexOf(sep); if (index != -1) { return new PyTuple(fromSubstring(0, index), sepObj, - fromSubstring(index + sep.length(), string.length())); + fromSubstring(index + sep.length(), getString().length())); } else { return new PyTuple(this, Py.EmptyString, Py.EmptyString); } @@ -1185,7 +1229,7 @@ final PyTuple unicodePartition(PyObject sepObj) { PyUnicode strObj = __unicode__(); - String str = strObj.string; + String str = strObj.getString(); // Will throw a TypeError if not a basestring String sep = sepObj.asString(); @@ -1216,7 +1260,7 @@ if (sepObj instanceof PyUnicode) { return unicodePartition(sepObj); } else if (sepObj instanceof PyString) { - sep = ((PyString)sepObj).string; + sep = ((PyString) sepObj).getString(); } else { throw Py.TypeError("expected a character buffer object"); } @@ -1225,10 +1269,10 @@ throw Py.ValueError("empty separator"); } - int index = string.lastIndexOf(sep); + int index = getString().lastIndexOf(sep); if (index != -1) { return new PyTuple(fromSubstring(0, index), sepObj, - fromSubstring(index + sep.length(), string.length())); + fromSubstring(index + sep.length(), getString().length())); } else { return new PyTuple(Py.EmptyString, Py.EmptyString, this); } @@ -1236,7 +1280,7 @@ final PyTuple unicodeRpartition(PyObject sepObj) { PyUnicode strObj = __unicode__(); - String str = strObj.string; + String str = strObj.getString(); // Will throw a TypeError if not a basestring String sep = sepObj.asString(); @@ -1259,7 +1303,7 @@ private PyList splitfields(String sep, int maxsplit) { PyList list = new PyList(); - int length = string.length(); + int length = getString().length(); if (maxsplit < 0) maxsplit = length + 1; @@ -1268,12 +1312,12 @@ int sepLength = sep.length(); int index; if((sep.length() == 0) && (maxsplit != 0)) { - index = string.indexOf(sep, lastbreak); + index = getString().indexOf(sep, lastbreak); list.append(fromSubstring(lastbreak, index)); splits++; } while (splits < maxsplit) { - index = string.indexOf(sep, lastbreak); + index = getString().indexOf(sep, lastbreak); if (index == -1) break; if(sep.length() == 0) @@ -1291,7 +1335,7 @@ private PyList rsplitfields(String sep, int maxsplit) { PyList list = new PyList(); - int length = string.length(); + int length = getString().length(); if (maxsplit < 0) { maxsplit = length + 1; } @@ -1302,7 +1346,7 @@ int sepLength = sep.length(); while (index > 0 && splits < maxsplit) { - int i = string.lastIndexOf(sep, index - sepLength); + int i = getString().lastIndexOf(sep, index - sepLength); if (i == index) { i -= sepLength; } @@ -1331,7 +1375,7 @@ final PyList str_splitlines(boolean keepends) { PyList list = new PyList(); - char[] chars = string.toCharArray(); + char[] chars = getString().toCharArray(); int n=chars.length; int j = 0; @@ -1361,7 +1405,7 @@ } protected PyString fromSubstring(int begin, int end) { - return createInstance(string.substring(begin, end), true); + return createInstance(getString().substring(begin, end), true); } public int index(String sub) { @@ -1421,14 +1465,14 @@ int[] indices = translateIndices(start, end); int n = sub.length(); if(n == 0) { - if (start > string.length()) { + if (start > getString().length()) { return 0; } return indices[1] - indices[0] + 1; } int count = 0; while(true){ - int index = string.indexOf(sub, indices[0]); + int index = getString().indexOf(sub, indices[0]); indices[0] = index + n; if(indices[0] > indices[1] || index == -1) { break; @@ -1453,7 +1497,7 @@ @ExposedMethod(defaults = {"0", "null"}, doc = BuiltinDocs.str_find_doc) final int str_find(String sub, int start, PyObject end) { int[] indices = translateIndices(start, end); - int index = string.indexOf(sub, indices[0]); + int index = getString().indexOf(sub, indices[0]); if (index < start || index > indices[1]) { return -1; } @@ -1475,7 +1519,7 @@ @ExposedMethod(defaults = {"0", "null"}, doc = BuiltinDocs.str_rfind_doc) final int str_rfind(String sub, int start, PyObject end) { int[] indices = translateIndices(start, end); - int index = string.lastIndexOf(sub, indices[1] - sub.length()); + int index = getString().lastIndexOf(sub, indices[1] - sub.length()); if (index < start) { return -1; } @@ -1484,20 +1528,20 @@ public double atof() { StringBuilder s = null; - int n = string.length(); + int n = getString().length(); for (int i = 0; i < n; i++) { - char ch = string.charAt(i); + char ch = getString().charAt(i); if (ch == '\u0000') { throw Py.ValueError("null byte in argument for float()"); } if (Character.isDigit(ch)) { if (s == null) - s = new StringBuilder(string); + s = new StringBuilder(getString()); int val = Character.digit(ch, 10); s.setCharAt(i, Character.forDigit(val, 10)); } } - String sval = string; + String sval = getString(); if (s != null) sval = s.toString(); try { @@ -1513,7 +1557,7 @@ return Double.valueOf(sval).doubleValue(); } catch (NumberFormatException exc) { - throw Py.ValueError("invalid literal for __float__: "+string); + throw Py.ValueError("invalid literal for __float__: "+getString()); } } @@ -1527,26 +1571,26 @@ } int b = 0; - int e = string.length(); + int e = getString().length(); - while (b < e && Character.isWhitespace(string.charAt(b))) + while (b < e && Character.isWhitespace(getString().charAt(b))) b++; - while (e > b && Character.isWhitespace(string.charAt(e-1))) + while (e > b && Character.isWhitespace(getString().charAt(e-1))) e--; char sign = 0; if (b < e) { - sign = string.charAt(b); + sign = getString().charAt(b); if (sign == '-' || sign == '+') { b++; - while (b < e && Character.isWhitespace(string.charAt(b))) b++; + while (b < e && Character.isWhitespace(getString().charAt(b))) b++; } if (base == 0 || base == 16) { - if (string.charAt(b) == '0') { + if (getString().charAt(b) == '0') { if (b < e-1 && - Character.toUpperCase(string.charAt(b+1)) == 'X') { + Character.toUpperCase(getString().charAt(b+1)) == 'X') { base = 16; b += 2; } else { @@ -1560,9 +1604,9 @@ if (base == 0) base = 10; - String s = string; - if (b > 0 || e < string.length()) - s = string.substring(b, e); + String s = getString(); + if (b > 0 || e < getString().length()) + s = getString().substring(b, e); try { BigInteger bi; @@ -1575,9 +1619,9 @@ } return bi.intValue(); } catch (NumberFormatException exc) { - throw Py.ValueError("invalid literal for int() with base " + base + ": " + string); + throw Py.ValueError("invalid literal for int() with base " + base + ": " + getString()); } catch (StringIndexOutOfBoundsException exc) { - throw Py.ValueError("invalid literal for int() with base " + base + ": " + string); + throw Py.ValueError("invalid literal for int() with base " + base + ": " + getString()); } } @@ -1586,7 +1630,7 @@ } public PyLong atol(int base) { - String str = string; + String str = getString(); int b = 0; int e = str.length(); @@ -1599,7 +1643,7 @@ char sign = 0; if (b < e) { - sign = string.charAt(b); + sign = getString().charAt(b); if (sign == '-' || sign == '+') { b++; while (b < e && Character.isWhitespace(str.charAt(b))) b++; @@ -1607,9 +1651,9 @@ if (base == 0 || base == 16) { - if (string.charAt(b) == '0') { + if (getString().charAt(b) == '0') { if (b < e-1 && - Character.toUpperCase(string.charAt(b+1)) == 'X') { + Character.toUpperCase(getString().charAt(b+1)) == 'X') { base = 16; b += 2; } else { @@ -1649,10 +1693,10 @@ 0,0, "invalid decimal Unicode string"); } else { - throw Py.ValueError("invalid literal for long() with base " + base + ": " + string); + throw Py.ValueError("invalid literal for long() with base " + base + ": " + getString()); } } catch (StringIndexOutOfBoundsException exc) { - throw Py.ValueError("invalid literal for long() with base " + base + ": " + string); + throw Py.ValueError("invalid literal for long() with base " + base + ": " + getString()); } } @@ -1682,10 +1726,10 @@ @ExposedMethod(defaults="null", doc = BuiltinDocs.str_ljust_doc) final String str_ljust(int width, String fillchar) { char pad = parse_fillchar("ljust", fillchar); - int n = width-string.length(); + int n = width-getString().length(); if (n <= 0) - return string; - return string+padding(n, pad); + return getString(); + return getString()+padding(n, pad); } public String rjust(int width) { @@ -1695,10 +1739,10 @@ @ExposedMethod(defaults="null", doc = BuiltinDocs.str_rjust_doc) final String str_rjust(int width, String fillchar) { char pad = parse_fillchar("rjust", fillchar); - int n = width-string.length(); + int n = width-getString().length(); if (n <= 0) - return string; - return padding(n, pad)+string; + return getString(); + return padding(n, pad)+getString(); } public String center(int width) { @@ -1708,14 +1752,14 @@ @ExposedMethod(defaults="null", doc = BuiltinDocs.str_center_doc) final String str_center(int width, String fillchar) { char pad = parse_fillchar("center", fillchar); - int n = width-string.length(); + int n = width-getString().length(); if (n <= 0) - return string; + return getString(); int half = n/2; if (n%2 > 0 && width%2 > 0) half += 1; - return padding(half, pad)+string+padding(n-half, pad); + return padding(half, pad)+getString()+padding(n-half, pad); } public String zfill(int width) { @@ -1724,7 +1768,7 @@ @ExposedMethod(doc = BuiltinDocs.str_zfill_doc) final String str_zfill(int width) { - String s = string; + String s = getString(); int n = s.length(); if (n >= width) return s; @@ -1758,7 +1802,7 @@ @ExposedMethod(defaults = "8", doc = BuiltinDocs.str_expandtabs_doc) final String str_expandtabs(int tabsize) { - String s = string; + String s = getString(); StringBuilder buf = new StringBuilder((int)(s.length()*1.5)); char[] chars = s.toCharArray(); int n = chars.length; @@ -1789,10 +1833,10 @@ @ExposedMethod(doc = BuiltinDocs.str_capitalize_doc) final String str_capitalize() { - if (string.length() == 0) - return string; - String first = string.substring(0,1).toUpperCase(); - return first.concat(string.substring(1).toLowerCase()); + if (getString().length() == 0) + return getString(); + String first = getString().substring(0,1).toUpperCase(); + return first.concat(getString().substring(1).toLowerCase()); } @ExposedMethod(defaults = "null", doc = BuiltinDocs.str_replace_doc) @@ -1805,25 +1849,25 @@ } protected PyString replace(PyString oldPiece, PyString newPiece, int maxsplit) { - int len = string.length(); - int old_len = oldPiece.string.length(); + int len = getString().length(); + int old_len = oldPiece.getString().length(); if (len == 0) { if (maxsplit == -1 && old_len == 0) { - return createInstance(newPiece.string, true); + return createInstance(newPiece.getString(), true); } - return createInstance(string, true); + return createInstance(getString(), true); } - if (old_len == 0 && newPiece.string.length() != 0 && maxsplit !=0) { + if (old_len == 0 && newPiece.getString().length() != 0 && maxsplit !=0) { // old="" and new != "", interleave new piece with each char in original, taking in effect maxsplit StringBuilder buffer = new StringBuilder(); int i = 0; - buffer.append(newPiece.string); + buffer.append(newPiece.getString()); for (; i < len && (i < maxsplit-1 || maxsplit == -1); i++) { - buffer.append(string.charAt(i)); - buffer.append(newPiece.string); + buffer.append(getString().charAt(i)); + buffer.append(newPiece.getString()); } - buffer.append(string.substring(i)); + buffer.append(getString().substring(i)); return createInstance(buffer.toString(), true); } @@ -1835,7 +1879,7 @@ } } - return newPiece.join(splitfields(oldPiece.string, maxsplit)); + return newPiece.join(splitfields(oldPiece.getString(), maxsplit)); } public PyString join(PyObject seq) { @@ -1864,7 +1908,7 @@ // join if appropriate int i = 0; long size = 0; - int sepLen = string.length(); + int sepLen = getString().length(); for (; i < seqLen; i++) { item = seq.pyget(i); if (!(item instanceof PyString)) { @@ -1880,7 +1924,7 @@ if (i != 0) { size += sepLen; } - size += ((PyString)item).string.length(); + size += ((PyString) item).getString().length(); if (size > Integer.MAX_VALUE) { throw Py.OverflowError("join() result is too long for a Python string"); } @@ -1891,9 +1935,9 @@ for (i = 0; i < seqLen; i++) { item = seq.pyget(i); if (i != 0) { - buf.append(string); + buf.append(getString()); } - buf.append(((PyString)item).string); + buf.append(((PyString) item).getString()); } return new PyString(buf.toString()); } @@ -1923,9 +1967,9 @@ String sep = null; if (seqLen > 1) { if (this instanceof PyUnicode) { - sep = string; + sep = getString(); } else { - sep = ((PyUnicode)decode()).string; + sep = ((PyUnicode) decode()).getString(); // In case decode()'s codec mutated seq seqLen = seq.__len__(); } @@ -1933,7 +1977,7 @@ // At least two items to join, or one that isn't exact Unicode long size = 0; - int sepLen = string.length(); + int sepLen = getString().length(); StringBuilder buf = new StringBuilder(); String itemString; for (int i = 0; i < seqLen; i++) { @@ -1949,7 +1993,7 @@ // In case decode()'s codec mutated seq seqLen = seq.__len__(); } - itemString = ((PyUnicode)item).string; + itemString = ((PyUnicode) item).getString(); if (i != 0) { size += sepLen; @@ -1981,11 +2025,11 @@ int[] indices = translateIndices(start, end); if (prefix instanceof PyString) { - String strPrefix = ((PyString)prefix).string; + String strPrefix = ((PyString) prefix).getString(); if (indices[1] - indices[0] < strPrefix.length()) return false; - return string.startsWith(strPrefix, indices[0]); + return getString().startsWith(strPrefix, indices[0]); } else if (prefix instanceof PyTuple) { PyObject[] prefixes = ((PyTuple)prefix).getArray(); @@ -1993,11 +2037,11 @@ if (!(prefixes[i] instanceof PyString)) throw Py.TypeError("expected a character buffer object"); - String strPrefix = ((PyString)prefixes[i]).string; + String strPrefix = ((PyString) prefixes[i]).getString(); if (indices[1] - indices[0] < strPrefix.length()) continue; - if (string.startsWith(strPrefix, indices[0])) + if (getString().startsWith(strPrefix, indices[0])) return true; } return false; @@ -2022,9 +2066,9 @@ final boolean str_endswith(PyObject suffix, int start, PyObject end) { int[] indices = translateIndices(start, end); - String substr = string.substring(indices[0], indices[1]); + String substr = getString().substring(indices[0], indices[1]); if (suffix instanceof PyString) { - return substr.endsWith(((PyString)suffix).string); + return substr.endsWith(((PyString) suffix).getString()); } else if (suffix instanceof PyTuple) { PyObject[] suffixes = ((PyTuple)suffix).getArray(); @@ -2032,7 +2076,7 @@ if (!(suffixes[i] instanceof PyString)) throw Py.TypeError("expected a character buffer object"); - if (substr.endsWith(((PyString)suffixes[i]).string)) + if (substr.endsWith(((PyString) suffixes[i]).getString())) return true; } return false; @@ -2053,11 +2097,11 @@ protected int[] translateIndices(int start, PyObject end) { int iEnd; if(end == null) { - iEnd = string.length(); + iEnd = getString().length(); } else { iEnd = end.asInt(); } - int n = string.length(); + int n = getString().length(); if(iEnd < 0) { iEnd = n + iEnd; if(iEnd < 0) { @@ -2092,9 +2136,9 @@ throw Py.ValueError( "translation table must be 256 characters long"); - StringBuilder buf = new StringBuilder(string.length()); - for (int i=0; i < string.length(); i++) { - char c = string.charAt(i); + StringBuilder buf = new StringBuilder(getString().length()); + for (int i=0; i < getString().length(); i++) { + char c = getString().charAt(i); if (deletechars != null && deletechars.indexOf(c) >= 0) continue; try { @@ -2110,9 +2154,9 @@ //XXX: is this needed? public String translate(PyObject table) { - StringBuilder v = new StringBuilder(string.length()); - for (int i=0; i < string.length(); i++) { - char ch = string.charAt(i); + StringBuilder v = new StringBuilder(getString().length()); + for (int i=0; i < getString().length(); i++) { + char ch = getString().charAt(i); PyObject w = Py.newInteger(ch); PyObject x = table.__finditem__(w); @@ -2152,15 +2196,15 @@ @ExposedMethod(doc = Builti... [truncated message content] |
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-17 19:23:28
|
Revision: 7097 http://jython.svn.sourceforge.net/jython/?rev=7097&view=rev Author: zyasoft Date: 2010-08-17 19:23:22 +0000 (Tue, 17 Aug 2010) Log Message: ----------- Refactored PyBoolean, PyFloat, PyLong so they consistently use getValue instead of accessing the field value directly. Fixes #1645, although we are awaiting more unit tests on how this be used by user types. Modified Paths: -------------- trunk/jython/src/org/python/core/PyBoolean.java trunk/jython/src/org/python/core/PyFloat.java trunk/jython/src/org/python/core/PyLong.java Modified: trunk/jython/src/org/python/core/PyBoolean.java =================================================================== --- trunk/jython/src/org/python/core/PyBoolean.java 2010-08-16 16:45:29 UTC (rev 7096) +++ trunk/jython/src/org/python/core/PyBoolean.java 2010-08-17 19:23:22 UTC (rev 7097) @@ -7,17 +7,27 @@ import org.python.expose.MethodType; /** - * The builtin python bool. + * The builtin python bool. It would be nice if it didn't extend PyInteger, + * but too hard to avoid pre-Python 2.2 semantics here. */ @ExposedType(name = "bool", isBaseType = false, doc = BuiltinDocs.bool_doc) public class PyBoolean extends PyInteger { public static final PyType TYPE = PyType.fromClass(PyBoolean.class); - private boolean value; + private final boolean value; + public boolean getBooleanValue() { + return value; + } + + @Override + public int getValue() { + return getBooleanValue() ? 1 : 0; + } + public PyBoolean(boolean value) { - super(TYPE, value ? 1 : 0); + super(TYPE, value ? 1 : 0); // XXX is this necessary? this.value = value; } @@ -39,7 +49,7 @@ @ExposedMethod(names = {"__str__", "__repr__"}, doc = BuiltinDocs.bool___str___doc) final String bool_toString() { - return value ? "True" : "False"; + return getBooleanValue() ? "True" : "False"; } @Override @@ -49,7 +59,7 @@ @ExposedMethod(doc = BuiltinDocs.bool___hash___doc) final int bool___hash__() { - return value ? 1 : 0; + return getBooleanValue() ? 1 : 0; } @Override @@ -59,31 +69,31 @@ @ExposedMethod(doc = BuiltinDocs.bool___nonzero___doc) final boolean bool___nonzero__() { - return value; + return getBooleanValue(); } @Override public Object __tojava__(Class<?> c) { if (c == Boolean.TYPE || c == Boolean.class || c == Object.class ) { - return Boolean.valueOf(value); + return Boolean.valueOf(getBooleanValue()); } if (c == Integer.TYPE || c == Number.class || c == Integer.class) { - return Integer.valueOf(value ? 1 : 0); + return Integer.valueOf(getValue()); } if (c == Byte.TYPE || c == Byte.class) { - return Byte.valueOf((byte)(value ? 1 : 0)); + return Byte.valueOf((byte)(getValue())); } if (c == Short.TYPE || c == Short.class) { - return Short.valueOf((short)(value ? 1 : 0)); + return Short.valueOf((short)(getValue())); } if (c == Long.TYPE || c == Long.class) { - return Long.valueOf(value ? 1 : 0); + return Long.valueOf(getValue()); } if (c == Float.TYPE || c == Float.class) { - return Float.valueOf(value ? 1 : 0); + return Float.valueOf(getValue()); } if (c == Double.TYPE || c == Double.class) { - return Double.valueOf(value ? 1 : 0); + return Double.valueOf(getValue()); } return super.__tojava__(c); } @@ -96,7 +106,7 @@ @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.bool___and___doc) final PyObject bool___and__(PyObject right) { if (right instanceof PyBoolean) { - return Py.newBoolean(value & ((PyBoolean)right).value); + return Py.newBoolean(getBooleanValue() & ((PyBoolean) right).getBooleanValue()); } else if (right instanceof PyInteger) { return Py.newInteger(getValue() & ((PyInteger)right).getValue()); } else { @@ -112,7 +122,7 @@ @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.bool___xor___doc) final PyObject bool___xor__(PyObject right) { if (right instanceof PyBoolean) { - return Py.newBoolean(value ^ ((PyBoolean)right).value); + return Py.newBoolean(getBooleanValue() ^ ((PyBoolean) right).getBooleanValue()); } else if (right instanceof PyInteger) { return Py.newInteger(getValue() ^ ((PyInteger)right).getValue()); } else { @@ -128,7 +138,7 @@ @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.bool___or___doc) final PyObject bool___or__(PyObject right) { if (right instanceof PyBoolean) { - return Py.newBoolean(value | ((PyBoolean)right).value); + return Py.newBoolean(getBooleanValue() | ((PyBoolean) right).getBooleanValue()); } else if (right instanceof PyInteger) { return Py.newInteger(getValue() | ((PyInteger)right).getValue()); } else { @@ -143,7 +153,7 @@ @ExposedMethod(doc = BuiltinDocs.bool___neg___doc) final PyObject bool___neg__() { - return Py.newInteger(value ? -1 : 0); + return Py.newInteger(getBooleanValue() ? -1 : 0); } @Override @@ -153,7 +163,7 @@ @ExposedMethod(doc = BuiltinDocs.bool___pos___doc) final PyObject bool___pos__() { - return Py.newInteger(value ? 1 : 0); + return Py.newInteger(getValue()); } @Override @@ -163,6 +173,6 @@ @ExposedMethod(doc = BuiltinDocs.bool___abs___doc) final PyObject bool___abs__() { - return Py.newInteger(value ? 1 : 0); + return Py.newInteger(getValue()); } } Modified: trunk/jython/src/org/python/core/PyFloat.java =================================================================== --- trunk/jython/src/org/python/core/PyFloat.java 2010-08-16 16:45:29 UTC (rev 7096) +++ trunk/jython/src/org/python/core/PyFloat.java 2010-08-17 19:23:22 UTC (rev 7097) @@ -25,8 +25,12 @@ private static final int PREC_REPR = 17; private static final int PREC_STR = 12; - private double value; + private final double value; + public double getValue() { + return value; + } + public PyFloat(PyType subtype, double v) { super(subtype); value = v; @@ -81,10 +85,6 @@ return !Double.isInfinite(value) && !Double.isNaN(value); } - public double getValue() { - return value; - } - @Override public String toString() { return __str__().toString(); @@ -111,7 +111,7 @@ } private String formatDouble(int precision) { - if (Double.isNaN(value)) { + if (Double.isNaN(getValue())) { return "nan"; } @@ -140,17 +140,17 @@ @ExposedMethod(doc = BuiltinDocs.float___hash___doc) final int float___hash__() { - double intPart = Math.floor(value); - double fractPart = value - intPart; + double intPart = Math.floor(getValue()); + double fractPart = getValue() - intPart; if (fractPart == 0) { if (intPart <= Integer.MAX_VALUE && intPart >= Integer.MIN_VALUE) { - return (int) value; + return (int) getValue(); } else { return __long__().hashCode(); } } else { - long v = Double.doubleToLongBits(value); + long v = Double.doubleToLongBits(getValue()); return (int) v ^ (int) (v >> 32); } } @@ -162,17 +162,17 @@ @ExposedMethod(doc = BuiltinDocs.float___nonzero___doc) final boolean float___nonzero__() { - return value != 0; + return getValue() != 0; } @Override public Object __tojava__(Class<?> c) { if (c == Double.TYPE || c == Number.class || c == Double.class || c == Object.class || c == Serializable.class) { - return new Double(value); + return new Double(getValue()); } if (c == Float.TYPE || c == Float.class) { - return new Float(value); + return new Float(getValue()); } return super.__tojava__(c); } @@ -181,7 +181,7 @@ public PyObject __eq__(PyObject other) { // preclude _cmp_unsafe's this == other shortcut because NaN != anything, even // itself - if (Double.isNaN(value)) { + if (Double.isNaN(getValue())) { return Py.False; } return null; @@ -189,7 +189,7 @@ @Override public PyObject __ne__(PyObject other) { - if (Double.isNaN(value)) { + if (Double.isNaN(getValue())) { return Py.True; } return null; @@ -203,11 +203,11 @@ // XXX: needs __doc__ @ExposedMethod(type = MethodType.CMP) final int float___cmp__(PyObject other) { - double i = value; + double i = getValue(); double j; if (other instanceof PyFloat) { - j = ((PyFloat) other).value; + j = ((PyFloat) other).getValue(); } else if (!isFinite()) { // we're infinity: our magnitude exceeds any finite // integer, so it doesn't matter which int we compare i @@ -220,7 +220,7 @@ } else if (other instanceof PyInteger) { j = ((PyInteger) other).getValue(); } else if (other instanceof PyLong) { - BigDecimal v = new BigDecimal(value); + BigDecimal v = new BigDecimal(getValue()); BigDecimal w = new BigDecimal(((PyLong) other).getValue()); return v.compareTo(w); } else { @@ -274,7 +274,7 @@ private static final double coerce(PyObject other) { if (other instanceof PyFloat) { - return ((PyFloat) other).value; + return ((PyFloat) other).getValue(); } else if (other instanceof PyInteger) { return ((PyInteger) other).getValue(); } else if (other instanceof PyLong) { @@ -295,7 +295,7 @@ return null; } double rightv = coerce(right); - return new PyFloat(value + rightv); + return new PyFloat(getValue() + rightv); } @Override @@ -319,7 +319,7 @@ return null; } double rightv = coerce(right); - return new PyFloat(value - rightv); + return new PyFloat(getValue() - rightv); } @Override @@ -333,7 +333,7 @@ return null; } double leftv = coerce(left); - return new PyFloat(leftv - value); + return new PyFloat(leftv - getValue()); } @Override @@ -347,7 +347,7 @@ return null; } double rightv = coerce(right); - return new PyFloat(value * rightv); + return new PyFloat(getValue() * rightv); } @Override @@ -378,7 +378,7 @@ if (rightv == 0) { throw Py.ZeroDivisionError("float division"); } - return new PyFloat(value / rightv); + return new PyFloat(getValue() / rightv); } @Override @@ -396,10 +396,10 @@ } double leftv = coerce(left); - if (value == 0) { + if (getValue() == 0) { throw Py.ZeroDivisionError("float division"); } - return new PyFloat(leftv / value); + return new PyFloat(leftv / getValue()); } @Override @@ -416,7 +416,7 @@ if (rightv == 0) { throw Py.ZeroDivisionError("float division"); } - return new PyFloat(Math.floor(value / rightv)); + return new PyFloat(Math.floor(getValue() / rightv)); } @Override @@ -430,10 +430,10 @@ return null; } double leftv = coerce(left); - if (value == 0) { + if (getValue() == 0) { throw Py.ZeroDivisionError("float division"); } - return new PyFloat(Math.floor(leftv / value)); + return new PyFloat(Math.floor(leftv / getValue())); } @Override @@ -450,7 +450,7 @@ if (rightv == 0) { throw Py.ZeroDivisionError("float division"); } - return new PyFloat(value / rightv); + return new PyFloat(getValue() / rightv); } @Override @@ -464,10 +464,10 @@ return null; } double leftv = coerce(left); - if (value == 0) { + if (getValue() == 0) { throw Py.ZeroDivisionError("float division"); } - return new PyFloat(leftv / value); + return new PyFloat(leftv / getValue()); } private static double modulo(double x, double y) { @@ -492,7 +492,7 @@ return null; } double rightv = coerce(right); - return new PyFloat(modulo(value, rightv)); + return new PyFloat(modulo(getValue(),rightv)); } @Override @@ -506,7 +506,7 @@ return null; } double leftv = coerce(left); - return new PyFloat(modulo(leftv, value)); + return new PyFloat(modulo(leftv, getValue())); } @Override @@ -524,9 +524,9 @@ if (rightv == 0) { throw Py.ZeroDivisionError("float division"); } - double z = Math.floor(value / rightv); + double z = Math.floor(getValue() / rightv); - return new PyTuple(new PyFloat(z), new PyFloat(value - z * rightv)); + return new PyTuple(new PyFloat(z), new PyFloat(getValue() - z * rightv)); } @Override @@ -536,12 +536,12 @@ } double leftv = coerce(left); - if (value == 0) { + if (getValue() == 0) { throw Py.ZeroDivisionError("float division"); } - double z = Math.floor(leftv / value); + double z = Math.floor(leftv / getValue()); - return new PyTuple(new PyFloat(z), new PyFloat(leftv - z * value)); + return new PyTuple(new PyFloat(z), new PyFloat(leftv - z * getValue())); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___rdivmod___doc) @@ -565,7 +565,7 @@ throw Py.TypeError("pow() 3rd argument not allowed unless all arguments are integers"); } - return _pow(value, coerce(right), modulo); + return _pow( getValue(), coerce(right), modulo); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___rpow___doc) @@ -579,7 +579,7 @@ return null; } - return _pow(coerce(left), value, null); + return _pow(coerce(left), getValue(), null); } private static PyFloat _pow(double value, double iw, PyObject modulo) { @@ -612,7 +612,7 @@ @ExposedMethod(doc = BuiltinDocs.float___neg___doc) final PyObject float___neg__() { - return new PyFloat(-value); + return new PyFloat(-getValue()); } @Override @@ -637,7 +637,7 @@ @ExposedMethod(doc = BuiltinDocs.float___abs___doc) final PyObject float___abs__() { - if (value < 0) { + if (getValue() < 0) { return float___neg__(); } return float___float__(); @@ -650,8 +650,8 @@ @ExposedMethod(doc = BuiltinDocs.float___int___doc) final PyObject float___int__() { - if (value <= Integer.MAX_VALUE && value >= Integer.MIN_VALUE) { - return new PyInteger((int) value); + if (getValue() <= Integer.MAX_VALUE && getValue() >= Integer.MIN_VALUE) { + return new PyInteger((int) getValue()); } return __long__(); } @@ -663,7 +663,7 @@ @ExposedMethod(doc = BuiltinDocs.float___long___doc) final PyObject float___long__() { - return new PyLong(value); + return new PyLong(getValue()); } @Override @@ -676,12 +676,12 @@ if (getType() == TYPE) { return this; } - return Py.newFloat(value); + return Py.newFloat(getValue()); } @Override public PyComplex __complex__() { - return new PyComplex(value, 0.); + return new PyComplex(getValue(), 0.); } @ExposedMethod(doc = BuiltinDocs.float___getnewargs___doc) @@ -696,7 +696,7 @@ @Override public double asDouble() { - return value; + return getValue(); } @Override Modified: trunk/jython/src/org/python/core/PyLong.java =================================================================== --- trunk/jython/src/org/python/core/PyLong.java 2010-08-16 16:45:29 UTC (rev 7096) +++ trunk/jython/src/org/python/core/PyLong.java 2010-08-17 19:23:22 UTC (rev 7097) @@ -36,8 +36,12 @@ @Deprecated public static final BigInteger maxULong = MAX_ULONG; - private BigInteger value; + private final BigInteger value; + public BigInteger getValue() { + return value; + } + public PyLong(PyType subType, BigInteger v) { super(subType); value = v; @@ -107,7 +111,7 @@ int intValue = ((PyInteger) tmp).getValue(); return new PyLongDerived(subtype, BigInteger.valueOf(intValue)); } else { - return new PyLongDerived(subtype, ((PyLong) tmp).value); + return new PyLongDerived(subtype, ((PyLong) tmp).getValue()); } } @@ -125,10 +129,6 @@ return new BigDecimal(value).toBigInteger(); } - public BigInteger getValue() { - return value; - } - @Override public String toString() { return long_toString(); @@ -136,7 +136,7 @@ @ExposedMethod(names = {"__str__", "__repr__"}, doc = BuiltinDocs.long___str___doc) final String long_toString() { - return value.toString() + "L"; + return getValue().toString() + "L"; } @Override @@ -146,7 +146,7 @@ @ExposedMethod(doc = BuiltinDocs.long___hash___doc) final int long___hash__() { - return value.intValue(); + return getValue().intValue(); } @Override @@ -160,7 +160,7 @@ } public double doubleValue() { - double v = value.doubleValue(); + double v = getValue().doubleValue(); if (Double.isInfinite(v)) { throw Py.OverflowError("long int too large to convert to float"); } @@ -196,7 +196,7 @@ } public double scaledDoubleValue(int[] exp) { - return scaledDoubleValue(value, exp); + return scaledDoubleValue(getValue(),exp); } public long getLong(long min, long max) { @@ -204,8 +204,8 @@ } public long getLong(long min, long max, String overflowMsg) { - if (value.compareTo(MAX_LONG) <= 0 && value.compareTo(MIN_LONG) >= 0) { - long v = value.longValue(); + if (getValue().compareTo(MAX_LONG) <= 0 && getValue().compareTo(MIN_LONG) >= 0) { + long v = getValue().longValue(); if (v >= min && v <= max) { return v; } @@ -255,7 +255,7 @@ } if (c == BigInteger.class || c == Number.class || c == Object.class || c == Serializable.class) { - return value; + return getValue(); } } catch (PyException e) { return Py.NoConversion; @@ -273,7 +273,7 @@ if (!canCoerce(other)) { return -2; } - return value.compareTo(coerce(other)); + return getValue().compareTo(coerce(other)); } @Override @@ -306,7 +306,7 @@ private static final BigInteger coerce(PyObject other) { if (other instanceof PyLong) { - return ((PyLong) other).value; + return ((PyLong) other).getValue(); } else if (other instanceof PyInteger) { return BigInteger.valueOf(((PyInteger) other).getValue()); } else { @@ -324,7 +324,7 @@ if (!canCoerce(right)) { return null; } - return Py.newLong(value.add(coerce(right))); + return Py.newLong(getValue().add(coerce(right))); } @Override @@ -347,7 +347,7 @@ if (!canCoerce(right)) { return null; } - return Py.newLong(value.subtract(coerce(right))); + return Py.newLong(getValue().subtract(coerce(right))); } @Override @@ -357,7 +357,7 @@ @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___rsub___doc) final PyObject long___rsub__(PyObject left) { - return Py.newLong(coerce(left).subtract(value)); + return Py.newLong(coerce(left).subtract(getValue())); } @Override @@ -374,7 +374,7 @@ if (!canCoerce(right)) { return null; } - return Py.newLong(value.multiply(coerce(right))); + return Py.newLong(getValue().multiply(coerce(right))); } @Override @@ -390,7 +390,7 @@ if (!canCoerce(left)) { return null; } - return Py.newLong(coerce(left).multiply(value)); + return Py.newLong(coerce(left).multiply(getValue())); } // Getting signs correct for integer division @@ -426,7 +426,7 @@ if (Options.divisionWarning > 0) { Py.warning(Py.DeprecationWarning, "classic long division"); } - return Py.newLong(divide(value, coerce(right))); + return Py.newLong(divide( getValue(), coerce(right))); } @Override @@ -442,7 +442,7 @@ if (Options.divisionWarning > 0) { Py.warning(Py.DeprecationWarning, "classic long division"); } - return Py.newLong(divide(coerce(left), value)); + return Py.newLong(divide(coerce(left), getValue())); } @Override @@ -455,7 +455,7 @@ if (!canCoerce(right)) { return null; } - return Py.newLong(divide(value, coerce(right))); + return Py.newLong(divide( getValue(), coerce(right))); } @Override @@ -468,7 +468,7 @@ if (!canCoerce(left)) { return null; } - return Py.newLong(divide(coerce(left), value)); + return Py.newLong(divide(coerce(left), getValue())); } private static final PyFloat true_divide(BigInteger a, BigInteger b) { @@ -511,7 +511,7 @@ if (!canCoerce(right)) { return null; } - return true_divide(this.value, coerce(right)); + return true_divide( this.getValue(), coerce(right)); } @Override @@ -524,7 +524,7 @@ if (!canCoerce(left)) { return null; } - return true_divide(coerce(left), this.value); + return true_divide(coerce(left), this.getValue()); } private BigInteger modulo(BigInteger x, BigInteger y, BigInteger xdivy) { @@ -542,7 +542,7 @@ return null; } BigInteger rightv = coerce(right); - return Py.newLong(modulo(value, rightv, divide(value, rightv))); + return Py.newLong(modulo(getValue(),rightv, divide(getValue(),rightv))); } @Override @@ -556,7 +556,7 @@ return null; } BigInteger leftv = coerce(left); - return Py.newLong(modulo(leftv, value, divide(leftv, value))); + return Py.newLong(modulo(leftv, getValue(), divide(leftv, getValue()))); } @Override @@ -571,8 +571,8 @@ } BigInteger rightv = coerce(right); - BigInteger xdivy = divide(value, rightv); - return new PyTuple(Py.newLong(xdivy), Py.newLong(modulo(value, rightv, xdivy))); + BigInteger xdivy = divide(getValue(),rightv); + return new PyTuple(Py.newLong(xdivy), Py.newLong(modulo(getValue(),rightv, xdivy))); } @Override @@ -587,8 +587,8 @@ } BigInteger leftv = coerce(left); - BigInteger xdivy = divide(leftv, value); - return new PyTuple(Py.newLong(xdivy), Py.newLong(modulo(leftv, value, xdivy))); + BigInteger xdivy = divide(leftv, getValue()); + return new PyTuple(Py.newLong(xdivy), Py.newLong(modulo(leftv, getValue(), xdivy))); } @Override @@ -606,7 +606,7 @@ if (modulo != null && !canCoerce(right)) { return null; } - return _pow(value, coerce(right), modulo, this, right); + return _pow( getValue(), coerce(right), modulo, this, right); } @Override @@ -619,7 +619,7 @@ if (!canCoerce(left)) { return null; } - return _pow(coerce(left), value, null, left, this); + return _pow(coerce(left), getValue(), null, left, this); } public static PyObject _pow(BigInteger value, BigInteger y, PyObject modulo, PyObject left, @@ -693,7 +693,7 @@ if (rightv < 0) { throw Py.ValueError("negative shift count"); } - return Py.newLong(value.shiftLeft(rightv)); + return Py.newLong(getValue().shiftLeft(rightv)); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___rlshift___doc) @@ -701,7 +701,7 @@ if (!canCoerce(left)) { return null; } - if (value.intValue() < 0) { + if (getValue().intValue() < 0) { throw Py.ValueError("negative shift count"); } return Py.newLong(coerce(left).shiftLeft(coerceInt(this))); @@ -721,7 +721,7 @@ if (rightv < 0) { throw Py.ValueError("negative shift count"); } - return Py.newLong(value.shiftRight(rightv)); + return Py.newLong(getValue().shiftRight(rightv)); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___rrshift___doc) @@ -729,7 +729,7 @@ if (!canCoerce(left)) { return null; } - if (value.intValue() < 0) { + if (getValue().intValue() < 0) { throw Py.ValueError("negative shift count"); } return Py.newLong(coerce(left).shiftRight(coerceInt(this))); @@ -745,7 +745,7 @@ if (!canCoerce(right)) { return null; } - return Py.newLong(value.and(coerce(right))); + return Py.newLong(getValue().and(coerce(right))); } @Override @@ -758,7 +758,7 @@ if (!canCoerce(left)) { return null; } - return Py.newLong(coerce(left).and(value)); + return Py.newLong(coerce(left).and(getValue())); } @Override @@ -771,7 +771,7 @@ if (!canCoerce(right)) { return null; } - return Py.newLong(value.xor(coerce(right))); + return Py.newLong(getValue().xor(coerce(right))); } @Override @@ -784,7 +784,7 @@ if (!canCoerce(left)) { return null; } - return Py.newLong(coerce(left).xor(value)); + return Py.newLong(coerce(left).xor(getValue())); } @Override @@ -797,7 +797,7 @@ if (!canCoerce(right)) { return null; } - return Py.newLong(value.or(coerce(right))); + return Py.newLong(getValue().or(coerce(right))); } @Override @@ -810,7 +810,7 @@ if (!canCoerce(left)) { return null; } - return Py.newLong(coerce(left).or(value)); + return Py.newLong(coerce(left).or(getValue())); } @Override @@ -820,7 +820,7 @@ @ExposedMethod(doc = BuiltinDocs.long___neg___doc) final PyObject long___neg__() { - return Py.newLong(value.negate()); + return Py.newLong(getValue().negate()); } @Override @@ -840,7 +840,7 @@ @ExposedMethod(doc = BuiltinDocs.long___abs___doc) final PyObject long___abs__() { - if (value.signum() == -1) { + if (getValue().signum() == -1) { return long___neg__(); } return long___long__(); @@ -853,7 +853,7 @@ @ExposedMethod(doc = BuiltinDocs.long___invert___doc) final PyObject long___invert__() { - return Py.newLong(value.not()); + return Py.newLong(getValue().not()); } @Override @@ -863,8 +863,8 @@ @ExposedMethod(doc = BuiltinDocs.long___int___doc) final PyObject long___int__() { - if (value.compareTo(PyInteger.MAX_INT) <= 0 && value.compareTo(PyInteger.MIN_INT) >= 0) { - return Py.newInteger(value.intValue()); + if (getValue().compareTo(PyInteger.MAX_INT) <= 0 && getValue().compareTo(PyInteger.MIN_INT) >= 0) { + return Py.newInteger(getValue().intValue()); } return long___long__(); } @@ -879,7 +879,7 @@ if (getType() == TYPE) { return this; } - return Py.newLong(value); + return Py.newLong(getValue()); } @Override @@ -908,7 +908,7 @@ @ExposedMethod(doc = BuiltinDocs.long___oct___doc) final PyString long___oct__() { - String s = value.toString(8); + String s = getValue().toString(8); if (s.startsWith("-")) { return new PyString("-0" + s.substring(1, s.length()) + "L"); } else if (s.startsWith("0")) { @@ -925,7 +925,7 @@ @ExposedMethod(doc = BuiltinDocs.long___hex___doc) final PyString long___hex__() { - String s = value.toString(16); + String s = getValue().toString(16); if (s.startsWith("-")) { return new PyString("-0x" + s.substring(1, s.length()) + "L"); } else { @@ -935,12 +935,12 @@ @Override public PyString __str__() { - return Py.newString(value.toString()); + return Py.newString(getValue().toString()); } @Override public PyUnicode __unicode__() { - return new PyUnicode(value.toString()); + return new PyUnicode(getValue().toString()); } @ExposedMethod(doc = BuiltinDocs.long___getnewargs___doc) @@ -970,15 +970,15 @@ @Override public int asIndex(PyObject err) { - boolean tooLow = value.compareTo(PyInteger.MIN_INT) < 0; - boolean tooHigh = value.compareTo(PyInteger.MAX_INT) > 0; + boolean tooLow = getValue().compareTo(PyInteger.MIN_INT) < 0; + boolean tooHigh = getValue().compareTo(PyInteger.MAX_INT) > 0; if (tooLow || tooHigh) { if (err != null) { throw new PyException(err, "cannot fit 'long' into an index-sized integer"); } return tooLow ? Integer.MIN_VALUE : Integer.MAX_VALUE; } - return (int) value.longValue(); + return (int) getValue().longValue(); } @Override 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-15 14:14:11
|
Revision: 7095 http://jython.svn.sourceforge.net/jython/?rev=7095&view=rev Author: zyasoft Date: 2010-08-15 14:14:05 +0000 (Sun, 15 Aug 2010) Log Message: ----------- Update for r7094 Modified Paths: -------------- trunk/jython/NEWS Modified: trunk/jython/NEWS =================================================================== --- trunk/jython/NEWS 2010-08-15 14:09:10 UTC (rev 7094) +++ trunk/jython/NEWS 2010-08-15 14:14:05 UTC (rev 7095) @@ -2,6 +2,7 @@ Jython 2.5.2b2 Bugs Fixed + - [ 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 - [ 1395 ] PyList.indexOf() and PyTuple.indexOf() do not function properly 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-14 21:00:25
|
Revision: 7093 http://jython.svn.sourceforge.net/jython/?rev=7093&view=rev Author: zyasoft Date: 2010-08-14 21:00:19 +0000 (Sat, 14 Aug 2010) Log Message: ----------- Removed JSR223TestCase.test_eval, it was causing action at a distance issues in the regrtest. Modified Paths: -------------- trunk/jython/Lib/test/test_jsr223.py Modified: trunk/jython/Lib/test/test_jsr223.py =================================================================== --- trunk/jython/Lib/test/test_jsr223.py 2010-08-14 18:52:58 UTC (rev 7092) +++ trunk/jython/Lib/test/test_jsr223.py 2010-08-14 21:00:19 UTC (rev 7093) @@ -1,30 +1,28 @@ -# test for ScriptEngine, otherwise we are not in Java 6/JSR223 support added +# XXX Earlier version of this test also tested put, get, eval on the +# engine, however this introduced action at a distance where aspects +# of the sys state changed (notably sys.stdin.newlines), which then +# impacted test_univnewlines later in the regrtest. +# +# For now, there may be limits in how much we can test Jython from +# itself, no matter how attractive from an ouroboros perspective that +# may be :). Certainly worth revisiting in 2.6. -# test each feature - -import sys import unittest -from javax.script import ScriptEngine, ScriptEngineManager +import sys from test import test_support +from javax.script import ScriptEngine, ScriptEngineManager 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 + engine = ScriptEngineManager().getEngineByName("python") + f = 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.assertNotEqual(f.scriptEngine, engine) # we don't pool engines + self.assertEqual(f.engineName, "jython") self.assertEqual(f.engineVersion, impl_version) self.assertEqual(set(f.extensions), set(['py'])) @@ -32,7 +30,7 @@ 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) @@ -42,8 +40,6 @@ self.assertEqual(f.getOutputStatement("abc"), "print u'abc'") self.assertEqual(f.getProgram("x = 42", "y = 'abc'"), "x = 42\ny = 'abc'\n") - - def test_main(): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-08-14 18:53:04
|
Revision: 7092 http://jython.svn.sourceforge.net/jython/?rev=7092&view=rev Author: zyasoft Date: 2010-08-14 18:52:58 +0000 (Sat, 14 Aug 2010) Log Message: ----------- Some additional testing of serializability of Jython builtin functions. This was intended for #1604, but actually not necessary. Modified Paths: -------------- trunk/jython/Lib/test/test_java_integration.py Modified: trunk/jython/Lib/test/test_java_integration.py =================================================================== --- trunk/jython/Lib/test/test_java_integration.py 2010-08-14 18:51:36 UTC (rev 7091) +++ trunk/jython/Lib/test/test_java_integration.py 2010-08-14 18:52:58 UTC (rev 7092) @@ -525,7 +525,13 @@ serialized_code = roundtrip_serialization(universal_answer.func_code) self.assertEqual(eval(serialized_code), universal_answer()) + def test_builtin_names(self): + import __builtin__ + names = [x for x in dir(__builtin__)] + self.assertEqual(names, roundtrip_serialization(names)) + + class CopyTest(unittest.TestCase): def test_copy(self): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2010-08-14 18:51:42
|
Revision: 7091 http://jython.svn.sourceforge.net/jython/?rev=7091&view=rev Author: zyasoft Date: 2010-08-14 18:51:36 +0000 (Sat, 14 Aug 2010) Log Message: ----------- Add Serialization marker interface to PyBuiltinCallable.Info. Fixes #1604. Modified Paths: -------------- trunk/jython/src/org/python/core/PyBuiltinCallable.java Modified: trunk/jython/src/org/python/core/PyBuiltinCallable.java =================================================================== --- trunk/jython/src/org/python/core/PyBuiltinCallable.java 2010-08-14 17:17:21 UTC (rev 7090) +++ trunk/jython/src/org/python/core/PyBuiltinCallable.java 2010-08-14 18:51:36 UTC (rev 7091) @@ -1,6 +1,8 @@ /* Copyright (c) Jython Developers */ package org.python.core; +import java.io.Serializable; + import org.python.expose.ExposedGet; import org.python.expose.ExposedType; @@ -65,7 +67,7 @@ } } - public interface Info { + public interface Info extends Serializable { String getName(); 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-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-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-09 20:58:30
|
Revision: 7087 http://jython.svn.sourceforge.net/jython/?rev=7087&view=rev Author: zyasoft Date: 2010-08-09 20:58:24 +0000 (Mon, 09 Aug 2010) Log Message: ----------- Missing file from the last commit, necessary for test_java_integration copy testing Added Paths: ----------- trunk/jython/tests/java/javatests/ProxyTests.java Added: trunk/jython/tests/java/javatests/ProxyTests.java =================================================================== --- trunk/jython/tests/java/javatests/ProxyTests.java (rev 0) +++ trunk/jython/tests/java/javatests/ProxyTests.java 2010-08-09 20:58:24 UTC (rev 7087) @@ -0,0 +1,38 @@ +package javatests; + +public class ProxyTests { + + public static class Person { + + // models conventions of names in certain parts of the world + + private String firstName; + private String lastName; + + public Person(String firstName, String lastName) { + this.firstName = firstName; + this.lastName = lastName; + } + + public String toString() { + return lastName + ", " + firstName; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + } + +} 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-06 14:11:53
|
Revision: 7085 http://jython.svn.sourceforge.net/jython/?rev=7085&view=rev Author: zyasoft Date: 2010-08-06 14:11:47 +0000 (Fri, 06 Aug 2010) Log Message: ----------- Missing NEWS item that #1559 was fixed in beta1 Modified Paths: -------------- trunk/jython/NEWS Modified: trunk/jython/NEWS =================================================================== --- trunk/jython/NEWS 2010-08-04 17:22:13 UTC (rev 7084) +++ trunk/jython/NEWS 2010-08-06 14:11:47 UTC (rev 7085) @@ -11,6 +11,7 @@ Jython 2.5.2b1 Bugs Fixed + - [ 1559 ] time.strptime broken for day of week for Sunday - [ 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 - [ 1605 ] float preference over PyComplex as arg to __call__ breaks logic 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. |