[Jython-checkins] jython: Make int() accept bytearray as convertible text.

jeff.allen jython-checkins at python.org
Sat Jul 21 00:35:11 CEST 2012


http://hg.python.org/jython/rev/31ebee268c70
changeset:   6807:31ebee268c70
user:        Jeff Allen <ja...py at farowl.co.uk>
date:        Fri Jul 20 21:30:58 2012 +0100
summary:
  Make int() accept bytearray as convertible text.
Also improvements to comments and code style in vicinity of change (needed to see how it works).

files:
  src/org/python/core/PyInteger.java |  85 ++++++++++++-----
  1 files changed, 57 insertions(+), 28 deletions(-)


diff --git a/src/org/python/core/PyInteger.java b/src/org/python/core/PyInteger.java
--- a/src/org/python/core/PyInteger.java
+++ b/src/org/python/core/PyInteger.java
@@ -52,75 +52,104 @@
     @ExposedNew
     public static PyObject int_new(PyNewWrapper new_, boolean init, PyType subtype,
             PyObject[] args, String[] keywords) {
+
         ArgParser ap = new ArgParser("int", args, keywords, new String[] {"x", "base"}, 0);
         PyObject x = ap.getPyObject(0, null);
         int base = ap.getInt(1, -909);
-        if (new_.for_type == subtype) {
+
+        if (new_.for_type == subtype) { // A substantive PyInteger is required as the return value
+
             if (x == null) {
                 return Py.Zero;
-            }
-            if (base == -909) {
+
+            } else if (base == -909) {
                 if (x instanceof PyBoolean) {
                     return (coerce(x) == 0) ? Py.Zero : Py.One;
+                } else if (x instanceof PyByteArray) {
+                    // Make use of the string to int conversion in PyString
+                    PyString xs = new PyString(x.asString());
+                    return asPyInteger(xs);
+                } else {
+                    return asPyInteger(x);
                 }
-                return asPyInteger(x);
-            }
-            if (!(x instanceof PyString)) {
+            } else if (!(x instanceof PyString)) {
                 throw Py.TypeError("int: can't convert non-string with explicit base");
             }
+
             try {
-                return Py.newInteger(((PyString) x).atoi(base));
+                return Py.newInteger(((PyString)x).atoi(base));
             } catch (PyException pye) {
                 if (pye.match(Py.OverflowError)) {
-                    return ((PyString) x).atol(base);
+                    return ((PyString)x).atol(base);
                 }
                 throw pye;
             }
-        } else {
+
+        } else { // A PyIntegerDerived(subtype, ... ) is required as the return value
+
             if (x == null) {
                 return new PyIntegerDerived(subtype, 0);
-            }
-            if (base == -909) {
+            } else if (base == -909) {
                 PyObject intOrLong = asPyInteger(x);
+
                 if (intOrLong instanceof PyInteger) {
-                    return new PyIntegerDerived(subtype, ((PyInteger) intOrLong).getValue());
+                    return new PyIntegerDerived(subtype, ((PyInteger)intOrLong).getValue());
                 } else {
                     throw Py.OverflowError("long int too large to convert to int");
                 }
-            }
-            if (!(x instanceof PyString)) {
+
+            } else if (!(x instanceof PyString)) {
                 throw Py.TypeError("int: can't convert non-string with explicit base");
             }
-            return new PyIntegerDerived(subtype, ((PyString) x).atoi(base));
+
+            return new PyIntegerDerived(subtype, ((PyString)x).atoi(base));
         }
     } // xxx
 
     /**
-     * @return convert to an int.
-     * @throws TypeError and AttributeError.
+     * Convert all sorts of object types to either <code>PyInteger</code> or <code>PyLong</code>,
+     * using their {@link PyObject#__int__()} method, whether exposed or not, or if that raises an
+     * exception (as the base <code>PyObject</code> one does), using any <code>__trunc__()</code>
+     * the type may have exposed. If all this fails, this method raises an exception. Equivalent to CPython
+     * <code>PyNumber_Int()</code>.
+     * 
+     * @param x to convert to an int
+     * @return int or long result.
+     * @throws PyException (TypeError) if no method of conversion can be found
+     * @throws PyException (AttributeError) if neither __int__ nor __trunc__ found (?)
      */
-    private static PyObject asPyInteger(PyObject x) {
-        //XXX: Not sure that this perfectly matches CPython semantics.
+    private static PyObject asPyInteger(PyObject x) throws PyException {
+        // XXX: Not sure that this perfectly matches CPython semantics.
         try {
+            // Try the object itself (raises AttributeError if not overridden from PyObject)
             return x.__int__();
+
         } catch (PyException pye) {
             if (!pye.match(Py.AttributeError)) {
+                // x had an __int__ method, but something else went wrong: pass it on
                 throw pye;
-            }
-            try {
-                PyObject integral = x.invoke("__trunc__");
-                return convertIntegralToInt(integral);
-            } catch (PyException pye2) {
-                if (!pye2.match(Py.AttributeError)) {
-                    throw pye2;
+
+            } else {
+                // x did not have an __int__ method, but maybe __trunc__ will work
+                try {
+                    PyObject integral = x.invoke("__trunc__");
+                    return convertIntegralToInt(integral);
+
+                } catch (PyException pye2) {
+                    if (!pye2.match(Py.AttributeError)) {
+                        throw pye2;
+                    }
+                    String fmt = "int() argument must be a string or a number, not '%.200s'";
+                    throw Py.TypeError(String.format(fmt, x));
                 }
-                throw Py.TypeError(
-                    String.format("int() argument must be a string or a number, not '%.200s'", x));
             }
         }
     }
 
     /**
+     * Helper called on whatever exposed method <code>__trunc__</code> returned: it may be
+     * <code>int</code>, <code>long</code> or something with an exposed <code>__int__</code>.
+     * 
      * @return convert to an int.
      * @throws TypeError and AttributeError.
      */

-- 
Repository URL: http://hg.python.org/jython


More information about the Jython-checkins mailing list