[pypy-commit] pypy py3k: make all the messages computed by operationerrfmt as unicode, even if the source message is a byte string

antocuni noreply at buildbot.pypy.org
Sat Aug 4 15:01:17 CEST 2012


Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: py3k
Changeset: r56568:de80c62c47f3
Date: 2012-08-04 15:00 +0200
http://bitbucket.org/pypy/pypy/changeset/de80c62c47f3/

Log:	make all the messages computed by operationerrfmt as unicode, even
	if the source message is a byte string

diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py
--- a/pypy/interpreter/error.py
+++ b/pypy/interpreter/error.py
@@ -1,4 +1,5 @@
 import os, sys
+import itertools
 from pypy.rlib import jit
 from pypy.rlib.objectmodel import we_are_translated
 from errno import EINTR
@@ -327,27 +328,30 @@
     except KeyError:
         from pypy.rlib.unroll import unrolling_iterable
         attrs = ['x%d' % i for i in range(len(formats))]
-        entries = unrolling_iterable(enumerate(attrs))
+        entries = unrolling_iterable(zip(itertools.count(), formats, attrs))
         #
         class OpErrFmt(OperationError):
             def __init__(self, w_type, strings, *args):
                 self.setup(w_type)
                 assert len(args) == len(strings) - 1
                 self.xstrings = strings
-                for i, attr in entries:
+                for i, fmt, attr in entries:
                     setattr(self, attr, args[i])
                 if not we_are_translated() and w_type is None:
                     from pypy.tool.error import FlowingError
                     raise FlowingError(self._compute_value())
             def _compute_value(self):
                 lst = [None] * (len(formats) + len(formats) + 1)
-                for i, attr in entries:
+                for i, fmt, attr in entries:
                     string = self.xstrings[i]
                     value = getattr(self, attr)
                     lst[i+i] = string
-                    lst[i+i+1] = str(value)
+                    if fmt == 'd':
+                        lst[i+i+1] = str(value).encode('ascii')
+                    else:
+                        lst[i+i+1] = unicode(value)
                 lst[-1] = self.xstrings[-1]
-                return ''.join(lst)
+                return u''.join(lst)
         #
         _fmtcache2[formats] = OpErrFmt
     return OpErrFmt, strings
@@ -363,7 +367,12 @@
 def operationerrfmt(w_type, valuefmt, *args):
     """Equivalent to OperationError(w_type, space.wrap(valuefmt % args)).
     More efficient in the (common) case where the value is not actually
-    needed."""
+    needed.
+    Note that:
+      1. in the py3k branch the exception message will always be unicode
+      2. only %s and %d are supported
+    """
+    valuefmt = valuefmt.decode('ascii')
     OpErrFmt, strings = get_operationerr_class(valuefmt)
     return OpErrFmt(w_type, strings, *args)
 operationerrfmt._annspecialcase_ = 'specialize:arg(1)'
diff --git a/pypy/interpreter/test/test_error.py b/pypy/interpreter/test/test_error.py
--- a/pypy/interpreter/test/test_error.py
+++ b/pypy/interpreter/test/test_error.py
@@ -1,3 +1,5 @@
+# -*- encoding: utf-8 -*-
+
 import py, os, errno
 from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.interpreter.error import decompose_valuefmt, get_operrcls2
@@ -27,7 +29,9 @@
     assert isinstance(operr, OperationError)
     assert operr.w_type == "w_type"
     assert operr._w_value is None
-    assert operr._compute_value() == "abc foo def 42"
+    val = operr._compute_value()
+    assert val == u"abc foo def 42"
+    assert isinstance(val, unicode)
     operr2 = operationerrfmt("w_type2", "a %s b %d c", "bar", 43)
     assert operr2.__class__ is operr.__class__
     operr3 = operationerrfmt("w_type2", "a %s b %s c", "bar", "4b")
@@ -36,6 +40,11 @@
 def test_operationerrfmt_empty():
     py.test.raises(AssertionError, operationerrfmt, "w_type", "foobar")
 
+def test_operationerrfmt_unicode():
+    operr = operationerrfmt("w_type", "abc %s", u"&#224;&#232;&#236;&#242;&#249;")
+    val = operr._compute_value()
+    assert val == u"abc &#224;&#232;&#236;&#242;&#249;"
+
 def test_errorstr(space):
     operr = OperationError(space.w_ValueError, space.wrap("message"))
     assert operr.errorstr(space) == "ValueError: message"


More information about the pypy-commit mailing list