SF.net SVN: jython:[7253] trunk/jython

[email protected] Sun, 20 Mar 2011 19:56:04 +0000
Newsgroups gmane.comp.lang.jython.cvs
Message-ID <[email protected]>
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.

------------------------------------------------------------------------------
Colocation vs. Managed Hosting
A question and answer guide to determining the best fit
for your organization - today and in the future.
http://p.sf.net/sfu/internap-sfd2d