Author: Manuel Jacob <m...@manueljacob.de>
Branch: py3.3
Changeset: r81986:edefd168b2b3
Date: 2016-01-27 19:52 +0100
http://bitbucket.org/pypy/pypy/changeset/edefd168b2b3/

Log:    hg merge 03591a1499c8

        This merges marky1991's changes before he merged the problematic
        merge 88aafcb7c318.

diff --git a/lib-python/3/code.py b/lib-python/3/code.py
--- a/lib-python/3/code.py
+++ b/lib-python/3/code.py
@@ -105,10 +105,9 @@
         The output is written by self.write(), below.
 
         """
-        type, value, tb = sys.exc_info()
+        type, value, sys.last_traceback = sys.exc_info()
         sys.last_type = type
         sys.last_value = value
-        sys.last_traceback = tb
         if filename and type is SyntaxError:
             # Work hard to stuff the correct filename in the exception
             try:
@@ -126,7 +125,7 @@
         else:
             # If someone has set sys.excepthook, we let that take precedence
             # over self.write
-            sys.excepthook(type, value, tb)
+            sys.excepthook(type, value, self.last_traceback)
 
     def showtraceback(self):
         """Display the exception that just occurred.
@@ -136,25 +135,35 @@
         The output is written by self.write(), below.
 
         """
+        sys.last_type, sys.last_value, last_tb = ei = sys.exc_info()
+        sys.last_traceback = last_tb
         try:
-            type, value, tb = sys.exc_info()
-            sys.last_type = type
-            sys.last_value = value
-            sys.last_traceback = tb
-            tblist = traceback.extract_tb(tb)
-            del tblist[:1]
-            lines = traceback.format_list(tblist)
-            if lines:
-                lines.insert(0, "Traceback (most recent call last):\n")
-            lines.extend(traceback.format_exception_only(type, value))
+            lines = []
+            for value, tb in traceback._iter_chain(*ei[1:]):
+                if isinstance(value, str):
+                    lines.append(value)
+                    lines.append('\n')
+                    continue
+                if tb:
+                    tblist = traceback.extract_tb(tb)
+                    if tb is last_tb:
+                        # The last traceback includes the frame we
+                        # exec'd in
+                        del tblist[:1]
+                    tblines = traceback.format_list(tblist)
+                    if tblines:
+                        lines.append("Traceback (most recent call last):\n")
+                        lines.extend(tblines)
+                lines.extend(traceback.format_exception_only(type(value),
+                                                             value))
         finally:
-            tblist = tb = None
+            tblist = last_tb = ei = None
         if sys.excepthook is sys.__excepthook__:
             self.write(''.join(lines))
         else:
             # If someone has set sys.excepthook, we let that take precedence
             # over self.write
-            sys.excepthook(type, value, tb)
+            sys.excepthook(sys.last_type, sys.last_value, last_tb)
 
     def write(self, data):
         """Write a string.
