Author: Ronan Lamy <ronan.l...@gmail.com> Branch: py3.5 Changeset: r92166:90593ef2b17c Date: 2017-08-18 16:28 +0200 http://bitbucket.org/pypy/pypy/changeset/90593ef2b17c/
Log: hg merge default diff --git a/lib-python/2.7/ctypes/__init__.py b/lib-python/2.7/ctypes/__init__.py --- a/lib-python/2.7/ctypes/__init__.py +++ b/lib-python/2.7/ctypes/__init__.py @@ -361,17 +361,20 @@ if handle is None: if flags & _FUNCFLAG_CDECL: - self._handle = _ffi.CDLL(name, mode) + pypy_dll = _ffi.CDLL(name, mode) else: - self._handle = _ffi.WinDLL(name, mode) - else: - self._handle = handle + pypy_dll = _ffi.WinDLL(name, mode) + self._pypy_dll = pypy_dll + handle = int(pypy_dll) + if _sys.maxint > 2 ** 32: + handle = int(handle) # long -> int + self._handle = handle def __repr__(self): - return "<%s '%s', handle %r at 0x%x>" % ( - self.__class__.__name__, self._name, self._handle, - id(self) & (_sys.maxint * 2 + 1)) - + return "<%s '%s', handle %x at %x>" % \ + (self.__class__.__name__, self._name, + (self._handle & (_sys.maxint*2 + 1)), + id(self) & (_sys.maxint*2 + 1)) def __getattr__(self, name): if name.startswith('__') and name.endswith('__'): diff --git a/lib_pypy/_ctypes/basics.py b/lib_pypy/_ctypes/basics.py --- a/lib_pypy/_ctypes/basics.py +++ b/lib_pypy/_ctypes/basics.py @@ -82,7 +82,7 @@ return False def in_dll(self, dll, name): - return self.from_address(dll._handle.getaddressindll(name)) + return self.from_address(dll._pypy_dll.getaddressindll(name)) def from_buffer(self, obj, offset=0): size = self._sizeofinstances() diff --git a/lib_pypy/_ctypes/function.py b/lib_pypy/_ctypes/function.py --- a/lib_pypy/_ctypes/function.py +++ b/lib_pypy/_ctypes/function.py @@ -430,7 +430,7 @@ ffires = restype.get_ffi_argtype() return _ffi.FuncPtr.fromaddr(ptr, '', ffiargs, ffires, self._flags_) - cdll = self.dll._handle + cdll = self.dll._pypy_dll try: ffi_argtypes = [argtype.get_ffi_argtype() for argtype in argtypes] ffi_restype = restype.get_ffi_argtype() 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 @@ -1632,7 +1632,7 @@ assert cpyext_glob_tid_ptr[0] == 0 cpyext_glob_tid_ptr[0] = tid - preexist_error = PyErr_Occurred(space) is not None + preexist_error = PyErr_Occurred(space) try: # Call the function result = call_external_function(func, *boxed_args) @@ -1656,17 +1656,20 @@ has_result = ret is not None # Check for exception consistency - has_error = PyErr_Occurred(space) is not None - if not preexist_error: - if has_error and has_result: - raise oefmt(space.w_SystemError, - "An exception was set, but function returned a " - "value") - elif not expect_null and not has_error and not has_result: - raise oefmt(space.w_SystemError, - "Function returned a NULL result without setting " - "an exception") - if has_error: + # XXX best attempt, will miss preexisting error that is + # overwritten with a new error of the same type + error = PyErr_Occurred(space) + has_new_error = (error is not None) and (error is not preexist_error) + has_result = ret is not None + if not expect_null and has_new_error and has_result: + raise oefmt(space.w_SystemError, + "An exception was set, but function returned a " + "value") + elif not expect_null and not has_new_error and not has_result: + raise oefmt(space.w_SystemError, + "Function returned a NULL result without setting " + "an exception") + elif has_new_error: state = space.fromcache(State) state.check_and_raise_exception() 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 @@ -24,6 +24,10 @@ def PyPy_Crash2(space): 1/0 +@api.cpython_api([api.PyObject], api.PyObject, result_is_ll=True) +def PyPy_Noop(space, pyobj): + return pyobj + class TestApi: def test_signature(self): common_functions = api.FUNCTIONS_BY_HEADER[api.pypy_decl] @@ -665,6 +669,7 @@ body = """ PyAPI_FUNC(PyObject*) PyPy_Crash1(void); PyAPI_FUNC(long) PyPy_Crash2(void); + PyAPI_FUNC(PyObject*) PyPy_Noop(PyObject*); static PyObject* foo_crash1(PyObject* self, PyObject *args) { return PyPy_Crash1(); @@ -688,9 +693,27 @@ int a = PyPy_Crash2(); return PyFloat_FromDouble(a); } + static PyObject* foo_noop(PyObject* self, PyObject* args) + { + Py_INCREF(args); + return PyPy_Noop(args); + } + static PyObject* foo_set(PyObject* self, PyObject *args) + { + PyErr_SetString(PyExc_TypeError, "clear called with no error"); + if (PyLong_Check(args)) { + Py_INCREF(args); + return args; + } + return NULL; + } static PyObject* foo_clear(PyObject* self, PyObject *args) { PyErr_Clear(); + if (PyLong_Check(args)) { + Py_INCREF(args); + return args; + } return NULL; } static PyMethodDef methods[] = { @@ -698,7 +721,9 @@ { "crash2", foo_crash2, METH_NOARGS }, { "crash3", foo_crash3, METH_NOARGS }, { "crash4", foo_crash4, METH_NOARGS }, - { "clear", foo_clear, METH_NOARGS }, + { "clear", foo_clear, METH_O }, + { "set", foo_set, METH_O }, + { "noop", foo_noop, METH_O }, { NULL } }; static struct PyModuleDef moduledef = { @@ -710,15 +735,46 @@ }; """ module = self.import_module(name='foo', body=body) + # uncaught interplevel exceptions are turned into SystemError - raises(SystemError, module.crash1) - raises(SystemError, module.crash2) - # caught exception + expected = "ZeroDivisionError('integer division or modulo by zero',)" + exc = raises(SystemError, module.crash1) + assert exc.value[0] == expected + + exc = raises(SystemError, module.crash2) + assert exc.value[0] == expected + + # caught exception, api.cpython_api return value works assert module.crash3() == -1 - # An exception was set, but function returned a value - raises(SystemError, module.crash4) - # No exception set, but NULL returned - raises(SystemError, module.clear) + + expected = 'An exception was set, but function returned a value' + # PyPy only incompatibility/extension + exc = raises(SystemError, module.crash4) + assert exc.value[0] == expected + + # An exception was set by the previous call, it can pass + # cleanly through a call that doesn't check error state + assert module.noop(1) == 1 + + # clear the exception but return NULL, signalling an error + expected = 'Function returned a NULL result without setting an exception' + exc = raises(SystemError, module.clear, None) + assert exc.value[0] == expected + + # Set an exception and return NULL + raises(TypeError, module.set, None) + + # clear any exception and return a value + assert module.clear(1) == 1 + + # Set an exception, but return non-NULL + expected = 'An exception was set, but function returned a value' + exc = raises(SystemError, module.set, 1) + assert exc.value[0] == expected + + + # Clear the exception and return a value, all is OK + assert module.clear(1) == 1 def test_new_exception(self): mod = self.import_extension('foo', [ diff --git a/pypy/module/imp/test/test_app.py b/pypy/module/imp/test/test_app.py --- a/pypy/module/imp/test/test_app.py +++ b/pypy/module/imp/test/test_app.py @@ -81,15 +81,17 @@ def test_suffixes(self): import imp for suffix, mode, type in imp.get_suffixes(): - if mode == imp.PY_SOURCE: + if type == imp.PY_SOURCE: assert suffix == '.py' - assert type == 'r' - elif mode == imp.PY_COMPILED: + assert mode == 'U' + elif type == imp.PY_COMPILED: assert suffix in ('.pyc', '.pyo') - assert type == 'rb' - elif mode == imp.C_EXTENSION: + assert mode == 'rb' + elif type == imp.C_EXTENSION: assert suffix.endswith(('.pyd', '.so')) - assert type == 'rb' + assert mode == 'rb' + else: + assert False, ("Unknown type", suffix, mode, type) def test_ext_suffixes(self): import _imp diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_loading.py b/pypy/module/test_lib_pypy/ctypes_tests/test_loading.py --- a/pypy/module/test_lib_pypy/ctypes_tests/test_loading.py +++ b/pypy/module/test_lib_pypy/ctypes_tests/test_loading.py @@ -43,6 +43,12 @@ cdll.LoadLibrary(lib) CDLL(lib) + def test__handle(self): + lib = find_library("c") + if lib: + cdll = CDLL(lib) + assert type(cdll._handle) in (int, long) + if os.name in ("nt", "ce"): def test_load_library(self): if is_resource_enabled("printing"): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit