[pypy-commit] pypy reflex-support: merge default into branch

wlav noreply at buildbot.pypy.org
Sat Apr 26 02:10:53 CEST 2014


Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r70985:b81d95fa41f2
Date: 2014-04-25 10:53 -0700
http://bitbucket.org/pypy/pypy/changeset/b81d95fa41f2/

Log:	merge default into branch

diff --git a/lib-python/2.7/test/test_builtin.py b/lib-python/2.7/test/test_builtin.py
--- a/lib-python/2.7/test/test_builtin.py
+++ b/lib-python/2.7/test/test_builtin.py
@@ -250,14 +250,12 @@
         self.assertRaises(TypeError, compile)
         self.assertRaises(ValueError, compile, 'print 42\n', '<string>', 'badmode')
         self.assertRaises(ValueError, compile, 'print 42\n', '<string>', 'single', 0xff)
-        if check_impl_detail(cpython=True):
-            self.assertRaises(TypeError, compile, chr(0), 'f', 'exec')
+        self.assertRaises(TypeError, compile, chr(0), 'f', 'exec')
         self.assertRaises(TypeError, compile, 'pass', '?', 'exec',
                           mode='eval', source='0', filename='tmp')
         if have_unicode:
             compile(unicode('print u"\xc3\xa5"\n', 'utf8'), '', 'exec')
-            if check_impl_detail(cpython=True):
-                self.assertRaises(TypeError, compile, unichr(0), 'f', 'exec')
+            self.assertRaises(TypeError, compile, unichr(0), 'f', 'exec')
             self.assertRaises(ValueError, compile, unicode('a = 1'), 'f', 'bad')
 
 