diff --git a/lib-python/3/pickle.py b/lib-python/3/pickle.py
--- a/lib-python/3/pickle.py
+++ b/lib-python/3/pickle.py
@@ -23,7 +23,7 @@
 
 """
 
-from types import FunctionType, BuiltinFunctionType
+from types import FunctionType, BuiltinFunctionType, ModuleType
 from copyreg import dispatch_table
 from copyreg import _extension_registry, _inverted_registry, _extension_cache
 import marshal
@@ -622,6 +622,9 @@
             # else tmp is empty, and we're done
 
     def save_dict(self, obj):
+        modict_saver = self._pickle_maybe_moduledict(obj)
+        if modict_saver is not None:
+            return self.save_reduce(*modict_saver)
         write = self.write
 
         if self.bin:
@@ -672,6 +675,44 @@
                 write(SETITEM)
             # else tmp is empty, and we're done
 
+    def _pickle_maybe_moduledict(self, obj):
+        # save module dictionary as "getattr(module, '__dict__')"
+        try:
+            name = obj['__name__']
+            if type(name) is not str:
+                return None
+            themodule = sys.modules[name]
+            if type(themodule) is not ModuleType:
+                return None
+            if themodule.__dict__ is not obj:
+                return None
+        except (AttributeError, KeyError, TypeError):
+            return None
+        return getattr, (themodule, '__dict__')
+
+    def save_function(self, obj):
+        try:
+            return self.save_global(obj)
+        except PicklingError:
+            pass
+        # Check copy_reg.dispatch_table
+        reduce = dispatch_table.get(type(obj))
+        if reduce:
+            rv = reduce(obj)
+        else:
+            # Check for a __reduce_ex__ method, fall back to __reduce__
+            reduce = getattr(obj, "__reduce_ex__", None)
+            if reduce:
+                rv = reduce(self.proto)
+            else:
+                reduce = getattr(obj, "__reduce__", None)
+                if reduce:
+                    rv = reduce()
+                else:
+                    raise e
+        return self.save_reduce(obj=obj, *rv)
+    dispatch[FunctionType] = save_function
+
     def save_global(self, obj, name=None, pack=struct.pack):
         write = self.write
         memo = self.memo
@@ -737,7 +778,7 @@
             return self.save_reduce(type, (...,), obj=obj)
         return self.save_global(obj)
 
-    dispatch[FunctionType] = save_global
+    dispatch[FunctionType] = save_function
     dispatch[BuiltinFunctionType] = save_global
     dispatch[type] = save_type
 
diff --git a/pypy/interpreter/astcompiler/codegen.py 
b/pypy/interpreter/astcompiler/codegen.py
--- a/pypy/interpreter/astcompiler/codegen.py
+++ b/pypy/interpreter/astcompiler/codegen.py
@@ -1381,7 +1381,7 @@
         # ... and store it as __module__
         self.name_op("__module__", ast.Store)
         # store the qualname
-        w_qualname = self.space.wrap(self.qualname)
+        w_qualname = self.space.wrap(self.qualname.decode("utf-8"))
         self.load_const(w_qualname)
         self.name_op("__qualname__", ast.Store)
         # compile the body proper
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -306,6 +306,7 @@
         tup_base = []
         tup_state = [
             w(self.name),
+            w(self.qualname),
             w_doc,
             w(self.code),
             w_func_globals,
@@ -319,8 +320,8 @@
     def descr_function__setstate__(self, space, w_args):
         args_w = space.unpackiterable(w_args)
         try:
-            (w_name, w_doc, w_code, w_func_globals, w_closure, w_defs,
-             w_func_dict, w_module) = args_w
+            (w_name, w_qualname, w_doc, w_code, w_func_globals, w_closure,
+             w_defs, w_func_dict, w_module) = args_w
         except ValueError:
             # wrong args
             raise OperationError(space.w_ValueError,
@@ -328,6 +329,7 @@
 
         self.space = space
         self.name = space.str_w(w_name)
+        self.qualname = space.str_w(w_qualname).decode("utf-8")
         self.code = space.interp_w(Code, w_code)
         if not space.is_w(w_closure, space.w_None):
             from pypy.interpreter.nestedscope import Cell
diff --git a/pypy/interpreter/test/test_app_main.py 
b/pypy/interpreter/test/test_app_main.py
--- a/pypy/interpreter/test/test_app_main.py
+++ b/pypy/interpreter/test/test_app_main.py
@@ -808,31 +808,6 @@
         data = self.run('-S -i', expect_prompt=True, expect_banner=True)
         assert 'copyright' not in data
 
-    def test_non_interactive_stdout_fully_buffered(self):
-        if os.name == 'nt':
-            try:
-                import __pypy__
-            except:
-                py.test.skip('app_main cannot run on non-pypy for windows')
-        path = getscript(r"""
-            import sys, time
-            sys.stdout.write('\x00(STDOUT)\n\x00')   # stays in buffers
-            time.sleep(1)
-            sys.stderr.write('\x00[STDERR]\n\x00')
-            time.sleep(1)
-            # stdout flushed automatically here
-            """)
-        cmdline = '%s -u "%s" %s' % (python3, app_main, path)
-        print 'POPEN:', cmdline
-        child_in, child_out_err = os.popen4(cmdline)
-        data = child_out_err.read(11)
-        # Py3 is always at least line buffered
-        assert data == '\x00(STDOUT)\n\x00'    # from stdout
-        child_in.close()
-        data = child_out_err.read(11)
-        assert data == '\x00[STDERR]\n\x00'    # from stderr
-        child_out_err.close()
-
     def test_non_interactive_stdout_unbuffered(self, monkeypatch):
         monkeypatch.setenv('PYTHONUNBUFFERED', '1')
         if os.name == 'nt':
diff --git a/pypy/interpreter/test/test_zzpickle_and_slow.py 
b/pypy/interpreter/test/test_zzpickle_and_slow.py
--- a/pypy/interpreter/test/test_zzpickle_and_slow.py
+++ b/pypy/interpreter/test/test_zzpickle_and_slow.py
@@ -394,8 +394,10 @@
         import pickle
         tdict = {'2':2, '3':3, '5':5}
         diter  = iter(tdict)
-        next(diter)
-        raises(TypeError, pickle.dumps, diter)
+        seen = next(diter)
+        pckl = pickle.dumps(diter)
+        result = pickle.loads(pckl)
+        assert set(result) == (set('235') - set(seen))
 
     def test_pickle_reversed(self):
         import pickle
diff --git a/pypy/module/__pypy__/test/test_stderrprinter.py 
b/pypy/module/__pypy__/test/test_stderrprinter.py
--- a/pypy/module/__pypy__/test/test_stderrprinter.py
+++ b/pypy/module/__pypy__/test/test_stderrprinter.py
@@ -7,7 +7,9 @@
     p.close()  # this should be a no-op
     p.flush()  # this should be a no-op
     assert p.fileno() == 2
-    assert p.isatty()
+    # It doesn't make sense to assert this.  Stderror could be a tty
+    # (the terminal) or not, depending on how we are running the tests.
+    # assert p.isatty()
     assert p.write('foo') == 3
     raises(TypeError, p.write, b'foo')
 
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py 
b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -1,6 +1,9 @@
 # ____________________________________________________________
 
 import sys
+assert __version__ == "1.4.2", ("This test_c.py file is for testing a version"
+                                " of cffi that differs from the one that we"
+                                " get from 'import _cffi_backend'")
 if sys.version_info < (3,):
     type_or_class = "type"
     mandatory_b_prefix = ''
@@ -2313,9 +2316,6 @@
     f(); f()
     assert get_errno() == 77
 
-def test_abi():
-    assert isinstance(FFI_DEFAULT_ABI, int)
-
 def test_cast_to_array():
     # not valid in C!  extension to get a non-owning <cdata 'int[3]'>
     BInt = new_primitive_type("int")
@@ -3393,6 +3393,78 @@
     check(4 | 8,  "CHB", "GTB")
     check(4 | 16, "CHB", "ROB")
 
+def test_memmove():
+    Short = new_primitive_type("short")
+    ShortA = new_array_type(new_pointer_type(Short), None)
+    Char = new_primitive_type("char")
+    CharA = new_array_type(new_pointer_type(Char), None)
+    p = newp(ShortA, [-1234, -2345, -3456, -4567, -5678])
+    memmove(p, p + 1, 4)
+    assert list(p) == [-2345, -3456, -3456, -4567, -5678]
+    p[2] = 999
+    memmove(p + 2, p, 6)
+    assert list(p) == [-2345, -3456, -2345, -3456, 999]
+    memmove(p + 4, newp(CharA, b"\x71\x72"), 2)
+    if sys.byteorder == 'little':
+        assert list(p) == [-2345, -3456, -2345, -3456, 0x7271]
+    else:
+        assert list(p) == [-2345, -3456, -2345, -3456, 0x7172]
+
+def test_memmove_buffer():
+    import array
+    Short = new_primitive_type("short")
+    ShortA = new_array_type(new_pointer_type(Short), None)
+    a = array.array('H', [10000, 20000, 30000])
+    p = newp(ShortA, 5)
+    memmove(p, a, 6)
+    assert list(p) == [10000, 20000, 30000, 0, 0]
+    memmove(p + 1, a, 6)
+    assert list(p) == [10000, 10000, 20000, 30000, 0]
+    b = array.array('h', [-1000, -2000, -3000])
+    memmove(b, a, 4)
+    assert b.tolist() == [10000, 20000, -3000]
+    assert a.tolist() == [10000, 20000, 30000]
+    p[0] = 999
+    p[1] = 998
+    p[2] = 997
+    p[3] = 996
+    p[4] = 995
+    memmove(b, p, 2)
+    assert b.tolist() == [999, 20000, -3000]
+    memmove(b, p + 2, 4)
+    assert b.tolist() == [997, 996, -3000]
+    p[2] = -p[2]
+    p[3] = -p[3]
+    memmove(b, p + 2, 6)
+    assert b.tolist() == [-997, -996, 995]
+
+def test_memmove_readonly_readwrite():
+    SignedChar = new_primitive_type("signed char")
+    SignedCharA = new_array_type(new_pointer_type(SignedChar), None)
+    p = newp(SignedCharA, 5)
+    memmove(p, b"abcde", 3)
+    assert list(p) == [ord("a"), ord("b"), ord("c"), 0, 0]
+    memmove(p, bytearray(b"ABCDE"), 2)
+    assert list(p) == [ord("A"), ord("B"), ord("c"), 0, 0]
+    py.test.raises((TypeError, BufferError), memmove, b"abcde", p, 3)
+    ba = bytearray(b"xxxxx")
+    memmove(dest=ba, src=p, n=3)
+    assert ba == bytearray(b"ABcxx")
+    memmove(ba, b"EFGH", 4)
+    assert ba == bytearray(b"EFGHx")
+
+def test_memmove_sign_check():
+    SignedChar = new_primitive_type("signed char")
+    SignedCharA = new_array_type(new_pointer_type(SignedChar), None)
+    p = newp(SignedCharA, 5)
+    py.test.raises(ValueError, memmove, p, p + 1, -1)   # not segfault
+
+def test_memmove_bad_cdata():
+    BInt = new_primitive_type("int")
+    p = cast(BInt, 42)
+    py.test.raises(TypeError, memmove, p, bytearray(b'a'), 1)
+    py.test.raises(TypeError, memmove, bytearray(b'a'), p, 1)
+
 def test_dereference_null_ptr():
     BInt = new_primitive_type("int")
     BIntPtr = new_pointer_type(BInt)
@@ -3425,6 +3497,20 @@
                             "that you are not e.g. mixing up different ffi "
                             "instances)")
 
-def test_version():
-    # this test is here mostly for PyPy
-    assert __version__ == "1.2.1"
+def test_stdcall_function_type():
+    assert FFI_CDECL == FFI_DEFAULT_ABI
+    try:
+        stdcall = FFI_STDCALL
+    except NameError:
+        stdcall = FFI_DEFAULT_ABI
+    BInt = new_primitive_type("int")
+    BFunc = new_function_type((BInt, BInt), BInt, False, stdcall)
+    if stdcall != FFI_DEFAULT_ABI:
+        assert repr(BFunc) == "<ctype 'int(__stdcall *)(int, int)'>"
+    else:
+        assert repr(BFunc) == "<ctype 'int(*)(int, int)'>"
+
+def test_get_common_types():
+    d = {}
+    _get_common_types(d)
+    assert d['bool'] == '_Bool'
diff --git a/pypy/module/_frozen_importlib/__init__.py 
b/pypy/module/_frozen_importlib/__init__.py
--- a/pypy/module/_frozen_importlib/__init__.py
+++ b/pypy/module/_frozen_importlib/__init__.py
@@ -30,7 +30,7 @@
                       space.wrap(space.builtin))
         code_w.exec_code(space, self.w_dict, self.w_dict)
 
-        self.w_import = space.wrap(interp_import.import_with_frames_removed)
+        self.w_import = space.wrap(interp_import.__import__)
 
     def startup(self, space):
         """Copy our __import__ to builtins."""
diff --git a/pypy/module/_frozen_importlib/interp_import.py 
b/pypy/module/_frozen_importlib/interp_import.py
--- a/pypy/module/_frozen_importlib/interp_import.py
+++ b/pypy/module/_frozen_importlib/interp_import.py
@@ -2,7 +2,7 @@
 from pypy.interpreter.error import OperationError
 
 @interp2app
-def import_with_frames_removed(space, __args__):
+def __import__(space, __args__):
     try:
         return space.call_args(
             space.getbuiltinmodule('_frozen_importlib').getdictvalue(
diff --git a/pypy/module/_io/test/test_io.py b/pypy/module/_io/test/test_io.py
--- a/pypy/module/_io/test/test_io.py
+++ b/pypy/module/_io/test/test_io.py
@@ -390,7 +390,7 @@
                     raises(TypeError, pickle.dumps, f, protocol)
 
     def test_mod(self):
-        import _io
+        import _io, _frozen_importlib
         typemods = dict((t, t.__module__) for t in vars(_io).values()
                         if isinstance(t, type))
         for t, mod in typemods.items():
@@ -398,6 +398,11 @@
                 assert mod == 'builtins'
             elif t is _io.UnsupportedOperation:
                 assert mod == 'io'
+            #TODO: Make sure this is a reasonable thing to do. Check if there 
is
+            #a cleaner way to do these checks or if these checks even make 
sense
+            #in general. They seem really brittle.
+            elif t is _frozen_importlib.BuiltinImporter:
+                assert mod == "_frozen_importlib"
             else:
                 assert mod == '_io'
 
diff --git a/pypy/module/_ssl/interp_ssl.py b/pypy/module/_ssl/interp_ssl.py
--- a/pypy/module/_ssl/interp_ssl.py
+++ b/pypy/module/_ssl/interp_ssl.py
@@ -1094,27 +1094,13 @@
     return space.str(space.getattr(w_exc, space.wrap("args")))
 
 
-class W_Error(interp_exceptions.W_OSError):
-    "An error occurred in the SSL implementation."
-
-    def descr_str(self, space):
-        if space.isinstance_w(self.w_strerror, space.w_unicode):
-            return self.w_strerror
-        else:
-            return space.str(space.newtuple(self.args_w))
-
-W_Error.typedef = TypeDef(
-    "ssl.SSLError",
-    interp_exceptions.W_OSError.typedef,
-    __new__  = interp_exceptions._new(W_Error),
-    __doc__  = W_Error.__doc__,
-    __str__  = interp2app(W_Error.descr_str),
-    )
-
-
 class ErrorCache:
     def __init__(self, space):
-        self.w_error = space.gettypefor(W_Error)
+        w_socketerror = interp_socket.get_error(space, "error")
+        self.w_error = space.new_exception_class(
+            "_ssl.SSLError", w_socketerror)
+        space.setattr(self.w_error, space.wrap('__str__'),
+                      space.wrap(interp2app(SSLError_descr_str)))
         self.w_ZeroReturnError = space.new_exception_class(
             "ssl.SSLZeroReturnError", self.w_error)
         self.w_WantReadError = space.new_exception_class(
diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -75,19 +75,25 @@
     w_mod = check_sys_modules_w(space, modulename)
     if w_mod:
         return w_mod
-    if modulename in space.builtin_modules:
-        return space.getbuiltinmodule(modulename)
+    try:
+        lock = getimportlock(space)
+        lock.acquire_lock()
 
-    ec = space.getexecutioncontext()
-    with open(os.path.join(lib_pypy, modulename + '.py')) as fp:
-        source = fp.read()
-    pathname = "<frozen %s>" % modulename
-    code_w = ec.compiler.compile(source, pathname, 'exec', 0)
-    w_mod = add_module(space, space.wrap(modulename))
-    space.setitem(space.sys.get('modules'), w_mod.w_name, w_mod)
-    space.setitem(w_mod.w_dict, space.wrap('__name__'), w_mod.w_name)
-    code_w.exec_code(space, w_mod.w_dict, w_mod.w_dict)
-    assert check_sys_modules_w(space, modulename)
+        if modulename in space.builtin_modules:
+            return space.getbuiltinmodule(modulename)
+
+        ec = space.getexecutioncontext()
+        with open(os.path.join(lib_pypy, modulename + '.py')) as fp:
+            source = fp.read()
+        pathname = "<frozen %s>" % modulename
+        code_w = ec.compiler.compile(source, pathname, 'exec', 0)
+        w_mod = add_module(space, space.wrap(modulename))
+        space.setitem(space.sys.get('modules'), w_mod.w_name, w_mod)
+        space.setitem(w_mod.w_dict, space.wrap('__name__'), w_mod.w_name)
+        code_w.exec_code(space, w_mod.w_dict, w_mod.w_dict)
+        assert check_sys_modules_w(space, modulename)
+    finally:
+        lock.release_lock(silent_after_fork=True)
     return w_mod
 
 
diff --git a/pypy/module/imp/interp_imp.py b/pypy/module/imp/interp_imp.py
--- a/pypy/module/imp/interp_imp.py
+++ b/pypy/module/imp/interp_imp.py
@@ -84,7 +84,9 @@
     name = space.str0_w(w_name)
     if name not in space.builtin_modules:
         return
-    return space.getbuiltinmodule(name)
+    # force_init is needed to make reload actually reload instead of just
+    # using the already-present module in sys.modules.
+    return space.getbuiltinmodule(name, force_init=True)
 
 def init_frozen(space, w_name):
     return None
diff --git a/pypy/module/imp/test/test_import.py 
b/pypy/module/imp/test/test_import.py
--- a/pypy/module/imp/test/test_import.py
+++ b/pypy/module/imp/test/test_import.py
@@ -499,7 +499,7 @@
         # Check relative fails when __package__ set to a non-string
         ns = dict(__package__=object())
         check_absolute()
-        raises(ValueError, check_relative)
+        raises(TypeError, check_relative)
 
     def test_import_function(self):
         # More tests for __import__
@@ -636,7 +636,9 @@
     def test_del_from_sys_modules(self):
         try:
             import del_sys_module
-        except ImportError:
+        #This raises a KeyError in cpython,
+        #not an import error
+        except KeyError:
             pass    # ok
         else:
             assert False, 'should not work'
diff --git a/pypy/module/sys/test/test_sysmodule.py 
b/pypy/module/sys/test/test_sysmodule.py
--- a/pypy/module/sys/test/test_sysmodule.py
+++ b/pypy/module/sys/test/test_sysmodule.py
@@ -32,7 +32,8 @@
         w_sys.flush_std_files(space)
 
         msg = space.bytes_w(space.call_function(w_read))
-        assert 'Exception IOError' in msg
+        # IOError has become an alias for OSError
+        assert 'Exception OSError' in msg
     finally:
         space.setattr(w_sys, space.wrap('stdout'), w_sys.get('__stdout__'))
         space.setattr(w_sys, space.wrap('stderr'), w_sys.get('__stderr__'))
diff --git a/pypy/module/test_lib_pypy/test_code_module.py 
b/pypy/module/test_lib_pypy/test_code_module.py
--- a/pypy/module/test_lib_pypy/test_code_module.py
+++ b/pypy/module/test_lib_pypy/test_code_module.py
@@ -21,7 +21,9 @@
 
     def test_cause_tb(self):
         interp = self.get_interp()
-        interp.runsource('raise IOError from OSError')
+        # (Arbitrarily) Changing to TypeError as IOError is now an alias of
+        # OSError, making testing confusing
+        interp.runsource('raise TypeError from OSError')
         result = interp.out.getvalue()
         expected_header = """OSError
 
@@ -30,7 +32,7 @@
 Traceback (most recent call last):
 """
         assert expected_header in result
-        assert result.endswith("IOError\n")
+        assert result.endswith("TypeError\n")
 
     def test_context_tb(self):
         interp = self.get_interp()
diff --git a/pypy/module/thread/test/test_import_lock.py 
b/pypy/module/thread/test/test_import_lock.py
--- a/pypy/module/thread/test/test_import_lock.py
+++ b/pypy/module/thread/test/test_import_lock.py
@@ -96,14 +96,14 @@
             original_acquire()
         importlock.count = 0
         monkeypatch.setattr(importlock, 'acquire_lock', acquire_lock)
+        # An already imported module
 
-        # An already imported module
         importhook(space, 'sys')
         assert importlock.count == 0
         # A new module
-        importhook(space, '__future__')
+        importhook(space, "time")
         assert importlock.count == 1
         # Import it again
         previous_count = importlock.count
-        importhook(space, '__future__')
+        importhook(space, "time")
         assert importlock.count == previous_count
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to