[pypy-commit] pypy default: document that in f(**d) d must contain only string keys

2017-05-06 Thread cfbolz
Author: Carl Friedrich Bolz 
Branch: 
Changeset: r91191:7f5084ffd6c2
Date: 2017-05-06 17:03 +0200
http://bitbucket.org/pypy/pypy/changeset/7f5084ffd6c2/

Log:document that in f(**d) d must contain only string keys

diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -501,7 +501,11 @@
   the rest is kept.  If you return an unexpected string from
   ``__hex__()`` you get an exception (or a crash before CPython 2.7.13).
 
-* PyPy3: ``__class__`` attritube assignment between heaptypes and non 
heaptypes.
+* In PyPy, dictionaries passed as ``**kwargs`` can contain only string keys,
+  even if the called function takes ``**kwargs``. E.g. this code always
+  produces a ``TypeError``, no matter what ``f`` is: ``f(**{1: 2})``.
+
+* PyPy3: ``__class__`` attribute assignment between heaptypes and non 
heaptypes.
   CPython allows that for module subtypes, but not for e.g. ``int``
   or ``float`` subtypes. Currently PyPy does not support the
   ``__class__`` attribute assignment for any non heaptype subtype.
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] pypy default: Bytearrays have amortized constant-time "del a[:n]" (backport branch py3.5-bytearray)

2017-05-06 Thread rlamy
Author: Ronan Lamy 
Branch: 
Changeset: r91192:42c69a434735
Date: 2017-05-06 19:29 +0100
http://bitbucket.org/pypy/pypy/changeset/42c69a434735/

Log:Bytearrays have amortized constant-time "del a[:n]" (backport branch
py3.5-bytearray)

diff --git a/pypy/objspace/std/bytearrayobject.py 
b/pypy/objspace/std/bytearrayobject.py
--- a/pypy/objspace/std/bytearrayobject.py
+++ b/pypy/objspace/std/bytearrayobject.py
@@ -4,54 +4,67 @@
 import_from_mixin, newlist_hint, resizelist_hint, specialize)
 from rpython.rlib.buffer import Buffer
 from rpython.rlib.rstring import StringBuilder, ByteListBuilder
-from rpython.rlib.debug import check_list_of_chars
+from rpython.rlib.debug import check_list_of_chars, check_nonneg
 from rpython.rtyper.lltypesystem import rffi
 from rpython.rlib.rgc import (resizable_list_supporting_raw_ptr,
 nonmoving_raw_ptr_for_resizable_list)
+from rpython.rlib import jit
 
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.error import OperationError, oefmt
 from pypy.interpreter.gateway import WrappedDefault, interp2app, unwrap_spec
-from pypy.interpreter.signature import Signature
 from pypy.interpreter.typedef import TypeDef
-from pypy.objspace.std.sliceobject import W_SliceObject
+from pypy.objspace.std.sliceobject import W_SliceObject, unwrap_start_stop
 from pypy.objspace.std.stringmethods import StringMethods, _get_buffer
+from pypy.objspace.std.stringmethods import _descr_getslice_slowpath
 from pypy.objspace.std.bytesobject import W_BytesObject
 from pypy.objspace.std.util import get_positive_index
 
 
-
 class W_BytearrayObject(W_Root):
 import_from_mixin(StringMethods)
+_KIND1 = "bytearray"
+_KIND2 = "bytearray"
 
 def __init__(self, data):
 check_list_of_chars(data)
-self.data = resizable_list_supporting_raw_ptr(data)
+self._data = resizable_list_supporting_raw_ptr(data)
+self._offset = 0
+# NOTE: the bytearray data is in 'self._data[self._offset:]'
+check_nonneg(self._offset)
+_tweak_for_tests(self)
+
+def getdata(self):
+if self._offset > 0:
+self._data = self._data[self._offset:]
+self._offset = 0
+return self._data
 
 def __repr__(self):
 """representation for debugging purposes"""
