[pypy-svn] r38647 - in pypy/dist/pypy/objspace: . test

arigo at codespeak.net arigo at codespeak.net
Mon Feb 12 22:57:06 CET 2007


Author: arigo
Date: Mon Feb 12 22:57:05 2007
New Revision: 38647

Modified:
   pypy/dist/pypy/objspace/descroperation.py
   pypy/dist/pypy/objspace/test/test_descroperation.py
Log:
(pedronis, arigo)

More longish templates, because string-returning special methods need
to do things slightly differently than int- or float-returning ones
(namely, encode unicode results).


Modified: pypy/dist/pypy/objspace/descroperation.py
==============================================================================
--- pypy/dist/pypy/objspace/descroperation.py	(original)
+++ pypy/dist/pypy/objspace/descroperation.py	Mon Feb 12 22:57:05 2007
@@ -515,11 +515,7 @@
 for targetname, specialname, checkerspec in [
     ('int', '__int__', ("space.w_int", "space.w_long")), 
     ('long', '__long__', ("space.w_int", "space.w_long")), 
-    ('float', '__float__', ("space.w_float",)), 
-    ('str', '__str__', ("space.w_str",)), 
-    ('repr', '__repr__', ("space.w_str",)), 
-    ('oct', '__oct__', ("space.w_str",)), 
-    ('hex', '__hex__', ("space.w_str",))]: 
+    ('float', '__float__', ("space.w_float",))]:
 
     l = ["space.is_true(space.isinstance(w_result, %s))" % x 
                 for x in checkerspec]
@@ -544,6 +540,40 @@
         \n""" % locals() 
     exec compile2(source) 
 
+for targetname, specialname in [
+    ('str', '__str__'), 
+    ('repr', '__repr__'), 
+    ('oct', '__oct__'), 
+    ('hex', '__hex__')]: 
+
+    source = """if 1:
+        def %(targetname)s(space, w_obj):
+            w_impl = space.lookup(w_obj, %(specialname)r)
+            if w_impl is None:
+                raise OperationError(space.w_TypeError,
+                       space.wrap("operand does not support unary %(targetname)s"))
+            w_result = space.get_and_call_function(w_impl, w_obj)
+
+            if space.is_true(space.isinstance(w_result, space.w_str)):
+                return w_result
+            try:
+                result = space.str_w(w_result)
+            except OperationError, e:
+                if not e.match(space, space.w_TypeError):
+                    raise
+                typename = space.str_w(space.getattr(space.type(w_result), 
+                                       space.wrap('__name__')))
+                msg = '%(specialname)s returned non-%(targetname)s (type %%s)' %% (typename,) 
+                raise OperationError(space.w_TypeError, space.wrap(msg))
+            else:
+                # re-wrap the result as a real string
+                return space.wrap(result)
+        assert not hasattr(DescrOperation, %(targetname)r)
+        DescrOperation.%(targetname)s = %(targetname)s
+        del %(targetname)s 
+        \n""" % locals() 
+    exec compile2(source) 
+
 # add default operation implementations for all still missing ops 
 
 for _name, _symbol, _arity, _specialnames in ObjSpace.MethodTable:

Modified: pypy/dist/pypy/objspace/test/test_descroperation.py
==============================================================================
--- pypy/dist/pypy/objspace/test/test_descroperation.py	(original)
+++ pypy/dist/pypy/objspace/test/test_descroperation.py	Mon Feb 12 22:57:05 2007
@@ -247,3 +247,24 @@
                     check(iexpr, c, a)
                     check(iexpr, c, b)
                     check(iexpr, c, 5)
+
+    def test_string_results(self):
+        class A(object):
+            def __str__(self):
+                return answer * 2
+            def __repr__(self):
+                return answer * 3
+            def __hex__(self):
+                return answer * 4
+            def __oct__(self):
+                return answer * 5
+
+        for operate, n in [(str, 2), (repr, 3), (hex, 4), (oct, 5)]:
+            answer = "hello"
+            assert operate(A()) == "hello" * n
+            if operate not in (hex, oct):
+                answer = u"world"
+                assert operate(A()) == "world" * n
+            assert type(operate(A())) is str
+            answer = 42
+            raises(TypeError, operate, A())



More information about the Pypy-commit mailing list