[pypy-commit] cffi sirtom67/float_complex: float complex progress. Added __complex__ method to cdata.
Author: Tom KraussBranch: sirtom67/float_complex Changeset: r2879:6dcf51c6003c Date: 2017-02-05 17:13 -0600 http://bitbucket.org/cffi/cffi/changeset/6dcf51c6003c/ Log:float complex progress. Added __complex__ method to cdata. Test currently failing at > assert repr(complex(cast(p, -0j))) == '-0j' E assert '0j' == '-0j' E - 0j E + -0j E ? + diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c --- a/c/_cffi_backend.c +++ b/c/_cffi_backend.c @@ -884,6 +884,26 @@ return 0; } +static Py_complex +read_raw_complex_data(char *target, int size) +{ +Py_complex r = {.real=0, .imag=0}; +if (size == 2*sizeof(float)) { +float real_part, imag_part; +memcpy(_part, target + 0, sizeof(float)); +memcpy(_part, target + sizeof(float), sizeof(float)); +r.real = real_part; +r.imag = imag_part; +return r; +} +if (size == 2*sizeof(double)) { +memcpy(&(r.real), target, 2*sizeof(double)); +return r; +} +Py_FatalError("read_raw_complex_data: bad float size"); +return r; +} + static void write_raw_float_data(char *target, double source, int size) { @@ -1011,6 +1031,10 @@ return (PyObject *)cd; } } +else if (ct->ct_flags & CT_PRIMITIVE_COMPLEX) { +Py_complex value = read_raw_complex_data(data, ct->ct_size); +return PyComplex_FromCComplex(value); +} else if (ct->ct_flags & CT_PRIMITIVE_CHAR) { /*READ(data, ct->ct_size)*/ if (ct->ct_size == sizeof(char)) @@ -2009,6 +2033,10 @@ } return PyFloat_FromDouble(value); } +if (cd->c_type->ct_flags & CT_PRIMITIVE_COMPLEX) { +double value = read_raw_float_data(cd->c_data, cd->c_type->ct_size); +return PyComplex_FromDoubles(value, 0.0); +} PyErr_Format(PyExc_TypeError, "float() not supported on cdata '%s'", cd->c_type->ct_name); return NULL; @@ -2808,6 +2836,19 @@ } } +static PyObject *cdata_complex(PyObject *cd_, PyObject *noarg) +{ +CDataObject *cd = (CDataObject *)cd_; + +if (cd->c_type->ct_flags & CT_PRIMITIVE_COMPLEX) { +Py_complex value = read_raw_complex_data(cd->c_data, cd->c_type->ct_size); +return PyComplex_FromCComplex(value); +} +PyErr_Format(PyExc_TypeError, "complex() not supported on cdata '%s'", + cd->c_type->ct_name); +return NULL; +} + static PyObject *cdata_iter(CDataObject *); static PyNumberMethods CData_as_number = { @@ -2857,8 +2898,9 @@ }; static PyMethodDef cdata_methods[] = { -{"__dir__", cdata_dir, METH_NOARGS}, -{NULL,NULL} /* sentinel */ +{"__dir__", cdata_dir, METH_NOARGS}, +{"__complex__", cdata_complex, METH_NOARGS}, +{NULL, NULL} /* sentinel */ }; static PyTypeObject CData_Type = { @@ -3599,7 +3641,6 @@ /* cast to a complex */ Py_complex value; PyObject *io; -printf("_cffi_backend.c do_cast ct->ct_size=%ld\n", ct->ct_size); if (CData_Check(ob)) { CDataObject *cdsrc = (CDataObject *)ob; @@ -3983,8 +4024,6 @@ int name_size; ffi_type *ffitype; -printf("hello\n"); - for (ptypes=types; ; ptypes++) { if (ptypes->name == NULL) { #ifndef HAVE_WCHAR_H diff --git a/c/realize_c_type.c b/c/realize_c_type.c --- a/c/realize_c_type.c +++ b/c/realize_c_type.c @@ -101,7 +101,6 @@ static PyObject *build_primitive_type(int num) { -fprintf(stderr, "fonum=%d\n",num); /* XXX too many translations between here and new_primitive_type() */ static const char *primitive_name[] = { NULL, diff --git a/c/test_c.py b/c/test_c.py --- a/c/test_c.py +++ b/c/test_c.py @@ -197,12 +197,12 @@ py.test.raises(TypeError, float, cast(p, -150)) assert complex(cast(p, 1.25)) == 1.25 assert complex(cast(p, 1.25j)) == 1.25j -assert float(cast(p, INF*1j)) == INF*1j -assert float(cast(p, -INF)) == -INF +assert complex(cast(p, complex(0,INF))) == complex(0,INF) +assert complex(cast(p, -INF)) == -INF if name == "float": assert complex(cast(p, 1.1j)) != 1.1j # rounding error assert complex(cast(p, 1E200+3j)) == INF+3j # limited range -assert complex(cast(p, 3+1E200j)) == 3+INF*1j # limited range +assert complex(cast(p, complex(3,1E200))) == complex(3,INF) # limited range assert cast(p, -1.1j) != cast(p, -1.1j) assert repr(complex(cast(p, -0.0)).real) == '-0.0' ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: hg merge vendor/stdlib-3.5: upgrade stdlib to 3.5.3
Author: Armin RigoBranch: py3.5 Changeset: r89962:08ae26119b9a Date: 2017-02-05 22:45 +0100 http://bitbucket.org/pypy/pypy/changeset/08ae26119b9a/ Log:hg merge vendor/stdlib-3.5: upgrade stdlib to 3.5.3 diff too long, truncating to 2000 out of 24845 lines diff --git a/lib-python/3/_collections_abc.py b/lib-python/3/_collections_abc.py --- a/lib-python/3/_collections_abc.py +++ b/lib-python/3/_collections_abc.py @@ -29,8 +29,8 @@ # so that they will pass tests like: # it = iter(somebytearray) # assert isinstance(it, Iterable) -# Note: in other implementations, these types many not be distinct -# and they make have their own implementation specific types that +# Note: in other implementations, these types might not be distinct +# and they may have their own implementation specific types that # are not included on this list. bytes_iterator = type(iter(b'')) bytearray_iterator = type(iter(bytearray())) @@ -41,6 +41,7 @@ list_iterator = type(iter([])) list_reverseiterator = type(iter(reversed([]))) range_iterator = type(iter(range(0))) +longrange_iterator = type(iter(range(1 << 1000))) set_iterator = type(iter(set())) str_iterator = type(iter("")) tuple_iterator = type(iter(())) @@ -234,6 +235,7 @@ Iterator.register(list_iterator) Iterator.register(list_reverseiterator) Iterator.register(range_iterator) +Iterator.register(longrange_iterator) Iterator.register(set_iterator) Iterator.register(str_iterator) Iterator.register(tuple_iterator) diff --git a/lib-python/3/_pydecimal.py b/lib-python/3/_pydecimal.py --- a/lib-python/3/_pydecimal.py +++ b/lib-python/3/_pydecimal.py @@ -1068,12 +1068,11 @@ return sign + intpart + fracpart + exp def to_eng_string(self, context=None): -"""Convert to engineering-type string. - -Engineering notation has an exponent which is a multiple of 3, so there -are up to 3 digits left of the decimal place. - -Same rules for when in exponential and when as a value as in __str__. +"""Convert to a string, using engineering notation if an exponent is needed. + +Engineering notation has an exponent which is a multiple of 3. This +can leave up to 3 digits to the left of the decimal place and may +require the addition of either one or two trailing zeros. """ return self.__str__(eng=True, context=context) @@ -4107,7 +4106,7 @@ >>> context.create_decimal_from_float(3.1415926535897932) Traceback (most recent call last): ... -decimal.Inexact +decimal.Inexact: None """ d = Decimal.from_float(f) # An exact conversion @@ -5502,9 +5501,29 @@ return r def to_eng_string(self, a): -"""Converts a number to a string, using scientific notation. +"""Convert to a string, using engineering notation if an exponent is needed. + +Engineering notation has an exponent which is a multiple of 3. This +can leave up to 3 digits to the left of the decimal place and may +require the addition of either one or two trailing zeros. The operation is not affected by the context. + +>>> ExtendedContext.to_eng_string(Decimal('123E+1')) +'1.23E+3' +>>> ExtendedContext.to_eng_string(Decimal('123E+3')) +'123E+3' +>>> ExtendedContext.to_eng_string(Decimal('123E-10')) +'12.3E-9' +>>> ExtendedContext.to_eng_string(Decimal('-123E-12')) +'-123E-12' +>>> ExtendedContext.to_eng_string(Decimal('7E-7')) +'700E-9' +>>> ExtendedContext.to_eng_string(Decimal('7E+1')) +'70' +>>> ExtendedContext.to_eng_string(Decimal('0E+1')) +'0.00E+3' + """ a = _convert_other(a, raiseit=True) return a.to_eng_string(context=self) diff --git a/lib-python/3/_pyio.py b/lib-python/3/_pyio.py --- a/lib-python/3/_pyio.py +++ b/lib-python/3/_pyio.py @@ -276,7 +276,7 @@ try: UnsupportedOperation = io.UnsupportedOperation except AttributeError: -class UnsupportedOperation(ValueError, OSError): +class UnsupportedOperation(OSError, ValueError): pass diff --git a/lib-python/3/antigravity.py b/lib-python/3/antigravity.py --- a/lib-python/3/antigravity.py +++ b/lib-python/3/antigravity.py @@ -2,7 +2,7 @@ import webbrowser import hashlib -webbrowser.open("http://xkcd.com/353/;) +webbrowser.open("https://xkcd.com/353/;) def geohash(latitude, longitude, datedow): '''Compute geohash() using the Munroe algorithm. diff --git a/lib-python/3/asyncio/base_events.py b/lib-python/3/asyncio/base_events.py --- a/lib-python/3/asyncio/base_events.py +++ b/lib-python/3/asyncio/base_events.py @@ -13,7 +13,6 @@ to modify the meaning of the API call itself. """ - import collections import concurrent.futures import heapq @@ -28,6 +27,7 @@ import traceback import sys import warnings +import weakref from .
[pypy-commit] pypy py3.5: hg merge
Author: Armin RigoBranch: py3.5 Changeset: r89963:748aa3022295 Date: 2017-02-05 22:45 +0100 http://bitbucket.org/pypy/pypy/changeset/748aa3022295/ Log:hg merge diff --git a/lib-python/2.7/weakref.py b/lib-python/2.7/weakref.py --- a/lib-python/2.7/weakref.py +++ b/lib-python/2.7/weakref.py @@ -31,6 +31,26 @@ "WeakKeyDictionary", "ReferenceError", "ReferenceType", "ProxyType", "CallableProxyType", "ProxyTypes", "WeakValueDictionary", 'WeakSet'] +try: +from __pypy__ import delitem_if_value_is as _delitem_if_value_is +except ImportError: +def _delitem_if_value_is(d, key, value): +try: +if self.data[key] is value: # fall-back: there is a potential +# race condition in multithreaded programs HERE +del self.data[key] +except KeyError: +pass + +def _remove_dead_weakref(d, key): +try: +wr = d[key] +except KeyError: +pass +else: +if wr() is None: +_delitem_if_value_is(d, key, wr) + class WeakValueDictionary(UserDict.UserDict): """Mapping class that references values weakly. @@ -58,14 +78,9 @@ if self._iterating: self._pending_removals.append(wr.key) else: -# Changed this for PyPy: made more resistent. The -# issue is that in some corner cases, self.data -# might already be changed or removed by the time -# this weakref's callback is called. If that is -# the case, we don't want to randomly kill an -# unrelated entry. -if self.data.get(wr.key) is wr: -del self.data[wr.key] +# Atomic removal is necessary since this function +# can be called asynchronously by the GC +_delitem_if_value_is(self.data, wr.key, wr) self._remove = remove # A list of keys to be removed self._pending_removals = [] @@ -78,7 +93,8 @@ # We shouldn't encounter any KeyError, because this method should # always be called *before* mutating the dict. while l: -del d[l.pop()] +key = l.pop() +_remove_dead_weakref(d, key) def __getitem__(self, key): o = self.data[key]() diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py --- a/pypy/module/__pypy__/__init__.py +++ b/pypy/module/__pypy__/__init__.py @@ -78,6 +78,7 @@ 'add_memory_pressure' : 'interp_magic.add_memory_pressure', 'newdict' : 'interp_dict.newdict', 'reversed_dict' : 'interp_dict.reversed_dict', +'delitem_if_value_is' : 'interp_dict.delitem_if_value_is', 'move_to_end' : 'interp_dict.move_to_end', 'strategy' : 'interp_magic.strategy', # dict,set,list 'set_debug' : 'interp_magic.set_debug', diff --git a/pypy/module/__pypy__/interp_dict.py b/pypy/module/__pypy__/interp_dict.py --- a/pypy/module/__pypy__/interp_dict.py +++ b/pypy/module/__pypy__/interp_dict.py @@ -59,3 +59,16 @@ if not isinstance(w_obj, W_DictMultiObject): raise OperationError(space.w_TypeError, space.w_None) return w_obj.nondescr_move_to_end(space, w_key, last) + +def delitem_if_value_is(space, w_obj, w_key, w_value): +"""Atomic equivalent to: 'if dict.get(key) is value: del dict[key]'. + +SPECIAL USE CASES ONLY! Avoid using on dicts which are specialized, +e.g. to int or str keys, because it switches to the object strategy. +Also, the 'is' operation is really pointer equality, so avoid using +it if 'value' is an immutable object like int or str. +""" +from pypy.objspace.std.dictmultiobject import W_DictMultiObject +if not isinstance(w_obj, W_DictMultiObject): +raise OperationError(space.w_TypeError, space.w_None) +return w_obj.nondescr_delitem_if_value_is(space, w_key, w_value) diff --git a/pypy/module/cpyext/__init__.py b/pypy/module/cpyext/__init__.py --- a/pypy/module/cpyext/__init__.py +++ b/pypy/module/cpyext/__init__.py @@ -40,6 +40,7 @@ import pypy.module.cpyext.pyerrors import pypy.module.cpyext.typeobject import pypy.module.cpyext.object +import pypy.module.cpyext.buffer import pypy.module.cpyext.bytesobject import pypy.module.cpyext.bytearrayobject import pypy.module.cpyext.tupleobject diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py --- a/pypy/module/cpyext/api.py +++ b/pypy/module/cpyext/api.py @@ -126,7 +126,7 @@ Py_TPFLAGS_HEAPTYPE Py_LT Py_LE Py_EQ Py_NE Py_GT Py_GE Py_MAX_NDIMS Py_CLEANUP_SUPPORTED -PyBUF_FORMAT PyBUF_ND PyBUF_STRIDES +PyBUF_FORMAT PyBUF_ND PyBUF_STRIDES PyBUF_WRITABLE PyBUF_SIMPLE """.split() for name in constant_names:
[pypy-commit] pypy py3.5: hg merge default
Author: Armin RigoBranch: py3.5 Changeset: r89961:4bd2a3132a3f Date: 2017-02-05 22:01 +0100 http://bitbucket.org/pypy/pypy/changeset/4bd2a3132a3f/ Log:hg merge default diff --git a/lib-python/2.7/weakref.py b/lib-python/2.7/weakref.py --- a/lib-python/2.7/weakref.py +++ b/lib-python/2.7/weakref.py @@ -31,6 +31,26 @@ "WeakKeyDictionary", "ReferenceError", "ReferenceType", "ProxyType", "CallableProxyType", "ProxyTypes", "WeakValueDictionary", 'WeakSet'] +try: +from __pypy__ import delitem_if_value_is as _delitem_if_value_is +except ImportError: +def _delitem_if_value_is(d, key, value): +try: +if self.data[key] is value: # fall-back: there is a potential +# race condition in multithreaded programs HERE +del self.data[key] +except KeyError: +pass + +def _remove_dead_weakref(d, key): +try: +wr = d[key] +except KeyError: +pass +else: +if wr() is None: +_delitem_if_value_is(d, key, wr) + class WeakValueDictionary(UserDict.UserDict): """Mapping class that references values weakly. @@ -58,14 +78,9 @@ if self._iterating: self._pending_removals.append(wr.key) else: -# Changed this for PyPy: made more resistent. The -# issue is that in some corner cases, self.data -# might already be changed or removed by the time -# this weakref's callback is called. If that is -# the case, we don't want to randomly kill an -# unrelated entry. -if self.data.get(wr.key) is wr: -del self.data[wr.key] +# Atomic removal is necessary since this function +# can be called asynchronously by the GC +_delitem_if_value_is(self.data, wr.key, wr) self._remove = remove # A list of keys to be removed self._pending_removals = [] @@ -78,7 +93,8 @@ # We shouldn't encounter any KeyError, because this method should # always be called *before* mutating the dict. while l: -del d[l.pop()] +key = l.pop() +_remove_dead_weakref(d, key) def __getitem__(self, key): o = self.data[key]() diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py --- a/pypy/module/__pypy__/__init__.py +++ b/pypy/module/__pypy__/__init__.py @@ -78,6 +78,7 @@ 'add_memory_pressure' : 'interp_magic.add_memory_pressure', 'newdict' : 'interp_dict.newdict', 'reversed_dict' : 'interp_dict.reversed_dict', +'delitem_if_value_is' : 'interp_dict.delitem_if_value_is', 'move_to_end' : 'interp_dict.move_to_end', 'strategy' : 'interp_magic.strategy', # dict,set,list 'set_debug' : 'interp_magic.set_debug', diff --git a/pypy/module/__pypy__/interp_dict.py b/pypy/module/__pypy__/interp_dict.py --- a/pypy/module/__pypy__/interp_dict.py +++ b/pypy/module/__pypy__/interp_dict.py @@ -59,3 +59,16 @@ if not isinstance(w_obj, W_DictMultiObject): raise OperationError(space.w_TypeError, space.w_None) return w_obj.nondescr_move_to_end(space, w_key, last) + +def delitem_if_value_is(space, w_obj, w_key, w_value): +"""Atomic equivalent to: 'if dict.get(key) is value: del dict[key]'. + +SPECIAL USE CASES ONLY! Avoid using on dicts which are specialized, +e.g. to int or str keys, because it switches to the object strategy. +Also, the 'is' operation is really pointer equality, so avoid using +it if 'value' is an immutable object like int or str. +""" +from pypy.objspace.std.dictmultiobject import W_DictMultiObject +if not isinstance(w_obj, W_DictMultiObject): +raise OperationError(space.w_TypeError, space.w_None) +return w_obj.nondescr_delitem_if_value_is(space, w_key, w_value) diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py --- a/pypy/objspace/std/dictmultiobject.py +++ b/pypy/objspace/std/dictmultiobject.py @@ -263,6 +263,14 @@ for i in range(len(keys_w)): self.setitem(keys_w[i], values_w[i]) +def nondescr_delitem_if_value_is(self, space, w_key, w_value): +"""Not exposed directly to app-level, but used by +_weakref._remove_dead_weakref and via __pypy__.delitem_if_value_is(). +""" +strategy = self.ensure_object_strategy() +d = strategy.unerase(self.dstorage) +objectmodel.delitem_if_value_is(d, w_key, w_value) + def descr_clear(self, space): """D.clear() -> None. Remove all items from D.""" self.clear() @@ -314,11 +322,12 @@ F: D[k]
[pypy-commit] pypy default: graft 6974fd5f5c47: Add __pypy__.move_to_end(), similar to
Author: Armin RigoBranch: Changeset: r89959:e0ea69f0a7d8 Date: 2017-02-05 21:25 +0100 http://bitbucket.org/pypy/pypy/changeset/e0ea69f0a7d8/ Log:graft 6974fd5f5c47: Add __pypy__.move_to_end(), similar to __pypy__.reversed_dict(). diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py --- a/pypy/module/__pypy__/__init__.py +++ b/pypy/module/__pypy__/__init__.py @@ -80,6 +80,7 @@ 'newdict' : 'interp_dict.newdict', 'reversed_dict' : 'interp_dict.reversed_dict', 'delitem_if_value_is' : 'interp_dict.delitem_if_value_is', +'move_to_end' : 'interp_dict.move_to_end', 'strategy' : 'interp_magic.strategy', # dict,set,list 'specialized_zip_2_lists' : 'interp_magic.specialized_zip_2_lists', 'set_debug' : 'interp_magic.set_debug', diff --git a/pypy/module/__pypy__/interp_dict.py b/pypy/module/__pypy__/interp_dict.py --- a/pypy/module/__pypy__/interp_dict.py +++ b/pypy/module/__pypy__/interp_dict.py @@ -57,3 +57,14 @@ if not isinstance(w_obj, W_DictMultiObject): raise OperationError(space.w_TypeError, space.w_None) return w_obj.nondescr_delitem_if_value_is(space, w_key, w_value) + +@unwrap_spec(last=bool) +def move_to_end(space, w_obj, w_key, last=True): +"""Move the key in a dictionary object into the first or last position. + +This is used in Python 3.x to implement OrderedDict.move_to_end(). +""" +from pypy.objspace.std.dictmultiobject import W_DictMultiObject +if not isinstance(w_obj, W_DictMultiObject): +raise OperationError(space.w_TypeError, space.w_None) +return w_obj.nondescr_move_to_end(space, w_key, last) diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py --- a/pypy/objspace/std/dictmultiobject.py +++ b/pypy/objspace/std/dictmultiobject.py @@ -307,6 +307,37 @@ """D.has_key(k) -> True if D has a key k, else False""" return space.newbool(self.getitem(w_key) is not None) +def nondescr_move_to_end(self, space, w_key, last_flag): +"""Not exposed directly to app-level, but via __pypy__.move_to_end(). +""" +strategy = self.get_strategy() +if strategy.has_move_to_end: +strategy.move_to_end(self, w_key, last_flag) +else: +# fall-back +w_value = self.getitem(w_key) +if w_value is None: +space.raise_key_error(w_key) +else: +self.delitem(w_key) +if last_flag: +self.setitem(w_key, w_value) +else: +# *very slow* fall-back +keys_w = [] +values_w = [] +iteratorimplementation = self.iteritems() +while True: +w_k, w_v = iteratorimplementation.next_item() +if w_k is None: +break +keys_w.append(w_k) +values_w.append(w_v) +self.clear() +self.setitem(w_key, w_value) +for i in range(len(keys_w)): +self.setitem(keys_w[i], values_w[i]) + def descr_clear(self, space): """D.clear() -> None. Remove all items from D.""" self.clear() @@ -578,7 +609,9 @@ raise NotImplementedError has_iterreversed = False -# no 'getiterreversed': no default implementation available +has_move_to_end = False +# no 'getiterreversed' and no 'move_to_end': no default +# implementation available def rev_update1_dict_dict(self, w_dict, w_updatedict): iteritems = self.iteritems(w_dict) @@ -849,6 +882,9 @@ dictimpl.iterreversed = iterreversed dictimpl.has_iterreversed = True +if hasattr(dictimpl, 'move_to_end'): +dictimpl.has_move_to_end = True + @jit.look_inside_iff(lambda self, w_dict, w_updatedict: w_dict_unrolling_heuristic(w_dict)) def rev_update1_dict_dict(self, w_dict, w_updatedict): @@ -1013,6 +1049,15 @@ def getiterreversed(self, w_dict): return objectmodel.reversed_dict(self.unerase(w_dict.dstorage)) +def move_to_end(self, w_dict, w_key, last_flag): +if self.is_correct_type(w_key): +d = self.unerase(w_dict.dstorage) +key = self.unwrap(w_key) +objectmodel.move_to_end(d, key, last_flag) +else: +self.switch_to_object_strategy(w_dict) +w_dict.nondescr_move_to_end(w_dict.space, w_key, last_flag) + def prepare_update(self, w_dict, num_extra): objectmodel.prepare_dict_update(self.unerase(w_dict.dstorage), num_extra) diff --git a/pypy/objspace/std/test/test_dictmultiobject.py
[pypy-commit] pypy default: merge heads
Author: Armin RigoBranch: Changeset: r89960:357c149fd26e Date: 2017-02-05 21:49 +0100 http://bitbucket.org/pypy/pypy/changeset/357c149fd26e/ Log:merge heads diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py --- a/pypy/module/cpyext/api.py +++ b/pypy/module/cpyext/api.py @@ -126,7 +126,7 @@ METH_NOARGS METH_VARARGS METH_KEYWORDS METH_O Py_TPFLAGS_HAVE_INPLACEOPS Py_TPFLAGS_HEAPTYPE Py_TPFLAGS_HAVE_CLASS Py_TPFLAGS_HAVE_NEWBUFFER Py_LT Py_LE Py_EQ Py_NE Py_GT Py_GE Py_TPFLAGS_CHECKTYPES Py_MAX_NDIMS -PyBUF_FORMAT PyBUF_ND PyBUF_STRIDES +PyBUF_FORMAT PyBUF_ND PyBUF_STRIDES PyBUF_WRITABLE """.split() for name in constant_names: setattr(CConfig_constants, name, rffi_platform.ConstantInteger(name)) diff --git a/pypy/module/cpyext/buffer.py b/pypy/module/cpyext/buffer.py --- a/pypy/module/cpyext/buffer.py +++ b/pypy/module/cpyext/buffer.py @@ -1,7 +1,10 @@ -from rpython.rtyper.lltypesystem import rffi +from rpython.rtyper.lltypesystem import rffi, lltype +from pypy.interpreter.error import oefmt from pypy.module.cpyext.api import ( -cpython_api, CANNOT_FAIL, Py_TPFLAGS_HAVE_NEWBUFFER, cts) -from pypy.module.cpyext.pyobject import PyObject +cpython_api, CANNOT_FAIL, Py_TPFLAGS_HAVE_NEWBUFFER, cts, Py_buffer, +Py_ssize_t, Py_ssize_tP, +PyBUF_WRITABLE, PyBUF_FORMAT, PyBUF_ND, PyBUF_STRIDES) +from pypy.module.cpyext.pyobject import PyObject, Py_IncRef, Py_DecRef @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) def PyObject_CheckBuffer(space, pyobj): @@ -11,7 +14,52 @@ if (flags & Py_TPFLAGS_HAVE_NEWBUFFER and as_buffer.c_bf_getbuffer): return 1 name = rffi.charp2str(cts.cast('char*', pyobj.c_ob_type.c_tp_name)) -if name in ('str', 'bytes'): +if name in ('str', 'bytes'): # XXX remove once wrapper of __buffer__ -> bf_getbuffer works return 1 return 0 + +@cpython_api([lltype.Ptr(Py_buffer), PyObject, rffi.VOIDP, Py_ssize_t, + lltype.Signed, lltype.Signed], rffi.INT, error=-1) +def PyBuffer_FillInfo(space, view, obj, buf, length, readonly, flags): +""" +Fills in a buffer-info structure correctly for an exporter that can only +share a contiguous chunk of memory of "unsigned bytes" of the given +length. Returns 0 on success and -1 (with raising an error) on error. +""" +if flags & PyBUF_WRITABLE and readonly: +raise oefmt(space.w_ValueError, "Object is not writable") +view.c_buf = buf +view.c_len = length +view.c_obj = obj +if obj: +Py_IncRef(space, obj) +view.c_itemsize = 1 +rffi.setintfield(view, 'c_readonly', readonly) +rffi.setintfield(view, 'c_ndim', 1) +view.c_format = lltype.nullptr(rffi.CCHARP.TO) +if (flags & PyBUF_FORMAT) == PyBUF_FORMAT: +view.c_format = rffi.str2charp("B") +view.c_shape = lltype.nullptr(Py_ssize_tP.TO) +if (flags & PyBUF_ND) == PyBUF_ND: +view.c_shape = rffi.cast(Py_ssize_tP, view.c__shape) +view.c_shape[0] = view.c_len +view.c_strides = lltype.nullptr(Py_ssize_tP.TO) +if (flags & PyBUF_STRIDES) == PyBUF_STRIDES: +view.c_strides = rffi.cast(Py_ssize_tP, view.c__strides) +view.c_strides[0] = view.c_itemsize +view.c_suboffsets = lltype.nullptr(Py_ssize_tP.TO) +view.c_internal = lltype.nullptr(rffi.VOIDP.TO) + +return 0 + + +@cpython_api([lltype.Ptr(Py_buffer)], lltype.Void, error=CANNOT_FAIL) +def PyBuffer_Release(space, view): +""" +Release the buffer view. This should be called when the buffer is +no longer being used as it may free memory from it +""" +Py_DecRef(space, view.c_obj) +view.c_obj = lltype.nullptr(PyObject.TO) +# XXX do other fields leak memory? diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py --- a/pypy/module/cpyext/object.py +++ b/pypy/module/cpyext/object.py @@ -1,13 +1,12 @@ from rpython.rtyper.lltypesystem import rffi, lltype from pypy.module.cpyext.api import ( cpython_api, generic_cpy_call, CANNOT_FAIL, Py_ssize_t, Py_ssize_tP, -PyVarObject, Py_buffer, size_t, slot_function, -PyBUF_FORMAT, PyBUF_ND, PyBUF_STRIDES, +PyVarObject, size_t, slot_function, Py_TPFLAGS_HEAPTYPE, Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT, Py_GE, CONST_STRING, CONST_STRINGP, FILEP, fwrite) from pypy.module.cpyext.pyobject import ( -PyObject, PyObjectP, create_ref, from_ref, Py_IncRef, Py_DecRef, -get_typedescr, _Py_NewReference) +PyObject, PyObjectP, from_ref, Py_IncRef, Py_DecRef, +get_typedescr) from pypy.module.cpyext.typeobject import PyTypeObjectPtr from pypy.module.cpyext.pyerrors import PyErr_NoMemory, PyErr_BadInternalCall from pypy.objspace.std.typeobject import W_TypeObject @@ -476,51 +475,3 @@ with rffi.scoped_nonmovingbuffer(data) as buf: fwrite(buf, 1, count, fp) return 0 - - -PyBUF_WRITABLE = 0x0001 # Copied from object.h - -@cpython_api([lltype.Ptr(Py_buffer), PyObject, rffi.VOIDP,
[pypy-commit] pypy default: Add objectmodel.delitem_if_value_is(), to be used next
Author: Armin RigoBranch: Changeset: r89957:bfc27e0e9d42 Date: 2017-02-05 19:46 +0100 http://bitbucket.org/pypy/pypy/changeset/bfc27e0e9d42/ Log:Add objectmodel.delitem_if_value_is(), to be used next diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py --- a/rpython/annotator/unaryop.py +++ b/rpython/annotator/unaryop.py @@ -575,6 +575,10 @@ pair(self, s_key).delitem() method_delitem_with_hash.can_only_throw = _dict_can_only_throw_keyerror +def method_delitem_if_value_is(self, s_key, s_value): +pair(self, s_key).setitem(s_value) +pair(self, s_key).delitem() + class __extend__(SomeOrderedDict): def method_move_to_end(self, s_key, s_last): diff --git a/rpython/rlib/objectmodel.py b/rpython/rlib/objectmodel.py --- a/rpython/rlib/objectmodel.py +++ b/rpython/rlib/objectmodel.py @@ -934,6 +934,20 @@ return d.delitem_with_hash(key, h) +@specialize.call_location() +def delitem_if_value_is(d, key, value): +"""Same as 'if d.get(key) is value: del d[key]'. It is safe even in +case 'd' is an r_dict and the lookup involves callbacks that might +release the GIL.""" +if not we_are_translated(): +try: +if d[key] is value: +del d[key] +except KeyError: +pass +return +d.delitem_if_value_is(key, value) + def _untranslated_move_to_end(d, key, last): "NOT_RPYTHON" value = d.pop(key) diff --git a/rpython/rlib/test/test_objectmodel.py b/rpython/rlib/test/test_objectmodel.py --- a/rpython/rlib/test/test_objectmodel.py +++ b/rpython/rlib/test/test_objectmodel.py @@ -7,7 +7,7 @@ resizelist_hint, is_annotation_constant, always_inline, NOT_CONSTANT, iterkeys_with_hash, iteritems_with_hash, contains_with_hash, setitem_with_hash, getitem_with_hash, delitem_with_hash, import_from_mixin, -fetch_translated_config, try_inline, move_to_end) +fetch_translated_config, try_inline, delitem_if_value_is, move_to_end) from rpython.translator.translator import TranslationContext, graphof from rpython.rtyper.test.tool import BaseRtypingTest from rpython.rtyper.test.test_llinterp import interpret @@ -661,6 +661,24 @@ f(29) interpret(f, [27]) +def test_delitem_if_value_is(): +class X: +pass +def f(i): +x42 = X() +x612 = X() +d = {i + .5: x42, i + .6: x612} +delitem_if_value_is(d, i + .5, x612) +assert (i + .5) in d +delitem_if_value_is(d, i + .5, x42) +assert (i + .5) not in d +delitem_if_value_is(d, i + .5, x612) +assert (i + .5) not in d +return 0 + +f(29) +interpret(f, [27]) + def test_rdict_with_hash(): def f(i): d = r_dict(strange_key_eq, strange_key_hash) diff --git a/rpython/rtyper/lltypesystem/rordereddict.py b/rpython/rtyper/lltypesystem/rordereddict.py --- a/rpython/rtyper/lltypesystem/rordereddict.py +++ b/rpython/rtyper/lltypesystem/rordereddict.py @@ -407,6 +407,12 @@ hop.exception_is_here() hop.gendirectcall(ll_dict_delitem_with_hash, v_dict, v_key, v_hash) +def rtype_method_delitem_if_value_is(self, hop): +v_dict, v_key, v_value = hop.inputargs( +self, self.key_repr, self.value_repr) +hop.exception_cannot_occur() +hop.gendirectcall(ll_dict_delitem_if_value_is, v_dict, v_key, v_value) + def rtype_method_move_to_end(self, hop): v_dict, v_key, v_last = hop.inputargs( self, self.key_repr, lltype.Bool) @@ -821,6 +827,15 @@ raise KeyError _ll_dict_del(d, hash, index) +def ll_dict_delitem_if_value_is(d, key, value): +hash = d.keyhash(key) +index = d.lookup_function(d, key, hash, FLAG_LOOKUP) +if index < 0: +return +if d.entries[index].value != value: +return +_ll_dict_del(d, hash, index) + def _ll_dict_del_entry(d, index): d.entries.mark_deleted(index) d.num_live_items -= 1 ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: Use objectmodel.delitem_if_value_is() to fix lib-python/2.7/weakref.py
Author: Armin RigoBranch: Changeset: r89958:cba1fc5e5dcf Date: 2017-02-05 20:54 +0100 http://bitbucket.org/pypy/pypy/changeset/cba1fc5e5dcf/ Log:Use objectmodel.delitem_if_value_is() to fix lib- python/2.7/weakref.py diff --git a/lib-python/2.7/weakref.py b/lib-python/2.7/weakref.py --- a/lib-python/2.7/weakref.py +++ b/lib-python/2.7/weakref.py @@ -31,6 +31,26 @@ "WeakKeyDictionary", "ReferenceError", "ReferenceType", "ProxyType", "CallableProxyType", "ProxyTypes", "WeakValueDictionary", 'WeakSet'] +try: +from __pypy__ import delitem_if_value_is as _delitem_if_value_is +except ImportError: +def _delitem_if_value_is(d, key, value): +try: +if self.data[key] is value: # fall-back: there is a potential +# race condition in multithreaded programs HERE +del self.data[key] +except KeyError: +pass + +def _remove_dead_weakref(d, key): +try: +wr = d[key] +except KeyError: +pass +else: +if wr() is None: +_delitem_if_value_is(d, key, wr) + class WeakValueDictionary(UserDict.UserDict): """Mapping class that references values weakly. @@ -58,14 +78,9 @@ if self._iterating: self._pending_removals.append(wr.key) else: -# Changed this for PyPy: made more resistent. The -# issue is that in some corner cases, self.data -# might already be changed or removed by the time -# this weakref's callback is called. If that is -# the case, we don't want to randomly kill an -# unrelated entry. -if self.data.get(wr.key) is wr: -del self.data[wr.key] +# Atomic removal is necessary since this function +# can be called asynchronously by the GC +_delitem_if_value_is(self.data, wr.key, wr) self._remove = remove # A list of keys to be removed self._pending_removals = [] @@ -78,7 +93,8 @@ # We shouldn't encounter any KeyError, because this method should # always be called *before* mutating the dict. while l: -del d[l.pop()] +key = l.pop() +_remove_dead_weakref(d, key) def __getitem__(self, key): o = self.data[key]() diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py --- a/pypy/module/__pypy__/__init__.py +++ b/pypy/module/__pypy__/__init__.py @@ -79,6 +79,7 @@ 'add_memory_pressure' : 'interp_magic.add_memory_pressure', 'newdict' : 'interp_dict.newdict', 'reversed_dict' : 'interp_dict.reversed_dict', +'delitem_if_value_is' : 'interp_dict.delitem_if_value_is', 'strategy' : 'interp_magic.strategy', # dict,set,list 'specialized_zip_2_lists' : 'interp_magic.specialized_zip_2_lists', 'set_debug' : 'interp_magic.set_debug', diff --git a/pypy/module/__pypy__/interp_dict.py b/pypy/module/__pypy__/interp_dict.py --- a/pypy/module/__pypy__/interp_dict.py +++ b/pypy/module/__pypy__/interp_dict.py @@ -44,3 +44,16 @@ if not isinstance(w_obj, W_DictMultiObject): raise OperationError(space.w_TypeError, space.w_None) return w_obj.nondescr_reversed_dict(space) + +def delitem_if_value_is(space, w_obj, w_key, w_value): +"""Atomic equivalent to: 'if dict.get(key) is value: del dict[key]'. + +SPECIAL USE CASES ONLY! Avoid using on dicts which are specialized, +e.g. to int or str keys, because it switches to the object strategy. +Also, the 'is' operation is really pointer equality, so avoid using +it if 'value' is an immutable object like int or str. +""" +from pypy.objspace.std.dictmultiobject import W_DictMultiObject +if not isinstance(w_obj, W_DictMultiObject): +raise OperationError(space.w_TypeError, space.w_None) +return w_obj.nondescr_delitem_if_value_is(space, w_key, w_value) diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py --- a/pypy/objspace/std/dictmultiobject.py +++ b/pypy/objspace/std/dictmultiobject.py @@ -283,6 +283,14 @@ w_keys = self.w_keys() return space.call_method(w_keys, '__reversed__') +def nondescr_delitem_if_value_is(self, space, w_key, w_value): +"""Not exposed directly to app-level, but used by +_weakref._remove_dead_weakref and via __pypy__.delitem_if_value_is(). +""" +strategy = self.ensure_object_strategy() +d = strategy.unerase(self.dstorage) +objectmodel.delitem_if_value_is(d, w_key, w_value) + def descr_viewitems(self, space): """D.viewitems() -> a set-like object providing a view on D's
[pypy-commit] pypy py3.5: fix minor merge error
Author: Armin RigoBranch: py3.5 Changeset: r89956:25ba5fb90782 Date: 2017-02-05 21:44 +0100 http://bitbucket.org/pypy/pypy/changeset/25ba5fb90782/ Log:fix minor merge error diff --git a/pypy/module/_cffi_backend/test/test_ffi_obj.py b/pypy/module/_cffi_backend/test/test_ffi_obj.py --- a/pypy/module/_cffi_backend/test/test_ffi_obj.py +++ b/pypy/module/_cffi_backend/test/test_ffi_obj.py @@ -258,8 +258,6 @@ assert ffi.buffer(a)[:] == b'\x05\x06\x07' assert ffi.buffer(cdata=a, size=2)[:] == b'\x05\x06' assert type(ffi.buffer(a)) is ffi.buffer -assert ffi.buffer(cdata=a, size=2)[:] == b'\x05\x06' -assert type(ffi.buffer(a)) is ffi.buffer def test_ffi_from_buffer(self): import _cffi_backend as _cffi1_backend ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: hg merge default
Author: Ronan LamyBranch: py3.5 Changeset: r89955:b32bdcb0c782 Date: 2017-02-05 20:38 + http://bitbucket.org/pypy/pypy/changeset/b32bdcb0c782/ Log:hg merge default diff --git a/pypy/module/_cffi_backend/test/test_ffi_obj.py b/pypy/module/_cffi_backend/test/test_ffi_obj.py --- a/pypy/module/_cffi_backend/test/test_ffi_obj.py +++ b/pypy/module/_cffi_backend/test/test_ffi_obj.py @@ -258,6 +258,8 @@ assert ffi.buffer(a)[:] == b'\x05\x06\x07' assert ffi.buffer(cdata=a, size=2)[:] == b'\x05\x06' assert type(ffi.buffer(a)) is ffi.buffer +assert ffi.buffer(cdata=a, size=2)[:] == b'\x05\x06' +assert type(ffi.buffer(a)) is ffi.buffer def test_ffi_from_buffer(self): import _cffi_backend as _cffi1_backend ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Move buffer functions to pypy.module.cpyext.buffer
Author: Ronan LamyBranch: py3.5 Changeset: r89954:1a3f307b706d Date: 2017-02-05 20:15 + http://bitbucket.org/pypy/pypy/changeset/1a3f307b706d/ Log:Move buffer functions to pypy.module.cpyext.buffer diff --git a/pypy/module/cpyext/__init__.py b/pypy/module/cpyext/__init__.py --- a/pypy/module/cpyext/__init__.py +++ b/pypy/module/cpyext/__init__.py @@ -40,6 +40,7 @@ import pypy.module.cpyext.pyerrors import pypy.module.cpyext.typeobject import pypy.module.cpyext.object +import pypy.module.cpyext.buffer import pypy.module.cpyext.bytesobject import pypy.module.cpyext.bytearrayobject import pypy.module.cpyext.tupleobject diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py --- a/pypy/module/cpyext/api.py +++ b/pypy/module/cpyext/api.py @@ -126,7 +126,7 @@ Py_TPFLAGS_HEAPTYPE Py_LT Py_LE Py_EQ Py_NE Py_GT Py_GE Py_MAX_NDIMS Py_CLEANUP_SUPPORTED -PyBUF_FORMAT PyBUF_ND PyBUF_STRIDES +PyBUF_FORMAT PyBUF_ND PyBUF_STRIDES PyBUF_WRITABLE PyBUF_SIMPLE """.split() for name in constant_names: setattr(CConfig_constants, name, rffi_platform.ConstantInteger(name)) diff --git a/pypy/module/cpyext/buffer.py b/pypy/module/cpyext/buffer.py new file mode 100644 --- /dev/null +++ b/pypy/module/cpyext/buffer.py @@ -0,0 +1,72 @@ +from rpython.rtyper.lltypesystem import rffi, lltype +from pypy.interpreter.error import oefmt +from pypy.module.cpyext.api import ( +cpython_api, Py_buffer, Py_ssize_t, Py_ssize_tP, CONST_STRINGP, +generic_cpy_call, +PyBUF_WRITABLE, PyBUF_FORMAT, PyBUF_ND, PyBUF_STRIDES, PyBUF_SIMPLE) +from pypy.module.cpyext.pyobject import PyObject, Py_IncRef, Py_DecRef + +@cpython_api([PyObject, CONST_STRINGP, Py_ssize_tP], rffi.INT_real, error=-1) +def PyObject_AsCharBuffer(space, obj, bufferp, sizep): +"""Returns a pointer to a read-only memory location usable as +character-based input. The obj argument must support the single-segment +character buffer interface. On success, returns 0, sets buffer to the +memory location and size to the buffer length. Returns -1 and sets a +TypeError on error. +""" +pto = obj.c_ob_type +pb = pto.c_tp_as_buffer +if not (pb and pb.c_bf_getbuffer): +raise oefmt(space.w_TypeError, +"expected an object with the buffer interface") +with lltype.scoped_alloc(Py_buffer) as view: +ret = generic_cpy_call( +space, pb.c_bf_getbuffer, +obj, view, rffi.cast(rffi.INT_real, PyBUF_SIMPLE)) +if rffi.cast(lltype.Signed, ret) == -1: +return -1 + +bufferp[0] = rffi.cast(rffi.CCHARP, view.c_buf) +sizep[0] = view.c_len + +if pb.c_bf_releasebuffer: +generic_cpy_call(space, pb.c_bf_releasebuffer, + obj, view) +Py_DecRef(space, view.c_obj) +return 0 + + +@cpython_api([lltype.Ptr(Py_buffer), PyObject, rffi.VOIDP, Py_ssize_t, + lltype.Signed, lltype.Signed], rffi.INT, error=-1) +def PyBuffer_FillInfo(space, view, obj, buf, length, readonly, flags): +""" +Fills in a buffer-info structure correctly for an exporter that can only +share a contiguous chunk of memory of "unsigned bytes" of the given +length. Returns 0 on success and -1 (with raising an error) on error. +""" +flags = rffi.cast(lltype.Signed, flags) +if flags & PyBUF_WRITABLE and readonly: +raise oefmt(space.w_ValueError, "Object is not writable") +view.c_buf = buf +view.c_len = length +view.c_obj = obj +if obj: +Py_IncRef(space, obj) +view.c_itemsize = 1 +rffi.setintfield(view, 'c_readonly', readonly) +rffi.setintfield(view, 'c_ndim', 1) +view.c_format = lltype.nullptr(rffi.CCHARP.TO) +if (flags & PyBUF_FORMAT) == PyBUF_FORMAT: +view.c_format = rffi.str2charp("B") +view.c_shape = lltype.nullptr(Py_ssize_tP.TO) +if (flags & PyBUF_ND) == PyBUF_ND: +view.c_shape = rffi.cast(Py_ssize_tP, view.c__shape) +view.c_shape[0] = view.c_len +view.c_strides = lltype.nullptr(Py_ssize_tP.TO) +if (flags & PyBUF_STRIDES) == PyBUF_STRIDES: +view.c_strides = rffi.cast(Py_ssize_tP, view.c__strides) +view.c_strides[0] = view.c_itemsize +view.c_suboffsets = lltype.nullptr(Py_ssize_tP.TO) +view.c_internal = lltype.nullptr(rffi.VOIDP.TO) + +return 0 diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py --- a/pypy/module/cpyext/object.py +++ b/pypy/module/cpyext/object.py @@ -1,13 +1,11 @@ from rpython.rtyper.lltypesystem import rffi, lltype from pypy.module.cpyext.api import ( -cpython_api, generic_cpy_call, CANNOT_FAIL, Py_ssize_t, Py_ssize_tP, -PyVarObject, Py_buffer, size_t, slot_function, cts, -PyBUF_FORMAT, PyBUF_ND, PyBUF_STRIDES, +cpython_api, generic_cpy_call, CANNOT_FAIL, Py_ssize_t, +PyVarObject, size_t, slot_function, cts, Py_TPFLAGS_HEAPTYPE, Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT, -Py_GE,
[pypy-commit] pypy default: Move buffer functions to pypy.module.cpyext.buffer
Author: Ronan LamyBranch: Changeset: r89953:ad2c1430f189 Date: 2017-02-05 19:38 + http://bitbucket.org/pypy/pypy/changeset/ad2c1430f189/ Log:Move buffer functions to pypy.module.cpyext.buffer diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py --- a/pypy/module/cpyext/api.py +++ b/pypy/module/cpyext/api.py @@ -126,7 +126,7 @@ METH_NOARGS METH_VARARGS METH_KEYWORDS METH_O Py_TPFLAGS_HAVE_INPLACEOPS Py_TPFLAGS_HEAPTYPE Py_TPFLAGS_HAVE_CLASS Py_TPFLAGS_HAVE_NEWBUFFER Py_LT Py_LE Py_EQ Py_NE Py_GT Py_GE Py_TPFLAGS_CHECKTYPES Py_MAX_NDIMS -PyBUF_FORMAT PyBUF_ND PyBUF_STRIDES +PyBUF_FORMAT PyBUF_ND PyBUF_STRIDES PyBUF_WRITABLE """.split() for name in constant_names: setattr(CConfig_constants, name, rffi_platform.ConstantInteger(name)) diff --git a/pypy/module/cpyext/buffer.py b/pypy/module/cpyext/buffer.py --- a/pypy/module/cpyext/buffer.py +++ b/pypy/module/cpyext/buffer.py @@ -1,7 +1,10 @@ -from rpython.rtyper.lltypesystem import rffi +from rpython.rtyper.lltypesystem import rffi, lltype +from pypy.interpreter.error import oefmt from pypy.module.cpyext.api import ( -cpython_api, CANNOT_FAIL, Py_TPFLAGS_HAVE_NEWBUFFER, cts) -from pypy.module.cpyext.pyobject import PyObject +cpython_api, CANNOT_FAIL, Py_TPFLAGS_HAVE_NEWBUFFER, cts, Py_buffer, +Py_ssize_t, Py_ssize_tP, +PyBUF_WRITABLE, PyBUF_FORMAT, PyBUF_ND, PyBUF_STRIDES) +from pypy.module.cpyext.pyobject import PyObject, Py_IncRef, Py_DecRef @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) def PyObject_CheckBuffer(space, pyobj): @@ -11,7 +14,52 @@ if (flags & Py_TPFLAGS_HAVE_NEWBUFFER and as_buffer.c_bf_getbuffer): return 1 name = rffi.charp2str(cts.cast('char*', pyobj.c_ob_type.c_tp_name)) -if name in ('str', 'bytes'): +if name in ('str', 'bytes'): # XXX remove once wrapper of __buffer__ -> bf_getbuffer works return 1 return 0 + +@cpython_api([lltype.Ptr(Py_buffer), PyObject, rffi.VOIDP, Py_ssize_t, + lltype.Signed, lltype.Signed], rffi.INT, error=-1) +def PyBuffer_FillInfo(space, view, obj, buf, length, readonly, flags): +""" +Fills in a buffer-info structure correctly for an exporter that can only +share a contiguous chunk of memory of "unsigned bytes" of the given +length. Returns 0 on success and -1 (with raising an error) on error. +""" +if flags & PyBUF_WRITABLE and readonly: +raise oefmt(space.w_ValueError, "Object is not writable") +view.c_buf = buf +view.c_len = length +view.c_obj = obj +if obj: +Py_IncRef(space, obj) +view.c_itemsize = 1 +rffi.setintfield(view, 'c_readonly', readonly) +rffi.setintfield(view, 'c_ndim', 1) +view.c_format = lltype.nullptr(rffi.CCHARP.TO) +if (flags & PyBUF_FORMAT) == PyBUF_FORMAT: +view.c_format = rffi.str2charp("B") +view.c_shape = lltype.nullptr(Py_ssize_tP.TO) +if (flags & PyBUF_ND) == PyBUF_ND: +view.c_shape = rffi.cast(Py_ssize_tP, view.c__shape) +view.c_shape[0] = view.c_len +view.c_strides = lltype.nullptr(Py_ssize_tP.TO) +if (flags & PyBUF_STRIDES) == PyBUF_STRIDES: +view.c_strides = rffi.cast(Py_ssize_tP, view.c__strides) +view.c_strides[0] = view.c_itemsize +view.c_suboffsets = lltype.nullptr(Py_ssize_tP.TO) +view.c_internal = lltype.nullptr(rffi.VOIDP.TO) + +return 0 + + +@cpython_api([lltype.Ptr(Py_buffer)], lltype.Void, error=CANNOT_FAIL) +def PyBuffer_Release(space, view): +""" +Release the buffer view. This should be called when the buffer is +no longer being used as it may free memory from it +""" +Py_DecRef(space, view.c_obj) +view.c_obj = lltype.nullptr(PyObject.TO) +# XXX do other fields leak memory? diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py --- a/pypy/module/cpyext/object.py +++ b/pypy/module/cpyext/object.py @@ -1,13 +1,12 @@ from rpython.rtyper.lltypesystem import rffi, lltype from pypy.module.cpyext.api import ( cpython_api, generic_cpy_call, CANNOT_FAIL, Py_ssize_t, Py_ssize_tP, -PyVarObject, Py_buffer, size_t, slot_function, -PyBUF_FORMAT, PyBUF_ND, PyBUF_STRIDES, +PyVarObject, size_t, slot_function, Py_TPFLAGS_HEAPTYPE, Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT, Py_GE, CONST_STRING, CONST_STRINGP, FILEP, fwrite) from pypy.module.cpyext.pyobject import ( -PyObject, PyObjectP, create_ref, from_ref, Py_IncRef, Py_DecRef, -get_typedescr, _Py_NewReference) +PyObject, PyObjectP, from_ref, Py_IncRef, Py_DecRef, +get_typedescr) from pypy.module.cpyext.typeobject import PyTypeObjectPtr from pypy.module.cpyext.pyerrors import PyErr_NoMemory, PyErr_BadInternalCall from pypy.objspace.std.typeobject import W_TypeObject @@ -476,51 +475,3 @@ with rffi.scoped_nonmovingbuffer(data) as buf: fwrite(buf, 1, count, fp) return 0 - - -PyBUF_WRITABLE = 0x0001 # Copied from object.h -
[pypy-commit] pypy dict-move-to-end: ready to merge
Author: Armin RigoBranch: dict-move-to-end Changeset: r89951:8a180d361371 Date: 2017-02-05 19:40 +0100 http://bitbucket.org/pypy/pypy/changeset/8a180d361371/ Log:ready to merge ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: hg merge dict-move-to-end
Author: Armin RigoBranch: Changeset: r89952:72b034121391 Date: 2017-02-05 19:41 +0100 http://bitbucket.org/pypy/pypy/changeset/72b034121391/ Log:hg merge dict-move-to-end Implement move_to_end(last=True/False) on RPython ordered dicts. Minor clean-ups in the ordered dict implementation. diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py --- a/rpython/annotator/unaryop.py +++ b/rpython/annotator/unaryop.py @@ -14,7 +14,7 @@ SomeUnicodeCodePoint, SomeInstance, SomeBuiltin, SomeBuiltinMethod, SomeFloat, SomeIterator, SomePBC, SomeNone, SomeTypeOf, s_ImpossibleValue, s_Bool, s_None, s_Int, unionof, add_knowntypedata, -SomeWeakRef, SomeUnicodeString, SomeByteArray) +SomeWeakRef, SomeUnicodeString, SomeByteArray, SomeOrderedDict) from rpython.annotator.bookkeeper import getbookkeeper, immutablevalue from rpython.annotator.binaryop import _clone ## XXX where to put this? from rpython.annotator.binaryop import _dict_can_only_throw_keyerror @@ -575,6 +575,13 @@ pair(self, s_key).delitem() method_delitem_with_hash.can_only_throw = _dict_can_only_throw_keyerror +class __extend__(SomeOrderedDict): + +def method_move_to_end(self, s_key, s_last): +assert s_Bool.contains(s_last) +pair(self, s_key).delitem() +method_move_to_end.can_only_throw = _dict_can_only_throw_keyerror + @op.contains.register(SomeString) @op.contains.register(SomeUnicodeString) def contains_String(annotator, string, char): diff --git a/rpython/rlib/objectmodel.py b/rpython/rlib/objectmodel.py --- a/rpython/rlib/objectmodel.py +++ b/rpython/rlib/objectmodel.py @@ -934,6 +934,24 @@ return d.delitem_with_hash(key, h) +def _untranslated_move_to_end(d, key, last): +"NOT_RPYTHON" +value = d.pop(key) +if last: +d[key] = value +else: +items = d.items() +d.clear() +d[key] = value +d.update(items) + +@specialize.call_location() +def move_to_end(d, key, last=True): +if not we_are_translated(): +_untranslated_move_to_end(d, key, last) +return +d.move_to_end(key, last) + # def import_from_mixin(M, special_methods=['__init__', '__del__']): diff --git a/rpython/rlib/test/test_objectmodel.py b/rpython/rlib/test/test_objectmodel.py --- a/rpython/rlib/test/test_objectmodel.py +++ b/rpython/rlib/test/test_objectmodel.py @@ -7,7 +7,7 @@ resizelist_hint, is_annotation_constant, always_inline, NOT_CONSTANT, iterkeys_with_hash, iteritems_with_hash, contains_with_hash, setitem_with_hash, getitem_with_hash, delitem_with_hash, import_from_mixin, -fetch_translated_config, try_inline) +fetch_translated_config, try_inline, move_to_end) from rpython.translator.translator import TranslationContext, graphof from rpython.rtyper.test.tool import BaseRtypingTest from rpython.rtyper.test.test_llinterp import interpret @@ -679,6 +679,16 @@ assert f(29) == 0 interpret(f, [27]) +def test_rordereddict_move_to_end(): +d = OrderedDict() +d['key1'] = 'val1' +d['key2'] = 'val2' +d['key3'] = 'val3' +move_to_end(d, 'key1') +assert d.items() == [('key2', 'val2'), ('key3', 'val3'), ('key1', 'val1')] +move_to_end(d, 'key1', last=False) +assert d.items() == [('key1', 'val1'), ('key2', 'val2'), ('key3', 'val3')] + def test_import_from_mixin(): class M:# old-style def f(self): diff --git a/rpython/rtyper/lltypesystem/rordereddict.py b/rpython/rtyper/lltypesystem/rordereddict.py --- a/rpython/rtyper/lltypesystem/rordereddict.py +++ b/rpython/rtyper/lltypesystem/rordereddict.py @@ -407,6 +407,15 @@ hop.exception_is_here() hop.gendirectcall(ll_dict_delitem_with_hash, v_dict, v_key, v_hash) +def rtype_method_move_to_end(self, hop): +v_dict, v_key, v_last = hop.inputargs( +self, self.key_repr, lltype.Bool) +if not self.custom_eq_hash: +hop.has_implicit_exception(KeyError) # record that we know about it +hop.exception_is_here() +hop.gendirectcall(ll_dict_move_to_end, v_dict, v_key, v_last) + + class __extend__(pairtype(OrderedDictRepr, rmodel.Repr)): def rtype_getitem((r_dict, r_key), hop): @@ -542,16 +551,18 @@ ll_assert(False, "ll_call_insert_clean_function(): invalid lookup_fun") assert False -def ll_call_delete_by_entry_index(d, hash, i): +def ll_call_delete_by_entry_index(d, hash, i, replace_with): +# only called from _ll_dict_del, whose @jit.look_inside_iff +# condition should control when we get inside here with the jit fun = d.lookup_function_no & FUNC_MASK if fun == FUNC_BYTE: -ll_dict_delete_by_entry_index(d, hash, i, TYPE_BYTE) +ll_dict_delete_by_entry_index(d, hash, i, replace_with, TYPE_BYTE) elif fun == FUNC_SHORT: -ll_dict_delete_by_entry_index(d, hash, i,
[pypy-commit] pypy vendor/stdlib-3.5: Import stdlib from CPython 3.5.3 (changeset 'v3.5.3')
Author: Armin RigoBranch: vendor/stdlib-3.5 Changeset: r89950:a9167602e69c Date: 2017-02-05 19:12 +0100 http://bitbucket.org/pypy/pypy/changeset/a9167602e69c/ Log:Import stdlib from CPython 3.5.3 (changeset 'v3.5.3') diff too long, truncating to 2000 out of 24911 lines diff --git a/lib-python/3/_collections_abc.py b/lib-python/3/_collections_abc.py --- a/lib-python/3/_collections_abc.py +++ b/lib-python/3/_collections_abc.py @@ -29,8 +29,8 @@ # so that they will pass tests like: # it = iter(somebytearray) # assert isinstance(it, Iterable) -# Note: in other implementations, these types many not be distinct -# and they make have their own implementation specific types that +# Note: in other implementations, these types might not be distinct +# and they may have their own implementation specific types that # are not included on this list. bytes_iterator = type(iter(b'')) bytearray_iterator = type(iter(bytearray())) @@ -41,6 +41,7 @@ list_iterator = type(iter([])) list_reverseiterator = type(iter(reversed([]))) range_iterator = type(iter(range(0))) +longrange_iterator = type(iter(range(1 << 1000))) set_iterator = type(iter(set())) str_iterator = type(iter("")) tuple_iterator = type(iter(())) @@ -234,6 +235,7 @@ Iterator.register(list_iterator) Iterator.register(list_reverseiterator) Iterator.register(range_iterator) +Iterator.register(longrange_iterator) Iterator.register(set_iterator) Iterator.register(str_iterator) Iterator.register(tuple_iterator) diff --git a/lib-python/3/_pydecimal.py b/lib-python/3/_pydecimal.py --- a/lib-python/3/_pydecimal.py +++ b/lib-python/3/_pydecimal.py @@ -1068,12 +1068,11 @@ return sign + intpart + fracpart + exp def to_eng_string(self, context=None): -"""Convert to engineering-type string. - -Engineering notation has an exponent which is a multiple of 3, so there -are up to 3 digits left of the decimal place. - -Same rules for when in exponential and when as a value as in __str__. +"""Convert to a string, using engineering notation if an exponent is needed. + +Engineering notation has an exponent which is a multiple of 3. This +can leave up to 3 digits to the left of the decimal place and may +require the addition of either one or two trailing zeros. """ return self.__str__(eng=True, context=context) @@ -4107,7 +4106,7 @@ >>> context.create_decimal_from_float(3.1415926535897932) Traceback (most recent call last): ... -decimal.Inexact +decimal.Inexact: None """ d = Decimal.from_float(f) # An exact conversion @@ -5502,9 +5501,29 @@ return r def to_eng_string(self, a): -"""Converts a number to a string, using scientific notation. +"""Convert to a string, using engineering notation if an exponent is needed. + +Engineering notation has an exponent which is a multiple of 3. This +can leave up to 3 digits to the left of the decimal place and may +require the addition of either one or two trailing zeros. The operation is not affected by the context. + +>>> ExtendedContext.to_eng_string(Decimal('123E+1')) +'1.23E+3' +>>> ExtendedContext.to_eng_string(Decimal('123E+3')) +'123E+3' +>>> ExtendedContext.to_eng_string(Decimal('123E-10')) +'12.3E-9' +>>> ExtendedContext.to_eng_string(Decimal('-123E-12')) +'-123E-12' +>>> ExtendedContext.to_eng_string(Decimal('7E-7')) +'700E-9' +>>> ExtendedContext.to_eng_string(Decimal('7E+1')) +'70' +>>> ExtendedContext.to_eng_string(Decimal('0E+1')) +'0.00E+3' + """ a = _convert_other(a, raiseit=True) return a.to_eng_string(context=self) diff --git a/lib-python/3/_pyio.py b/lib-python/3/_pyio.py --- a/lib-python/3/_pyio.py +++ b/lib-python/3/_pyio.py @@ -276,7 +276,7 @@ try: UnsupportedOperation = io.UnsupportedOperation except AttributeError: -class UnsupportedOperation(ValueError, OSError): +class UnsupportedOperation(OSError, ValueError): pass diff --git a/lib-python/3/antigravity.py b/lib-python/3/antigravity.py --- a/lib-python/3/antigravity.py +++ b/lib-python/3/antigravity.py @@ -2,7 +2,7 @@ import webbrowser import hashlib -webbrowser.open("http://xkcd.com/353/;) +webbrowser.open("https://xkcd.com/353/;) def geohash(latitude, longitude, datedow): '''Compute geohash() using the Munroe algorithm. diff --git a/lib-python/3/asyncio/base_events.py b/lib-python/3/asyncio/base_events.py --- a/lib-python/3/asyncio/base_events.py +++ b/lib-python/3/asyncio/base_events.py @@ -13,7 +13,6 @@ to modify the meaning of the API call itself. """ - import collections import concurrent.futures import heapq @@ -28,6 +27,7 @@ import traceback import sys import warnings +import
[pypy-commit] pypy default: PyOS_AfterFork()
Author: Armin RigoBranch: Changeset: r89948:1d2ae5c36cef Date: 2017-02-05 19:03 +0100 http://bitbucket.org/pypy/pypy/changeset/1d2ae5c36cef/ Log:PyOS_AfterFork() diff --git a/pypy/module/cpyext/pystate.py b/pypy/module/cpyext/pystate.py --- a/pypy/module/cpyext/pystate.py +++ b/pypy/module/cpyext/pystate.py @@ -1,6 +1,7 @@ from pypy.module.cpyext.api import ( cpython_api, generic_cpy_call, CANNOT_FAIL, CConfig, cpython_struct) from pypy.module.cpyext.pyobject import PyObject, Py_DecRef, make_ref, from_ref +from pypy.interpreter.error import OperationError from rpython.rtyper.lltypesystem import rffi, lltype from rpython.rlib import rthread from rpython.rlib.objectmodel import we_are_translated @@ -313,3 +314,16 @@ be held. The thread state must have been reset with a previous call to PyThreadState_Clear().""" +@cpython_api([], lltype.Void) +def PyOS_AfterFork(space): +"""Function to update some internal state after a process fork; this should be +called in the new process if the Python interpreter will continue to be used. +If a new executable is loaded into the new process, this function does not need +to be called.""" +if not space.config.translation.thread: +return +from pypy.module.thread import os_thread +try: +os_thread.reinit_threads(space) +except OperationError as e: +e.write_unraisable(space, "PyOS_AfterFork()") diff --git a/pypy/module/cpyext/stubs.py b/pypy/module/cpyext/stubs.py --- a/pypy/module/cpyext/stubs.py +++ b/pypy/module/cpyext/stubs.py @@ -1515,14 +1515,6 @@ one of the strings '' or '???'.""" raise NotImplementedError -@cpython_api([], lltype.Void) -def PyOS_AfterFork(space): -"""Function to update some internal state after a process fork; this should be -called in the new process if the Python interpreter will continue to be used. -If a new executable is loaded into the new process, this function does not need -to be called.""" -raise NotImplementedError - @cpython_api([], rffi.INT_real, error=CANNOT_FAIL) def PyOS_CheckStack(space): """Return true when the interpreter runs out of stack space. This is a reliable ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: hg merge default
Author: Armin RigoBranch: py3.5 Changeset: r89949:9ba6ab77fd29 Date: 2017-02-05 19:05 +0100 http://bitbucket.org/pypy/pypy/changeset/9ba6ab77fd29/ Log:hg merge default diff --git a/pypy/module/cpyext/pystate.py b/pypy/module/cpyext/pystate.py --- a/pypy/module/cpyext/pystate.py +++ b/pypy/module/cpyext/pystate.py @@ -1,6 +1,7 @@ from pypy.module.cpyext.api import ( cpython_api, generic_cpy_call, CANNOT_FAIL, CConfig, cpython_struct) from pypy.module.cpyext.pyobject import PyObject, Py_DecRef, make_ref, from_ref +from pypy.interpreter.error import OperationError from rpython.rtyper.lltypesystem import rffi, lltype from rpython.rlib import rthread from rpython.rlib.objectmodel import we_are_translated @@ -317,3 +318,16 @@ be held. The thread state must have been reset with a previous call to PyThreadState_Clear().""" +@cpython_api([], lltype.Void) +def PyOS_AfterFork(space): +"""Function to update some internal state after a process fork; this should be +called in the new process if the Python interpreter will continue to be used. +If a new executable is loaded into the new process, this function does not need +to be called.""" +if not space.config.translation.thread: +return +from pypy.module.thread import os_thread +try: +os_thread.reinit_threads(space) +except OperationError as e: +e.write_unraisable(space, "PyOS_AfterFork()") diff --git a/pypy/module/cpyext/stubs.py b/pypy/module/cpyext/stubs.py --- a/pypy/module/cpyext/stubs.py +++ b/pypy/module/cpyext/stubs.py @@ -1468,14 +1468,6 @@ one of the strings '' or '???'.""" raise NotImplementedError -@cpython_api([], lltype.Void) -def PyOS_AfterFork(space): -"""Function to update some internal state after a process fork; this should be -called in the new process if the Python interpreter will continue to be used. -If a new executable is loaded into the new process, this function does not need -to be called.""" -raise NotImplementedError - @cpython_api([], rffi.INT_real, error=CANNOT_FAIL) def PyOS_CheckStack(space): """Return true when the interpreter runs out of stack space. This is a reliable ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: PyCoro_CheckExact()
Author: Armin RigoBranch: py3.5 Changeset: r89946:1368d86f0ce9 Date: 2017-02-05 18:00 +0100 http://bitbucket.org/pypy/pypy/changeset/1368d86f0ce9/ Log:PyCoro_CheckExact() diff --git a/pypy/module/cpyext/genobject.py b/pypy/module/cpyext/genobject.py --- a/pypy/module/cpyext/genobject.py +++ b/pypy/module/cpyext/genobject.py @@ -1,5 +1,7 @@ -from pypy.interpreter.generator import GeneratorIterator +from pypy.interpreter.generator import GeneratorIterator, Coroutine from pypy.module.cpyext.api import build_type_checkers PyGen_Check, PyGen_CheckExact = build_type_checkers("Gen", GeneratorIterator) + +_, PyCoro_CheckExact = build_type_checkers("Coro", Coroutine) diff --git a/pypy/module/cpyext/test/test_genobject.py b/pypy/module/cpyext/test/test_genobject.py --- a/pypy/module/cpyext/test/test_genobject.py +++ b/pypy/module/cpyext/test/test_genobject.py @@ -1,5 +1,6 @@ from pypy.module.cpyext.test.test_api import BaseApiTest from pypy.module.cpyext.genobject import PyGen_Check, PyGen_CheckExact +from pypy.module.cpyext.genobject import PyCoro_CheckExact class TestGenObject(BaseApiTest): @@ -11,5 +12,16 @@ """) assert PyGen_Check(space, w_geniter) assert PyGen_CheckExact(space, w_geniter) +assert not PyCoro_CheckExact(space, w_geniter) assert not PyGen_Check(space, space.wrap(2)) assert not PyGen_CheckExact(space, space.wrap("b")) +assert not PyCoro_CheckExact(space, space.wrap([])) + +w_coroutine = space.appexec([], """(): +async def f(): +pass +return f() +""") +assert not PyGen_Check(space, w_coroutine) +assert not PyGen_CheckExact(space, w_coroutine) +assert PyCoro_CheckExact(space, w_coroutine) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy buffer-cleanup: kill buffer_w_ex()
Author: Ronan LamyBranch: buffer-cleanup Changeset: r89947:d57c072db0e5 Date: 2017-02-05 17:02 + http://bitbucket.org/pypy/pypy/changeset/d57c072db0e5/ Log:kill buffer_w_ex() diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -25,15 +25,6 @@ reds=['items', 'w_iterator']) -@specialize.memo() -def _does_override_buffer_w(type): -return type.buffer_w != W_Root.buffer_w - -@specialize.memo() -def _does_override_buffer_w_ex(type): -return type.buffer_w_ex != W_Root.buffer_w_ex - - class W_Root(object): """This is the abstract root class of all wrapped objects that live in a 'normal' object space like StdObjSpace.""" @@ -223,15 +214,8 @@ return None def buffer_w(self, space, flags): -if _does_override_buffer_w_ex(self.__class__): -return self.buffer_w_ex(space, flags)[0] return self.__buffer_w(space, flags).buffer_w(space, flags) -def buffer_w_ex(self, space, flags): -if _does_override_buffer_w(self.__class__): -return self.buffer_w(space, flags), 'B', 1 -return self.__buffer_w(space, flags).buffer_w_ex(space, flags) - def __buffer_w(self, space, flags): if flags & space.BUF_WRITABLE: w_impl = space.lookup(self, '__wbuffer__') @@ -1469,15 +1453,6 @@ raise oefmt(self.w_TypeError, "'%T' does not support the buffer interface", w_obj) -def buffer_w_ex(self, w_obj, flags): -# New buffer interface, returns a buffer based on flags (PyObject_GetBuffer) -# Returns extra information: (buffer, typecode, itemsize) -try: -return w_obj.buffer_w_ex(self, flags) -except BufferInterfaceNotFound: -raise oefmt(self.w_TypeError, -"'%T' does not support the buffer interface", w_obj) - def readbuf_w(self, w_obj): # Old buffer interface, returns a readonly buffer (PyObject_AsReadBuffer) try: 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 @@ -189,10 +189,6 @@ for i in range(len(value)): ll_buffer[start + i] = value[i] -def buffer_w_ex(self, space, flags): -buf = self.buffer_w(space, flags) -return buf, buf.getformat(), buf.getitemsize() - W_ArrayInstance.typedef = TypeDef( 'ArrayInstance', diff --git a/pypy/module/array/interp_array.py b/pypy/module/array/interp_array.py --- a/pypy/module/array/interp_array.py +++ b/pypy/module/array/interp_array.py @@ -259,10 +259,6 @@ def buffer_w(self, space, flags): return ArrayBuffer(self, False) -def buffer_w_ex(self, space, flags): -buf = self.buffer_w(space, flags) -return buf, buf.getformat(), buf.getitemsize() - def descr_append(self, space, w_x): """ append(x) diff --git a/pypy/objspace/std/memoryobject.py b/pypy/objspace/std/memoryobject.py --- a/pypy/objspace/std/memoryobject.py +++ b/pypy/objspace/std/memoryobject.py @@ -74,17 +74,18 @@ def setformat(self, value): self.format = value -def buffer_w_ex(self, space, flags): +def buffer_w(self, space, flags): self._check_released(space) space.check_buf_flags(flags, self.buf.readonly) -return self.buf, self.getformat(), self.itemsize +return self.buf @staticmethod def descr_new_memoryview(space, w_subtype, w_object): if isinstance(w_object, W_MemoryView): w_object._check_released(space) return W_MemoryView.copy(w_object) -return W_MemoryView(*space.buffer_w_ex(w_object, space.BUF_FULL_RO)) +buf = space.buffer_w(w_object, space.BUF_FULL_RO) +return W_MemoryView(buf, buf.getformat(), buf.getitemsize()) def _make_descr__cmp(name): def descr__cmp(self, space, w_other): 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 @@ -345,9 +345,6 @@ return MockBuffer(space, self.w_list, self.w_dim, self.w_fmt, \ self.w_size, self.w_strides, self.w_shape) -def buffer_w_ex(self, space, flags): -return self.buffer_w(space, flags), space.str_w(self.w_fmt), space.int_w(self.w_size) - W_MockArray.typedef = TypeDef("MockArray", __new__ = interp2app(W_MockArray.descr_new), ) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: hg merge default
Author: Armin RigoBranch: py3.5 Changeset: r89945:6a45f8963c90 Date: 2017-02-05 17:55 +0100 http://bitbucket.org/pypy/pypy/changeset/6a45f8963c90/ Log:hg merge default diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py --- a/lib_pypy/cffi/api.py +++ b/lib_pypy/cffi/api.py @@ -93,6 +93,7 @@ # ctypes backend: attach these constants to the instance self.NULL = self.cast(self.BVoidP, 0) self.CData, self.CType = backend._get_types() +self.buffer = backend.buffer def cdef(self, csource, override=False, packed=False): """Parse the given C source. This registers all declared functions, @@ -316,18 +317,18 @@ """ return self._backend.unpack(cdata, length) -def buffer(self, cdata, size=-1): -"""Return a read-write buffer object that references the raw C data -pointed to by the given 'cdata'. The 'cdata' must be a pointer or -an array. Can be passed to functions expecting a buffer, or directly -manipulated with: - -buf[:] get a copy of it in a regular string, or -buf[idx]as a single character -buf[:] = ... -buf[idx] = ... change the content -""" -return self._backend.buffer(cdata, size) + #def buffer(self, cdata, size=-1): + #"""Return a read-write buffer object that references the raw C data + #pointed to by the given 'cdata'. The 'cdata' must be a pointer or + #an array. Can be passed to functions expecting a buffer, or directly + #manipulated with: + # + #buf[:] get a copy of it in a regular string, or + #buf[idx]as a single character + #buf[:] = ... + #buf[idx] = ... change the content + #""" + #note that 'buffer' is a type, set on this instance by __init__ def from_buffer(self, python_buffer): """Return a that points to the data of the @@ -593,11 +594,15 @@ ensure('extra_link_args', '/MANIFEST') def set_source(self, module_name, source, source_extension='.c', **kwds): +import os if hasattr(self, '_assigned_source'): raise ValueError("set_source() cannot be called several times " "per ffi object") if not isinstance(module_name, basestring): raise TypeError("'module_name' must be a string") +if os.sep in module_name or (os.altsep and os.altsep in module_name): +raise ValueError("'module_name' must not contain '/': use a dotted " + "name to make a 'package.module' location") self._assigned_source = (str(module_name), source, source_extension, kwds) diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py --- a/pypy/module/_cffi_backend/__init__.py +++ b/pypy/module/_cffi_backend/__init__.py @@ -50,7 +50,7 @@ 'string': 'func.string', 'unpack': 'func.unpack', -'buffer': 'cbuffer.buffer', +'buffer': 'cbuffer.MiniBuffer', 'memmove': 'func.memmove', 'get_errno': 'cerrno.get_errno', diff --git a/pypy/module/_cffi_backend/cbuffer.py b/pypy/module/_cffi_backend/cbuffer.py --- a/pypy/module/_cffi_backend/cbuffer.py +++ b/pypy/module/_cffi_backend/cbuffer.py @@ -75,18 +75,8 @@ self.buffer.setslice(start, value.as_str()) -MiniBuffer.typedef = TypeDef( -"_cffi_backend.buffer", -__len__ = interp2app(MiniBuffer.descr_len), -__getitem__ = interp2app(MiniBuffer.descr_getitem), -__setitem__ = interp2app(MiniBuffer.descr_setitem), -__weakref__ = make_weakref_descr(MiniBuffer), -) -MiniBuffer.typedef.acceptable_as_base_class = False - - @unwrap_spec(w_cdata=cdataobj.W_CData, size=int) -def buffer(space, w_cdata, size=-1): +def MiniBuffer___new__(space, w_subtype, w_cdata, size=-1): ctype = w_cdata.ctype if isinstance(ctype, ctypeptr.W_CTypePointer): if size < 0: @@ -107,3 +97,24 @@ "don't know the size pointed to by '%s'", ctype.name) ptr = w_cdata.unsafe_escaping_ptr()# w_cdata kept alive by MiniBuffer() return space.wrap(MiniBuffer(LLBuffer(ptr, size), w_cdata)) + +MiniBuffer.typedef = TypeDef( +"_cffi_backend.buffer", +__new__ = interp2app(MiniBuffer___new__), +__len__ = interp2app(MiniBuffer.descr_len), +__getitem__ = interp2app(MiniBuffer.descr_getitem), +__setitem__ = interp2app(MiniBuffer.descr_setitem), +__weakref__ = make_weakref_descr(MiniBuffer), +__doc__ = """ffi.buffer(cdata[, byte_size]): +Return a read-write buffer object that references the raw C data +pointed to by the given 'cdata'. The 'cdata' must be a pointer or an +array. Can be passed to functions expecting a buffer, or directly +manipulated with: + +buf[:] get a copy of it in a regular string, or
[pypy-commit] pypy default: PyGen_Check(), PyGen_CheckExact()
Author: Armin RigoBranch: Changeset: r89944:7a5c63c2feec Date: 2017-02-05 17:52 +0100 http://bitbucket.org/pypy/pypy/changeset/7a5c63c2feec/ Log:PyGen_Check(), PyGen_CheckExact() diff --git a/pypy/module/cpyext/genobject.py b/pypy/module/cpyext/genobject.py new file mode 100644 --- /dev/null +++ b/pypy/module/cpyext/genobject.py @@ -0,0 +1,5 @@ +from pypy.interpreter.generator import GeneratorIterator +from pypy.module.cpyext.api import build_type_checkers + + +PyGen_Check, PyGen_CheckExact = build_type_checkers("Gen", GeneratorIterator) diff --git a/pypy/module/cpyext/stubs.py b/pypy/module/cpyext/stubs.py --- a/pypy/module/cpyext/stubs.py +++ b/pypy/module/cpyext/stubs.py @@ -695,17 +695,6 @@ extension modules.""" raise NotImplementedError -@cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyGen_Check(space, ob): -"""Return true if ob is a generator object; ob must not be NULL.""" -raise NotImplementedError - -@cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyGen_CheckExact(space, ob): -"""Return true if ob's type is PyGen_Type is a generator object; ob must not -be NULL.""" -raise NotImplementedError - @cpython_api([PyFrameObject], PyObject) def PyGen_New(space, frame): """Create and return a new generator object based on the frame object. A diff --git a/pypy/module/cpyext/test/test_genobject.py b/pypy/module/cpyext/test/test_genobject.py new file mode 100644 --- /dev/null +++ b/pypy/module/cpyext/test/test_genobject.py @@ -0,0 +1,15 @@ +from pypy.module.cpyext.test.test_api import BaseApiTest +from pypy.module.cpyext.genobject import PyGen_Check, PyGen_CheckExact + + +class TestGenObject(BaseApiTest): +def test_genobject(self, space): +w_geniter = space.appexec([], """(): +def f(): +yield 42 +return f() +""") +assert PyGen_Check(space, w_geniter) +assert PyGen_CheckExact(space, w_geniter) +assert not PyGen_Check(space, space.wrap(2)) +assert not PyGen_CheckExact(space, space.wrap("b")) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: PyErr_WarnFormat
Author: Armin RigoBranch: py3.5 Changeset: r89943:386cfc419af7 Date: 2017-02-05 17:44 +0100 http://bitbucket.org/pypy/pypy/changeset/386cfc419af7/ Log:PyErr_WarnFormat diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py --- a/pypy/module/cpyext/api.py +++ b/pypy/module/cpyext/api.py @@ -571,6 +571,7 @@ '_Py_BuildValue_SizeT', '_Py_VaBuildValue_SizeT', 'PyErr_Format', 'PyErr_NewException', 'PyErr_NewExceptionWithDoc', +'PyErr_WarnFormat', 'PySys_WriteStdout', 'PySys_WriteStderr', 'PyEval_CallFunction', 'PyEval_CallMethod', 'PyObject_CallFunction', @@ -1321,6 +1322,7 @@ source_dir / "bytesobject.c", source_dir / "complexobject.c", source_dir / "import.c", + source_dir / "_warnings.c", ] def build_eci(code, use_micronumpy=False, translating=False): diff --git a/pypy/module/cpyext/include/warnings.h b/pypy/module/cpyext/include/warnings.h --- a/pypy/module/cpyext/include/warnings.h +++ b/pypy/module/cpyext/include/warnings.h @@ -6,6 +6,9 @@ #define PyErr_WarnPy3k(msg, stacklevel) 0 +PyAPI_FUNC(int) PyErr_WarnFormat(PyObject *category, Py_ssize_t stack_level, + const char *format, ...); + #ifdef __cplusplus } #endif diff --git a/pypy/module/cpyext/src/_warnings.c b/pypy/module/cpyext/src/_warnings.c new file mode 100644 --- /dev/null +++ b/pypy/module/cpyext/src/_warnings.c @@ -0,0 +1,25 @@ +#include + +int +PyErr_WarnFormat(PyObject *category, Py_ssize_t stack_level, + const char *format, ...) +{ +int ret; +PyObject *message; +va_list vargs; + +#ifdef HAVE_STDARG_PROTOTYPES +va_start(vargs, format); +#else +va_start(vargs); +#endif +message = PyUnicode_FromFormatV(format, vargs); +if (message != NULL) { +ret = PyErr_WarnEx(category, PyUnicode_AsUTF8(message), stack_level); +Py_DECREF(message); +} +else +ret = -1; +va_end(vargs); +return ret; +} diff --git a/pypy/module/cpyext/stubs.py b/pypy/module/cpyext/stubs.py --- a/pypy/module/cpyext/stubs.py +++ b/pypy/module/cpyext/stubs.py @@ -405,14 +405,6 @@ (sys.getfilesystemencoding()).""" raise NotImplementedError -@cpython_api([PyObject, Py_ssize_t, rffi.CCHARP, ], rffi.INT_real, error=-1) -def PyErr_WarnFormat(space, category, stack_level, format, ): -"""Function similar to PyErr_WarnEx(), but use -PyUnicode_FromFormat() to format the warning message. format is -an ASCII-encoded string. -""" -raise NotImplementedError - @cpython_api([rffi.INT_real], rffi.INT_real, error=-1) def PySignal_SetWakeupFd(space, fd): diff --git a/pypy/module/cpyext/test/test_pyerrors.py b/pypy/module/cpyext/test/test_pyerrors.py --- a/pypy/module/cpyext/test/test_pyerrors.py +++ b/pypy/module/cpyext/test/test_pyerrors.py @@ -428,3 +428,18 @@ assert orig_exc_info == reset_sys_exc_info assert new_exc_info == (new_exc.__class__, new_exc, None) assert new_exc_info == new_sys_exc_info + +def test_PyErr_WarnFormat(self): +import warnings + +module = self.import_extension('foo', [ +("test", "METH_NOARGS", + ''' + PyErr_WarnFormat(PyExc_UserWarning, 1, "foo %d bar", 42); + Py_RETURN_NONE; + '''), +]) +with warnings.catch_warnings(record=True) as l: +module.test() +assert len(l) == 1 +assert "foo 42 bar" in str(l[0]) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: silence a warning
Author: Armin RigoBranch: Changeset: r89941:587b40019180 Date: 2017-02-05 17:21 +0100 http://bitbucket.org/pypy/pypy/changeset/587b40019180/ Log:silence a warning diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py --- a/pypy/module/cpyext/api.py +++ b/pypy/module/cpyext/api.py @@ -1069,7 +1069,8 @@ struct PyPyAPI { %(members)s } _pypyAPI; -RPY_EXTERN struct PyPyAPI* pypyAPI = &_pypyAPI; +RPY_EXTERN struct PyPyAPI* pypyAPI; +struct PyPyAPI* pypyAPI = &_pypyAPI; """ % dict(members=structmembers) global_objects = [] ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy buffer-cleanup: Add W_ArrayBase.buffer_w()
Author: Ronan LamyBranch: buffer-cleanup Changeset: r89942:1ed5b196b55d Date: 2017-02-05 16:31 + http://bitbucket.org/pypy/pypy/changeset/1ed5b196b55d/ Log:Add W_ArrayBase.buffer_w() diff --git a/pypy/module/array/interp_array.py b/pypy/module/array/interp_array.py --- a/pypy/module/array/interp_array.py +++ b/pypy/module/array/interp_array.py @@ -256,8 +256,12 @@ if oldbuffer: lltype.free(oldbuffer, flavor='raw') +def buffer_w(self, space, flags): +return ArrayBuffer(self, False) + def buffer_w_ex(self, space, flags): -return ArrayBuffer(self, False), self.typecode, self.itemsize +buf = self.buffer_w(space, flags) +return buf, buf.getformat(), buf.getitemsize() def descr_append(self, space, w_x): """ append(x) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: silence a warning
Author: Armin RigoBranch: Changeset: r89940:c763e1ab0f07 Date: 2017-02-05 17:17 +0100 http://bitbucket.org/pypy/pypy/changeset/c763e1ab0f07/ Log:silence a warning diff --git a/rpython/rlib/rposix_stat.py b/rpython/rlib/rposix_stat.py --- a/rpython/rlib/rposix_stat.py +++ b/rpython/rlib/rposix_stat.py @@ -602,7 +602,7 @@ if rposix.HAVE_FSTATAT: from rpython.rlib.rposix import AT_FDCWD, AT_SYMLINK_NOFOLLOW -c_fstatat = rffi.llexternal('fstatat', +c_fstatat = rffi.llexternal('fstatat64' if _LINUX else 'fstatat', [rffi.INT, rffi.CCHARP, STAT_STRUCT, rffi.INT], rffi.INT, compilation_info=compilation_info, save_err=rffi.RFFI_SAVE_ERRNO, macro=True) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy buffer-cleanup: Add getformat() and getitemsize() to RawFFIBuffer
Author: Ronan LamyBranch: buffer-cleanup Changeset: r89939:82e6578296c4 Date: 2017-02-05 16:15 + http://bitbucket.org/pypy/pypy/changeset/82e6578296c4/ Log:Add getformat() and getitemsize() to RawFFIBuffer 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 @@ -91,6 +91,8 @@ W_DataInstance.__init__(self, space, memsize, address) self.length = length self.shape = shape +self.fmt = shape.itemcode +self.itemsize = shape.size def descr_repr(self, space): addr = rffi.cast(lltype.Unsigned, self.ll_buffer) @@ -105,8 +107,7 @@ raise segfault_exception(space, "setting element of freed array") if num >= self.length or num < 0: raise OperationError(space.w_IndexError, space.w_None) -unwrap_value(space, write_ptr, self.ll_buffer, num, - self.shape.itemcode, w_value) +unwrap_value(space, write_ptr, self.ll_buffer, num, self.fmt, w_value) def descr_setitem(self, space, w_index, w_value): try: @@ -123,8 +124,7 @@ raise segfault_exception(space, "accessing elements of freed array") if num >= self.length or num < 0: raise OperationError(space.w_IndexError, space.w_None) -return wrap_value(space, read_ptr, self.ll_buffer, num, - self.shape.itemcode) +return wrap_value(space, read_ptr, self.ll_buffer, num, self.fmt) def descr_getitem(self, space, w_index): try: @@ -141,19 +141,16 @@ @unwrap_spec(num=int) def descr_itemaddress(self, space, num): -itemsize = self.shape.size -ptr = rffi.ptradd(self.ll_buffer, itemsize * num) +ptr = rffi.ptradd(self.ll_buffer, self.itemsize * num) return space.wrap(rffi.cast(lltype.Unsigned, ptr)) def getrawsize(self): -itemsize = self.shape.size -return itemsize * self.length +return self.itemsize * self.length def decodeslice(self, space, w_slice): if not space.isinstance_w(w_slice, space.w_slice): raise oefmt(space.w_TypeError, "index must be int or slice") -letter = self.shape.itemcode -if letter != 'c': +if self.fmt != 'c': raise oefmt(space.w_TypeError, "only 'c' arrays support slicing") w_start = space.getattr(w_slice, space.wrap('start')) w_stop = space.getattr(w_slice, space.wrap('stop')) @@ -193,7 +190,8 @@ ll_buffer[start + i] = value[i] def buffer_w_ex(self, space, flags): -return self.buffer_w(space, flags), self.shape.itemcode, self.shape.size +buf = self.buffer_w(space, flags) +return buf, buf.getformat(), buf.getitemsize() W_ArrayInstance.typedef = TypeDef( diff --git a/pypy/module/_rawffi/buffer.py b/pypy/module/_rawffi/buffer.py --- a/pypy/module/_rawffi/buffer.py +++ b/pypy/module/_rawffi/buffer.py @@ -14,6 +14,12 @@ def getlength(self): return self.datainstance.getrawsize() +def getformat(self): +return self.datainstance.fmt + +def getitemsize(self): +return self.datainstance.itemsize + def getitem(self, index): ll_buffer = self.datainstance.ll_buffer return ll_buffer[index] diff --git a/pypy/module/_rawffi/interp_rawffi.py b/pypy/module/_rawffi/interp_rawffi.py --- a/pypy/module/_rawffi/interp_rawffi.py +++ b/pypy/module/_rawffi/interp_rawffi.py @@ -337,6 +337,8 @@ class W_DataInstance(W_Root): +fmt = 'B' +itemsize = 1 def __init__(self, space, size, address=r_uint(0)): if address: self.ll_buffer = rffi.cast(rffi.VOIDP, address) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Normalize the PyMem_Xxx functions and macros to CPython 3.5's situation
Author: Armin RigoBranch: py3.5 Changeset: r89938:319cd6335518 Date: 2017-02-05 17:13 +0100 http://bitbucket.org/pypy/pypy/changeset/319cd6335518/ Log:Normalize the PyMem_Xxx functions and macros to CPython 3.5's situation diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py --- a/pypy/module/cpyext/api.py +++ b/pypy/module/cpyext/api.py @@ -612,6 +612,9 @@ 'Py_FrozenFlag', 'Py_TabcheckFlag', 'Py_UnicodeFlag', 'Py_IgnoreEnvironmentFlag', 'Py_DivisionWarningFlag', 'Py_DontWriteBytecodeFlag', 'Py_NoUserSiteDirectory', '_Py_QnewFlag', 'Py_Py3kWarningFlag', 'Py_HashRandomizationFlag', '_Py_PackageContext', + +'PyMem_RawMalloc', 'PyMem_RawCalloc', 'PyMem_RawRealloc', 'PyMem_RawFree', +'PyMem_Malloc', 'PyMem_Calloc', 'PyMem_Realloc', 'PyMem_Free', ] TYPES = {} FORWARD_DECLS = [] diff --git a/pypy/module/cpyext/include/pymem.h b/pypy/module/cpyext/include/pymem.h --- a/pypy/module/cpyext/include/pymem.h +++ b/pypy/module/cpyext/include/pymem.h @@ -7,17 +7,22 @@ extern "C" { #endif -#define PyMem_MALLOC(n)malloc((n) ? (n) : 1) -#define PyMem_REALLOC(p, n)realloc((p), (n) ? (n) : 1) -#define PyMem_FREE free +#ifndef Py_LIMITED_API +PyAPI_FUNC(void *) PyMem_RawMalloc(size_t size); +PyAPI_FUNC(void *) PyMem_RawCalloc(size_t nelem, size_t elsize); +PyAPI_FUNC(void *) PyMem_RawRealloc(void *ptr, size_t new_size); +PyAPI_FUNC(void) PyMem_RawFree(void *ptr); +#endif -PyAPI_FUNC(void *) PyMem_Malloc(size_t); -#define PyMem_Free PyMem_FREE -#define PyMem_Realloc PyMem_REALLOC +PyAPI_FUNC(void *) PyMem_Malloc(size_t size); +PyAPI_FUNC(void *) PyMem_Calloc(size_t nelem, size_t elsize); +PyAPI_FUNC(void *) PyMem_Realloc(void *ptr, size_t new_size); +PyAPI_FUNC(void) PyMem_Free(void *ptr); -#define PyMem_RawMalloc PyMem_Malloc -#define PyMem_RawFree PyMem_Free -#define PyMem_RawRealloc PyMem_Realloc +#define PyMem_MALLOC(n) PyMem_Malloc(n) +#define PyMem_REALLOC(p, n) PyMem_Realloc(p, n) +#define PyMem_FREE(p) PyMem_Free(p) + /* * Type-oriented memory interface diff --git a/pypy/module/cpyext/src/pymem.c b/pypy/module/cpyext/src/pymem.c --- a/pypy/module/cpyext/src/pymem.c +++ b/pypy/module/cpyext/src/pymem.c @@ -1,6 +1,86 @@ #include -void * PyMem_Malloc(size_t n) +void * +PyMem_RawMalloc(size_t size) { -return malloc((n) ? (n) : 1); +/* + * Limit ourselves to PY_SSIZE_T_MAX bytes to prevent security holes. + * Most python internals blindly use a signed Py_ssize_t to track + * things without checking for overflows or negatives. + * As size_t is unsigned, checking for size < 0 is not required. + */ +if (size > (size_t)PY_SSIZE_T_MAX) +return NULL; +if (size == 0) +size = 1; +return malloc(size); } + +void * +PyMem_RawCalloc(size_t nelem, size_t elsize) +{ +/* see PyMem_RawMalloc() */ +if (elsize != 0 && nelem > (size_t)PY_SSIZE_T_MAX / elsize) +return NULL; +/* PyMem_RawCalloc(0, 0) means calloc(1, 1). Some systems would return NULL + for calloc(0, 0), which would be treated as an error. Some platforms + would return a pointer with no memory behind it, which would break + pymalloc. To solve these problems, allocate an extra byte. */ +if (nelem == 0 || elsize == 0) { +nelem = 1; +elsize = 1; +} +return calloc(nelem, elsize); +} + +void* +PyMem_RawRealloc(void *ptr, size_t size) +{ +/* see PyMem_RawMalloc() */ +if (size > (size_t)PY_SSIZE_T_MAX) +return NULL; +if (size == 0) +size = 1; +return realloc(ptr, size); +} + +void PyMem_RawFree(void *ptr) +{ +free(ptr); +} + + +/* the PyMem_Xxx functions are the same as PyMem_RawXxx in PyPy, for now */ +void *PyMem_Malloc(size_t size) +{ +if (size > (size_t)PY_SSIZE_T_MAX) +return NULL; +if (size == 0) +size = 1; +return malloc(size); +} + +void *PyMem_Calloc(size_t nelem, size_t elsize) +{ +if (elsize != 0 && nelem > (size_t)PY_SSIZE_T_MAX / elsize) +return NULL; +if (nelem == 0 || elsize == 0) { +nelem = 1; +elsize = 1; +} +return calloc(nelem, elsize); +} + +void* PyMem_Realloc(void *ptr, size_t size) +{ +if (size > (size_t)PY_SSIZE_T_MAX) +return NULL; +if (size == 0) +size = 1; +return realloc(ptr, size); +} + +void PyMem_Free(void *ptr) +{ +free(ptr); +} diff --git a/pypy/module/cpyext/test/test_pymem.py b/pypy/module/cpyext/test/test_pymem.py new file mode 100644 --- /dev/null +++ b/pypy/module/cpyext/test/test_pymem.py @@ -0,0 +1,34 @@ +from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase + + +class AppTestPyMem(AppTestCpythonExtensionBase): +def test_pymem_alloc(self): +module = self.import_extension('foo', [ +("test", "METH_NOARGS", + """ +int *a, *b; +a = PyMem_RawCalloc(4, 50); +
[pypy-commit] extradoc extradoc: done
Author: Armin RigoBranch: extradoc Changeset: r5773:811543e4ff04 Date: 2017-02-05 15:33 +0100 http://bitbucket.org/pypy/extradoc/changeset/811543e4ff04/ Log:done diff --git a/planning/py3.5/milestone-2-progress.rst b/planning/py3.5/milestone-2-progress.rst --- a/planning/py3.5/milestone-2-progress.rst +++ b/planning/py3.5/milestone-2-progress.rst @@ -17,6 +17,7 @@ * collections.py: ``OrderedDict`` should again be a thin wrapper over ``dict``. The main pain point is ``move_to_end(last=False)``. See https://mail.python.org/pipermail/python-dev/2016-August/145837.html + [DONE] * compare ``dir(posix)`` on py3.5 and cpython 3.5. ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: missing import
Author: Armin RigoBranch: py3.5 Changeset: r89937:fb91b76b7210 Date: 2017-02-05 11:40 +0100 http://bitbucket.org/pypy/pypy/changeset/fb91b76b7210/ Log:missing import diff --git a/lib_pypy/_pypy_collections.py b/lib_pypy/_pypy_collections.py --- a/lib_pypy/_pypy_collections.py +++ b/lib_pypy/_pypy_collections.py @@ -1,4 +1,5 @@ from __pypy__ import reversed_dict, move_to_end +from _operator import eq as _eq from reprlib import recursive_repr as _recursive_repr class OrderedDict(dict): ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy.org extradoc: update the values
Author: Armin RigoBranch: extradoc Changeset: r851:f22c38f24a8b Date: 2017-02-05 11:08 +0100 http://bitbucket.org/pypy/pypy.org/changeset/f22c38f24a8b/ Log:update the values diff --git a/don1.html b/don1.html --- a/don1.html +++ b/don1.html @@ -15,7 +15,7 @@ - $66561 of $105000 (63.4%) + $66570 of $105000 (63.4%) @@ -23,7 +23,7 @@ This donation goes towards supporting Python 3 in PyPy. Current status: -we have $2391 left +we have $2399 left in the account. Read proposal ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: hg merge dict-move-to-end
Author: Armin RigoBranch: py3.5 Changeset: r89934:5e325b5c62d9 Date: 2017-02-05 08:29 +0100 http://bitbucket.org/pypy/pypy/changeset/5e325b5c62d9/ Log:hg merge dict-move-to-end diff --git a/pypy/doc/stackless.rst b/pypy/doc/stackless.rst --- a/pypy/doc/stackless.rst +++ b/pypy/doc/stackless.rst @@ -190,7 +190,7 @@ from GC issues: if the program "forgets" an unfinished greenlet, it will always be collected at the next garbage collection. -.. _documentation of the greenlets: http://packages.python.org/greenlet/ +.. _documentation of the greenlets: https://greenlet.readthedocs.io/ Unimplemented features diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py --- a/rpython/annotator/unaryop.py +++ b/rpython/annotator/unaryop.py @@ -14,7 +14,7 @@ SomeUnicodeCodePoint, SomeInstance, SomeBuiltin, SomeBuiltinMethod, SomeFloat, SomeIterator, SomePBC, SomeNone, SomeTypeOf, s_ImpossibleValue, s_Bool, s_None, s_Int, unionof, add_knowntypedata, -SomeWeakRef, SomeUnicodeString, SomeByteArray) +SomeWeakRef, SomeUnicodeString, SomeByteArray, SomeOrderedDict) from rpython.annotator.bookkeeper import getbookkeeper, immutablevalue from rpython.annotator.binaryop import _clone ## XXX where to put this? from rpython.annotator.binaryop import _dict_can_only_throw_keyerror @@ -575,6 +575,13 @@ pair(self, s_key).delitem() method_delitem_with_hash.can_only_throw = _dict_can_only_throw_keyerror +class __extend__(SomeOrderedDict): + +def method_move_to_end(self, s_key, s_last): +assert s_Bool.contains(s_last) +pair(self, s_key).delitem() +method_move_to_end.can_only_throw = _dict_can_only_throw_keyerror + @op.contains.register(SomeString) @op.contains.register(SomeUnicodeString) def contains_String(annotator, string, char): diff --git a/rpython/rlib/objectmodel.py b/rpython/rlib/objectmodel.py --- a/rpython/rlib/objectmodel.py +++ b/rpython/rlib/objectmodel.py @@ -934,6 +934,24 @@ return d.delitem_with_hash(key, h) +def _untranslated_move_to_end(d, key, last): +"NOT_RPYTHON" +value = d.pop(key) +if last: +d[key] = value +else: +items = d.items() +d.clear() +d[key] = value +d.update(items) + +@specialize.call_location() +def move_to_end(d, key, last=True): +if not we_are_translated(): +_untranslated_move_to_end(d, key, last) +return +d.move_to_end(key, last) + # def import_from_mixin(M, special_methods=['__init__', '__del__']): diff --git a/rpython/rlib/test/test_objectmodel.py b/rpython/rlib/test/test_objectmodel.py --- a/rpython/rlib/test/test_objectmodel.py +++ b/rpython/rlib/test/test_objectmodel.py @@ -7,7 +7,7 @@ resizelist_hint, is_annotation_constant, always_inline, NOT_CONSTANT, iterkeys_with_hash, iteritems_with_hash, contains_with_hash, setitem_with_hash, getitem_with_hash, delitem_with_hash, import_from_mixin, -fetch_translated_config, try_inline) +fetch_translated_config, try_inline, move_to_end) from rpython.translator.translator import TranslationContext, graphof from rpython.rtyper.test.tool import BaseRtypingTest from rpython.rtyper.test.test_llinterp import interpret @@ -679,6 +679,16 @@ assert f(29) == 0 interpret(f, [27]) +def test_rordereddict_move_to_end(): +d = OrderedDict() +d['key1'] = 'val1' +d['key2'] = 'val2' +d['key3'] = 'val3' +move_to_end(d, 'key1') +assert d.items() == [('key2', 'val2'), ('key3', 'val3'), ('key1', 'val1')] +move_to_end(d, 'key1', last=False) +assert d.items() == [('key1', 'val1'), ('key2', 'val2'), ('key3', 'val3')] + def test_import_from_mixin(): class M:# old-style def f(self): diff --git a/rpython/rtyper/lltypesystem/rordereddict.py b/rpython/rtyper/lltypesystem/rordereddict.py --- a/rpython/rtyper/lltypesystem/rordereddict.py +++ b/rpython/rtyper/lltypesystem/rordereddict.py @@ -407,6 +407,15 @@ hop.exception_is_here() hop.gendirectcall(ll_dict_delitem_with_hash, v_dict, v_key, v_hash) +def rtype_method_move_to_end(self, hop): +v_dict, v_key, v_last = hop.inputargs( +self, self.key_repr, lltype.Bool) +if not self.custom_eq_hash: +hop.has_implicit_exception(KeyError) # record that we know about it +hop.exception_is_here() +hop.gendirectcall(ll_dict_move_to_end, v_dict, v_key, v_last) + + class __extend__(pairtype(OrderedDictRepr, rmodel.Repr)): def rtype_getitem((r_dict, r_key), hop): @@ -542,16 +551,18 @@ ll_assert(False, "ll_call_insert_clean_function(): invalid lookup_fun") assert False -def ll_call_delete_by_entry_index(d, hash, i): +def ll_call_delete_by_entry_index(d, hash, i, replace_with): +# only called from _ll_dict_del, whose @jit.look_inside_iff +# condition should control when we get
[pypy-commit] pypy py3.5: PyPy's simplified version of OrderedDict
Author: Armin RigoBranch: py3.5 Changeset: r89936:5764bb3f54a2 Date: 2017-02-05 11:08 +0100 http://bitbucket.org/pypy/pypy/changeset/5764bb3f54a2/ Log:PyPy's simplified version of OrderedDict diff --git a/lib_pypy/_collections.py b/lib_pypy/_collections.py --- a/lib_pypy/_collections.py +++ b/lib_pypy/_collections.py @@ -439,3 +439,8 @@ return (type(self), (self.default_factory,), None, None, iter(self.items())) + +try: +from _pypy_collections import OrderedDict +except ImportError: +pass diff --git a/lib_pypy/_pypy_collections.py b/lib_pypy/_pypy_collections.py new file mode 100644 --- /dev/null +++ b/lib_pypy/_pypy_collections.py @@ -0,0 +1,69 @@ +from __pypy__ import reversed_dict, move_to_end +from reprlib import recursive_repr as _recursive_repr + +class OrderedDict(dict): +'''Dictionary that remembers insertion order. + +In PyPy all dicts are ordered anyway. This is mostly useful as a +placeholder to mean "this dict must be ordered even on CPython". + +Known difference: iterating over an OrderedDict which is being +concurrently modified raises RuntimeError in PyPy. In CPython +instead we get some behavior that appears reasonable in some +cases but is nonsensical in other cases. This is officially +forbidden by the CPython docs, so we forbid it explicitly for now. +''' + +def __reversed__(self): +return reversed_dict(self) + +def popitem(self, last=True): +'''od.popitem() -> (k, v), return and remove a (key, value) pair. +Pairs are returned in LIFO order if last is true or FIFO order if false. + +''' +if last: +return dict.popitem(self) +else: +it = dict.__iter__(self) +try: +k = it.next() +except StopIteration: +raise KeyError('dictionary is empty') +return (k, self.pop(k)) + +def move_to_end(self, key, last=True): +'''Move an existing element to the end (or beginning if last==False). + +Raises KeyError if the element does not exist. +When last=True, acts like a fast version of self[key]=self.pop(key). + +''' +return move_to_end(self, key, last) + +@_recursive_repr() +def __repr__(self): +'od.__repr__() <==> repr(od)' +if not self: +return '%s()' % (self.__class__.__name__,) +return '%s(%r)' % (self.__class__.__name__, list(self.items())) + +def __reduce__(self): +'Return state information for pickling' +inst_dict = vars(self).copy() +return self.__class__, (), inst_dict or None, None, iter(self.items()) + +def copy(self): +'od.copy() -> a shallow copy of od' +return self.__class__(self) + +def __eq__(self, other): +'''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive +while comparison to a regular mapping is order-insensitive. + +''' +if isinstance(other, OrderedDict): +return dict.__eq__(self, other) and all(map(_eq, self, other)) +return dict.__eq__(self, other) + +__ne__ = object.__ne__ diff --git a/pypy/module/_collections/__init__.py b/pypy/module/_collections/__init__.py --- a/pypy/module/_collections/__init__.py +++ b/pypy/module/_collections/__init__.py @@ -25,3 +25,15 @@ space = self.space space.getattr(self, space.wrap('defaultdict')) # force importing space.delattr(self, space.wrap('__missing__')) + +def startup(self, space): +# OrderedDict is normally present, but in some cases the line +# "from __pypy__ import reversed_dict, move_to_end" from +# _pypy_collections.py raises +space.appexec([space.wrap(self)], """(mod): +try: +from _pypy_collections import OrderedDict +mod.OrderedDict = OrderedDict +except ImportError: +pass +""") diff --git a/pypy/module/_collections/test/test_ordereddict.py b/pypy/module/_collections/test/test_ordereddict.py new file mode 100644 --- /dev/null +++ b/pypy/module/_collections/test/test_ordereddict.py @@ -0,0 +1,8 @@ + +class AppTestBasic: +spaceconfig = dict(usemodules=['_collections']) + +def test_ordereddict_present(self): +from _collections import OrderedDict +assert issubclass(OrderedDict, dict) +assert hasattr(OrderedDict, 'move_to_end') ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Add __pypy__.move_to_end(), similar to __pypy__.reversed_dict().
Author: Armin RigoBranch: py3.5 Changeset: r89935:6974fd5f5c47 Date: 2017-02-05 10:57 +0100 http://bitbucket.org/pypy/pypy/changeset/6974fd5f5c47/ Log:Add __pypy__.move_to_end(), similar to __pypy__.reversed_dict(). diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py --- a/pypy/module/__pypy__/__init__.py +++ b/pypy/module/__pypy__/__init__.py @@ -78,6 +78,7 @@ 'add_memory_pressure' : 'interp_magic.add_memory_pressure', 'newdict' : 'interp_dict.newdict', 'reversed_dict' : 'interp_dict.reversed_dict', +'move_to_end' : 'interp_dict.move_to_end', 'strategy' : 'interp_magic.strategy', # dict,set,list 'set_debug' : 'interp_magic.set_debug', 'locals_to_fast': 'interp_magic.locals_to_fast', diff --git a/pypy/module/__pypy__/interp_dict.py b/pypy/module/__pypy__/interp_dict.py --- a/pypy/module/__pypy__/interp_dict.py +++ b/pypy/module/__pypy__/interp_dict.py @@ -44,3 +44,18 @@ if not isinstance(w_obj, W_DictMultiObject): raise OperationError(space.w_TypeError, space.w_None) return w_obj.nondescr_reversed_dict(space) + +@unwrap_spec(last=bool) +def move_to_end(space, w_obj, w_key, last=True): +"""Move the key in a dictionary object into the first or last position. + +This is a __pypy__ function instead of being simply done by calling +dict.move_to_end(), for CPython compatibility: dictionaries are only +ordered on PyPy. You should use the collections.OrderedDict class for +cases where ordering is important. That class implements the +move_to_end() method by calling __pypy__.move_to_end(). +""" +from pypy.objspace.std.dictmultiobject import W_DictMultiObject +if not isinstance(w_obj, W_DictMultiObject): +raise OperationError(space.w_TypeError, space.w_None) +return w_obj.nondescr_move_to_end(space, w_key, last) diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py --- a/pypy/objspace/std/dictmultiobject.py +++ b/pypy/objspace/std/dictmultiobject.py @@ -232,6 +232,37 @@ w_keys = self.w_keys() return space.call_method(w_keys, '__reversed__') +def nondescr_move_to_end(self, space, w_key, last_flag): +"""Not exposed directly to app-level, but via __pypy__.move_to_end(). +""" +strategy = self.get_strategy() +if strategy.has_move_to_end: +strategy.move_to_end(self, w_key, last_flag) +else: +# fall-back +w_value = self.getitem(w_key) +if w_value is None: +space.raise_key_error(w_key) +else: +self.delitem(w_key) +if last_flag: +self.setitem(w_key, w_value) +else: +# *very slow* fall-back +keys_w = [] +values_w = [] +iteratorimplementation = self.iteritems() +while True: +w_k, w_v = iteratorimplementation.next_item() +if w_k is None: +break +keys_w.append(w_k) +values_w.append(w_v) +self.clear() +self.setitem(w_key, w_value) +for i in range(len(keys_w)): +self.setitem(keys_w[i], values_w[i]) + def descr_clear(self, space): """D.clear() -> None. Remove all items from D.""" self.clear() @@ -499,7 +530,9 @@ raise NotImplementedError has_iterreversed = False -# no 'getiterreversed': no default implementation available +has_move_to_end = False +# no 'getiterreversed' and no 'move_to_end': no default +# implementation available def rev_update1_dict_dict(self, w_dict, w_updatedict): iteritems = self.iteritems(w_dict) @@ -783,6 +816,9 @@ dictimpl.iterreversed = iterreversed dictimpl.has_iterreversed = True +if hasattr(dictimpl, 'move_to_end'): +dictimpl.has_move_to_end = True + @jit.look_inside_iff(lambda self, w_dict, w_updatedict: w_dict_unrolling_heuristic(w_dict)) def rev_update1_dict_dict(self, w_dict, w_updatedict): @@ -962,6 +998,15 @@ def getiterreversed(self, w_dict): return objectmodel.reversed_dict(self.unerase(w_dict.dstorage)) +def move_to_end(self, w_dict, w_key, last_flag): +if self.is_correct_type(w_key): +d = self.unerase(w_dict.dstorage) +key = self.unwrap(w_key) +objectmodel.move_to_end(d, key, last_flag) +else: +self.switch_to_object_strategy(w_dict) +w_dict.nondescr_move_to_end(w_dict.space, w_key, last_flag) + def prepare_update(self, w_dict,