From: <pj...@us...> - 2011-03-20 19:56:10
|
Revision: 7253 http://jython.svn.sourceforge.net/jython/?rev=7253&view=rev Author: pjenvey Date: 2011-03-20 19:56:03 +0000 (Sun, 20 Mar 2011) Log Message: ----------- o 2.6 core exception related changes o fix exceptions.getString allowing unicode Modified Paths: -------------- trunk/jython/Lib/test/junit_xml.py trunk/jython/src/org/python/core/PyBaseException.java trunk/jython/src/org/python/core/PyException.java trunk/jython/src/org/python/core/exceptions.java Modified: trunk/jython/Lib/test/junit_xml.py =================================================================== --- trunk/jython/Lib/test/junit_xml.py 2011-03-20 19:43:03 UTC (rev 7252) +++ trunk/jython/Lib/test/junit_xml.py 2011-03-20 19:56:03 UTC (rev 7253) @@ -248,8 +248,8 @@ exc = exc_info[1] if exc is None: return safe_str(exc_info[0]) - if isinstance(exc, BaseException) and isinstance(exc.message, unicode): - return safe_str(exc.message) + if isinstance(exc, BaseException) and isinstance(exc.args[0], unicode): + return safe_str(exc.args[0]) try: return safe_str(str(exc)) except UnicodeEncodeError: Modified: trunk/jython/src/org/python/core/PyBaseException.java =================================================================== --- trunk/jython/src/org/python/core/PyBaseException.java 2011-03-20 19:43:03 UTC (rev 7252) +++ trunk/jython/src/org/python/core/PyBaseException.java 2011-03-20 19:56:03 UTC (rev 7253) @@ -18,9 +18,7 @@ public static final PyType TYPE = PyType.fromClass(PyBaseException.class); /** Exception message. */ - @ExposedGet(doc = BuiltinDocs.BaseException_message_doc) - @ExposedSet - public PyObject message = Py.EmptyString; + private PyObject message = Py.EmptyString; /** Exception's arguments. */ @ExposedGet(doc = BuiltinDocs.BaseException_args_doc) @@ -52,25 +50,32 @@ } } + @Override public PyObject __getitem__(PyObject index) { return BaseException___getitem__(index); } @ExposedMethod(doc = BuiltinDocs.BaseException___getitem___doc) final PyObject BaseException___getitem__(PyObject index) { + Py.warnPy3k("__getitem__ not supported for exception classes in 3.x; use args " + + "attribute"); return args.__getitem__(index); } + @Override public PyObject __getslice__(PyObject start, PyObject stop) { return BaseException___getslice__(start, stop); } @ExposedMethod(doc = BuiltinDocs.BaseException___getslice___doc) final PyObject BaseException___getslice__(PyObject start, PyObject stop) { + Py.warnPy3k("__getslice__ not supported for exception classes in 3.x; use args " + + "attribute"); return args.__getslice__(start, stop); } + @Override public PyObject __reduce__() { return BaseException___reduce__(); } @@ -101,6 +106,7 @@ return Py.None; } + @Override public PyObject __findattr_ex__(String name) { return BaseException___findattr__(name); } @@ -116,6 +122,7 @@ return super.__findattr_ex__(name); } + @Override public void __setattr__(String name, PyObject value) { BaseException___setattr__(name, value); } @@ -126,16 +133,19 @@ super.__setattr__(name, value); } + @Override public PyObject fastGetDict() { return __dict__; } + @Override @ExposedGet(name = "__dict__", doc = BuiltinDocs.BaseException___dict___doc) public PyObject getDict() { ensureDict(); return __dict__; } + @Override @ExposedSet(name = "__dict__") public void setDict(PyObject val) { if (!(val instanceof PyStringMap) && !(val instanceof PyDictionary)) { @@ -145,12 +155,14 @@ } private void ensureDict() { + // XXX: __dict__ should really be volatile if (__dict__ == null) { __dict__ = new PyStringMap(); } } - public PyString __str__() { + @Override + public PyString __str__() { return BaseException___str__(); } @@ -167,6 +179,35 @@ } @Override + public PyUnicode __unicode__() { + return BaseException___unicode__(); + } + + @ExposedMethod(doc = BuiltinDocs.BaseException___unicode___doc) + final PyUnicode BaseException___unicode__() { + // CPython issue6108: if __str__ has been overridden in the subclass, unicode() + // should return the message returned by __str__ as used to happen before this + // method was implemented + PyType type = getType(); + PyObject[] where = new PyObject[1]; + PyObject str = type.lookup_where("__str__", where); + if (str != null && where[0] != TYPE) { + // Unlike str(), __str__ can return unicode (i.e. return the equivalent + // of unicode(e.__str__()) instead of unicode(str(e))) + return str.__get__(this, type).__call__().__unicode__(); + } + + switch (args.__len__()) { + case 0: + return new PyUnicode(""); + case 1: + return args.__getitem__(0).__unicode__(); + default: + return args.__unicode__(); + } + } + + @Override public String toString() { return BaseException_toString(); } @@ -187,8 +228,33 @@ args = PyTuple.fromIterable(val); } + @ExposedGet(name = "message", doc = BuiltinDocs.BaseException_message_doc) + public PyObject getMessage() { + PyObject message; + + // if "message" is in self->dict, accessing a user-set message attribute + if (__dict__ != null && (message = __dict__.__finditem__("message")) != null) { + return message; + } + + if (this.message == null) { + throw Py.AttributeError("message attribute was deleted"); + } + + Py.DeprecationWarning("BaseException.message has been deprecated as of Python 2.6"); + return this.message; + } + + @ExposedSet(name = "message") + public void setMessage(PyObject value) { + getDict().__setitem__("message", value); + } + @ExposedDelete(name = "message") public void delMessage() { - message = Py.None; + if (__dict__ != null && (message = __dict__.__finditem__("message")) != null) { + __dict__.__delitem__("message"); + message = null; + } } } Modified: trunk/jython/src/org/python/core/PyException.java =================================================================== --- trunk/jython/src/org/python/core/PyException.java 2011-03-20 19:43:03 UTC (rev 7252) +++ trunk/jython/src/org/python/core/PyException.java 2011-03-20 19:56:03 UTC (rev 7253) @@ -194,9 +194,7 @@ type = type.__getitem__(0); } - if (type.getType() == PyString.TYPE) { - Py.warning(Py.DeprecationWarning, "raising a string exception is deprecated"); - } else if (isExceptionClass(type)) { + if (isExceptionClass(type)) { PyException pye = new PyException(type, value, (PyTraceback)traceback); pye.normalize(); return pye; @@ -212,10 +210,14 @@ } else { // Not something you can raise. You get an exception // anyway, just not what you specified :-) - throw Py.TypeError("exceptions must be classes, instances, or strings (deprecated), " - + "not " + type.getType().fastGetName()); + throw Py.TypeError("exceptions must be old-style classes or derived from " + + "BaseException, not " + type.getType().fastGetName()); } + if (Options.py3kwarning && type instanceof PyClass) { + Py.DeprecationWarning("exceptions must derive from BaseException in 3.x"); + } + return new PyException(type, value, (PyTraceback)traceback); } @@ -255,7 +257,13 @@ } if (isExceptionClass(type) && isExceptionClass(exc)) { - return Py.isSubClass(type, exc); + try { + return Py.isSubClass(type, exc); + } catch (PyException pye) { + // This function must not fail, so print the error here + Py.writeUnraisable(pye, type); + return false; + } } return type == exc; Modified: trunk/jython/src/org/python/core/exceptions.java =================================================================== --- trunk/jython/src/org/python/core/exceptions.java 2011-03-20 19:43:03 UTC (rev 7252) +++ trunk/jython/src/org/python/core/exceptions.java 2011-03-20 19:56:03 UTC (rev 7253) @@ -133,10 +133,12 @@ buildClass(dict, "MemoryError", "StandardError", "Out of memory."); + buildClass(dict, "BufferError", "StandardError", "Buffer error."); + buildClass(dict, "StopIteration", "Exception", "Signal the end from iterator.next()."); - buildClass(dict, "GeneratorExit", "Exception", "Request that a generator exit."); + buildClass(dict, "GeneratorExit", "BaseException", "Request that a generator exit."); buildClass(dict, "Warning", "Exception", "Base class for warning categories."); @@ -166,10 +168,10 @@ buildClass(dict, "UnicodeWarning", "Warning", "Base class for warnings about Unicode related problems, mostly\n" + "related to conversion problems."); - + buildClass(dict, "BytesWarning", "Warning", "Base class for warnings about bytes and buffer related problems, mostly\n" - + "related to conversion from str or comparing to str."); + + "related to conversion from str or comparing to str."); // Initialize ZipImportError here, where it's safe to; it's // needed immediately @@ -373,14 +375,16 @@ public static PyString UnicodeDecodeError__str__(PyObject self, PyObject[] args, String[] kwargs) { - int start = getStart(self, false); - int end = getEnd(self, false); - PyObject encoding = self.__getattr__("encoding"); - PyObject reason = self.__getattr__("reason"); + int start = self.__getattr__("start").asInt(); + int end = self.__getattr__("end").asInt(); + // Get reason and encoding as strings, which they might not be if they've been + // modified after we were contructed + PyObject reason = self.__getattr__("reason").__str__(); + PyObject encoding = self.__getattr__("encoding").__str__(); + PyObject object = getString(self.__getattr__("object"), "object"); String result; - if (end == (start + 1)) { - PyObject object = self.__getattr__("object"); + if (start < object.__len__() && end == (start + 1)) { int badByte = (object.toString().charAt(start)) & 0xff; result = String.format("'%.400s' codec can't decode byte 0x%x in position %d: %.400s", encoding, badByte, start, reason); @@ -406,14 +410,16 @@ public static PyString UnicodeEncodeError__str__(PyObject self, PyObject[] args, String[] kwargs) { - int start = getStart(self, true); - int end = getEnd(self, true); - PyObject encoding = self.__getattr__("encoding"); - PyObject reason = self.__getattr__("reason"); + int start = self.__getattr__("start").asInt(); + int end = self.__getattr__("end").asInt(); + // Get reason and encoding as strings, which they might not be if they've been + // modified after we were contructed + PyObject reason = self.__getattr__("reason").__str__(); + PyObject encoding = self.__getattr__("encoding").__str__(); + PyObject object = getUnicode(self.__getattr__("object"), "object"); String result; - if (end == (start + 1)) { - PyObject object = self.__getattr__("object"); + if (start < object.__len__() && end == (start + 1)) { int badchar = object.toString().codePointAt(start); String badcharStr; if (badchar <= 0xff) { @@ -455,13 +461,16 @@ public static PyString UnicodeTranslateError__str__(PyObject self, PyObject[] args, String[] kwargs) { - int start = getStart(self, true); - int end = getEnd(self, true); - PyObject reason = self.__getattr__("reason"); + int start = self.__getattr__("start").asInt(); + int end = self.__getattr__("end").asInt(); + // Get reason as a string, which it might not be if it's been modified after we + // were contructed + PyObject reason = self.__getattr__("reason").__str__(); + PyObject object = getUnicode(self.__getattr__("object"), "object"); String result; - if (end == (start + 1)) { - int badchar = (self.__getattr__("object").toString().codePointAt(start)); + if (start < object.__len__() && end == (start + 1)) { + int badchar = object.toString().codePointAt(start); String badCharStr; if (badchar <= 0xff) { badCharStr = String.format("x%02x", badchar); @@ -488,7 +497,7 @@ * @return an the start position */ public static int getStart(PyObject self, boolean unicode) { - int start = getInt(self.__getattr__("start"), "start"); + int start = self.__getattr__("start").asInt(); PyObject object; if (unicode) { object = getUnicode(self.__getattr__("object"), "object"); @@ -513,7 +522,7 @@ * @return an the end position */ public static int getEnd(PyObject self, boolean unicode) { - int end = getInt(self.__getattr__("end"), "end"); + int end = self.__getattr__("end").asInt(); PyObject object; if (unicode) { object = getUnicode(self.__getattr__("object"), "object"); @@ -530,22 +539,6 @@ } /** - * Parse an int value for UnicodeErrors - * - * @param attr a PyObject - * @param name of the attribute - * @return an int value - */ - public static int getInt(PyObject attr, String name) { - if (attr instanceof PyInteger) { - return ((PyInteger)attr).asInt(); - } else if (attr instanceof PyLong) { - return ((PyLong)attr).asInt(); - } - throw Py.TypeError(String.format("%.200s attribute must be int", name)); - } - - /** * Ensure a PyString value for UnicodeErrors * * @param attr a PyObject @@ -553,7 +546,7 @@ * @return an PyString */ public static PyString getString(PyObject attr, String name) { - if (!(attr instanceof PyString)) { + if (!Py.isInstance(attr, PyString.TYPE)) { throw Py.TypeError(String.format("%.200s attribute must be str", name)); } return (PyString)attr; @@ -663,10 +656,12 @@ this.javaMethod = javaMethod; } + @Override public PyBuiltinCallable bind(PyObject self) { return new BoundStaticJavaMethod(getType(), self, info, javaMethod); } + @Override public PyObject __get__(PyObject obj, PyObject type) { if (obj != null) { return bind(obj); @@ -674,6 +669,7 @@ return makeDescriptor((PyType)type); } + @Override public PyObject __call__(PyObject[] args, String kwargs[]) { try { return Py.java2py(javaMethod.invoke(null, self, args, kwargs)); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |