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. |