Armin Rigo avatar Armin Rigo committed 4239096 Merge

hg merge default: only a few changes

Comments (0)

Files changed (7)

pypy/interpreter/generator.py

         new_inst = mod.get('generator_new')
         w        = space.wrap
         if self.frame:
-            w_frame = w(self.frame)
+            w_frame = self.frame._reduce_state(space)
         else:
             w_frame = space.w_None
 
             w(self.running),
             ]
 
-        return space.newtuple([new_inst, space.newtuple(tup)])
+        return space.newtuple([new_inst, space.newtuple([]),
+                               space.newtuple(tup)])
+
+    def descr__setstate__(self, space, w_args):
+        from rpython.rlib.objectmodel import instantiate
+        args_w = space.unpackiterable(w_args)
+        w_framestate, w_running = args_w
+        if space.is_w(w_framestate, space.w_None):
+            self.frame = None
+        else:
+            frame = instantiate(space.FrameClass)   # XXX fish
+            frame.descr__setstate__(space, w_framestate)
+            GeneratorIterator.__init__(self, frame)
+        self.running = self.space.is_true(w_running)
 
     def descr__iter__(self):
         """x.__iter__() <==> iter(x)"""

pypy/interpreter/pyframe.py

 from rpython.tool.stdlib_opcode import host_bytecode_spec
 
 # Define some opcodes used
-g = globals()
 for op in '''DUP_TOP POP_TOP SETUP_LOOP SETUP_EXCEPT SETUP_FINALLY
 POP_BLOCK END_FINALLY'''.split():
-    g[op] = stdlib_opcode.opmap[op]
+    globals()[op] = stdlib_opcode.opmap[op]
 HAVE_ARGUMENT = stdlib_opcode.HAVE_ARGUMENT
 
 class PyFrame(eval.Frame):
     @jit.dont_look_inside
     def descr__reduce__(self, space):
         from pypy.interpreter.mixedmodule import MixedModule
-        from pypy.module._pickle_support import maker # helper fns
         w_mod    = space.getbuiltinmodule('_pickle_support')
         mod      = space.interp_w(MixedModule, w_mod)
         new_inst = mod.get('frame_new')
-        w        = space.wrap
+        w_tup_state = self._reduce_state(space)
+        nt = space.newtuple
+        return nt([new_inst, nt([]), w_tup_state])
+
+    @jit.dont_look_inside
+    def _reduce_state(self, space):
+        from pypy.module._pickle_support import maker # helper fns
+        w = space.wrap
         nt = space.newtuple
 
         cells = self._getcells()
             w(self.instr_prev_plus_one),
             w_cells,
             ]
-
-        return nt([new_inst, nt([]), nt(tup_state)])
+        return nt(tup_state)
 
     @jit.dont_look_inside
     def descr__setstate__(self, space, w_args):

pypy/interpreter/test/test_zzpickle_and_slow.py

         pckl   = pickle.dumps(pack.mod)
         result = pickle.loads(pckl)
         assert pack.mod is result
+
+
+class AppTestGeneratorCloning:
+
+    def setup_class(cls):
+        try:
+            cls.space.appexec([], """():
+                def f(): yield 42
+                f().__reduce__()
+            """)
+        except TypeError, e:
+            if 'pickle generator' not in str(e):
+                raise
+            py.test.skip("Frames can't be __reduce__()-ed")
+
+    def test_deepcopy_generator(self):
+        import copy
+
+        def f(n):
+            for i in range(n):
+                yield 42 + i
+        g = f(4)
+        g2 = copy.deepcopy(g)
+        res = g.next()
+        assert res == 42
+        res = g2.next()
+        assert res == 42
+        g3 = copy.deepcopy(g)
+        res = g.next()
+        assert res == 43
+        res = g2.next()
+        assert res == 43
+        res = g3.next()
+        assert res == 43
+
+    def test_shallowcopy_generator(self):
+        """Note: shallow copies of generators are often confusing.
+        To start with, 'for' loops have an iterator that will not
+        be copied, and so create tons of confusion.
+        """
+        import copy
+
+        def f(n):
+            while n > 0:
+                yield 42 + n
+                n -= 1
+        g = f(2)
+        g2 = copy.copy(g)
+        res = g.next()
+        assert res == 44
+        res = g2.next()
+        assert res == 44
+        g3 = copy.copy(g)
+        res = g.next()
+        assert res == 43
+        res = g2.next()
+        assert res == 43
+        res = g3.next()
+        assert res == 43
+        g4 = copy.copy(g2)
+        for i in range(2):
+            raises(StopIteration, g.next)
+            raises(StopIteration, g2.next)
+            raises(StopIteration, g3.next)
+            raises(StopIteration, g4.next)

pypy/interpreter/typedef.py

 GeneratorIterator.typedef = TypeDef("generator",
     __repr__   = interp2app(GeneratorIterator.descr__repr__),
     __reduce__   = interp2app(GeneratorIterator.descr__reduce__),
+    __setstate__ = interp2app(GeneratorIterator.descr__setstate__),
     next       = interp2app(GeneratorIterator.descr_next,
                             descrmismatch='next'),
     send       = interp2app(GeneratorIterator.descr_send,

pypy/module/_cffi_backend/misc.py

 eci = ExternalCompilationInfo(post_include_bits=["""
 #define pypy__is_nonnull_longdouble(x)  ((x) != 0.0)
 """])
-is_nonnull_longdouble = rffi.llexternal(
+_is_nonnull_longdouble = rffi.llexternal(
     "pypy__is_nonnull_longdouble", [rffi.LONGDOUBLE], lltype.Bool,
     compilation_info=eci, _nowrapper=True, elidable_function=True,
     sandboxsafe=True)
 
+# split here for JIT backends that don't support floats/longlongs/etc.
+def is_nonnull_longdouble(cdata):
+    return _is_nonnull_longdouble(read_raw_longdouble_data(cdata))
+def is_nonnull_float(cdata, size):
+    return read_raw_float_data(cdata, size) != 0.0
+
 def object_as_bool(space, w_ob):
     # convert and cast a Python object to a boolean.  Accept an integer
     # or a float object, up to a CData 'long double'.
     is_cdata = isinstance(w_ob, W_CData)
     if is_cdata and isinstance(w_ob.ctype, W_CTypePrimitiveFloat):
         if isinstance(w_ob.ctype, W_CTypePrimitiveLongDouble):
-            result = is_nonnull_longdouble(
-                read_raw_longdouble_data(w_ob._cdata))
+            result = is_nonnull_longdouble(w_ob._cdata)
         else:
-            result = read_raw_float_data(w_ob._cdata, w_ob.ctype.size) != 0.0
+            result = is_nonnull_float(w_ob._cdata, w_ob.ctype.size)
         keepalive_until_here(w_ob)
         return result
     #

pypy/module/_pickle_support/maker.py

     tb = instantiate(PyTraceback)
     return space.wrap(tb)
 
-@unwrap_spec(running=int)
-def generator_new(space, w_frame, running):
-    frame = space.interp_w(PyFrame, w_frame, can_be_None=True)
-    new_generator = GeneratorIterator(frame)
-    new_generator.running = running
+def generator_new(space):
+    new_generator = instantiate(GeneratorIterator)
     return space.wrap(new_generator)
 
 @unwrap_spec(current=int, remaining=int, step=int)

rpython/translator/goal/translate.py

     else:
         show_help(translateconfig, opt_parser, None, config)
 
+    # print the version of the host
+    # (if it's PyPy, it includes the hg checksum)
+    log.info(sys.version)
+
     # apply the platform settings
     set_platform(config)
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.