Author: Matti Picus <matti.pi...@gmail.com> Branch: py3.6 Changeset: r96032:6e5e91318ea6 Date: 2019-02-16 20:13 +0200 http://bitbucket.org/pypy/pypy/changeset/6e5e91318ea6/
Log: merge default into branch diff --git a/extra_tests/cffi_tests/cffi0/test_ownlib.py b/extra_tests/cffi_tests/cffi0/test_ownlib.py --- a/extra_tests/cffi_tests/cffi0/test_ownlib.py +++ b/extra_tests/cffi_tests/cffi0/test_ownlib.py @@ -352,6 +352,8 @@ def test_modify_struct_value(self): if self.module is None: py.test.skip("fix the auto-generation of the tiny test lib") + if self.Backend is CTypesBackend: + py.test.skip("fails with the ctypes backend on some architectures") ffi = FFI(backend=self.Backend()) ffi.cdef(""" typedef struct { diff --git a/extra_tests/cffi_tests/embedding/thread3-test.c b/extra_tests/cffi_tests/embedding/thread3-test.c --- a/extra_tests/cffi_tests/embedding/thread3-test.c +++ b/extra_tests/cffi_tests/embedding/thread3-test.c @@ -52,5 +52,6 @@ assert(status == 0); } printf("done\n"); + fflush(stdout); /* this is occasionally needed on Windows */ return 0; } diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py --- a/lib_pypy/cffi/__init__.py +++ b/lib_pypy/cffi/__init__.py @@ -5,8 +5,8 @@ from .error import CDefError, FFIError, VerificationError, VerificationMissing from .error import PkgConfigError -__version__ = "1.12.0" -__version_info__ = (1, 12, 0) +__version__ = "1.12.1" +__version_info__ = (1, 12, 1) # The verifier module file names are based on the CRC32 of a string that # contains the following version number. It may be older than __version__ diff --git a/lib_pypy/cffi/_cffi_include.h b/lib_pypy/cffi/_cffi_include.h --- a/lib_pypy/cffi/_cffi_include.h +++ b/lib_pypy/cffi/_cffi_include.h @@ -8,43 +8,20 @@ the same works for the other two macros. Py_DEBUG implies them, but not the other way around. - The implementation is messy (issue #350): on Windows, with _MSC_VER, - we have to define Py_LIMITED_API even before including pyconfig.h. - In that case, we guess what pyconfig.h will do to the macros above, - and check our guess after the #include. - - Note that on Windows, with CPython 3.x, you need virtualenv version - >= 16.0.0. Older versions don't copy PYTHON3.DLL. As a workaround - you can remove the definition of Py_LIMITED_API here. - - See also 'py_limited_api' in cffi/setuptools_ext.py. + Issue #350 is still open: on Windows, the code here causes it to link + with PYTHON36.DLL (for example) instead of PYTHON3.DLL. A fix was + attempted in 164e526a5515 and 14ce6985e1c3, but reverted: virtualenv + does not make PYTHON3.DLL available, and so the "correctly" compiled + version would not run inside a virtualenv. We will re-apply the fix + after virtualenv has been fixed for some time. For explanation, see + issue #355. For a workaround if you want PYTHON3.DLL and don't worry + about virtualenv, see issue #350. See also 'py_limited_api' in + setuptools_ext.py. */ #if !defined(_CFFI_USE_EMBEDDING) && !defined(Py_LIMITED_API) -# ifdef _MSC_VER -# if !defined(_DEBUG) && !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG) -# define Py_LIMITED_API -# endif -# include <pyconfig.h> - /* sanity-check: Py_LIMITED_API will cause crashes if any of these - are also defined. Normally, the Python file PC/pyconfig.h does not - cause any of these to be defined, with the exception that _DEBUG - causes Py_DEBUG. Double-check that. */ -# ifdef Py_LIMITED_API -# if defined(Py_DEBUG) -# error "pyconfig.h unexpectedly defines Py_DEBUG, but Py_LIMITED_API is set" -# endif -# if defined(Py_TRACE_REFS) -# error "pyconfig.h unexpectedly defines Py_TRACE_REFS, but Py_LIMITED_API is set" -# endif -# if defined(Py_REF_DEBUG) -# error "pyconfig.h unexpectedly defines Py_REF_DEBUG, but Py_LIMITED_API is set" -# endif -# endif -# else -# include <pyconfig.h> -# if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG) -# define Py_LIMITED_API -# endif +# include <pyconfig.h> +# if !defined(Py_DEBUG) && !defined(Py_TRACE_REFS) && !defined(Py_REF_DEBUG) +# define Py_LIMITED_API # endif #endif diff --git a/lib_pypy/cffi/_embedding.h b/lib_pypy/cffi/_embedding.h --- a/lib_pypy/cffi/_embedding.h +++ b/lib_pypy/cffi/_embedding.h @@ -221,7 +221,7 @@ if (f != NULL && f != Py_None) { PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME - "\ncompiled with cffi version: 1.12.0" + "\ncompiled with cffi version: 1.12.1" "\n_cffi_backend module: ", f); modules = PyImport_GetModuleDict(); mod = PyDict_GetItemString(modules, "_cffi_backend"); diff --git a/lib_pypy/cffi/setuptools_ext.py b/lib_pypy/cffi/setuptools_ext.py --- a/lib_pypy/cffi/setuptools_ext.py +++ b/lib_pypy/cffi/setuptools_ext.py @@ -81,8 +81,14 @@ it doesn't so far, creating troubles. That's why we check for "not hasattr(sys, 'gettotalrefcount')" (the 2.7 compatible equivalent of 'd' not in sys.abiflags). (http://bugs.python.org/issue28401) + + On Windows, with CPython <= 3.4, it's better not to use py_limited_api + because virtualenv *still* doesn't copy PYTHON3.DLL on these versions. + For now we'll skip py_limited_api on all Windows versions to avoid an + inconsistent mess. """ - if 'py_limited_api' not in kwds and not hasattr(sys, 'gettotalrefcount'): + if ('py_limited_api' not in kwds and not hasattr(sys, 'gettotalrefcount') + and sys.platform != 'win32'): import setuptools try: setuptools_major_version = int(setuptools.__version__.partition('.')[0]) diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -1,7 +1,7 @@ # ____________________________________________________________ import sys -assert __version__ == "1.12.0", ("This test_c.py file is for testing a version" +assert __version__ == "1.12.1", ("This test_c.py file is for testing a version" " of cffi that differs from the one that we" " get from 'import _cffi_backend'") if sys.version_info < (3,): diff --git a/pypy/module/cpyext/listobject.py b/pypy/module/cpyext/listobject.py --- a/pypy/module/cpyext/listobject.py +++ b/pypy/module/cpyext/listobject.py @@ -104,7 +104,8 @@ def PyList_GET_SIZE(space, w_obj): """Macro form of PyList_Size() without error checking. """ - return space.len_w(w_obj) + assert isinstance(w_obj, W_ListObject) + return w_obj.length() @cpython_api([PyObject], Py_ssize_t, error=-1) diff --git a/pypy/module/cpyext/sequence.py b/pypy/module/cpyext/sequence.py --- a/pypy/module/cpyext/sequence.py +++ b/pypy/module/cpyext/sequence.py @@ -50,50 +50,56 @@ converted to a sequence, and raises a TypeError, raise a new TypeError with m as the message text. If the conversion otherwise, fails, reraise the original exception""" - if isinstance(w_obj, tupleobject.W_TupleObject): + if isinstance(w_obj, tupleobject.W_AbstractTupleObject): return w_obj # CCC avoid the double conversion that occurs here if isinstance(w_obj, W_ListObject): - # make sure we can return a borrowed obj from PySequence_Fast_GET_ITEM - w_obj.convert_to_cpy_strategy(space) + # note: we used to call w_obj.convert_to_cpy_strategy() here, + # but we really have to call it from PySequence_Fast_GET_ITEM() + # because some people never call PySequence_Fast() if they know + # the object is a list. return w_obj try: - return W_ListObject.newlist_cpyext(space, space.listview(w_obj)) + return tupleobject.W_TupleObject(space.fixedview(w_obj)) except OperationError as e: if e.match(space, space.w_TypeError): raise OperationError(space.w_TypeError, space.newtext(rffi.charp2str(m))) raise e -# CCC this should be written as a C macro -@cpython_api([rffi.VOIDP, Py_ssize_t], PyObject, result_borrowed=True) -def PySequence_Fast_GET_ITEM(space, w_obj, index): +# CCC this should be written as a C macro, at least for the tuple case +@cpython_api([rffi.VOIDP, Py_ssize_t], PyObject, result_is_ll=True) +def PySequence_Fast_GET_ITEM(space, py_obj, index): """Return the ith element of o, assuming that o was returned by PySequence_Fast(), o is not NULL, and that i is within bounds. """ - if isinstance(w_obj, W_ListObject): - return w_obj.getitem(index) - elif isinstance(w_obj, tupleobject.W_TupleObject): - return w_obj.wrappeditems[index] - raise oefmt(space.w_TypeError, - "PySequence_Fast_GET_ITEM called but object is not a list or " - "sequence") + py_obj = rffi.cast(PyObject, py_obj) + if PyTuple_Check(space, py_obj): + from pypy.module.cpyext.tupleobject import PyTupleObject + py_tuple = rffi.cast(PyTupleObject, py_obj) + return py_tuple.c_ob_item[index] + else: + from pypy.module.cpyext.listobject import PyList_GET_ITEM + w_obj = from_ref(space, py_obj) + return PyList_GET_ITEM(space, w_obj, index) @cpython_api([rffi.VOIDP], Py_ssize_t, error=CANNOT_FAIL) -def PySequence_Fast_GET_SIZE(space, w_obj): +def PySequence_Fast_GET_SIZE(space, py_obj): """Returns the length of o, assuming that o was returned by PySequence_Fast() and that o is not NULL. The size can also be gotten by calling PySequence_Size() on o, but PySequence_Fast_GET_SIZE() is faster because it can assume o is a list or tuple.""" - if isinstance(w_obj, W_ListObject): - return w_obj.length() - elif isinstance(w_obj, tupleobject.W_TupleObject): - return len(w_obj.wrappeditems) - raise oefmt(space.w_TypeError, - "PySequence_Fast_GET_SIZE called but object is not a list or " - "sequence") + py_obj = rffi.cast(PyObject, py_obj) + if PyTuple_Check(space, py_obj): + from pypy.module.cpyext.tupleobject import PyTupleObject + py_tuple = rffi.cast(PyTupleObject, py_obj) + return py_tuple.c_ob_size + else: + from pypy.module.cpyext.listobject import PyList_GET_SIZE + w_obj = from_ref(space, py_obj) + return PyList_GET_SIZE(space, w_obj) @cpython_api([rffi.VOIDP], PyObjectP) -def PySequence_Fast_ITEMS(space, w_obj): +def PySequence_Fast_ITEMS(space, py_obj): """Return the underlying array of PyObject pointers. Assumes that o was returned by PySequence_Fast() and o is not NULL. @@ -101,18 +107,17 @@ So, only use the underlying array pointer in contexts where the sequence cannot change. """ - if isinstance(w_obj, W_ListObject): - cpy_strategy = space.fromcache(CPyListStrategy) - if w_obj.strategy is cpy_strategy: - return w_obj.get_raw_items() # asserts it's a cpyext strategy - elif isinstance(w_obj, tupleobject.W_TupleObject): + py_obj = rffi.cast(PyObject, py_obj) + if PyTuple_Check(space, py_obj): from pypy.module.cpyext.tupleobject import PyTupleObject - py_obj = as_pyobj(space, w_obj) py_tuple = rffi.cast(PyTupleObject, py_obj) return rffi.cast(PyObjectP, py_tuple.c_ob_item) - raise oefmt(space.w_TypeError, - "PySequence_Fast_ITEMS called but object is not the result of " - "PySequence_Fast") + else: + from pypy.module.cpyext.listobject import get_list_storage + w_obj = from_ref(space, py_obj) + assert isinstance(w_obj, W_ListObject) + storage = get_list_storage(space, w_obj) + return rffi.cast(PyObjectP, storage._elems) @cpython_api([PyObject, Py_ssize_t, Py_ssize_t], PyObject) def PySequence_GetSlice(space, w_obj, start, end): @@ -300,10 +305,6 @@ storage = self.unerase(w_list.lstorage) return storage._length - def get_raw_items(self, w_list): - storage = self.unerase(w_list.lstorage) - return storage._elems - def getslice(self, w_list, start, stop, step, length): w_list.switch_to_object_strategy() return w_list.strategy.getslice(w_list, start, stop, step, length) diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py --- a/pypy/module/cpyext/test/test_cpyext.py +++ b/pypy/module/cpyext/test/test_cpyext.py @@ -141,6 +141,7 @@ '_cffi_backend', ], "objspace.disable_entrypoints_in_cffi": True} + spaceconfig["objspace.std.withspecialisedtuple"] = True @classmethod def preload_builtins(cls, space): diff --git a/pypy/module/cpyext/test/test_sequence.py b/pypy/module/cpyext/test/test_sequence.py --- a/pypy/module/cpyext/test/test_sequence.py +++ b/pypy/module/cpyext/test/test_sequence.py @@ -5,7 +5,7 @@ from pypy.module.cpyext.sequence import ( PySequence_Fast, PySequence_Contains, PySequence_Index, PySequence_GetItem, PySequence_SetItem, PySequence_DelItem) -from pypy.module.cpyext.pyobject import get_w_obj_and_decref +from pypy.module.cpyext.pyobject import get_w_obj_and_decref, from_ref from pypy.module.cpyext.state import State import pytest @@ -21,12 +21,14 @@ w_l = space.wrap([1, 2, 3, 4]) assert api.PySequence_Fast(w_l, "message") is w_l - assert space.int_w(api.PySequence_Fast_GET_ITEM(w_l, 1)) == 2 + py_result = api.PySequence_Fast_GET_ITEM(w_l, 1) + w_result = from_ref(space, py_result) + assert space.int_w(w_result) == 2 assert api.PySequence_Fast_GET_SIZE(w_l) == 4 w_set = space.wrap(set((1, 2, 3, 4))) w_seq = api.PySequence_Fast(w_set, "message") - assert space.type(w_seq) is space.w_list + assert space.type(w_seq) is space.w_tuple assert space.len_w(w_seq) == 4 w_seq = api.PySequence_Tuple(w_set) @@ -83,7 +85,7 @@ def test_get_slice_fast(self, space, api): w_t = space.wrap([1, 2, 3, 4, 5]) - api.PySequence_Fast(w_t, "foo") # converts + api.PyList_GetItem(w_t, 0) # converts to cpy strategy assert space.unwrap(api.PySequence_GetSlice(w_t, 2, 4)) == [3, 4] assert space.unwrap(api.PySequence_GetSlice(w_t, 1, -1)) == [2, 3, 4] @@ -215,7 +217,7 @@ class TestCPyListStrategy(BaseApiTest): def test_getitem_setitem(self, space, api): w_l = space.wrap([1, 2, 3, 4]) - api.PySequence_Fast(w_l, "foo") # converts + api.PyList_GetItem(w_l, 0) # converts to cpy strategy assert space.int_w(space.len(w_l)) == 4 assert space.int_w(space.getitem(w_l, space.wrap(1))) == 2 assert space.int_w(space.getitem(w_l, space.wrap(0))) == 1 @@ -229,17 +231,17 @@ w = space.wrap w_l = w([1, 2, 3, 4]) - api.PySequence_Fast(w_l, "foo") # converts + api.PyList_GetItem(w_l, 0) # converts to cpy strategy space.call_method(w_l, 'insert', w(0), w(0)) assert space.int_w(space.len(w_l)) == 5 assert space.int_w(space.getitem(w_l, w(3))) == 3 - api.PySequence_Fast(w_l, "foo") # converts + api.PyList_GetItem(w_l, 0) # converts to cpy strategy space.call_method(w_l, 'sort') assert space.int_w(space.len(w_l)) == 5 assert space.int_w(space.getitem(w_l, w(0))) == 0 - api.PySequence_Fast(w_l, "foo") # converts + api.PyList_GetItem(w_l, 0) # converts to cpy strategy w_t = space.wrap(space.fixedview(w_l)) assert space.int_w(space.len(w_t)) == 5 assert space.int_w(space.getitem(w_t, w(0))) == 0 @@ -247,22 +249,22 @@ assert space.int_w(space.len(w_l2)) == 5 assert space.int_w(space.getitem(w_l2, w(0))) == 0 - api.PySequence_Fast(w_l, "foo") # converts + api.PyList_GetItem(w_l, 0) # converts to cpy strategy w_sum = space.add(w_l, w_l) assert space.int_w(space.len(w_sum)) == 10 - api.PySequence_Fast(w_l, "foo") # converts + api.PyList_GetItem(w_l, 0) # converts to cpy strategy w_prod = space.mul(w_l, space.wrap(2)) assert space.int_w(space.len(w_prod)) == 10 - api.PySequence_Fast(w_l, "foo") # converts + api.PyList_GetItem(w_l, 0) # converts to cpy strategy w_l.inplace_mul(2) assert space.int_w(space.len(w_l)) == 10 def test_getstorage_copy(self, space, api): w = space.wrap w_l = w([1, 2, 3, 4]) - api.PySequence_Fast(w_l, "foo") # converts + api.PyList_GetItem(w_l, 0) # converts to cpy strategy w_l1 = w([]) space.setitem(w_l1, space.newslice(w(0), w(0), w(1)), w_l) @@ -285,6 +287,10 @@ if (objects == NULL) return NULL; size = PySequence_Fast_GET_SIZE(foo); + for (i = 0; i < size; ++i) { + if (objects[i] != PySequence_Fast_GET_ITEM(foo, i)) + return PyBool_FromLong(0); + } common_type = size > 0 ? Py_TYPE(objects[0]) : NULL; for (i = 1; i < size; ++i) { if (Py_TYPE(objects[i]) != common_type) { @@ -304,6 +310,9 @@ s = (1, 2, 3, 4) assert module.test_fast_sequence(s[0:-1]) assert module.test_fast_sequence(s[::-1]) + s = (1, 2) # specialized tuple + assert module.test_fast_sequence(s[0:-1]) + assert module.test_fast_sequence(s[::-1]) s = "1234" assert module.test_fast_sequence(s[0:-1]) assert module.test_fast_sequence(s[::-1]) diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py --- a/pypy/module/cpyext/test/test_typeobject.py +++ b/pypy/module/cpyext/test/test_typeobject.py @@ -514,7 +514,8 @@ py_type = rffi.cast(PyTypeObjectPtr, ref) assert py_type.c_tp_alloc - assert from_ref(space, py_type.c_tp_mro).wrappeditems is w_class.mro_w + w_tup = from_ref(space, py_type.c_tp_mro) + assert space.fixedview(w_tup) == w_class.mro_w decref(space, ref) 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 @@ -45,7 +45,8 @@ # for json decoder def create_empty_unicode_key_dict(space): return r_dict(unicode_eq, unicode_hash, - force_non_null=True) + force_non_null=True, + simple_hash_eq=True) def from_unicode_key_dict(space, d): strategy = space.fromcache(UnicodeDictStrategy) @@ -1176,6 +1177,7 @@ return unwrapped def unwrap(self, wrapped): + assert type(wrapped) is self.space.UnicodeObjectCls return wrapped def is_correct_type(self, w_obj): diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py --- a/pypy/objspace/std/listobject.py +++ b/pypy/objspace/std/listobject.py @@ -214,13 +214,6 @@ storage = strategy.erase(list_f) return W_ListObject.from_storage_and_strategy(space, storage, strategy) - @staticmethod - def newlist_cpyext(space, list): - from pypy.module.cpyext.sequence import CPyListStrategy, CPyListStorage - strategy = space.fromcache(CPyListStrategy) - storage = strategy.erase(CPyListStorage(space, list)) - return W_ListObject.from_storage_and_strategy(space, storage, strategy) - def __repr__(self): """ representation for debugging purposes """ return "%s(%s, %s)" % (self.__class__.__name__, self.strategy, @@ -259,13 +252,6 @@ self.strategy = cpy_strategy self.lstorage = cpy_strategy.erase(CPyListStorage(space, lst)) - def get_raw_items(self): - from pypy.module.cpyext.sequence import CPyListStrategy - - cpy_strategy = self.space.fromcache(CPyListStrategy) - assert self.strategy is cpy_strategy # should we return an error? - return cpy_strategy.get_raw_items(self) - # ___________________________________________________ def init_from_list_w(self, list_w): diff --git a/rpython/rlib/rutf8.py b/rpython/rlib/rutf8.py --- a/rpython/rlib/rutf8.py +++ b/rpython/rlib/rutf8.py @@ -133,9 +133,11 @@ return pos + 1 if _is_64bit and not jit.we_are_jitted(): # optimized for Intel x86-64 by hand - return pos + 1 + ( + res = pos + 1 + ( ((chr1 > 0xDF) << 1) + rarithmetic.intmask((_constant_ncp >> (chr1 & 0x3F)) & 1)) + assert res >= 0 + return res if chr1 <= 0xDF: return pos + 2 if chr1 <= 0xEF: _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit