[pypy-commit] pypy decimal-libmpdec: Implement Context.__reduce__ to fix copy.copy()

amauryfa noreply at buildbot.pypy.org
Sun Oct 5 20:23:00 CEST 2014


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: decimal-libmpdec
Changeset: r73797:e08246460e6a
Date: 2014-09-19 19:02 +0200
http://bitbucket.org/pypy/pypy/changeset/e08246460e6a/

Log:	Implement Context.__reduce__ to fix copy.copy()

diff --git a/pypy/module/_decimal/interp_context.py b/pypy/module/_decimal/interp_context.py
--- a/pypy/module/_decimal/interp_context.py
+++ b/pypy/module/_decimal/interp_context.py
@@ -232,8 +232,7 @@
         return interp_decimal.decimal_from_float(
             space, None, w_value, self, exact=False)
 
-    def descr_repr(self, space):
-        # Rounding string.
+    def _rounding_string(self, space):
         rounding = rffi.cast(lltype.Signed, self.ctx.c_round)
         for name, value in ROUND_CONSTANTS:
             if value == rounding:
@@ -242,15 +241,32 @@
         else:
             raise oefmt(space.w_RuntimeError,
                         "bad rounding value")
+        return round_string
+
+    def descr_repr(self, space):
         flags = interp_signals.flags_as_string(self.ctx.c_status)
         traps = interp_signals.flags_as_string(self.ctx.c_traps)
         return space.wrap("Context(prec=%s, rounding=%s, Emin=%s, Emax=%s, "
                           "capitals=%s, clamp=%s, flags=%s, traps=%s)" % (
-                self.ctx.c_prec, round_string,
+                self.ctx.c_prec, self._rounding_string(space),
                 self.ctx.c_emin, self.ctx.c_emax,
                 self.capitals, rffi.cast(lltype.Signed, self.ctx.c_clamp),
                 flags, traps))
 
+    def descr_reduce(self, space):
+        return space.newtuple([
+                space.type(self),
+                space.newtuple([
+                        space.wrap(self.ctx.c_prec),
+                        space.wrap(self._rounding_string(space)),
+                        space.wrap(self.ctx.c_emin),
+                        space.wrap(self.ctx.c_emax),
+                        space.wrap(self.capitals),
+                        space.wrap(self.ctx.c_clamp),
+                        interp_signals.flags_as_list(space, self.ctx.c_status),
+                        interp_signals.flags_as_list(space, self.ctx.c_traps),
+                        ])])
+
     def divmod_w(self, space, w_x, w_y):
         from pypy.module._decimal import interp_decimal
         return interp_decimal.W_Decimal.divmod_impl(space, self, w_x, w_y)
@@ -353,6 +369,7 @@
     clamp=GetSetProperty(W_Context.get_clamp, W_Context.set_clamp),
     #
     __repr__ = interp2app(W_Context.descr_repr),
+    __reduce__ = interp2app(W_Context.descr_reduce),
     #
     copy=interp2app(W_Context.copy_w),
     clear_flags=interp2app(W_Context.clear_flags_w),
diff --git a/pypy/module/_decimal/interp_signals.py b/pypy/module/_decimal/interp_signals.py
--- a/pypy/module/_decimal/interp_signals.py
+++ b/pypy/module/_decimal/interp_signals.py
@@ -60,6 +60,15 @@
     raise oefmt(space.w_KeyError,
                 "invalid error flag")
 
+def flags_as_list(space, flags):
+    result_w = []
+    flags = rffi.cast(lltype.Signed, flags)
+    for (name, flag) in SIGNAL_MAP:
+        if flag & flags:
+            w_exc = getattr(get(space), 'w_' + name)
+            result_w.append(w_exc)
+    return space.newlist(result_w)
+
 def flags_as_string(flags):
     builder = rstring.StringBuilder(30)
     builder.append('[')
diff --git a/pypy/module/_decimal/test/test_context.py b/pypy/module/_decimal/test/test_context.py
--- a/pypy/module/_decimal/test/test_context.py
+++ b/pypy/module/_decimal/test/test_context.py
@@ -24,9 +24,20 @@
         def assertIs(space, w_x, w_y):
             assert space.is_w(w_x, w_y)
         cls.w_assertIs = space.wrap(gateway.interp2app(assertIs))
+        def assertIsInstance(space, w_x, w_y):
+            assert space.isinstance_w(w_x, w_y)
+        cls.w_assertIsInstance = space.wrap(
+            gateway.interp2app(assertIsInstance))
 
         cls.w_assertRaises = space.appexec([], """(): return raises""")
 
+    def test_deepcopy(self):
+        import copy
+        c = self.decimal.DefaultContext.copy()
+        c.traps[self.decimal.InvalidOperation] = False
+        nc = copy.deepcopy(c)
+        assert nc.traps[self.decimal.InvalidOperation] == False
+
     def test_context_repr(self):
         c = self.decimal.DefaultContext.copy()
 


More information about the pypy-commit mailing list