diff --git a/pypy/module/__builtin__/compiling.py b/pypy/module/__builtin__/compiling.py
--- a/pypy/module/__builtin__/compiling.py
+++ b/pypy/module/__builtin__/compiling.py
@@ -22,22 +22,6 @@
 compile; if absent or zero these statements do influence the compilation,
 in addition to any features explicitly specified.
 """
-
-    ast_node = None
-    w_ast_type = space.gettypeobject(ast.AST.typedef)
-    str_ = None
-    if space.isinstance_w(w_source, w_ast_type):
-        ast_node = space.interp_w(ast.mod, w_source)
-        ast_node.sync_app_attrs(space)
-    elif space.isinstance_w(w_source, space.w_unicode):
-        w_utf_8_source = space.call_method(w_source, "encode",
-                                           space.wrap("utf-8"))
-        str_ = space.str_w(w_utf_8_source)
-        # This flag tells the parser to reject any coding cookies it sees.
-        flags |= consts.PyCF_SOURCE_IS_UTF8
-    else:
-        str_ = space.str_w(w_source)
-
     ec = space.getexecutioncontext()
     if flags & ~(ec.compiler.compiler_flags | consts.PyCF_ONLY_AST |
                  consts.PyCF_DONT_IMPLY_DEDENT | consts.PyCF_SOURCE_IS_UTF8):
@@ -53,14 +37,30 @@
                              space.wrap("compile() arg 3 must be 'exec' "
                                         "or 'eval' or 'single'"))
 
-    if ast_node is None:
-        if flags & consts.PyCF_ONLY_AST:
-            mod = ec.compiler.compile_to_ast(str_, filename, mode, flags)
-            return space.wrap(mod)
-        else:
-            code = ec.compiler.compile(str_, filename, mode, flags)
+    w_ast_type = space.gettypeobject(ast.AST.typedef)
+    if space.isinstance_w(w_source, w_ast_type):
+        ast_node = space.interp_w(ast.mod, w_source)
+        ast_node.sync_app_attrs(space)
+        code = ec.compiler.compile_ast(ast_node, filename, mode, flags)
+        return space.wrap(code)
+
+    if space.isinstance_w(w_source, space.w_unicode):
+        w_utf_8_source = space.call_method(w_source, "encode",
+                                           space.wrap("utf-8"))
+        str_ = space.str_w(w_utf_8_source)
+        # This flag tells the parser to reject any coding cookies it sees.
+        flags |= consts.PyCF_SOURCE_IS_UTF8
     else:
-        code = ec.compiler.compile_ast(ast_node, filename, mode, flags)
+        str_ = space.readbuf_w(w_source).as_str()
+
+    if '\x00' in str_:
+        raise OperationError(space.w_TypeError, space.wrap(
+            "compile() expected string without null bytes"))
+
+    if flags & consts.PyCF_ONLY_AST:
+        code = ec.compiler.compile_to_ast(str_, filename, mode, flags)
+    else:
+        code = ec.compiler.compile(str_, filename, mode, flags)
     return space.wrap(code)
 
 
diff --git a/pypy/module/__builtin__/test/test_builtin.py b/pypy/module/__builtin__/test/test_builtin.py
--- a/pypy/module/__builtin__/test/test_builtin.py
+++ b/pypy/module/__builtin__/test/test_builtin.py
@@ -490,6 +490,14 @@
     def test_compile(self):
         co = compile('1+2', '?', 'eval')
         assert eval(co) == 3
+        co = compile(buffer('1+2'), '?', 'eval')
+        assert eval(co) == 3
+        exc = raises(TypeError, compile, chr(0), '?', 'eval')
+        assert str(exc.value) == "compile() expected string without null bytes"
+        exc = raises(TypeError, compile, unichr(0), '?', 'eval')
+        assert str(exc.value) == "compile() expected string without null bytes"
+        exc = raises(TypeError, compile, memoryview('1+2'), '?', 'eval')
+        assert str(exc.value) == "expected a readable buffer object"
         compile("from __future__ import with_statement", "<test>", "exec")
         raises(SyntaxError, compile, '-', '?', 'eval')
         raises(ValueError, compile, '"\\xt"', '?', 'eval')
diff --git a/pypy/module/_codecs/interp_codecs.py b/pypy/module/_codecs/interp_codecs.py
--- a/pypy/module/_codecs/interp_codecs.py
+++ b/pypy/module/_codecs/interp_codecs.py
@@ -679,7 +679,7 @@
     if space.isinstance_w(w_string, space.w_unicode):
         return space.newtuple([w_string, space.len(w_string)])
 
-    string = space.str_w(w_string)
+    string = space.readbuf_w(w_string).as_str()
 
     if len(string) == 0:
         return space.newtuple([space.wrap(u''), space.wrap(0)])
diff --git a/pypy/module/_codecs/test/test_codecs.py b/pypy/module/_codecs/test/test_codecs.py
--- a/pypy/module/_codecs/test/test_codecs.py
+++ b/pypy/module/_codecs/test/test_codecs.py
@@ -276,7 +276,7 @@
                 assert enc == "a\x00\x00\x00"
 
     def test_unicode_internal_decode(self):
-        import sys
+        import sys, _codecs, array
         if sys.maxunicode == 65535: # UCS2 build
             if sys.byteorder == "big":
                 bytes = "\x00a"
@@ -291,6 +291,9 @@
                 bytes2 = "\x98\x00\x01\x00"
             assert bytes2.decode("unicode_internal") == u"\U00010098"
         assert bytes.decode("unicode_internal") == u"a"
+        assert _codecs.unicode_internal_decode(array.array('c', bytes))[0] == u"a"
+        exc = raises(TypeError, _codecs.unicode_internal_decode, memoryview(bytes))
+        assert str(exc.value) == "expected a readable buffer object"
 
     def test_raw_unicode_escape(self):
         assert unicode("\u0663", "raw-unicode-escape") == u"\u0663"
diff --git a/pypy/module/_file/interp_file.py b/pypy/module/_file/interp_file.py
--- a/pypy/module/_file/interp_file.py
+++ b/pypy/module/_file/interp_file.py
@@ -460,14 +460,17 @@
 
         space = self.space
         self.check_closed()
-        w_iterator = space.iter(w_lines)
-        while True:
-            try:
-                w_line = space.next(w_iterator)
-            except OperationError, e:
-                if not e.match(space, space.w_StopIteration):
-                    raise
-                break  # done
+        lines = space.fixedview(w_lines)
+        for i, w_line in enumerate(lines):
+            if not space.isinstance_w(w_line, space.w_str):
+                try:
+                    line = w_line.charbuf_w(space)
+                except TypeError:
+                    raise OperationError(space.w_TypeError, space.wrap(
+                        "writelines() argument must be a sequence of strings"))
+                else:
+                    lines[i] = space.wrap(line)
+        for w_line in lines:
             self.file_write(w_line)
 
     def file_readinto(self, w_rwbuffer):
diff --git a/pypy/module/_file/test/test_file_extra.py b/pypy/module/_file/test/test_file_extra.py
--- a/pypy/module/_file/test/test_file_extra.py
+++ b/pypy/module/_file/test/test_file_extra.py
@@ -386,6 +386,32 @@
         assert len(somelines) > 200
         assert somelines == lines[:len(somelines)]
 
+    def test_writelines(self):
+        import array
+        fn = self.temptestfile
+        with file(fn, 'w') as f:
+            f.writelines(['abc'])
+            f.writelines([u'def'])
+            exc = raises(TypeError, f.writelines, [array.array('c', 'ghi')])
+            assert str(exc.value) == "writelines() argument must be a sequence of strings"
+            exc = raises(TypeError, f.writelines, [memoryview('jkl')])
+            assert str(exc.value) == "writelines() argument must be a sequence of strings"
+        assert open(fn, 'r').readlines() == ['abcdef']
+
+        with file(fn, 'wb') as f:
+            f.writelines(['abc'])
+            f.writelines([u'def'])
+            exc = raises(TypeError, f.writelines, [array.array('c', 'ghi')])
+            assert str(exc.value) == "writelines() argument must be a sequence of strings"
+            exc = raises(TypeError, f.writelines, [memoryview('jkl')])
+            assert str(exc.value) == "writelines() argument must be a sequence of strings"
+        assert open(fn, 'rb').readlines() == ['abcdef']
+
+        with file(fn, 'wb') as f:
+            exc = raises(TypeError, f.writelines, ['abc', memoryview('def')])
+            assert str(exc.value) == "writelines() argument must be a sequence of strings"
+        assert open(fn, 'rb').readlines() == []
+
     def test_nasty_writelines(self):
         # The stream lock should be released between writes
         fn = self.temptestfile
diff --git a/pypy/module/_rawffi/array.py b/pypy/module/_rawffi/array.py
--- a/pypy/module/_rawffi/array.py
+++ b/pypy/module/_rawffi/array.py
@@ -193,7 +193,7 @@
 
     def setslice(self, space, w_slice, w_value):
         start, stop = self.decodeslice(space, w_slice)
-        value = space.bufferstr_w(w_value)
+        value = space.str_w(w_value)
         if start + len(value) != stop:
             raise OperationError(space.w_ValueError,
                                  space.wrap("cannot resize array"))
diff --git a/pypy/sandbox/pypy_interact.py b/pypy/sandbox/pypy_interact.py
--- a/pypy/sandbox/pypy_interact.py
+++ b/pypy/sandbox/pypy_interact.py
@@ -21,7 +21,7 @@
 """
 
 import sys, os
-sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), '..', '..', '..')))
+sys.path.insert(0, os.path.realpath(os.path.join(os.path.dirname(__file__), '..', '..')))
 from rpython.translator.sandbox.sandlib import SimpleIOSandboxedProc
 from rpython.translator.sandbox.sandlib import VirtualizedSandboxedProc
 from rpython.translator.sandbox.vfs import Dir, RealDir, RealFile
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -8356,6 +8356,31 @@
         """
         self.optimize_loop(ops, ops)
 
+    def test_unroll_failargs(self):
+        ops = """
+        [p0, i1]
+        p1 = getfield_gc(p0, descr=valuedescr)
+        i2 = int_add(i1, 1)
+        i3 = int_le(i2, 13)
+        guard_true(i3) [p1]
+        jump(p0, i2)      
+        """
+        expected = """
+        [p0, i1, p1]
+        i2 = int_add(i1, 1)
+        i3 = int_le(i2, 13)
+        guard_true(i3) [p1]
+        jump(p0, i2, p1)
+        """
+        preamble = """
+        [p0, i1]
+        p1 = getfield_gc(p0, descr=valuedescr)
+        i2 = int_add(i1, 1)
+        i3 = int_le(i2, 13)
+        guard_true(i3) [p1]
+        jump(p0, i2, p1)        
+        """
+        self.optimize_loop(ops, expected, preamble)
 
 class TestLLtype(OptimizeOptTest, LLtypeMixin):
     pass
diff --git a/rpython/jit/metainterp/test/test_string.py b/rpython/jit/metainterp/test/test_string.py
--- a/rpython/jit/metainterp/test/test_string.py
+++ b/rpython/jit/metainterp/test/test_string.py
@@ -654,3 +654,23 @@
         self.check_resops(call_pure=0, unicodesetitem=0, call=2,
                           newunicode=0, unicodegetitem=0,
                           copyunicodecontent=0)
+
+    def test_string_interpolation(self):
+        def f(x, y):
+            return len('<%d %d>' % (x, y))
+        res = self.interp_operations(f, [222, 3333])
+        assert res == 10
+
+    def test_string_interpolation_constants(self):
+        jitdriver = JitDriver(greens=['x', 'y'], reds=['z'])
+        def f(x, y):
+            z = 0
+            while z < 10:
+                jitdriver.jit_merge_point(x=x, y=y, z=z)
+                if len('<%d %d>' % (x, y)) != 10:
+                    raise Exception
+                z += 1
+            return 0
+        self.meta_interp(f, [222, 3333])
+        self.check_simple_loop({'guard_true': 1, 'int_add': 1,
+                                'int_lt': 1, 'jump': 1})
diff --git a/rpython/translator/platform/test/test_posix.py b/rpython/translator/platform/test/test_posix.py
--- a/rpython/translator/platform/test/test_posix.py
+++ b/rpython/translator/platform/test/test_posix.py
@@ -9,13 +9,8 @@
     res = host.execute('echo', '42 24')
     assert res.out == '42 24\n'
 
-    if sys.platform == 'win32':
-        # echo is a shell builtin on Windows
-        res = host.execute('cmd', ['/c', 'echo', '42', '24'])
-        assert res.out == '42 24\n'
-    else:
-        res = host.execute('echo', ['42', '24'])
-        assert res.out == '42 24\n'
+    res = host.execute('echo', ['42', '24'])
+    assert res.out == '42 24\n'
 
 class TestMakefile(object):
     platform = host
@@ -61,8 +56,13 @@
         finally:
             del os.environ['PYPY_LOCALBASE']
         Makefile = tmpdir.join('Makefile').read()
-        assert 'INCLUDEDIRS = -I/foo/baz/include' in Makefile
-        assert 'LIBDIRS = -L/foo/baz/lib' in Makefile
+        include_prefix = '-I'
+        lib_prefix = '-L'
+        if self.platform.name == 'msvc':
+            include_prefix = '/I'
+            lib_prefix = '/LIBPATH:'
+        assert 'INCLUDEDIRS = %s/foo/baz/include' % include_prefix in Makefile
+        assert 'LIBDIRS = %s/foo/baz/lib' % lib_prefix in Makefile
 
 class TestMaemo(TestMakefile):
     strict_on_stderr = False
diff --git a/rpython/translator/platform/windows.py b/rpython/translator/platform/windows.py
--- a/rpython/translator/platform/windows.py
+++ b/rpython/translator/platform/windows.py
@@ -292,7 +292,10 @@
         rel_ofiles = [rel_cfile[:rel_cfile.rfind('.')]+'.obj' for rel_cfile in rel_cfiles]
         m.cfiles = rel_cfiles
 
-        rel_includedirs = [rpyrel(incldir) for incldir in eci.include_dirs]
+        rel_includedirs = [rpyrel(incldir) for incldir in
+                           self.preprocess_include_dirs(eci.include_dirs)]
+        rel_libdirs = [rpyrel(libdir) for libdir in
+                       self.preprocess_library_dirs(eci.library_dirs)]
 
         m.comment('automatically generated makefile')
         definitions = [
@@ -302,7 +305,7 @@
             ('SOURCES', rel_cfiles),
             ('OBJECTS', rel_ofiles),
             ('LIBS', self._libs(eci.libraries)),
-            ('LIBDIRS', self._libdirs(eci.library_dirs)),
+            ('LIBDIRS', self._libdirs(rel_libdirs)),
             ('INCLUDEDIRS', self._includedirs(rel_includedirs)),
             ('CFLAGS', self.cflags),
             ('CFLAGSEXTRA', list(eci.compile_extra)),
diff --git a/rpython/translator/sandbox/rsandbox.py b/rpython/translator/sandbox/rsandbox.py
--- a/rpython/translator/sandbox/rsandbox.py
+++ b/rpython/translator/sandbox/rsandbox.py
@@ -3,6 +3,10 @@
 trampolines that marshal their input arguments, dump them to STDOUT,
 and wait for an answer on STDIN.  Enable with 'translate.py --sandbox'.
 """
+import sys
+if sys.platform == 'win32':
+    raise TypeError("sandbox not supported on windows")
+
 import py
 
 from rpython.rlib import rmarshal, types
diff --git a/rpython/translator/sandbox/test/test_sandbox.py b/rpython/translator/sandbox/test/test_sandbox.py
--- a/rpython/translator/sandbox/test/test_sandbox.py
+++ b/rpython/translator/sandbox/test/test_sandbox.py
@@ -25,7 +25,20 @@
                     check_str_without_nul=True)
     return str(t.compile())
 
+unsupported_platform = ('False', '')
+if sys.platform == 'win32':
+    unsupported_platform = ('True', 'sandbox not supported on this platform')
+    def test_unavailable():
+        def entry_point(argv):
+            fd = os.open("/tmp/foobar", os.O_RDONLY, 0777)
+            os.close(fd)
+            return 0
+        exc = py.test.raises(TypeError, compile, entry_point)
+        assert str(exc).find('not supported') >= 0
 
+supported = py.test.mark.skipif(unsupported_platform[0], reason=unsupported_platform[1])
+
+ at supported
 def test_open_dup():
     def entry_point(argv):
         fd = os.open("/tmp/foobar", os.O_RDONLY, 0777)
@@ -43,6 +56,7 @@
     f.close()
     assert tail == ""
 
+ at supported
 def test_read_write():
     def entry_point(argv):
         fd = os.open("/tmp/foobar", os.O_RDONLY, 0777)
@@ -65,6 +79,7 @@
     f.close()
     assert tail == ""
 
+ at supported
 def test_dup2_access():
     def entry_point(argv):
         os.dup2(34, 56)
@@ -80,6 +95,7 @@
     f.close()
     assert tail == ""
 
+ at supported
 def test_stat_ftruncate():
     from rpython.translator.sandbox.sandlib import RESULTTYPE_STATRESULT
     from rpython.rlib.rarithmetic import r_longlong
@@ -101,6 +117,7 @@
     f.close()
     assert tail == ""
 
+ at supported
 def test_time():
     def entry_point(argv):
         t = time.time()
@@ -116,6 +133,7 @@
     f.close()
     assert tail == ""
 
+ at supported
 def test_getcwd():
     def entry_point(argv):
         t = os.getcwd()
@@ -131,6 +149,7 @@
     f.close()
     assert tail == ""
 
+ at supported
 def test_oserror():
     def entry_point(argv):
         try:
@@ -148,6 +167,7 @@
     f.close()
     assert tail == ""
 
+ at supported
 def test_hybrid_gc():
     def entry_point(argv):
         l = []
@@ -172,6 +192,7 @@
     rescode = pipe.wait()
     assert rescode == 0
 
+ at supported
 def test_segfault_1():
     class A:
         def __init__(self, m):
@@ -194,6 +215,7 @@
     e.close()
     assert 'Invalid RPython operation' in errors
 
+ at supported
 def test_segfault_2():
     py.test.skip("hum, this is one example, but we need to be very careful")
     class Base:
@@ -226,6 +248,7 @@
     e.close()
     assert '...think what kind of errors to get...' in errors
 
+ at supported
 def test_safe_alloc():
     from rpython.rlib.rmmap import alloc, free
 
@@ -246,6 +269,7 @@
     rescode = pipe.wait()
     assert rescode == 0
 
+ at supported
 def test_unsafe_mmap():
     py.test.skip("Since this stuff is unimplemented, it won't work anyway "
                  "however, the day it starts working, it should pass test")
@@ -271,6 +295,7 @@
     rescode = pipe.wait()
     assert rescode == 0
 
