From: <pj...@us...> - 2008-06-14 05:37:37
|
Revision: 4621 http://jython.svn.sourceforge.net/jython/?rev=4621&view=rev Author: pjenvey Date: 2008-06-13 22:37:36 -0700 (Fri, 13 Jun 2008) Log Message: ----------- fix PyClassMethodDescr.__get__ called with one arg, or None as one of the args. convert to exposed annotations Modified Paths: -------------- trunk/jython/CoreExposed.includes trunk/jython/src/org/python/core/PyClassMethodDescr.java Modified: trunk/jython/CoreExposed.includes =================================================================== --- trunk/jython/CoreExposed.includes 2008-06-14 03:51:58 UTC (rev 4620) +++ trunk/jython/CoreExposed.includes 2008-06-14 05:37:36 UTC (rev 4621) @@ -4,6 +4,7 @@ org/python/core/PyBuiltinFunction.class org/python/core/PyCell.class org/python/core/PyClassMethod.class +org/python/core/PyClassMethodDescr.class org/python/core/PyComplex.class org/python/core/PyDataDescr.class org/python/core/PyDictionary.class Modified: trunk/jython/src/org/python/core/PyClassMethodDescr.java =================================================================== --- trunk/jython/src/org/python/core/PyClassMethodDescr.java 2008-06-14 03:51:58 UTC (rev 4620) +++ trunk/jython/src/org/python/core/PyClassMethodDescr.java 2008-06-14 05:37:36 UTC (rev 4621) @@ -1,19 +1,36 @@ package org.python.core; +import org.python.expose.ExposedMethod; +import org.python.expose.ExposedType; + +@ExposedType(name = "classmethod_descriptor") public class PyClassMethodDescr extends PyMethodDescr { + public static final PyType TYPE = PyType.fromClass(PyClassMethodDescr.class); + PyClassMethodDescr(PyType t, PyBuiltinFunction meth) { super(t, meth); } public PyObject __get__(PyObject obj, PyObject type) { - if (obj != null) { - checkGetterType(obj.getType()); - return meth.bind(obj.getType()); - } else if(type != null) { - checkGetterType((PyType)type); - return meth.bind(type); + return classmethod_descriptor___get__(obj, type); + } + + @ExposedMethod(defaults = "null") + public PyObject classmethod_descriptor___get__(PyObject obj, PyObject type) { + if (type == null || type == Py.None) { + if (obj != null) { + type = obj.getType(); + } else { + throw Py.TypeError(String.format("descriptor '%s' for type '%s' needs either an " + + " object or a type", name, dtype.fastGetName())); + } + } else if (!(type instanceof PyType)) { + throw Py.TypeError(String.format("descriptor '%s' for type '%s' needs a type, not a" + + " '%s' as arg 2", name, dtype.fastGetName(), + type.getType().fastGetName())); } - return this; + checkGetterType((PyType)type); + return meth.bind(type); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2008-06-15 04:35:32
|
Revision: 4639 http://jython.svn.sourceforge.net/jython/?rev=4639&view=rev Author: pjenvey Date: 2008-06-14 21:35:29 -0700 (Sat, 14 Jun 2008) Log Message: ----------- enable 2.5's test_descr in the regrtest with various tests disabled. give regrtest more memory for now until slices are fixed (they're currently broken, causing test_descr.slottrash to use a lot of memory) Modified Paths: -------------- trunk/jython/Lib/test/regrtest.py trunk/jython/Lib/test/test_descr.py trunk/jython/build.xml Modified: trunk/jython/Lib/test/regrtest.py =================================================================== --- trunk/jython/Lib/test/regrtest.py 2008-06-15 03:17:48 UTC (rev 4638) +++ trunk/jython/Lib/test/regrtest.py 2008-06-15 04:35:29 UTC (rev 4639) @@ -1035,7 +1035,6 @@ test_class test_copy test_dis - test_descr test_descrtut test_eof test_frozen Modified: trunk/jython/Lib/test/test_descr.py =================================================================== --- trunk/jython/Lib/test/test_descr.py 2008-06-15 03:17:48 UTC (rev 4638) +++ trunk/jython/Lib/test/test_descr.py 2008-06-15 04:35:29 UTC (rev 4639) @@ -1,9 +1,14 @@ # Test enhancements related to descriptors and new-style classes -from test.test_support import verify, vereq, verbose, TestFailed, TESTFN, get_original_stdout +from test.test_support import verify, vereq, verbose, TestFailed, TESTFN, get_original_stdout, is_jython from copy import deepcopy import warnings import types +if is_jython: + from test_weakref import extra_collect +else: + def extra_collect(): + pass warnings.filterwarnings("ignore", r'complex divmod\(\), // and % are deprecated$', @@ -339,8 +344,8 @@ verify('im_self' in dir(a.Amethod)) # Try a module subclass. - import sys - class M(type(sys)): + from types import ModuleType + class M(ModuleType): pass minstance = M("m") minstance.b = 2 @@ -692,13 +697,15 @@ class _instance(object): pass class M2(object): - @staticmethod + # XXX: Jython 2.3 + #@staticmethod def __new__(cls, name, bases, dict): self = object.__new__(cls) self.name = name self.bases = bases self.dict = dict return self + __new__ = staticmethod(__new__) def __call__(self): it = _instance() # Early binding of methods @@ -824,8 +831,7 @@ def pymods(): if verbose: print "Testing Python subclass of module..." log = [] - import sys - MT = type(sys) + from types import ModuleType as MT class MM(MT): def __init__(self, name): MT.__init__(self, name) @@ -1965,6 +1971,7 @@ r = weakref.ref(c) verify(r() is c) del c + extra_collect() verify(r() is None) del r class NoWeak(object): @@ -1975,13 +1982,16 @@ except TypeError, msg: verify(str(msg).find("weak reference") >= 0) else: - verify(0, "weakref.ref(no) should be illegal") + # XXX: Jython allows a weakref here + if not is_jython: + verify(0, "weakref.ref(no) should be illegal") class Weak(object): __slots__ = ['foo', '__weakref__'] yes = Weak() r = weakref.ref(yes) verify(r() is yes) del yes + extra_collect() verify(r() is None) del r @@ -2170,9 +2180,11 @@ aProp = property(lambda self: "foo") class Sub(Base): - @classmethod + # XXX: Jython 2.3 + #@classmethod def test(klass): return super(Sub,klass).aProp + test = classmethod(test) veris(Sub.test(), Base.aProp) @@ -3311,6 +3323,7 @@ c = C() vereq(log, []) del c + extra_collect() vereq(log, [1]) class D(object): pass @@ -3417,7 +3430,11 @@ if verbose: print "Testing dict-proxy iterkeys..." keys = [ key for key in C.__dict__.iterkeys() ] keys.sort() - vereq(keys, ['__dict__', '__doc__', '__module__', '__weakref__', 'meth']) + if is_jython: + # XXX: It should include __doc__, but no __weakref__ (for now) + vereq(keys, ['__dict__', '__module__', 'meth']) + else: + vereq(keys, ['__dict__', '__doc__', '__module__', '__weakref__', 'meth']) def dictproxyitervalues(): class C(object): @@ -3425,7 +3442,8 @@ pass if verbose: print "Testing dict-proxy itervalues..." values = [ values for values in C.__dict__.itervalues() ] - vereq(len(values), 5) + # XXX: See dictproxyiterkeys + vereq(len(values), is_jython and 3 or 5) def dictproxyiteritems(): class C(object): @@ -3434,7 +3452,10 @@ if verbose: print "Testing dict-proxy iteritems..." keys = [ key for (key, value) in C.__dict__.iteritems() ] keys.sort() - vereq(keys, ['__dict__', '__doc__', '__module__', '__weakref__', 'meth']) + if is_jython: + vereq(keys, ['__dict__', '__module__', 'meth']) + else: + vereq(keys, ['__dict__', '__doc__', '__module__', '__weakref__', 'meth']) def funnynew(): if verbose: print "Testing __new__ returning something unexpected..." @@ -4126,6 +4147,11 @@ attr = Descr() c = C() + if is_jython: + # XXX: 'attr' key is a Java String in PyStringMap, which + # prevents Evil's __eq__ from being called. Force __eq__ by + # using a dict instead + c.__dict__ = {} c.__dict__[Evil()] = 0 vereq(c.attr, 1) @@ -4354,6 +4380,57 @@ notimplemented, test_assign_slice, ] + if is_jython: + for testfunc in [ + # Requires CPython specific xxsubtype module + spamlists, + spamdicts, + classmethods_in_c, + staticmethods_in_c, + + # pjenvey broke slots + slots, + slotspecials, + + # Jython allows subclassing of classes it shouldn't (like + # builtin_function_or_method): + # http://bugs.jython.org/issue1758319 + errors, + + # Requires validation of mro() results + # http://bugs.jython.org/issue1056 + altmro, + + # CPython's unicode.__cmp__ is derived from type (and only + # takes 1 arg) + specials, + + # Jython file lacks doc strings + descrdoc, + + # Already fixed on the pep352 branch + setdict, + + # New style classes don't support __del__: + # http://bugs.jython.org/issue1057 + delhook, + subtype_resurrection, + + # Lack __basicsize__: http://bugs.jython.org/issue1017 + slotmultipleinheritance, + + # Carlo hacked us: http://bugs.jython.org/issue1058 + carloverre, + + # Jython lacks CPython method-wrappers (though maybe this + # should pass anyway?) + methodwrapper, + + # __ixxx__ doesn't act like a binary op + # http://bugs.jython.org/issue1873148 + notimplemented + ]: + testfuncs.remove(testfunc) if __name__ == '__main__': import sys if len(sys.argv) > 1: @@ -4364,7 +4441,8 @@ for testfunc in testfuncs: try: - print "*"*40 + if verbose: + print "*"*40 testfunc() except Exception, e: if isinstance(e, KeyboardInterrupt) or n == 1: @@ -4372,7 +4450,8 @@ print "-->", testfunc.__name__, "FAILURE(%d/%d)" % (success, n), str(e) else: success += 1 - print "-->", testfunc.__name__, "OK(%d/%d)" % (success, n) + if verbose: + print "-->", testfunc.__name__, "OK(%d/%d)" % (success, n) if n != success: raise TestFailed, "%d/%d" % (success, n) Modified: trunk/jython/build.xml =================================================================== --- trunk/jython/build.xml 2008-06-15 03:17:48 UTC (rev 4638) +++ trunk/jython/build.xml 2008-06-15 04:35:29 UTC (rev 4639) @@ -728,6 +728,8 @@ </target> <target name="regrtest" depends="developer-build"> <exec executable="${dist.dir}/bin/jython"> + <!-- Temporarily give regrtest more memory until slots are fixed --> + <arg value="-J-Xmx128m"/> <arg value="${dist.dir}/Lib/test/regrtest.py"/> <!-- Only run the tests that are expected to work on Jython --> <arg value="--expected"/> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2008-06-15 20:29:51
|
Revision: 4641 http://jython.svn.sourceforge.net/jython/?rev=4641&view=rev Author: pjenvey Date: 2008-06-15 13:29:43 -0700 (Sun, 15 Jun 2008) Log Message: ----------- context manager-ize file Modified Paths: -------------- trunk/jython/Lib/test/test_file.py trunk/jython/src/org/python/core/PyFile.java Modified: trunk/jython/Lib/test/test_file.py =================================================================== --- trunk/jython/Lib/test/test_file.py 2008-06-15 05:13:59 UTC (rev 4640) +++ trunk/jython/Lib/test/test_file.py 2008-06-15 20:29:43 UTC (rev 4641) @@ -5,7 +5,7 @@ from array import array from weakref import proxy -from test.test_support import TESTFN, findfile, run_unittest +from test.test_support import TESTFN, findfile, is_jython, run_unittest from UserList import UserList class AutoFileTests(unittest.TestCase): @@ -19,14 +19,16 @@ self.f.close() os.remove(TESTFN) - # XXX: assumes CPython style garbage collection - def _testWeakRefs(self): + def testWeakRefs(self): # verify weak references p = proxy(self.f) p.write('teststring') self.assertEquals(self.f.tell(), p.tell()) self.f.close() self.f = None + if is_jython: + from test_weakref import extra_collect + extra_collect() self.assertRaises(ReferenceError, getattr, p, 'tell') def testAttributes(self): @@ -111,9 +113,7 @@ methods.remove('truncate') # __exit__ should close the file - # XXX: __exit__ is 2.5 specific - #self.f.__exit__(None, None, None) - self.f.close() + self.f.__exit__(None, None, None) self.assert_(self.f.closed) for methodname, arg in methods.iteritems(): @@ -125,8 +125,6 @@ self.assertRaises(ValueError, method, arg) self.assertRaises(ValueError, self.f.writelines, []) - # XXX: __exit__ is 2.5 specific - return # file is closed, __exit__ shouldn't do anything self.assertEquals(self.f.__exit__(None, None, None), None) # it must also return None if an exception was given @@ -149,9 +147,7 @@ f.close() self.fail('%r is an invalid file mode' % mode) - # XXX: Jython's stdin can't seek, it's not backed by a - # RandomAccessFile - def _testStdin(self): + def testStdin(self): # This causes the interpreter to exit on OSF1 v5.1. if sys.platform != 'osf1V5': self.assertRaises(IOError, sys.stdin.seek, -1) @@ -232,8 +228,7 @@ finally: os.unlink(TESTFN) - # XXX: Jython allows mixing reads with iteration - def _testIteration(self): + def testIteration(self): # Test the complex interaction when mixing file-iteration and the # various read* methods. Ostensibly, the mixture could just be tested # to work when it should work according to the Python language, @@ -346,6 +341,13 @@ def test_main(): + if is_jython: + # Jython's stdin can't seek, it's not backed by a + # RandomAccessFile + del OtherFileTests.testStdin + # Jython allows mixing reads with iteration + del OtherFileTests.testIteration + # Historically, these tests have been sloppy about removing TESTFN. # So get rid of it no matter what. try: Modified: trunk/jython/src/org/python/core/PyFile.java =================================================================== --- trunk/jython/src/org/python/core/PyFile.java 2008-06-15 05:13:59 UTC (rev 4640) +++ trunk/jython/src/org/python/core/PyFile.java 2008-06-15 20:29:43 UTC (rev 4641) @@ -386,14 +386,18 @@ return file_next(); } - @ExposedMethod - final PyObject file_xreadlines() { + @ExposedMethod(names = {"__enter__", "xreadlines"}) + final PyObject file_self() { checkClosed(); return this; } + public PyObject __enter__() { + return file_self(); + } + public PyObject xreadlines() { - return file_xreadlines(); + return file_self(); } @ExposedMethod @@ -484,6 +488,15 @@ file_close(); } + @ExposedMethod + final void file___exit__(PyObject type, PyObject value, PyObject traceback) { + file_close(); + } + + public void __exit__(PyObject type, PyObject value, PyObject traceback) { + file___exit__(type, value, traceback); + } + @ExposedMethod(defaults = {"null"}) final void file_truncate(PyObject position) { if (position == null) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2008-06-18 20:01:38
|
Revision: 4666 http://jython.svn.sourceforge.net/jython/?rev=4666&view=rev Author: pjenvey Date: 2008-06-18 13:01:28 -0700 (Wed, 18 Jun 2008) Log Message: ----------- fix slotted objects always having a __dict__ which was broken in r4303. match the CPython slot behavior in test_slots_jy. and fix the test_descr slots tests Modified Paths: -------------- trunk/jython/Lib/test/test_descr.py trunk/jython/build.xml trunk/jython/src/org/python/core/PyType.java Added Paths: ----------- trunk/jython/Lib/test/test_slots_jy.py Modified: trunk/jython/Lib/test/test_descr.py =================================================================== --- trunk/jython/Lib/test/test_descr.py 2008-06-18 14:59:31 UTC (rev 4665) +++ trunk/jython/Lib/test/test_descr.py 2008-06-18 20:01:28 UTC (rev 4666) @@ -1251,7 +1251,10 @@ raise TestFailed, "[unichr(128)] slots not caught" # Test leaks - class Counted(object): + # XXX: Jython new style classes don't support __del__ + # http://bugs.jython.org/issue1057 + class Counted: + #class Counted(object): counter = 0 # counts the number of instances alive def __init__(self): Counted.counter += 1 @@ -1265,6 +1268,7 @@ x.c = Counted() vereq(Counted.counter, 3) del x + extra_collect() vereq(Counted.counter, 0) class D(C): pass @@ -1273,6 +1277,7 @@ x.z = Counted() vereq(Counted.counter, 2) del x + extra_collect() vereq(Counted.counter, 0) class E(D): __slots__ = ['e'] @@ -1282,6 +1287,7 @@ x.e = Counted() vereq(Counted.counter, 3) del x + extra_collect() vereq(Counted.counter, 0) # Test cyclical leaks [SF bug 519621] @@ -1294,8 +1300,13 @@ s = None import gc gc.collect() + extra_collect() vereq(Counted.counter, 0) + # XXX: This tests a CPython GC reference count bug and Jython lacks + # gc.get_objects + import sys + """ # Test lookup leaks [SF bug 572567] import sys,gc class G(object): @@ -1307,6 +1318,7 @@ g==g new_objects = len(gc.get_objects()) vereq(orig_objects, new_objects) + """ class H(object): __slots__ = ['a', 'b'] def __init__(self): @@ -1321,6 +1333,7 @@ h = H() try: del h + extra_collect() finally: sys.stderr = save_stderr @@ -1335,6 +1348,9 @@ a.foo = 42 vereq(a.__dict__, {"foo": 42}) + # XXX: Jython doesn't support __weakref__ + return + class W(object): __slots__ = ["__weakref__"] a = W() @@ -4388,10 +4404,6 @@ classmethods_in_c, staticmethods_in_c, - # pjenvey broke slots - slots, - slotspecials, - # Jython allows subclassing of classes it shouldn't (like # builtin_function_or_method): # http://bugs.jython.org/issue1758319 Added: trunk/jython/Lib/test/test_slots_jy.py =================================================================== --- trunk/jython/Lib/test/test_slots_jy.py (rev 0) +++ trunk/jython/Lib/test/test_slots_jy.py 2008-06-18 20:01:28 UTC (rev 4666) @@ -0,0 +1,133 @@ +"""Slot tests + +Made for Jython. +""" +import test_support +import unittest + +# The strict tests fail on PyPy (but work on CPython and Jython). +# They're questionable +strict = True + +class SlottedTestCase(unittest.TestCase): + + def test_slotted(self): + class Foo(object): + __slots__ = 'bar' + self.assert_('__dict__' not in Foo.__dict__) + foo = Foo() + self.assert_(not hasattr(foo, '__dict__')) + foo.bar = 'hello bar' + self.assertEqual(foo.bar, 'hello bar') + self.assertRaises(AttributeError, setattr, foo, 'foo', 'hello foo') + + class Baz(object): + __slots__ = ['python', 'jython'] + self.assert_('__dict__' not in Baz.__dict__) + baz = Baz() + self.assert_(not hasattr(baz, '__dict__')) + baz.python = 'hello python' + baz.jython = 'hello jython' + self.assertEqual(baz.python, 'hello python') + self.assertEqual(baz.jython, 'hello jython') + self.assertRaises(AttributeError, setattr, baz, 'foo', 'hello') + + +class SlottedWithDictTestCase(unittest.TestCase): + + def test_subclass(self): + class Base(object): + pass + class Foo(Base): + __slots__ = 'bar' + self.assert_('__dict__' not in Foo.__dict__) + foo = Foo() + self.assert_(hasattr(foo, '__dict__')) + foo.bar = 'hello bar' + foo.foo = 'hello foo' + self.assertEqual(foo.bar, 'hello bar') + self.assertEqual(foo.__dict__, {'foo': 'hello foo'}) + + def test_subclass_mro(self): + class Base(object): + pass + class Slotted(object): + __slots__ = 'baz' + class Foo(Slotted, Base): + __slots__ = 'bar' + if strict: + self.assert_('__dict__' in Foo.__dict__) + self.assertEqual(Foo.__dict__['__dict__'].__objclass__, Foo) + foo = Foo() + self.assert_(hasattr(foo, '__dict__')) + foo.bar = 'hello bar' + foo.baz = 'hello baz' + foo.foo = 'hello foo' + self.assertEqual(foo.bar, 'hello bar') + self.assertEqual(foo.baz, 'hello baz') + self.assertEqual(foo.__dict__, {'foo': 'hello foo'}) + + class Bar(Slotted, Base): + pass + if strict: + self.assert_('__dict__' in Bar.__dict__) + self.assertEqual(Bar.__dict__['__dict__'].__objclass__, Bar) + bar = Bar() + self.assert_(hasattr(bar, '__dict__')) + bar.bar = 'hello bar' + bar.baz = 'hello baz' + bar.foo = 'hello foo' + self.assertEqual(bar.bar, 'hello bar') + self.assertEqual(bar.baz, 'hello baz') + self.assertEqual(bar.__dict__, {'foo': 'hello foo', 'bar': 'hello bar'}) + + def test_subclass_oldstyle(self): + class OldBase: + pass + class Foo(OldBase, object): + __slots__ = 'bar' + if strict: + self.assert_('__dict__' in Foo.__dict__) + self.assertEqual(Foo.__dict__['__dict__'].__objclass__, Foo) + foo = Foo() + self.assert_(hasattr(foo, '__dict__')) + foo.bar = 'hello bar' + foo.foo = 'hello foo' + self.assertEqual(foo.bar, 'hello bar') + self.assertEqual(foo.__dict__, {'foo': 'hello foo'}) + + class Bar(OldBase, object): + __slots__ = '__dict__' + self.assert_('__dict__' in Bar.__dict__) + self.assertEqual(Bar.__dict__['__dict__'].__objclass__, Bar) + bar = Bar() + self.assert_(hasattr(bar, '__dict__')) + bar.bar = 'hello bar' + bar.foo = 'hello foo' + self.assertEqual(bar.bar, 'hello bar') + self.assertEqual(bar.__dict__, {'foo': 'hello foo', 'bar': 'hello bar'}) + + def test_mixin_oldstyle(self): + class OldBase: + pass + class NewBase(object): + pass + class Baz(NewBase, OldBase): + __slots__ = 'baz' + self.assert_('__dict__' not in Baz.__dict__) + baz = Baz() + self.assert_(hasattr(baz, '__dict__')) + baz.baz = 'hello baz' + baz.bar = 'hello bar' + self.assertEqual(baz.baz, 'hello baz') + self.assertEqual(baz.bar, 'hello bar') + self.assertEqual(baz.__dict__, {'bar': 'hello bar'}) + + +def test_main(): + test_support.run_unittest(SlottedTestCase, + SlottedWithDictTestCase) + + +if __name__ == '__main__': + test_main() Modified: trunk/jython/build.xml =================================================================== --- trunk/jython/build.xml 2008-06-18 14:59:31 UTC (rev 4665) +++ trunk/jython/build.xml 2008-06-18 20:01:28 UTC (rev 4666) @@ -728,8 +728,6 @@ </target> <target name="regrtest" depends="developer-build"> <exec executable="${dist.dir}/bin/jython"> - <!-- Temporarily give regrtest more memory until slots are fixed --> - <arg value="-J-Xmx128m"/> <arg value="${dist.dir}/Lib/test/regrtest.py"/> <!-- Only run the tests that are expected to work on Jython --> <arg value="--expected"/> Modified: trunk/jython/src/org/python/core/PyType.java =================================================================== --- trunk/jython/src/org/python/core/PyType.java 2008-06-18 14:59:31 UTC (rev 4665) +++ trunk/jython/src/org/python/core/PyType.java 2008-06-18 20:01:28 UTC (rev 4666) @@ -70,7 +70,7 @@ private boolean needs_finalizer; /** Whether this type's instances require a __dict__. */ - private boolean needs_userdict = true; + private boolean needs_userdict = false; /** The number of __slots__ defined. */ private int numSlots; @@ -172,8 +172,15 @@ newtype.bases = bases_list; PyObject slots = dict.__finditem__("__slots__"); - if (slots != null) { - newtype.needs_userdict = false; + boolean needsDictDescr = false; + if (slots == null) { + newtype.needs_userdict = true; + // a dict descriptor is required if base doesn't already provide a dict + needsDictDescr = !newtype.base.needs_userdict; + } else { + // have slots, but may inherit a dict + newtype.needs_userdict = newtype.base.needs_userdict; + if (slots instanceof PyString) { addSlot(newtype, slots); } else { @@ -181,10 +188,33 @@ addSlot(newtype, slotname); } } + + if (!newtype.base.needs_userdict && newtype.needs_userdict) { + // base doesn't provide dict but addSlot found the __dict__ slot + needsDictDescr = true; + } else if (bases_list.length > 0 && !newtype.needs_userdict) { + // secondary bases may provide dict + for (PyObject base : bases_list) { + if (base == newtype.base) { + // Skip primary base + continue; + } + if (base instanceof PyClass) { + // Classic base class provides dict + newtype.needs_userdict = true; + needsDictDescr = true; + break; + } + PyType tmpType = (PyType)base; + if (tmpType.needs_userdict) { + newtype.needs_userdict = true; + needsDictDescr = true; + // Nothing more to check + break; + } + } + } } - if (!newtype.needs_userdict) { - newtype.needs_userdict = necessitatesUserdict(bases_list); - } newtype.tp_flags = Py.TPFLAGS_HEAPTYPE; @@ -196,7 +226,7 @@ newtype.mro_internal(); // __dict__ descriptor - if (newtype.needs_userdict && newtype.lookup("__dict__") == null) { + if (needsDictDescr && dict.__finditem__("__dict__") == null) { dict.__setitem__("__dict__", new PyDataDescr(newtype, "__dict__", PyObject.class) { @Override @@ -832,17 +862,6 @@ return best; } - private static boolean necessitatesUserdict(PyObject[] bases_list) { - for (int i = 0; i < bases_list.length; i++) { - PyObject cur = bases_list[i]; - if ((cur instanceof PyType && ((PyType)cur).needs_userdict) - || cur instanceof PyClass) { - return true; - } - } - return false; - } - /** * Finds the most derived subtype of initialMetatype in the types * of bases, or initialMetatype if it is already the most derived. @@ -883,6 +902,9 @@ confirmIdentifier(slotname); String slotstring = mangleName(newtype.name, slotname.toString()); if (slotstring.equals("__dict__")) { + if (newtype.base.needs_userdict || newtype.needs_userdict) { + throw Py.TypeError("__dict__ slot disallowed: we already got one"); + } newtype.needs_userdict = true; } else if (newtype.dict.__finditem__(slotstring) == null) { newtype.dict.__setitem__(slotstring, new PySlot(newtype, slotstring, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2008-06-18 23:22:04
|
Revision: 4670 http://jython.svn.sourceforge.net/jython/?rev=4670&view=rev Author: pjenvey Date: 2008-06-18 16:21:51 -0700 (Wed, 18 Jun 2008) Log Message: ----------- o fix mro_internal to validate mro() results with solid_base o rerarrange solid_base to search down __bases__ instead of __mro__ which may not be defined yet fixes #1056 and test_descr.altmro Modified Paths: -------------- trunk/jython/Lib/test/test_descr.py trunk/jython/src/org/python/core/PyType.java Modified: trunk/jython/Lib/test/test_descr.py =================================================================== --- trunk/jython/Lib/test/test_descr.py 2008-06-18 22:08:10 UTC (rev 4669) +++ trunk/jython/Lib/test/test_descr.py 2008-06-18 23:21:51 UTC (rev 4670) @@ -4409,10 +4409,6 @@ # http://bugs.jython.org/issue1758319 errors, - # Requires validation of mro() results - # http://bugs.jython.org/issue1056 - altmro, - # CPython's unicode.__cmp__ is derived from type (and only # takes 1 arg) specials, Modified: trunk/jython/src/org/python/core/PyType.java =================================================================== --- trunk/jython/src/org/python/core/PyType.java 2008-06-18 22:08:10 UTC (rev 4669) +++ trunk/jython/src/org/python/core/PyType.java 2008-06-18 23:21:51 UTC (rev 4670) @@ -582,10 +582,31 @@ } private void mro_internal() { - if (getType().underlying_class != PyType.class && getType().lookup("mro") != null) { - mro = Py.make_array(getType().lookup("mro").__get__(null, getType()).__call__(this)); + if (getType() == TYPE) { + mro = compute_mro(); } else { - mro = compute_mro(); + PyObject mroDescr = getType().lookup("mro"); + if (mroDescr == null) { + throw Py.AttributeError("mro"); + } + PyObject[] result = Py.make_array(mroDescr.__get__(null, getType()).__call__(this)); + + PyType solid = solid_base(this); + for (PyObject cls : result) { + if (cls instanceof PyClass) { + continue; + } + if (!(cls instanceof PyType)) { + throw Py.TypeError(String.format("mro() returned a non-class ('%.500s')", + cls.getType().fastGetName())); + } + PyType t = (PyType)cls; + if (!solid.isSubType(solid_base(t))) { + throw Py.TypeError(String.format("mro() returned base with unsuitable layout " + + "('%.500s')", t.fastGetName())); + } + } + mro = result; } } @@ -802,22 +823,16 @@ } /** - * Finds the parent of base with an underlying_class or with slots - * - * @raises Py.TypeError if there is no solid base for base + * Finds the parent of type with an underlying_class or with slots. */ - private static PyType solid_base(PyType base) { - PyObject[] mro = base.mro; - for (int i = 0; i < mro.length; i++) { - PyObject parent = mro[i]; - if (parent instanceof PyType) { - PyType parent_type = (PyType)parent; - if (isSolidBase(parent_type)) { - return parent_type; - } + private static PyType solid_base(PyType type) { + do { + if (isSolidBase(type)) { + return type; } - } - throw Py.TypeError("base without solid base"); + type = type.base; + } while (type != null); + return PyObject.TYPE; } private static boolean isSolidBase(PyType type) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <nr...@us...> - 2008-06-20 03:00:20
|
Revision: 4689 http://jython.svn.sourceforge.net/jython/?rev=4689&view=rev Author: nriley Date: 2008-06-19 20:00:18 -0700 (Thu, 19 Jun 2008) Log Message: ----------- Use correct variable name for classpath delimiter when profiling; test this behavior (related JRuby bug filed as JRUBY-2678). Modified Paths: -------------- trunk/jython/src/shell/jython trunk/jython/tests/shell/test-jython.sh Modified: trunk/jython/src/shell/jython =================================================================== --- trunk/jython/src/shell/jython 2008-06-20 02:56:16 UTC (rev 4688) +++ trunk/jython/src/shell/jython 2008-06-20 03:00:18 UTC (rev 4689) @@ -169,7 +169,7 @@ if [ -n "$profile_requested" ] ; then echo "Running with instrumented profiler" - java_args=("${java_args[@]}" -classpath "$CP$CP_SEPARATOR$CLASSPATH") + java_args=("${java_args[@]}" -classpath "$CP$CP_DELIMITER$CLASSPATH") else if [ -z $help_requested ] ; then JAVA_CMD="exec $JAVA_CMD" Modified: trunk/jython/tests/shell/test-jython.sh =================================================================== --- trunk/jython/tests/shell/test-jython.sh 2008-06-20 02:56:16 UTC (rev 4688) +++ trunk/jython/tests/shell/test-jython.sh 2008-06-20 03:00:18 UTC (rev 4689) @@ -49,6 +49,16 @@ [ `egrep -c "^\| Thread depth limit:"` == 1 ] [ -f profile.txt ] && rm profile.txt + # $CLASSPATH + CLASSPATH="$JYTHON_HOME/Lib/test/blob.jar" \ + "$JYTHON" -c "print __import__('Blob')" | \ + [ `egrep -c "^Blob"` == 1 ] + + # $CLASSPATH + profiling + CLASSPATH="$JYTHON_HOME/Lib/test/blob.jar" \ + "$JYTHON" --profile -c "print __import__('Blob')" | \ + [ `egrep -c "^Blob"` == 1 ] + set +ex done This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pj...@us...> - 2008-06-20 05:20:12
|
Revision: 4691 http://jython.svn.sourceforge.net/jython/?rev=4691&view=rev Author: pjenvey Date: 2008-06-19 22:20:10 -0700 (Thu, 19 Jun 2008) Log Message: ----------- update operator to 2.5 (minus the inplace operations). add attr/itemgetter and nuke __is__ and __is_not__ which don't exist Modified Paths: -------------- trunk/jython/CoreExposed.includes trunk/jython/src/org/python/modules/operator.java Modified: trunk/jython/CoreExposed.includes =================================================================== --- trunk/jython/CoreExposed.includes 2008-06-20 03:02:18 UTC (rev 4690) +++ trunk/jython/CoreExposed.includes 2008-06-20 05:20:10 UTC (rev 4691) @@ -39,6 +39,8 @@ org/python/modules/_weakref/ProxyType.class org/python/modules/collections/PyDefaultDict.class org/python/modules/collections/PyDeque.class +org/python/modules/operator$PyAttrGetter.class +org/python/modules/operator$PyItemGetter.class org/python/modules/random/PyRandom.class org/python/modules/thread/PyLocal.class org/python/modules/time/PyTimeTuple.class Modified: trunk/jython/src/org/python/modules/operator.java =================================================================== --- trunk/jython/src/org/python/modules/operator.java 2008-06-20 03:02:18 UTC (rev 4690) +++ trunk/jython/src/org/python/modules/operator.java 2008-06-20 05:20:10 UTC (rev 4691) @@ -2,6 +2,10 @@ package org.python.modules; import org.python.core.*; +import org.python.expose.ExposedGet; +import org.python.expose.ExposedMethod; +import org.python.expose.ExposedNew; +import org.python.expose.ExposedType; class OperatorFunctions extends PyBuiltinFunctionSet { @@ -204,9 +208,9 @@ dict.__setitem__("pow", new OperatorFunctions("pow", 36, 2)); dict.__setitem__("__pow__", new OperatorFunctions("pow", 36, 2)); dict.__setitem__("is_", new OperatorFunctions("is_", 37, 2)); - dict.__setitem__("__is__", new OperatorFunctions("__is__", 37, 2)); dict.__setitem__("is_not", new OperatorFunctions("is_not", 38, 2)); - dict.__setitem__("__is_not__", new OperatorFunctions("__is_not__", 38, 2)); + dict.__setitem__("attrgetter", PyAttrGetter.TYPE); + dict.__setitem__("itemgetter", PyItemGetter.TYPE); } public static int countOf(PyObject seq, PyObject item) { @@ -230,4 +234,115 @@ } throw Py.ValueError("sequence.index(x): x not in list"); } + + /** + * The attrgetter type. + */ + // XXX: not subclassable + @ExposedType(name = "operator.attrgetter") + static class PyAttrGetter extends PyObject { + + public static final PyType TYPE = PyType.fromClass(PyAttrGetter.class); + + public PyObject[] attrs; + + public PyAttrGetter(PyObject[] attrs) { + this.attrs = attrs; + } + + @ExposedNew + final static PyObject attrgetter___new__(PyNewWrapper new_, boolean init, PyType subtype, + PyObject[] args, String[] keywords) { + ArgParser ap = new ArgParser("attrgetter", args, keywords, "attr"); + ap.noKeywords(); + ap.getPyObject(0); + return new PyAttrGetter(args); + } + + @Override + public PyObject __call__(PyObject[] args, String[] keywords) { + return attrgetter___call__(args, keywords); + } + + @ExposedMethod + final PyObject attrgetter___call__(PyObject[] args, String[] keywords) { + ArgParser ap = new ArgParser("attrgetter", args, Py.NoKeywords, "obj"); + PyObject obj = ap.getPyObject(0); + + if (attrs.length == 1) { + return getattr(obj, attrs[0]); + } + + PyObject[] result = new PyObject[attrs.length]; + int i = 0; + for (PyObject attr : attrs) { + result[i++] = getattr(obj, attr); + } + return new PyTuple(result); + } + + private PyObject getattr(PyObject obj, PyObject name) { + // XXX: We should probably have a PyObject.__getattr__(PyObject) that does + // this. This is different than __builtin__.getattr (in how it handles + // exceptions) + String nameStr; + if (name instanceof PyUnicode) { + nameStr = ((PyUnicode)name).encode(); + } else if (name instanceof PyString) { + nameStr = name.asString(); + } else { + throw Py.TypeError(String.format("attribute name must be string, not '%.200s'", + name.getType().fastGetName())); + } + return obj.__getattr__(nameStr.intern()); + } + + } + + /** + * The itemgetter type. + */ + // XXX: not subclassable + @ExposedType(name = "operator.itemgetter") + static class PyItemGetter extends PyObject { + + public static final PyType TYPE = PyType.fromClass(PyItemGetter.class); + + public PyObject[] items; + + public PyItemGetter(PyObject[] items) { + this.items = items; + } + + @ExposedNew + final static PyObject itemgetter___new__(PyNewWrapper new_, boolean init, PyType subtype, + PyObject[] args, String[] keywords) { + ArgParser ap = new ArgParser("itemgetter", args, keywords, "attr"); + ap.noKeywords(); + ap.getPyObject(0); + return new PyItemGetter(args); + } + + @Override + public PyObject __call__(PyObject[] args, String[] keywords) { + return itemgetter___call__(args, keywords); + } + + @ExposedMethod + final PyObject itemgetter___call__(PyObject[] args, String[] keywords) { + ArgParser ap = new ArgParser("itemgetter", args, Py.NoKeywords, "obj"); + PyObject obj = ap.getPyObject(0); + + if (items.length == 1) { + return obj.__getitem__(items[0]); + } + + PyObject[] result = new PyObject[items.length]; + int i = 0; + for (PyObject item : items) { + result[i++] = obj.__getitem__(item); + } + return new PyTuple(result); + } + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <zy...@us...> - 2008-06-23 21:54:56
|
Revision: 4727 http://jython.svn.sourceforge.net/jython/?rev=4727&view=rev Author: zyasoft Date: 2008-06-23 14:54:55 -0700 (Mon, 23 Jun 2008) Log Message: ----------- Merged revisions 4090-4091,4097,4115-4116,4121,4136,4142 via svnmerge from https://jython.svn.sourceforge.net/svnroot/jython/branches/utf16 ........ r4090 | zyasoft | 2008-02-02 17:46:27 -0700 (Sat, 02 Feb 2008) | 1 line escape, UTF-8, UTF-16, UTF-7 codecs working against an UTF-16 encoding in PyUnicode backing string ........ r4091 | zyasoft | 2008-02-02 19:35:17 -0700 (Sat, 02 Feb 2008) | 1 line ord/unichr tests are now passing in test_builtin, this of course has to take in account codepoints being one or two codeunits (chars) ........ r4097 | zyasoft | 2008-02-04 09:53:33 -0700 (Mon, 04 Feb 2008) | 1 line We now throw the exceptions that test_unicode expects; added version of test_unicode (still needs cleanup) that does not test for lone surrogate codepoint support. We of course need to add the opposite soon. ........ r4115 | zyasoft | 2008-02-09 08:16:37 -0700 (Sat, 09 Feb 2008) | 1 line For PyUnicode, implements most of the necessary UTF-16 aware modifications (or at least the approaches for doing so), still need to support negative stepping on subsequences and IDN/Punycode ........ r4116 | zyasoft | 2008-02-09 14:17:57 -0700 (Sat, 09 Feb 2008) | 1 line Now supports negative strides for subsequences on UTF-16 encoded strings ........ r4121 | zyasoft | 2008-02-10 00:33:33 -0700 (Sun, 10 Feb 2008) | 1 line Completed utf16 mods for PyUnicode. Need to add some optimizations including some per Charlie Groves. ........ r4136 | zyasoft | 2008-02-16 15:34:41 -0700 (Sat, 16 Feb 2008) | 1 line Added punycode support ........ r4142 | zyasoft | 2008-02-16 19:26:36 -0700 (Sat, 16 Feb 2008) | 1 line Widened SRE to use UCS-4 codepoints instead of UCS-2 ........ Modified Paths: -------------- trunk/jython/Lib/test/string_tests.py trunk/jython/src/org/python/core/Py.java trunk/jython/src/org/python/core/PyList.java trunk/jython/src/org/python/core/PyString.java trunk/jython/src/org/python/core/PySystemState.java trunk/jython/src/org/python/core/PyUnicode.java trunk/jython/src/org/python/core/__builtin__.java trunk/jython/src/org/python/core/codecs.java trunk/jython/src/org/python/modules/_codecs.java trunk/jython/src/org/python/modules/_sre.java trunk/jython/src/org/python/modules/sre/PatternObject.java trunk/jython/src/org/python/modules/sre/SRE_STATE.java Added Paths: ----------- trunk/jython/Lib/test/test_unicode.py Property Changed: ---------------- trunk/jython/ Property changes on: trunk/jython ___________________________________________________________________ Name: svnmerge-integrated - /branches/utf16:1-4089 + /branches/utf16:1-4726 Modified: trunk/jython/Lib/test/string_tests.py =================================================================== --- trunk/jython/Lib/test/string_tests.py 2008-06-23 21:40:58 UTC (rev 4726) +++ trunk/jython/Lib/test/string_tests.py 2008-06-23 21:54:55 UTC (rev 4727) @@ -185,7 +185,7 @@ self.checkequal(['a', 'b', 'c d'], 'a b c d', 'split', None, 2) self.checkequal(['a', 'b', 'c', 'd'], 'a b c d ', 'split') self.checkequal(['a', 'b', 'c', 'd'], 'a//b//c//d', 'split', '//') - self.checkequal(['endcase ', ''], 'endcase test', 'split', 'test') + #self.checkequal(['endcase ', ''], 'endcase test', 'split', 'test') self.checkraises(TypeError, 'hello', 'split', 42, 42, 42) Copied: trunk/jython/Lib/test/test_unicode.py (from rev 4142, branches/utf16/Lib/test/test_unicode.py) =================================================================== --- trunk/jython/Lib/test/test_unicode.py (rev 0) +++ trunk/jython/Lib/test/test_unicode.py 2008-06-23 21:54:55 UTC (rev 4727) @@ -0,0 +1,718 @@ +# -*- coding: iso-8859-1 -*- +""" Test script for the Unicode implementation. + +Written by Marc-Andre Lemburg (ma...@le...). + +(c) Copyright CNRI, All Rights Reserved. NO WARRANTY. + +"""#" +import unittest, sys, string, codecs, new +from test import test_support, string_tests + +class UnicodeTest( + string_tests.CommonTest, + string_tests.MixinStrUnicodeUserStringTest + ): + type2test = unicode + + def checkequalnofix(self, result, object, methodname, *args): + method = getattr(object, methodname) + realresult = method(*args) + self.assertEqual(realresult, result) + self.assert_(type(realresult) is type(result)) + + # if the original is returned make sure that + # this doesn't happen with subclasses + if realresult is object: + class usub(unicode): + def __repr__(self): + return 'usub(%r)' % unicode.__repr__(self) + object = usub(object) + method = getattr(object, methodname) + realresult = method(*args) + self.assertEqual(realresult, result) + self.assert_(object is not realresult) + + def test_repr(self): + if not sys.platform.startswith('java'): + # Test basic sanity of repr() + self.assertEqual(repr(u'abc'), "u'abc'") + self.assertEqual(repr(u'ab\\c'), "u'ab\\\\c'") + self.assertEqual(repr(u'ab\\'), "u'ab\\\\'") + self.assertEqual(repr(u'\\c'), "u'\\\\c'") + self.assertEqual(repr(u'\\'), "u'\\\\'") + self.assertEqual(repr(u'\n'), "u'\\n'") + self.assertEqual(repr(u'\r'), "u'\\r'") + self.assertEqual(repr(u'\t'), "u'\\t'") + self.assertEqual(repr(u'\b'), "u'\\x08'") + self.assertEqual(repr(u"'\""), """u'\\'"'""") + self.assertEqual(repr(u"'\""), """u'\\'"'""") + self.assertEqual(repr(u"'"), '''u"'"''') + self.assertEqual(repr(u'"'), """u'"'""") + latin1repr = ( + "u'\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\t\\n\\x0b\\x0c\\r" + "\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a" + "\\x1b\\x1c\\x1d\\x1e\\x1f !\"#$%&\\'()*+,-./0123456789:;<=>?@ABCDEFGHI" + "JKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\\x7f" + "\\x80\\x81\\x82\\x83\\x84\\x85\\x86\\x87\\x88\\x89\\x8a\\x8b\\x8c\\x8d" + "\\x8e\\x8f\\x90\\x91\\x92\\x93\\x94\\x95\\x96\\x97\\x98\\x99\\x9a\\x9b" + "\\x9c\\x9d\\x9e\\x9f\\xa0\\xa1\\xa2\\xa3\\xa4\\xa5\\xa6\\xa7\\xa8\\xa9" + "\\xaa\\xab\\xac\\xad\\xae\\xaf\\xb0\\xb1\\xb2\\xb3\\xb4\\xb5\\xb6\\xb7" + "\\xb8\\xb9\\xba\\xbb\\xbc\\xbd\\xbe\\xbf\\xc0\\xc1\\xc2\\xc3\\xc4\\xc5" + "\\xc6\\xc7\\xc8\\xc9\\xca\\xcb\\xcc\\xcd\\xce\\xcf\\xd0\\xd1\\xd2\\xd3" + "\\xd4\\xd5\\xd6\\xd7\\xd8\\xd9\\xda\\xdb\\xdc\\xdd\\xde\\xdf\\xe0\\xe1" + "\\xe2\\xe3\\xe4\\xe5\\xe6\\xe7\\xe8\\xe9\\xea\\xeb\\xec\\xed\\xee\\xef" + "\\xf0\\xf1\\xf2\\xf3\\xf4\\xf5\\xf6\\xf7\\xf8\\xf9\\xfa\\xfb\\xfc\\xfd" + "\\xfe\\xff'") + testrepr = repr(u''.join(map(unichr, xrange(256)))) + self.assertEqual(testrepr, latin1repr) + + def test_count(self): + string_tests.CommonTest.test_count(self) + # check mixed argument types + self.checkequalnofix(3, 'aaa', 'count', u'a') + self.checkequalnofix(0, 'aaa', 'count', u'b') + self.checkequalnofix(3, u'aaa', 'count', 'a') + self.checkequalnofix(0, u'aaa', 'count', 'b') + self.checkequalnofix(0, u'aaa', 'count', 'b') + self.checkequalnofix(1, u'aaa', 'count', 'a', -1) + self.checkequalnofix(3, u'aaa', 'count', 'a', -10) + self.checkequalnofix(2, u'aaa', 'count', 'a', 0, -1) + self.checkequalnofix(0, u'aaa', 'count', 'a', 0, -10) + + def test_find(self): + self.checkequalnofix(0, u'abcdefghiabc', 'find', u'abc') + self.checkequalnofix(9, u'abcdefghiabc', 'find', u'abc', 1) + self.checkequalnofix(-1, u'abcdefghiabc', 'find', u'def', 4) + + self.assertRaises(TypeError, u'hello'.find) + self.assertRaises(TypeError, u'hello'.find, 42) + + def test_rfind(self): + string_tests.CommonTest.test_rfind(self) + # check mixed argument types + self.checkequalnofix(9, 'abcdefghiabc', 'rfind', u'abc') + self.checkequalnofix(12, 'abcdefghiabc', 'rfind', u'') + self.checkequalnofix(12, u'abcdefghiabc', 'rfind', '') + + def test_index(self): + string_tests.CommonTest.test_index(self) + # check mixed argument types + for (t1, t2) in ((str, unicode), (unicode, str)): + self.checkequalnofix(0, t1('abcdefghiabc'), 'index', t2('')) + self.checkequalnofix(3, t1('abcdefghiabc'), 'index', t2('def')) + self.checkequalnofix(0, t1('abcdefghiabc'), 'index', t2('abc')) + self.checkequalnofix(9, t1('abcdefghiabc'), 'index', t2('abc'), 1) + self.assertRaises(ValueError, t1('abcdefghiabc').index, t2('hib')) + self.assertRaises(ValueError, t1('abcdefghiab').index, t2('abc'), 1) + self.assertRaises(ValueError, t1('abcdefghi').index, t2('ghi'), 8) + self.assertRaises(ValueError, t1('abcdefghi').index, t2('ghi'), -1) + + def test_rindex(self): + string_tests.CommonTest.test_rindex(self) + # check mixed argument types + for (t1, t2) in ((str, unicode), (unicode, str)): + self.checkequalnofix(12, t1('abcdefghiabc'), 'rindex', t2('')) + self.checkequalnofix(3, t1('abcdefghiabc'), 'rindex', t2('def')) + self.checkequalnofix(9, t1('abcdefghiabc'), 'rindex', t2('abc')) + self.checkequalnofix(0, t1('abcdefghiabc'), 'rindex', t2('abc'), 0, -1) + + self.assertRaises(ValueError, t1('abcdefghiabc').rindex, t2('hib')) + self.assertRaises(ValueError, t1('defghiabc').rindex, t2('def'), 1) + self.assertRaises(ValueError, t1('defghiabc').rindex, t2('abc'), 0, -1) + self.assertRaises(ValueError, t1('abcdefghi').rindex, t2('ghi'), 0, 8) + self.assertRaises(ValueError, t1('abcdefghi').rindex, t2('ghi'), 0, -1) + + def test_translate(self): + self.checkequalnofix(u'bbbc', u'abababc', 'translate', {ord('a'):None}) + self.checkequalnofix(u'iiic', u'abababc', 'translate', {ord('a'):None, ord('b'):ord('i')}) + self.checkequalnofix(u'iiix', u'abababc', 'translate', {ord('a'):None, ord('b'):ord('i'), ord('c'):u'x'}) + self.checkequalnofix(u'<i><i><i>c', u'abababc', 'translate', {ord('a'):None, ord('b'):u'<i>'}) + self.checkequalnofix(u'c', u'abababc', 'translate', {ord('a'):None, ord('b'):u''}) + self.checkequalnofix(u'xyyx', u'xzx', 'translate', {ord('z'):u'yy'}) + + self.assertRaises(TypeError, u'hello'.translate) + self.assertRaises(TypeError, u'abababc'.translate, {ord('a'):''}) + + def test_split(self): + string_tests.CommonTest.test_split(self) + + # Mixed arguments + self.checkequalnofix([u'a', u'b', u'c', u'd'], u'a//b//c//d', 'split', '//') + self.checkequalnofix([u'a', u'b', u'c', u'd'], 'a//b//c//d', 'split', u'//') + # 2.5 (and perhaps before) requires that the separator be a non-empty string + # self.checkequalnofix([u'endcase ', u''], u'endcase test', 'split', 'test') + + def test_join(self): + string_tests.MixinStrUnicodeUserStringTest.test_join(self) + + # mixed arguments + self.checkequalnofix(u'a b c d', u' ', 'join', ['a', 'b', u'c', u'd']) + self.checkequalnofix(u'abcd', u'', 'join', (u'a', u'b', u'c', u'd')) + self.checkequalnofix(u'w x y z', u' ', 'join', string_tests.Sequence('wxyz')) + self.checkequalnofix(u'a b c d', ' ', 'join', [u'a', u'b', u'c', u'd']) + self.checkequalnofix(u'a b c d', ' ', 'join', ['a', 'b', u'c', u'd']) + self.checkequalnofix(u'abcd', '', 'join', (u'a', u'b', u'c', u'd')) + self.checkequalnofix(u'w x y z', ' ', 'join', string_tests.Sequence(u'wxyz')) + + def test_strip(self): + string_tests.CommonTest.test_strip(self) + self.assertRaises(UnicodeError, u"hello".strip, "\xff") + + def test_replace(self): + string_tests.CommonTest.test_replace(self) + + # method call forwarded from str implementation because of unicode argument + self.checkequalnofix(u'one@two!three!', 'one!two!three!', 'replace', u'!', u'@', 1) + self.assertRaises(TypeError, 'replace'.replace, u"r", 42) + + def test_comparison(self): + # Comparisons: + self.assertEqual(u'abc', 'abc') + self.assertEqual('abc', u'abc') + self.assertEqual(u'abc', u'abc') + self.assert_(u'abcd' > 'abc') + self.assert_('abcd' > u'abc') + self.assert_(u'abcd' > u'abc') + self.assert_(u'abc' < 'abcd') + self.assert_('abc' < u'abcd') + self.assert_(u'abc' < u'abcd') + + if 0: + # Move these tests to a Unicode collation module test... + # Testing UTF-16 code point order comparisons... + + # No surrogates, no fixup required. + self.assert_(u'\u0061' < u'\u20ac') + # Non surrogate below surrogate value, no fixup required + #self.assert_(u'\u0061' < u'\ud800\udc02') + + # Non surrogate above surrogate value, fixup required + def test_lecmp(s, s2): + self.assert_(s < s2) + +# def test_fixup(s): +# s2 = u'\ud800\udc01' +# test_lecmp(s, s2) +# s2 = u'\ud900\udc01' +# test_lecmp(s, s2) +# s2 = u'\uda00\udc01' +# test_lecmp(s, s2) +# s2 = u'\udb00\udc01' +# test_lecmp(s, s2) +# s2 = u'\ud800\udd01' +# test_lecmp(s, s2) +# s2 = u'\ud900\udd01' +# test_lecmp(s, s2) +# s2 = u'\uda00\udd01' +# test_lecmp(s, s2) +# s2 = u'\udb00\udd01' +# test_lecmp(s, s2) +# s2 = u'\ud800\ude01' +# test_lecmp(s, s2) +# s2 = u'\ud900\ude01' +# test_lecmp(s, s2) +# s2 = u'\uda00\ude01' +# test_lecmp(s, s2) +# s2 = u'\udb00\ude01' +# test_lecmp(s, s2) +# s2 = u'\ud800\udfff' +# test_lecmp(s, s2) +# s2 = u'\ud900\udfff' +# test_lecmp(s, s2) +# s2 = u'\uda00\udfff' +# test_lecmp(s, s2) +# s2 = u'\udb00\udfff' +# test_lecmp(s, s2) + +# test_fixup(u'\ue000') +# test_fixup(u'\uff61') + + # Surrogates on both sides, no fixup required + # self.assert_(u'\ud800\udc02' < u'\ud84d\udc56') + + def test_islower(self): + string_tests.MixinStrUnicodeUserStringTest.test_islower(self) + self.checkequalnofix(False, u'\u1FFc', 'islower') + + def test_isupper(self): + string_tests.MixinStrUnicodeUserStringTest.test_isupper(self) + if not sys.platform.startswith('java'): + self.checkequalnofix(False, u'\u1FFc', 'isupper') + + def test_istitle(self): + string_tests.MixinStrUnicodeUserStringTest.test_title(self) + self.checkequalnofix(True, u'\u1FFc', 'istitle') + self.checkequalnofix(True, u'Greek \u1FFcitlecases ...', 'istitle') + + def test_isspace(self): + string_tests.MixinStrUnicodeUserStringTest.test_isspace(self) + self.checkequalnofix(True, u'\u2000', 'isspace') + self.checkequalnofix(True, u'\u200a', 'isspace') + self.checkequalnofix(False, u'\u2014', 'isspace') + + def test_isalpha(self): + string_tests.MixinStrUnicodeUserStringTest.test_isalpha(self) + self.checkequalnofix(True, u'\u1FFc', 'isalpha') + + def test_isdecimal(self): + self.checkequalnofix(False, u'', 'isdecimal') + self.checkequalnofix(False, u'a', 'isdecimal') + self.checkequalnofix(True, u'0', 'isdecimal') + self.checkequalnofix(False, u'\u2460', 'isdecimal') # CIRCLED DIGIT ONE + self.checkequalnofix(False, u'\xbc', 'isdecimal') # VULGAR FRACTION ONE QUARTER + self.checkequalnofix(True, u'\u0660', 'isdecimal') # ARABIC-INDIC DIGIT ZERO + self.checkequalnofix(True, u'0123456789', 'isdecimal') + self.checkequalnofix(False, u'0123456789a', 'isdecimal') + + self.checkraises(TypeError, 'abc', 'isdecimal', 42) + + def test_isdigit(self): + string_tests.MixinStrUnicodeUserStringTest.test_isdigit(self) + # JYTHON: U+2460 is CIRCLED DIGIT ONE; it's not a digit + # self.checkequalnofix(True, u'\u2460', 'isdigit') + self.checkequalnofix(False, u'\xbc', 'isdigit') + self.checkequalnofix(True, u'\u0660', 'isdigit') + + def test_isnumeric(self): + self.checkequalnofix(False, u'', 'isnumeric') + self.checkequalnofix(False, u'a', 'isnumeric') + self.checkequalnofix(True, u'0', 'isnumeric') + self.checkequalnofix(True, u'\u2460', 'isnumeric') + self.checkequalnofix(True, u'\xbc', 'isnumeric') + self.checkequalnofix(True, u'\u0660', 'isnumeric') + self.checkequalnofix(True, u'0123456789', 'isnumeric') + self.checkequalnofix(False, u'0123456789a', 'isnumeric') + + self.assertRaises(TypeError, u"abc".isnumeric, 42) + + def test_contains(self): + # Testing Unicode contains method + self.assert_('a' in u'abdb') + self.assert_('a' in u'bdab') + self.assert_('a' in u'bdaba') + self.assert_('a' in u'bdba') + self.assert_('a' in u'bdba') + self.assert_(u'a' in u'bdba') + self.assert_(u'a' not in u'bdb') + self.assert_(u'a' not in 'bdb') + self.assert_(u'a' in 'bdba') + self.assert_(u'a' in ('a',1,None)) + self.assert_(u'a' in (1,None,'a')) + self.assert_(u'a' in (1,None,u'a')) + self.assert_('a' in ('a',1,None)) + self.assert_('a' in (1,None,'a')) + self.assert_('a' in (1,None,u'a')) + self.assert_('a' not in ('x',1,u'y')) + self.assert_('a' not in ('x',1,None)) + self.assert_(u'abcd' not in u'abcxxxx') + self.assert_(u'ab' in u'abcd') + self.assert_('ab' in u'abc') + self.assert_(u'ab' in 'abc') + self.assert_(u'ab' in (1,None,u'ab')) + self.assert_(u'' in u'abc') + self.assert_('' in u'abc') + + # If the following fails either + # the contains operator does not propagate UnicodeErrors or + # someone has changed the default encoding + #self.assertRaises(UnicodeError, 'g\xe2teau'.__contains__, u'\xe2') + + self.assert_(u'' in '') + self.assert_('' in u'') + self.assert_(u'' in u'') + self.assert_(u'' in 'abc') + self.assert_('' in u'abc') + self.assert_(u'' in u'abc') + self.assert_(u'\0' not in 'abc') + self.assert_('\0' not in u'abc') + self.assert_(u'\0' not in u'abc') + self.assert_(u'\0' in '\0abc') + self.assert_('\0' in u'\0abc') + self.assert_(u'\0' in u'\0abc') + self.assert_(u'\0' in 'abc\0') + self.assert_('\0' in u'abc\0') + self.assert_(u'\0' in u'abc\0') + self.assert_(u'a' in '\0abc') + self.assert_('a' in u'\0abc') + self.assert_(u'a' in u'\0abc') + self.assert_(u'asdf' in 'asdf') + self.assert_('asdf' in u'asdf') + self.assert_(u'asdf' in u'asdf') + self.assert_(u'asdf' not in 'asd') + self.assert_('asdf' not in u'asd') + self.assert_(u'asdf' not in u'asd') + self.assert_(u'asdf' not in '') + self.assert_('asdf' not in u'') + self.assert_(u'asdf' not in u'') + + self.assertRaises(TypeError, u"abc".__contains__) + + def test_formatting(self): + string_tests.MixinStrUnicodeUserStringTest.test_formatting(self) + # Testing Unicode formatting strings... + self.assertEqual(u"%s, %s" % (u"abc", "abc"), u'abc, abc') + self.assertEqual(u"%s, %s, %i, %f, %5.2f" % (u"abc", "abc", 1, 2, 3), u'abc, abc, 1, 2.000000, 3.00') + self.assertEqual(u"%s, %s, %i, %f, %5.2f" % (u"abc", "abc", 1, -2, 3), u'abc, abc, 1, -2.000000, 3.00') + self.assertEqual(u"%s, %s, %i, %f, %5.2f" % (u"abc", "abc", -1, -2, 3.5), u'abc, abc, -1, -2.000000, 3.50') + self.assertEqual(u"%s, %s, %i, %f, %5.2f" % (u"abc", "abc", -1, -2, 3.57), u'abc, abc, -1, -2.000000, 3.57') + self.assertEqual(u"%s, %s, %i, %f, %5.2f" % (u"abc", "abc", -1, -2, 1003.57), u'abc, abc, -1, -2.000000, 1003.57') + if not sys.platform.startswith('java'): + self.assertEqual(u"%r, %r" % (u"abc", "abc"), u"u'abc', 'abc'") + self.assertEqual(u"%(x)s, %(y)s" % {'x':u"abc", 'y':"def"}, u'abc, def') + self.assertEqual(u"%(x)s, %(\xfc)s" % {'x':u"abc", u'\xfc':"def"}, u'abc, def') + + # self.assertEqual(u'%c' % 0x1234, u'\u1234') + # self.assertRaises(OverflowError, u"%c".__mod__, (sys.maxunicode+1,)) + + # formatting jobs delegated from the string implementation: + self.assertEqual('...%(foo)s...' % {'foo':u"abc"}, u'...abc...') + self.assertEqual('...%(foo)s...' % {'foo':"abc"}, '...abc...') + self.assertEqual('...%(foo)s...' % {u'foo':"abc"}, '...abc...') + self.assertEqual('...%(foo)s...' % {u'foo':u"abc"}, u'...abc...') + self.assertEqual('...%(foo)s...' % {u'foo':u"abc",'def':123}, u'...abc...') + self.assertEqual('...%(foo)s...' % {u'foo':u"abc",u'def':123}, u'...abc...') + self.assertEqual('...%s...%s...%s...%s...' % (1,2,3,u"abc"), u'...1...2...3...abc...') + self.assertEqual('...%%...%%s...%s...%s...%s...%s...' % (1,2,3,u"abc"), u'...%...%s...1...2...3...abc...') + self.assertEqual('...%s...' % u"abc", u'...abc...') + self.assertEqual('%*s' % (5,u'abc',), u' abc') + self.assertEqual('%*s' % (-5,u'abc',), u'abc ') + self.assertEqual('%*.*s' % (5,2,u'abc',), u' ab') + self.assertEqual('%*.*s' % (5,3,u'abc',), u' abc') + self.assertEqual('%i %*.*s' % (10, 5,3,u'abc',), u'10 abc') + self.assertEqual('%i%s %*.*s' % (10, 3, 5, 3, u'abc',), u'103 abc') + self.assertEqual('%c' % u'a', u'a') + + + def test_constructor(self): + # unicode(obj) tests (this maps to PyObject_Unicode() at C level) + + self.assertEqual( + unicode(u'unicode remains unicode'), + u'unicode remains unicode' + ) + + class UnicodeSubclass(unicode): + pass + + self.assertEqual( + unicode(UnicodeSubclass('unicode subclass becomes unicode')), + u'unicode subclass becomes unicode' + ) + + self.assertEqual( + unicode('strings are converted to unicode'), + u'strings are converted to unicode' + ) + + class UnicodeCompat: + def __init__(self, x): + self.x = x + def __unicode__(self): + return self.x + + self.assertEqual( + unicode(UnicodeCompat('__unicode__ compatible objects are recognized')), + u'__unicode__ compatible objects are recognized') + + class StringCompat: + def __init__(self, x): + self.x = x + def __str__(self): + return self.x + + self.assertEqual( + unicode(StringCompat('__str__ compatible objects are recognized')), + u'__str__ compatible objects are recognized' + ) + + # unicode(obj) is compatible to str(): + + o = StringCompat('unicode(obj) is compatible to str()') + self.assertEqual(unicode(o), u'unicode(obj) is compatible to str()') + self.assertEqual(str(o), 'unicode(obj) is compatible to str()') + + for obj in (123, 123.45, 123L): + self.assertEqual(unicode(obj), unicode(str(obj))) + + # unicode(obj, encoding, error) tests (this maps to + # PyUnicode_FromEncodedObject() at C level) + + if not sys.platform.startswith('java'): + self.assertRaises( + TypeError, + unicode, + u'decoding unicode is not supported', + 'utf-8', + 'strict' + ) + + self.assertEqual( + unicode('strings are decoded to unicode', 'utf-8', 'strict'), + u'strings are decoded to unicode' + ) + + if not sys.platform.startswith('java'): + self.assertEqual( + unicode( + buffer('character buffers are decoded to unicode'), + 'utf-8', + 'strict' + ), + u'character buffers are decoded to unicode' + ) + + self.assertRaises(TypeError, unicode, 42, 42, 42) + + def test_codecs_utf7(self): + utfTests = [ + (u'A\u2262\u0391.', 'A+ImIDkQ.'), # RFC2152 example + (u'Hi Mom -\u263a-!', 'Hi Mom -+Jjo--!'), # RFC2152 example + (u'\u65E5\u672C\u8A9E', '+ZeVnLIqe-'), # RFC2152 example + (u'Item 3 is \u00a31.', 'Item 3 is +AKM-1.'), # RFC2152 example + (u'+', '+-'), + (u'+-', '+--'), + (u'+?', '+-?'), + (u'\?', '+AFw?'), + (u'+?', '+-?'), + (ur'\\?', '+AFwAXA?'), + (ur'\\\?', '+AFwAXABc?'), + (ur'++--', '+-+---') + ] + + for (x, y) in utfTests: + self.assertEqual(x.encode('utf-7'), y) + + # surrogates not supported + self.assertRaises(UnicodeError, unicode, '+3ADYAA-', 'utf-7') + + self.assertEqual(unicode('+3ADYAA-', 'utf-7', 'replace'), u'\ufffd') + + def test_codecs_utf8(self): + self.assertEqual(u''.encode('utf-8'), '') + self.assertEqual(u'\u20ac'.encode('utf-8'), '\xe2\x82\xac') + #self.assertEqual(u'\ud800\udc02'.encode('utf-8'), '\xf0\x90\x80\x82') + #self.assertEqual(u'\ud84d\udc56'.encode('utf-8'), '\xf0\xa3\x91\x96') + #self.assertEqual(u'\ud800'.encode('utf-8'), '\xed\xa0\x80') + #self.assertEqual(u'\udc00'.encode('utf-8'), '\xed\xb0\x80') + #self.assertEqual( + # (u'\ud800\udc02'*1000).encode('utf-8'), + # '\xf0\x90\x80\x82'*1000 + #) + self.assertEqual( + u'\u6b63\u78ba\u306b\u8a00\u3046\u3068\u7ffb\u8a33\u306f' + u'\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002\u4e00' + u'\u90e8\u306f\u30c9\u30a4\u30c4\u8a9e\u3067\u3059\u304c' + u'\u3001\u3042\u3068\u306f\u3067\u305f\u3089\u3081\u3067' + u'\u3059\u3002\u5b9f\u969b\u306b\u306f\u300cWenn ist das' + u' Nunstuck git und'.encode('utf-8'), + '\xe6\xad\xa3\xe7\xa2\xba\xe3\x81\xab\xe8\xa8\x80\xe3\x81' + '\x86\xe3\x81\xa8\xe7\xbf\xbb\xe8\xa8\xb3\xe3\x81\xaf\xe3' + '\x81\x95\xe3\x82\x8c\xe3\x81\xa6\xe3\x81\x84\xe3\x81\xbe' + '\xe3\x81\x9b\xe3\x82\x93\xe3\x80\x82\xe4\xb8\x80\xe9\x83' + '\xa8\xe3\x81\xaf\xe3\x83\x89\xe3\x82\xa4\xe3\x83\x84\xe8' + '\xaa\x9e\xe3\x81\xa7\xe3\x81\x99\xe3\x81\x8c\xe3\x80\x81' + '\xe3\x81\x82\xe3\x81\xa8\xe3\x81\xaf\xe3\x81\xa7\xe3\x81' + '\x9f\xe3\x82\x89\xe3\x82\x81\xe3\x81\xa7\xe3\x81\x99\xe3' + '\x80\x82\xe5\xae\x9f\xe9\x9a\x9b\xe3\x81\xab\xe3\x81\xaf' + '\xe3\x80\x8cWenn ist das Nunstuck git und' + ) + + # UTF-8 specific decoding tests + self.assertEqual(unicode('\xf0\xa3\x91\x96', 'utf-8'), u'\U00023456' ) + self.assertEqual(unicode('\xf0\x90\x80\x82', 'utf-8'), u'\U00010002' ) + self.assertEqual(unicode('\xe2\x82\xac', 'utf-8'), u'\u20ac' ) + + # Other possible utf-8 test cases: + # * strict decoding testing for all of the + # UTF8_ERROR cases in PyUnicode_DecodeUTF8 + + def test_codecs_idna(self): + # Test whether trailing dot is preserved + self.assertEqual(u"www.python.org.".encode("idna"), "www.python.org.") + + def test_codecs_errors(self): + # Error handling (encoding) + self.assertRaises(UnicodeError, u'Andr\202 x'.encode, 'ascii') + self.assertRaises(UnicodeError, u'Andr\202 x'.encode, 'ascii','strict') + self.assertEqual(u'Andr\202 x'.encode('ascii','ignore'), "Andr x") + self.assertEqual(u'Andr\202 x'.encode('ascii','replace'), "Andr? x") + + # Error handling (decoding) + self.assertRaises(UnicodeError, unicode, 'Andr\202 x', 'ascii') + self.assertRaises(UnicodeError, unicode, 'Andr\202 x', 'ascii','strict') + self.assertEqual(unicode('Andr\202 x','ascii','ignore'), u"Andr x") + self.assertEqual(unicode('Andr\202 x','ascii','replace'), u'Andr\uFFFD x') + + # Error handling (unknown character names) + self.assertEqual("\\N{foo}xx".decode("unicode-escape", "ignore"), u"xx") + + # Error handling (truncated escape sequence) + self.assertRaises(UnicodeError, "\\".decode, "unicode-escape") + + # Error handling (bad decoder return) + def search_function(encoding): + def decode1(input, errors="strict"): + return 42 # not a tuple + def encode1(input, errors="strict"): + return 42 # not a tuple + def encode2(input, errors="strict"): + return (42, 42) # no unicode + def decode2(input, errors="strict"): + return (42, 42) # no unicode + if encoding=="test.unicode1": + return (encode1, decode1, None, None) + elif encoding=="test.unicode2": + return (encode2, decode2, None, None) + else: + return None + codecs.register(search_function) + self.assertRaises(TypeError, "hello".decode, "test.unicode1") + self.assertRaises(TypeError, unicode, "hello", "test.unicode2") + self.assertRaises(TypeError, u"hello".encode, "test.unicode1") + self.assertRaises(TypeError, u"hello".encode, "test.unicode2") + # executes PyUnicode_Encode() + import imp + self.assertRaises( + ImportError, + imp.find_module, + "non-existing module", + [u"non-existing dir"] + ) + + # Error handling (wrong arguments) + self.assertRaises(TypeError, u"hello".encode, 42, 42, 42) + + # Error handling (PyUnicode_EncodeDecimal()) + self.assertRaises(UnicodeError, int, u"\u0200") + + def test_codecs(self): + # Encoding + self.assertEqual(u'hello'.encode('ascii'), 'hello') + self.assertEqual(u'hello'.encode('utf-7'), 'hello') + self.assertEqual(u'hello'.encode('utf-8'), 'hello') + self.assertEqual(u'hello'.encode('utf8'), 'hello') + self.assertEqual(u'hello'.encode('utf-16-le'), 'h\000e\000l\000l\000o\000') + self.assertEqual(u'hello'.encode('utf-16-be'), '\000h\000e\000l\000l\000o') + self.assertEqual(u'hello'.encode('latin-1'), 'hello') + + # Roundtrip safety for BMP (just the first 1024 chars) + u = u''.join(map(unichr, xrange(1024))) + for encoding in ('utf-7', 'utf-8', 'utf-16', 'utf-16-le', 'utf-16-be', + 'raw_unicode_escape', 'unicode_escape', 'unicode_internal'): + self.assertEqual(unicode(u.encode(encoding),encoding), u) + + # Roundtrip safety for BMP (just the first 256 chars) + u = u''.join(map(unichr, xrange(256))) + for encoding in ('latin-1',): + self.assertEqual(unicode(u.encode(encoding),encoding), u) + + # Roundtrip safety for BMP (just the first 128 chars) + u = u''.join(map(unichr, xrange(128))) + for encoding in ('ascii',): + self.assertEqual(unicode(u.encode(encoding),encoding), u) + + # Roundtrip safety for non-BMP (just a few chars) + u = u'\U00010001\U00020002\U00030003\U00040004\U00050005' + for encoding in ('utf-8', 'utf-16', 'utf-16-le', 'utf-16-be', + #'raw_unicode_escape', + 'unicode_escape', 'unicode_internal'): + self.assertEqual(unicode(u.encode(encoding),encoding), u) + + # UTF-8 must be roundtrip safe for all UCS-2 code points + # This excludes surrogates: in the full range, there would be + # a surrogate pair (\udbff\udc00), which gets converted back + # to a non-BMP character (\U0010fc00) + u = u''.join(map(unichr, range(0,0xd800)+range(0xe000,0x10000))) + for encoding in ('utf-8',): + self.assertEqual(unicode(u.encode(encoding),encoding), u) + + def test_codecs_charmap(self): + # 0-127 + s = ''.join(map(chr, xrange(128))) + for encoding in ( + 'cp037', 'cp1026', + 'cp437', 'cp500', 'cp737', 'cp775', 'cp850', + 'cp852', 'cp855', 'cp860', 'cp861', 'cp862', + 'cp863', 'cp865', 'cp866', + 'iso8859_10', 'iso8859_13', 'iso8859_14', 'iso8859_15', + 'iso8859_2', 'iso8859_3', 'iso8859_4', 'iso8859_5', 'iso8859_6', + 'iso8859_7', 'iso8859_9', 'koi8_r', 'latin_1', + 'mac_cyrillic', 'mac_latin2', + + 'cp1250', 'cp1251', 'cp1252', 'cp1253', 'cp1254', 'cp1255', + 'cp1256', 'cp1257', 'cp1258', + 'cp856', 'cp857', 'cp864', 'cp869', 'cp874', + + 'mac_greek', 'mac_iceland','mac_roman', 'mac_turkish', + 'cp1006', 'iso8859_8', + + ### These have undefined mappings: + #'cp424', + + ### These fail the round-trip: + #'cp875' + + ): + self.assertEqual(unicode(s, encoding).encode(encoding), s) + + # 128-255 + s = ''.join(map(chr, xrange(128, 256))) + for encoding in ( + 'cp037', 'cp1026', + 'cp437', 'cp500', 'cp737', 'cp775', 'cp850', + 'cp852', 'cp855', 'cp860', 'cp861', 'cp862', + 'cp863', 'cp865', 'cp866', + 'iso8859_10', 'iso8859_13', 'iso8859_14', 'iso8859_15', + 'iso8859_2', 'iso8859_4', 'iso8859_5', + 'iso8859_9', 'koi8_r', 'latin_1', + 'mac_cyrillic', 'mac_latin2', + + ### These have undefined mappings: + #'cp1250', 'cp1251', 'cp1252', 'cp1253', 'cp1254', 'cp1255', + #'cp1256', 'cp1257', 'cp1258', + #'cp424', 'cp856', 'cp857', 'cp864', 'cp869', 'cp874', + #'iso8859_3', 'iso8859_6', 'iso8859_7', + #'mac_greek', 'mac_iceland','mac_roman', 'mac_turkish', + + ### These fail the round-trip: + #'cp1006', 'cp875', 'iso8859_8', + + ): + self.assertEqual(unicode(s, encoding).encode(encoding), s) + + def test_concatenation(self): + self.assertEqual((u"abc" u"def"), u"abcdef") + self.assertEqual(("abc" u"def"), u"abcdef") + self.assertEqual((u"abc" "def"), u"abcdef") + self.assertEqual((u"abc" u"def" "ghi"), u"abcdefghi") + self.assertEqual(("abc" "def" u"ghi"), u"abcdefghi") + + def test_printing(self): + class BitBucket: + def write(self, text): + pass + + out = BitBucket() + print >>out, u'abc' + print >>out, u'abc', u'def' + print >>out, u'abc', 'def' + print >>out, 'abc', u'def' + print >>out, u'abc\n' + print >>out, u'abc\n', + print >>out, u'abc\n', + print >>out, u'def\n' + print >>out, u'def\n' + + def test_ucs4(self): + if sys.maxunicode == 0xFFFF: + return + x = u'\U00100000' + y = x.encode("raw-unicode-escape").decode("raw-unicode-escape") + self.assertEqual(x, y) + +def test_main(): + test_support.run_unittest(UnicodeTest) + +if __name__ == "__main__": + test_main() Modified: trunk/jython/src/org/python/core/Py.java =================================================================== --- trunk/jython/src/org/python/core/Py.java 2008-06-23 21:40:58 UTC (rev 4726) +++ trunk/jython/src/org/python/core/Py.java 2008-06-23 21:54:55 UTC (rev 4727) @@ -22,15 +22,16 @@ import org.python.modules.errno; import org.python.parser.ast.modType; -public final class Py -{ +public final class Py { + static class SingletonResolver implements Serializable { + private String which; - + SingletonResolver(String which) { this.which = which; } - + private Object readResolve() throws ObjectStreamException { if (which.equals("None")) { return Py.None; @@ -39,56 +40,40 @@ } else if (which.equals("NotImplemented")) { return Py.NotImplemented; } - throw new StreamCorruptedException("unknown singleton: "+which); + throw new StreamCorruptedException("unknown singleton: " + which); } } - - /* Holds the singleton None and Ellipsis objects */ /** The singleton None Python object **/ public static PyObject None; - /** The singleton Ellipsis Python object - written as ... when indexing */ public static PyObject Ellipsis; - /** The singleton NotImplemented Python object. Used in rich comparison */ public static PyObject NotImplemented; - /** A zero-length array of Strings to pass to functions that - don't have any keyword arguments **/ + don't have any keyword arguments **/ public static String[] NoKeywords; - /** A zero-length array of PyObject's to pass to functions that - expect zero-arguments **/ + expect zero-arguments **/ public static PyObject[] EmptyObjects; - /** A frozenset with zero elements **/ public static PyFrozenSet EmptyFrozenSet; - /** A tuple with zero elements **/ public static PyTuple EmptyTuple; - /** The Python integer 0 **/ public static PyInteger Zero; - /** The Python integer 1 **/ public static PyInteger One; - /** The Python boolean False **/ public static PyBoolean False; - /** The Python boolean True **/ public static PyBoolean True; - /** A zero-length Python string **/ public static PyString EmptyString; - /** A Python string containing '\n' **/ public static PyString Newline; - /** A Python string containing ' ' **/ public static PyString Space; - /** Set if the type object is dynamically allocated */ public static long TPFLAGS_HEAPTYPE; @@ -102,9 +87,8 @@ } /** A unique object to indicate no conversion is possible - in __tojava__ methods **/ + in __tojava__ methods **/ public static Object NoConversion; - public static PyObject OSError; public static PyException OSError(String message) { return new PyException(Py.OSError, message); @@ -122,39 +106,38 @@ /* The standard Python exceptions */ public static PyObject OverflowError; + public static PyException OverflowError(String message) { return new PyException(Py.OverflowError, message); } - public static PyObject RuntimeError; + public static PyException RuntimeError(String message) { return new PyException(Py.RuntimeError, message); } - public static PyObject KeyboardInterrupt; /*public static PyException KeyboardInterrupt(String message) { - return new PyException(Py.KeyboardInterrupt, message); - }*/ - + return new PyException(Py.KeyboardInterrupt, message); + }*/ public static PyObject FloatingPointError; + public static PyException FloatingPointError(String message) { return new PyException(Py.FloatingPointError, message); } - public static PyObject SyntaxError; + public static PyException SyntaxError(String message) { return new PyException(Py.SyntaxError, message); } - public static PyObject IndentationError; public static PyObject TabError; - public static PyObject AttributeError; + public static PyException AttributeError(String message) { return new PyException(Py.AttributeError, message); } - public static PyObject IOError; + public static PyException IOError(java.io.IOException ioe) { String message = ioe.getMessage(); if (message == null) { @@ -166,6 +149,7 @@ } return new PyException(Py.IOError, message); } + public static PyException IOError(String message) { return new PyException(Py.IOError, message); } @@ -174,227 +158,213 @@ PyTuple args = new PyTuple(new PyInteger(errno), new PyString(message)); return new PyException(Py.IOError, args); } - public static PyObject KeyError; + public static PyException KeyError(String message) { return new PyException(Py.KeyError, message); } + public static PyException KeyError(PyObject key) { return new PyException(Py.KeyError, key); } - public static PyObject AssertionError; + public static PyException AssertionError(String message) { return new PyException(Py.AssertionError, message); } - public static PyObject TypeError; + public static PyException TypeError(String message) { return new PyException(Py.TypeError, message); } - public static PyObject ReferenceError; + public static PyException ReferenceError(String message) { return new PyException(Py.ReferenceError, message); } - public static PyObject SystemError; + public static PyException SystemError(String message) { return new PyException(Py.SystemError, message); } - public static PyObject IndexError; + public static PyException IndexError(String message) { return new PyException(Py.IndexError, message); } - public static PyObject ZeroDivisionError; + public static PyException ZeroDivisionError(String message) { return new PyException(Py.ZeroDivisionError, message); } - public static PyObject NameError; + public static PyException NameError(String message) { return new PyException(Py.NameError, message); } - public static PyObject UnboundLocalError; + public static PyException UnboundLocalError(String message) { return new PyException(Py.UnboundLocalError, message); } - public static PyObject SystemExit; - /*public static PyException SystemExit(String message) { - return new PyException(Py.SystemExit, message); - }*/ + static void maybeSystemExit(PyException exc) { - //System.err.println("maybeSystemExit: " + exc.type.toString()); if (Py.matchException(exc, Py.SystemExit)) { PyObject value = exc.value; - //System.err.println("exiting: "+value.getClass().getName()); if (value instanceof PyInstance) { PyObject tmp = value.__findattr__("code"); - if (tmp != null) + if (tmp != null) { value = tmp; + } } Py.getSystemState().callExitFunc(); if (value instanceof PyInteger) { - System.exit(((PyInteger)value).getValue()); + System.exit(((PyInteger) value).getValue()); } else { if (value != Py.None) { try { Py.println(value); System.exit(1); + } catch (Throwable t0) { } - catch (Throwable t0) { } } System.exit(0); } } } - public static PyObject StopIteration; + public static PyException StopIteration(String message) { return new PyException(Py.StopIteration, message); } - public static PyObject GeneratorExit; + public static PyException GeneratorExit(String message) { return new PyException(Py.GeneratorExit, message); } - public static PyObject ImportError; + public static PyException ImportError(String message) { return new PyException(Py.ImportError, message); } - public static PyObject ValueError; + public static PyException ValueError(String message) { return new PyException(Py.ValueError, message); } - public static PyObject UnicodeError; + public static PyException UnicodeError(String message) { return new PyException(Py.UnicodeError, message); } - public static PyObject UnicodeTranslateError; + public static PyException UnicodeTranslateError(String object, - int start, - int end, String reason) { + int start, + int end, String reason) { return new PyException(Py.UnicodeTranslateError, new PyTuple(new PyString(object), - new PyInteger(start), - new PyInteger(end), - new PyString(reason))); + new PyInteger(start), + new PyInteger(end), + new PyString(reason))); } - public static PyObject UnicodeDecodeError; public static PyException UnicodeDecodeError(String encoding, - String object, - int start, - int end, - String reason) { + String object, + int start, + int end, + String reason) { return new PyException(Py.UnicodeDecodeError, new PyTuple(new PyString(encoding), - new PyString(object), - new PyInteger(start), - new PyInteger(end), - new PyString(reason))); + new PyString(object), + new PyInteger(start), + new PyInteger(end), + new PyString(reason))); } - public static PyObject UnicodeEncodeError; public static PyException UnicodeEncodeError(String encoding, - String object, - int start, - int end, - String reason) { + String object, + int start, + int end, + String reason) { return new PyException(Py.UnicodeEncodeError, new PyTuple(new PyString(encoding), - new PyString(object), - new PyInteger(start), - new PyInteger(end), - new PyString(reason))); + new PyString(object), + new PyInteger(start), + new PyInteger(end), + new PyString(reason))); } - public static PyObject EOFError; + public static PyException EOFError(String message) { return new PyException(Py.EOFError, message); } - public static PyObject MemoryError; - + public static void memory_error(OutOfMemoryError t) { if (Options.showJavaExceptions) { t.printStackTrace(); } -// this logic would allow to re-enable the old behavior when it makes sense, -// or better offer a hook? -// try { -// byte[] alloc = new byte[(512*1024)]; -// } catch(OutOfMemoryError oome) { -// System.err.println("Out Of Memory"); -// System.err.println("You might want to try the -mx flag to increase heap size."); -// System.exit(-1); -// } } public static PyException MemoryError(String message) { return new PyException(Py.MemoryError, message); } - public static PyObject ArithmeticError; public static PyObject LookupError; public static PyObject StandardError; public static PyObject Exception; - public static PyObject Warning; + public static void Warning(String message) { warning(Warning, message); } - public static PyObject UserWarning; + public static void UserWarning(String message) { warning(UserWarning, message); } - public static PyObject DeprecationWarning; + public static void DeprecationWarning(String message) { warning(DeprecationWarning, message); } - public static PyObject PendingDeprecationWarning; + public static void PendingDeprecationWarning(String message) { - warning( PendingDeprecationWarning, message); + warning(PendingDeprecationWarning, message); } - public static PyObject SyntaxWarning; + public static void SyntaxWarning(String message) { warning(SyntaxWarning, message); } - public static PyObject OverflowWarning; + public static void OverflowWarning(String message) { warning(OverflowWarning, message); } - public static PyObject RuntimeWarning; + public static void RuntimeWarning(String message) { warning(RuntimeWarning, message); } - public static PyObject FutureWarning; + public static void FutureWarning(String message) { warning(FutureWarning, message); } - private static PyObject warnings_mod; + private static PyObject importWarnings() { - if (warnings_mod != null) return warnings_mod; + if (warnings_mod != null) { + return warnings_mod; + } PyObject mod; try { mod = __builtin__.__import__("warnings"); - } catch(PyException e) { - if (matchException(e,ImportError)) { + } catch (PyException e) { + if (matchException(e, ImportError)) { return null; } throw e; @@ -405,15 +375,18 @@ private static String warn_hcategory(PyObject category) { PyObject name = category.__findattr__("__name__"); - if (name != null) return "["+name+"]"; + if (name != null) { + return "[" + name + "]"; + } return "[warning]"; } public static void warning(PyObject category, String message) { PyObject func = null; PyObject mod = importWarnings(); - if (mod != null) + if (mod != null) { func = mod.__getattr__("warn"); + } if (func == null) { System.err.println(warn_hcategory(category) + ": " + message); return; @@ -423,35 +396,35 @@ } public static void warning(PyObject category, String message, - String filename, int lineno, String module, - PyObject registry) - { + String filename, int lineno, String module, + PyObject registry) { PyObject func = null; PyObject mod = importWarnings(); - if (mod != null) + if (mod != null) { func = mod.__getattr__("warn_explicit"); + } if (func == null) { System.err.println(filename + ":" + lineno + ":" + - warn_hcategory(category) + ": " + message); + warn_hcategory(category) + ": " + message); return; } else { - func.__call__(new PyObject[] { + func.__call__(new PyObject[]{ Py.newString(message), category, Py.newString(filename), Py.newInteger(lineno), (module == null) ? Py.None : Py.newString(module), - registry}, Py.NoKeywords); + registry + }, Py.NoKeywords); } } - - public static PyObject JavaError; + public static PyException JavaError(Throwable t) { - if(t instanceof PyException) { - return (PyException)t; - } else if(t instanceof InvocationTargetException) { - return JavaError(((InvocationTargetException)t).getTargetException()); - } else if(t instanceof OutOfMemoryError) { - memory_error((OutOfMemoryError)t); + if (t instanceof PyException) { + return (PyException) t; + } else if (t instanceof InvocationTargetException) { + return JavaError(((InvocationTargetException) t).getTargetException()); + } else if (t instanceof OutOfMemoryError) { + memory_error((OutOfMemoryError) t); } PyJavaInstance exc = new PyJavaInstance(t); PyException pyex = new PyException(exc.instclass, exc); @@ -461,22 +434,21 @@ return pyex; } - // Don't allow any constructors. Class only provides static methods. - private Py() {} + private Py() { + } /** - Convert a given <code>PyObject</code> to an instance of a Java class. - Identical to <code>o.__tojava__(c)</code> except that it will - raise a <code>TypeError</code> if the conversion fails. - - @param o the <code>PyObject</code> to convert. - @param c the class to convert it to. - **/ + Convert a given <code>PyObject</code> to an instance of a Java class. + Identical to <code>o.__tojava__(c)</code> except that it will + raise a <code>TypeError</code> if the conversion fails. + @param o the <code>PyObject</code> to convert. + @param c the class to convert it to. + **/ public static Object tojava(PyObject o, Class c) { Object obj = o.__tojava__(c); if (obj == Py.NoConversion) { - throw Py.TypeError("can't convert "+o.__repr__()+" to "+ - c.getName()); + throw Py.TypeError("can't convert " + o.__repr__() + " to " + + c.getName()); } return obj; } @@ -485,7 +457,9 @@ // Can get rid of it? public static Object tojava(PyObject o, String s) { Class c = findClass(s); - if (c == null) throw Py.TypeError("can't convert to: "+s); + if (c == null) { + throw Py.TypeError("can't convert to: " + s); + } return tojava(o, c); // prev:Class.forName } /* Helper functions for PyProxy's */ @@ -499,6 +473,7 @@ return ret; } + /** @deprecated */ public static PyObject jgetattr(PyProxy proxy, String name) { PyObject ret = getInstance(proxy, name); @@ -524,22 +499,23 @@ public static final PyInteger newInteger(int i) { if (integerCache == null) { integerCache = new PyInteger[1000]; - for(int j=-100; j<900; j++) { - integerCache[j+100] = new PyInteger(j); + for (int j = -100; j < 900; j++) { + integerCache[j + 100] = new PyInteger(j); } } - if (i>=-100 && i < 900) { - return integerCache[i+100]; + if (i >= -100 && i < 900) { + return integerCache[i + 100]; } else { return new PyInteger(i); } } public static PyObject newInteger(long i) { - if (i < Integer.MIN_VALUE || i > Integer.MAX_VALUE) + if (i < Integer.MIN_VALUE || i > Integer.MAX_VALUE) { return new PyLong(i); - else - return newInteger((int)i); + } else { + return newInteger((int) i); + } } public static PyLong newLong(String s) { @@ -563,7 +539,7 @@ } public static PyFloat newFloat(float v) { - return new PyFloat((double)v); + return new PyFloat((double) v); } public static PyFloat newFloat(double v) { @@ -577,11 +553,15 @@ public static PyString newString(String s) { return new PyString(s); } - + public static PyUnicode newUnicode(char c) { - return (PyUnicode)makeCharacter(c, true); + return (PyUnicode) makeCharacter(c, true); } + static PyObject newUnicode(int codepoint) { + return (PyUnicode) makeCharacter(codepoint, true); + } + public static PyUnicode newUnicode(String s) { return new PyUnicode(s); } @@ -590,58 +570,49 @@ return t ? Py.True : Py.False; } - // nested scopes: - // String[] cellvars,String[] freevars,int npurecell & int moreflags - public static PyCode newCode(int argcount, String varnames[], - String filename, String name, - boolean args, boolean keywords, - PyFunctionTable funcs, int func_id, - String[] cellvars,String[] freevars, - int npurecell, int moreflags) - { + String filename, String name, + boolean args, boolean keywords, + PyFunctionTable funcs, int func_id, + String[] cellvars, String[] freevars, + int npurecell, int moreflags) { return new PyTableCode(argcount, varnames, - filename, name, 0, args, keywords, funcs, - func_id, cellvars, freevars, npurecell, - moreflags); + filename, name, 0, args, keywords, funcs, + func_id, cellvars, freevars, npurecell, + moreflags); } public static PyCode newCode(int argcount, String varnames[], - String filename, String name, - int firstlineno, - boolean args, boolean keywords, - PyFunctionTable funcs, int func_id, - String[] cellvars,String[] freevars, - int npurecell, int moreflags) - - { + String filename, String name, + int firstlineno, + boolean args, boolean keywords, + PyFunctionTable funcs, int func_id, + String[] cellvars, String[] freevars, + int npurecell, int moreflags) { return new PyTableCode(argcount, varnames, - filename, name, firstlineno, args, keywords, - funcs, func_id, cellvars, freevars, npurecell, - moreflags); + filename, name, firstlineno, args, keywords, + funcs, func_id, cellvars, freevars, npurecell, + moreflags); } // -- - public static PyCode newCode(int argcount, String varnames[], - String filename, String name, - boolean args, boolean keywords, - PyFunctionTable funcs, int func_id) - { + String filename, String name, + boolean args, boolean keywords, + PyFunctionTable funcs, int func_id) { return new PyTableCode(argcount, varnames, - filename, name, 0, args, keywords, funcs, - func_id); + filename, name, 0, args, keywords, funcs, + func_id); } public static PyCode newCode(int argcount, String varnames[], - String filename, String name, - int firstlineno, - boolean args, boolean keywords, - PyFunctionTable funcs, int func_id) - { + String filename, String name, + ... [truncated message content] |