-return "%s(%s)" % (self.__class__.__name__, ''.join(self.data))
+return "%s(%s)" % (self.__class__.__name__,
+   ''.join(self._data[self._offset:]))
 
 def buffer_w(self, space, flags):
-return BytearrayBuffer(self.data, False)
+return BytearrayBuffer(self)
 
 def readbuf_w(self, space):
-return BytearrayBuffer(self.data, True)
+return BytearrayBuffer(self, readonly=True)
 
 def writebuf_w(self, space):
-return BytearrayBuffer(self.data, False)
+return BytearrayBuffer(self)
 
 def charbuf_w(self, space):
-return ''.join(self.data)
+return ''.join(self.getdata())
 
 def bytearray_list_of_chars_w(self, space):
-return self.data
+return self.getdata()
 
 def nonmovable_carray(self, space):
-return BytearrayBuffer(self.data, False).get_raw_address()
+return BytearrayBuffer(self).get_raw_address()
 
 def _new(self, value):
-if value is self.data:
+if value is self._data:
 value = value[:]
 return W_BytearrayObject(value)
 
@@ -65,17 +78,27 @@
 return W_BytearrayObject([])
 
 def _len(self):
-return len(self.data)
+return len(self._data) - self._offset
+
+def _fixindex(self, space, index, errmsg="bytearray index out of range"):
+# for getitem/setitem/delitem of a single char
+if index >= 0:
+index += self._offset
+if index >= len(self._data):
+raise OperationError(space.w_IndexError, space.newtext(errmsg))
+else:
+index += len(self._data)# count from the end
+if index < self._offset:
+raise OperationError(space.w_IndexError, space.newtext(errmsg))
+check_nonneg(index)
+return index
 
 def _getitem_result(self, space, index):
-try:
-character = self.data[index]
-except IndexError:
-raise oefmt(space.w_IndexError, "bytearray index out of range")
+character = self._data[self._fixindex(space, index)]
 return space.newint(ord(character))
 
 def _val(self, space):
-return self.data
+return self.getdata()
 
 @staticmethod
 def _use_rstr_ops(space, w_other):
@@ -152,11 +175,12 @@
 return 1
 
 def ord(self, space):
-if len(self.data) != 1:
+length = self._len()
+if length != 1:
 raise oefmt(space.w_TypeError,
 "ord() expected a character, but string of length %d "
-"found", len(self.data))
-return space.ne

[pypy-commit] pypy default: merge heads

2017-05-06 Thread rlamy
Author: Ronan Lamy 
Branch: 
Changeset: r91193:df2a94c7ae6f
Date: 2017-05-06 19:38 +0100
http://bitbucket.org/pypy/pypy/changeset/df2a94c7ae6f/

Log:merge heads

diff --git a/include/README b/include/README
--- a/include/README
+++ b/include/README
@@ -1,7 +1,11 @@
 This directory contains all the include files needed to build cpython
 extensions with PyPy.  Note that these are just copies of the original headers
-that are in pypy/module/cpyext/include: they are automatically copied from
-there during translation.
+that are in pypy/module/cpyext/{include,parse}: they are automatically copied
+from there during translation.
 
-Moreover, pypy_decl.h and pypy_macros.h are automatically generated, also
-during translation.
+Moreover, some pypy-specific files are automatically generated, also during
+translation. Currently they are:
+* pypy_decl.h
+* pypy_macros.h
+* pypy_numpy.h
+* pypy_structmember_decl.h
diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -501,7 +501,11 @@
   the rest is kept.  If you return an unexpected string from
   ``__hex__()`` you get an exception (or a crash before CPython 2.7.13).
 
-* PyPy3: ``__class__`` attritube assignment between heaptypes and non 
heaptypes.
+* In PyPy, dictionaries passed as ``**kwargs`` can contain only string keys,
+  even if the called function takes ``**kwargs``. E.g. this code always
+  produces a ``TypeError``, no matter what ``f`` is: ``f(**{1: 2})``.
+
+* PyPy3: ``__class__`` attribute assignment between heaptypes and non 
heaptypes.
   CPython allows that for module subtypes, but not for e.g. ``int``
   or ``float`` subtypes. Currently PyPy does not support the
   ``__class__`` attribute assignment for any non heaptype subtype.
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
@@ -38,6 +38,8 @@
 "compile() arg 3 must be 'exec', 'eval' or 'single'")
 
 if space.isinstance_w(w_source, space.gettypeobject(ast.W_AST.typedef)):
+if flags & consts.PyCF_ONLY_AST:
+return w_source
 ast_node = ast.mod.from_object(space, w_source)
 return ec.compiler.compile_ast(ast_node, filename, mode, flags)
 
diff --git a/pypy/module/__builtin__/test/test_compile.py 
b/pypy/module/__builtin__/test/test_compile.py
--- a/pypy/module/__builtin__/test/test_compile.py
+++ b/pypy/module/__builtin__/test/test_compile.py
@@ -50,7 +50,8 @@
 co1 = compile('print 1', '', 'exec', _ast.PyCF_ONLY_AST)
 raises(TypeError, compile, co1, '', 'eval')
 co2 = compile('1+1', '', 'eval', _ast.PyCF_ONLY_AST)
-compile(co2, '', 'eval')
+tree = compile(co2, '', 'eval')
+assert compile(co2, '', 'eval', _ast.PyCF_ONLY_AST) is co2
 
 def test_leading_newlines(self):
 src = """
diff --git a/pypy/module/cpyext/test/test_userslots.py 
b/pypy/module/cpyext/test/test_userslots.py
--- a/pypy/module/cpyext/test/test_userslots.py
+++ b/pypy/module/cpyext/test/test_userslots.py
@@ -47,6 +47,33 @@
 w_year = space.getattr(w_obj, space.newtext('year'))
 assert space.int_w(w_year) == 1
 
+def test_descr_slots(self, space, api):
+w_descr = space.appexec([], """():
+class Descr(object):
+def __get__(self, obj, type):
+return 42
+def __set__(self, obj, value):
+obj.append('set')
+def __delete__(self, obj):
+obj.append('del')
+return Descr()
+""")
+w_descrtype = space.type(w_descr)
+py_descr = make_ref(space, w_descr)
+py_descrtype = rffi.cast(PyTypeObjectPtr, make_ref(space, w_descrtype))
+w_obj = space.newlist([])
+py_obj = make_ref(space, w_obj)
+w_res = generic_cpy_call(space, py_descrtype.c_tp_descr_get,
+ py_descr, py_obj, py_obj)
+assert space.int_w(w_res) == 42
+assert generic_cpy_call(
+space, py_descrtype.c_tp_descr_set,
+py_descr, py_obj, make_ref(space, space.w_None)) == 0
+assert generic_cpy_call(
+space, py_descrtype.c_tp_descr_set,
+py_descr, py_obj, None) == 0
+assert space.eq_w(w_obj, space.wrap(['set', 'del']))
+
 class AppTestUserSlots(AppTestCpythonExtensionBase):
 def test_tp_hash_from_python(self):
 # to see that the functions are being used,
diff --git a/pypy/module/cpyext/userslot.py b/pypy/module/cpyext/userslot.py
--- a/pypy/module/cpyext/userslot.py
+++ b/pypy/module/cpyext/userslot.py
@@ -109,4 +109,14 @@
 def slot_tp_getattr(space, w_obj1, w_obj2):
 return space.getattr(w_obj1, w_obj2)
 
+@slot_function([PyObject, PyObject, PyObject], PyObject)
+def slot_tp_descr_get(space, w_self, w_obj, w_type)

[pypy-commit] pypy PyBuffer-backport: Fix bytearray

2017-05-06 Thread rlamy
Author: Ronan Lamy 
Branch: PyBuffer-backport
Changeset: r91195:dc72a659d99a
Date: 2017-05-06 19:50 +0100
http://bitbucket.org/pypy/pypy/changeset/dc72a659d99a/

Log:Fix bytearray

diff --git a/pypy/objspace/std/bytearrayobject.py 
b/pypy/objspace/std/bytearrayobject.py
--- a/pypy/objspace/std/bytearrayobject.py
+++ b/pypy/objspace/std/bytearrayobject.py
@@ -2,18 +2,19 @@
 
 from rpython.rlib.objectmodel import (
 import_from_mixin, newlist_hint, resizelist_hint, specialize)
-from rpython.rlib.buffer import Buffer
 from rpython.rlib.rstring import StringBuilder, ByteListBuilder
 from rpython.rlib.debug import check_list_of_chars, check_nonneg
 from rpython.rtyper.lltypesystem import rffi
 from rpython.rlib.rgc import (resizable_list_supporting_raw_ptr,
 nonmoving_raw_ptr_for_resizable_list)
 from rpython.rlib import jit
+from rpython.rlib.buffer import Buffer
 
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.error import OperationError, oefmt
 from pypy.interpreter.gateway import WrappedDefault, interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef
+from pypy.interpreter.buffer import SimpleView
 from pypy.objspace.std.sliceobject import W_SliceObject, unwrap_start_stop
 from pypy.objspace.std.stringmethods import StringMethods, _get_buffer
 from pypy.objspace.std.stringmethods import _descr_getslice_slowpath
@@ -46,7 +47,7 @@
''.join(self._data[self._offset:]))
 
 def buffer_w(self, space, flags):
-return BytearrayBuffer(self)
+return SimpleView(BytearrayBuffer(self))
 
 def readbuf_w(self, space):
 return BytearrayBuffer(self, readonly=True)
diff --git a/pypy/objspace/std/stringmethods.py 
b/pypy/objspace/std/stringmethods.py
--- a/pypy/objspace/std/stringmethods.py
+++ b/pypy/objspace/std/stringmethods.py
@@ -812,4 +812,4 @@
 return [selfvalue[start + i*step] for i in range(sl)]
 
 def _get_buffer(space, w_obj):
-return space.buffer_w(w_obj, space.BUF_SIMPLE)
+return space.buffer_w(w_obj, space.BUF_SIMPLE).as_readbuf()
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit


[pypy-commit] pypy PyBuffer-backport: hg merge default

2017-05-06 Thread rlamy
Author: Ronan Lamy 
Branch: PyBuffer-backport
Changeset: r91194:9d07ac7eaf1a
Date: 2017-05-06 19:40 +0100
http://bitbucket.org/pypy/pypy/changeset/9d07ac7eaf1a/

Log:hg merge default

diff --git a/include/README b/include/README
--- a/include/README
+++ b/include/README
@@ -1,7 +1,11 @@
 This directory contains all the include files needed to build cpython
 extensions with PyPy.  Note that these are just copies of the original headers
-that are in pypy/module/cpyext/include: they are automatically copied from
-there during translation.
+that are in pypy/module/cpyext/{include,parse}: they are automatically copied
+from there during translation.
 
-Moreover, pypy_decl.h and pypy_macros.h are automatically generated, also
-during translation.
+Moreover, some pypy-specific files are automatically generated, also during
+translation. Currently they are:
+* pypy_decl.h
+* pypy_macros.h
+* pypy_numpy.h
+* pypy_structmember_decl.h
diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -501,7 +501,11 @@
   the rest is kept.  If you return an unexpected string from
   ``__hex__()`` you get an exception (or a crash before CPython 2.7.13).
 
-* PyPy3: ``__class__`` attritube assignment between heaptypes and non 
heaptypes.
+* In PyPy, dictionaries passed as ``**kwargs`` can contain only string keys,
+  even if the called function takes ``**kwargs``. E.g. this code always
+  produces a ``TypeError``, no matter what ``f`` is: ``f(**{1: 2})``.
+
+* PyPy3: ``__class__`` attribute assignment between heaptypes and non 
heaptypes.
   CPython allows that for module subtypes, but not for e.g. ``int``
   or ``float`` subtypes. Currently PyPy does not support the
   ``__class__`` attribute assignment for any non heaptype subtype.
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
@@ -38,6 +38,8 @@
 "compile() arg 3 must be 'exec', 'eval' or 'single'")
 
 if space.isinstance_w(w_source, space.gettypeobject(ast.W_AST.typedef)):
+if flags & consts.PyCF_ONLY_AST:
+return w_source
 ast_node = ast.mod.from_object(space, w_source)
 return ec.compiler.compile_ast(ast_node, filename, mode, flags)
 
diff --git a/pypy/module/__builtin__/test/test_compile.py 
b/pypy/module/__builtin__/test/test_compile.py
--- a/pypy/module/__builtin__/test/test_compile.py
+++ b/pypy/module/__builtin__/test/test_compile.py
@@ -50,7 +50,8 @@
 co1 = compile('print 1', '', 'exec', _ast.PyCF_ONLY_AST)
 raises(TypeError, compile, co1, '', 'eval')
 co2 = compile('1+1', '', 'eval', _ast.PyCF_ONLY_AST)
-compile(co2, '', 'eval')
+tree = compile(co2, '', 'eval')
+assert compile(co2, '', 'eval', _ast.PyCF_ONLY_AST) is co2
 
 def test_leading_newlines(self):
 src = """
diff --git a/pypy/module/cpyext/test/test_userslots.py 
b/pypy/module/cpyext/test/test_userslots.py
--- a/pypy/module/cpyext/test/test_userslots.py
+++ b/pypy/module/cpyext/test/test_userslots.py
@@ -47,6 +47,33 @@
 w_year = space.getattr(w_obj, space.newtext('year'))
 assert space.int_w(w_year) == 1
 
+def test_descr_slots(self, space, api):
+w_descr = space.appexec([], """():
+class Descr(object):
+def __get__(self, obj, type):
+return 42
+def __set__(self, obj, value):
+obj.append('set')
+def __delete__(self, obj):
+obj.append('del')
+return Descr()
+""")
+w_descrtype = space.type(w_descr)
+py_descr = make_ref(space, w_descr)
+py_descrtype = rffi.cast(PyTypeObjectPtr, make_ref(space, w_descrtype))
+w_obj = space.newlist([])
+py_obj = make_ref(space, w_obj)
+w_res = generic_cpy_call(space, py_descrtype.c_tp_descr_get,
+ py_descr, py_obj, py_obj)
+assert space.int_w(w_res) == 42
+assert generic_cpy_call(
+space, py_descrtype.c_tp_descr_set,
+py_descr, py_obj, make_ref(space, space.w_None)) == 0
+assert generic_cpy_call(
+space, py_descrtype.c_tp_descr_set,
+py_descr, py_obj, None) == 0
+assert space.eq_w(w_obj, space.wrap(['set', 'del']))
+
 class AppTestUserSlots(AppTestCpythonExtensionBase):
 def test_tp_hash_from_python(self):
 # to see that the functions are being used,