+ at supported
 class TestPrintedResults:
 
     def run(self, entry_point, args, expected):
diff --git a/rpython/translator/sandbox/test/test_sandlib.py b/rpython/translator/sandbox/test/test_sandlib.py
--- a/rpython/translator/sandbox/test/test_sandlib.py
+++ b/rpython/translator/sandbox/test/test_sandlib.py
@@ -6,10 +6,10 @@
 from rpython.translator.sandbox.sandlib import SimpleIOSandboxedProc
 from rpython.translator.sandbox.sandlib import VirtualizedSandboxedProc
 from rpython.translator.sandbox.sandlib import VirtualizedSocketProc
-from rpython.translator.sandbox.test.test_sandbox import compile
+from rpython.translator.sandbox.test.test_sandbox import compile, supported
 from rpython.translator.sandbox.vfs import Dir, File, RealDir, RealFile
 
-
+ at supported
 class MockSandboxedProc(SandboxedProc):
     """A sandbox process wrapper that replays expected syscalls."""
 
@@ -35,7 +35,7 @@
     do_ll_os__ll_os_write = _make_method("write")
     do_ll_os__ll_os_close = _make_method("close")
 
-
+ at supported
 def test_lib():
     def entry_point(argv):
         fd = os.open("/tmp/foobar", os.O_RDONLY, 0777)
@@ -63,6 +63,7 @@
     proc.handle_forever()
     assert proc.seen == len(proc.expected)
 
+ at supported
 def test_foobar():
     py.test.skip("to be updated")
     foobar = rffi.llexternal("foobar", [rffi.CCHARP], rffi.LONG)
@@ -79,6 +80,7 @@
     proc.handle_forever()
     assert proc.seen == len(proc.expected)
 
+ at supported
 def test_simpleio():
     def entry_point(argv):
         print "Please enter a number:"
@@ -100,6 +102,7 @@
     assert output == "Please enter a number:\nThe double is: 42\n"
     assert error == ""
 
+ at supported
 def test_socketio():
     class SocketProc(VirtualizedSocketProc, SimpleIOSandboxedProc):
         def build_virtual_root(self):
@@ -116,6 +119,7 @@
     output, error = proc.communicate("")
     assert output.startswith('HTTP/1.0 503 Service Unavailable')
 
+ at supported
 def test_oserror():
     def entry_point(argv):
         try:
@@ -133,6 +137,7 @@
     assert proc.seen == len(proc.expected)
 
 
+ at supported
 class SandboxedProcWithFiles(VirtualizedSandboxedProc, SimpleIOSandboxedProc):
     """A sandboxed process with a simple virtualized filesystem.
 
@@ -145,6 +150,7 @@
             'this.pyc': RealFile(__file__),
              })
 
+ at supported
 def test_too_many_opens():
     def entry_point(argv):
         try:
@@ -186,6 +192,7 @@
     assert output == "All ok!\n"
     assert error == ""
 
+ at supported
 def test_fstat():
     def compare(a, b, i):
         if a != b:
@@ -219,6 +226,7 @@
     assert output == "All ok!\n"
     assert error == ""
 
+ at supported
 def test_lseek():
     def char_should_be(c, should):
         if c != should:
@@ -248,6 +256,7 @@
     assert output == "All ok!\n"
     assert error == ""
 
+ at supported
 def test_getuid():
     def entry_point(argv):
         import os
diff --git a/rpython/translator/sandbox/test/test_vfs.py b/rpython/translator/sandbox/test/test_vfs.py
--- a/rpython/translator/sandbox/test/test_vfs.py
+++ b/rpython/translator/sandbox/test/test_vfs.py
@@ -2,10 +2,13 @@
 import sys, stat, os
 from rpython.translator.sandbox.vfs import *
 from rpython.tool.udir import udir
+from rpython.translator.sandbox.test.test_sandbox import unsupported_platform
 
 HASLINK = hasattr(os, 'symlink')
 
 def setup_module(mod):
+    if unsupported_platform[0] == 'True':
+        py.test.skip(unsupported_platform[1])
     d = udir.ensure('test_vfs', dir=1)
     d.join('file1').write('somedata1')
     d.join('file2').write('somelongerdata2')


More information about the pypy-commit mailing list