diff --git a/pypy/module/cpyext/userslot.py b/pypy/module/cpyext/userslot.py
--- a/pypy/module/cpyext/userslot.py
+++ b/pypy/module/cpyext/userslot.py
@@ -109,4 +109,14 @@
 def slot_tp_getattr(space, w_obj1, w_obj2):
 return space.getattr(w_obj1, w_obj2)
 
+@slot_function([PyObject, PyObject, PyObject], PyObject)
+def slot_tp_descr_get(space, 

[pypy-commit] pypy PyBuffer-backport: Add space.byte_w()

2017-05-06 Thread rlamy
Author: Ronan Lamy 
Branch: PyBuffer-backport
Changeset: r91196:97f60ebf3ec0
Date: 2017-05-06 20:42 +0100
http://bitbucket.org/pypy/pypy/changeset/97f60ebf3ec0/

Log:Add space.byte_w()

diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1654,6 +1654,23 @@
 def fsencode_or_none_w(self, w_obj):
 return None if self.is_none(w_obj) else self.fsencode_w(w_obj)
 
+def byte_w(self, w_obj):
+"""
+Convert an index-like object to an interp-level char
+
+Used for app-level code like "bytearray(b'abc')[0] = 42".
+"""
+if self.isinstance_w(w_obj, self.w_bytes):
+string = self.bytes_w(w_obj)
+if len(string) != 1:
+raise oefmt(self.w_ValueError, "string must be of size 1")
+return string[0]
+value = self.getindex_w(w_obj, None)
+if not 0 <= value < 256:
+# this includes the OverflowError in case the long is too large
+raise oefmt(self.w_ValueError, "byte must be in range(0, 256)")
+return chr(value)
+
 def int_w(self, w_obj, allow_conversion=True):
 """
 Unwrap an app-level int object into an interpret-level int.
diff --git a/pypy/objspace/std/bytearrayobject.py 
b/pypy/objspace/std/bytearrayobject.py
--- a/pypy/objspace/std/bytearrayobject.py
+++ b/pypy/objspace/std/bytearrayobject.py
@@ -415,7 +415,7 @@
 else:
 idx = space.getindex_w(w_index, space.w_IndexError,
"bytearray index")
-newvalue = getbytevalue(space, w_other)
+newvalue = space.byte_w(w_other)
 self._data[self._fixindex(space, idx)] = newvalue
 
 def descr_delitem(self, space, w_idx):
@@ -442,7 +442,7 @@
  _shrink_after_delete_from_start, self)
 
 def descr_append(self, space, w_item):
-self._data.append(getbytevalue(space, w_item))
+self._data.append(space.byte_w(w_item))
 
 def descr_extend(self, space, w_other):
 if isinstance(w_other, W_BytearrayObject):
@@ -452,10 +452,9 @@
 
 def descr_insert(self, space, w_idx, w_other):
 where = space.int_w(w_idx)
-val = getbytevalue(space, w_other)
 data = self.getdata()
-length = len(data)
-index = get_positive_index(where, length)
+index = get_positive_index(where, len(data))
+val = space.byte_w(w_other)
 data.insert(index, val)
 
 @unwrap_spec(w_idx=WrappedDefault(-1))
@@ -552,20 +551,6 @@
 # 
 
 
-def getbytevalue(space, w_value):
-if space.isinstance_w(w_value, space.w_bytes):
-string = space.bytes_w(w_value)
-if len(string) != 1:
-raise oefmt(space.w_ValueError, "string must be of size 1")
-return string[0]
-
-value = space.getindex_w(w_value, None)
-if not 0 <= value < 256:
-# this includes the OverflowError in case the long is too large
-raise oefmt(space.w_ValueError, "byte must be in range(0, 256)")
-return chr(value)
-
-
 def new_bytearray(space, w_bytearraytype, data):
 w_obj = space.allocate_instance(W_BytearrayObject, w_bytearraytype)
 W_BytearrayObject.__init__(w_obj, data)
@@ -594,8 +579,7 @@
 if not e.match(space, space.w_StopIteration):
 raise
 break
-value = getbytevalue(space, w_item)
-data.append(value)
+data.append(space.byte_w(w_item))
 extended += 1
 if extended < length_hint:
 resizelist_hint(data, extended)
diff --git a/pypy/objspace/std/test/test_memoryobject.py 
b/pypy/objspace/std/test/test_memoryobject.py
--- a/pypy/objspace/std/test/test_memoryobject.py
+++ b/pypy/objspace/std/test/test_memoryobject.py
@@ -27,7 +27,8 @@
 v[0:3] = v[2:5]
 assert data == bytearray(eval("b'23f3fg'"))
 exc = raises(ValueError, "v[2] = 'spam'")
-assert str(exc.value) == "cannot modify size of memoryview object"
+assert str(exc.value) in ("cannot modify size of memoryview object",
+  "string must be of size 1")
 exc = raises(NotImplementedError, "v[0:2:2] = 'spam'")
 assert str(exc.value) == ""
 
___
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit