Author: Matti Picus <matti.pi...@gmail.com> Branch: unicode-utf8-py3 Changeset: r95210:07afb9936e34 Date: 2018-10-12 15:56 +0300 http://bitbucket.org/pypy/pypy/changeset/07afb9936e34/
Log: merge py3.5 into branch diff --git a/lib_pypy/_cffi_ssl/_stdssl/__init__.py b/lib_pypy/_cffi_ssl/_stdssl/__init__.py --- a/lib_pypy/_cffi_ssl/_stdssl/__init__.py +++ b/lib_pypy/_cffi_ssl/_stdssl/__init__.py @@ -186,7 +186,7 @@ # Prefer poll, if available, since you can poll() any fd # which can't be done with select(). if HAVE_POLL: - p.register(sock.fileno(), POLLOUT | POLLIN) + p.register(sock.fileno(), POLLOUT if writing else POLLIN) rc = len(p.poll(timeout * 1000.0)) else: diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py --- a/pypy/module/_cffi_backend/cdataobj.py +++ b/pypy/module/_cffi_backend/cdataobj.py @@ -79,13 +79,6 @@ w_result = self.ctype.cast_to_int(ptr) return w_result - def long(self, space): - w_result = self.int(space) - space = self.space - if space.is_w(space.type(w_result), space.w_int): - w_result = space.newlong(space.int_w(w_result)) - return w_result - def float(self): with self as ptr: w_result = self.ctype.float(ptr) @@ -664,7 +657,6 @@ __repr__ = interp2app(W_CData.repr), __bool__ = interp2app(W_CData.bool), __int__ = interp2app(W_CData.int), - __long__ = interp2app(W_CData.long), __float__ = interp2app(W_CData.float), __complex__ = interp2app(W_CData.complex), __len__ = interp2app(W_CData.len), diff --git a/pypy/module/_cffi_backend/embedding.py b/pypy/module/_cffi_backend/embedding.py --- a/pypy/module/_cffi_backend/embedding.py +++ b/pypy/module/_cffi_backend/embedding.py @@ -95,7 +95,9 @@ if os.name == 'nt': do_includes = r""" +#ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0501 +#endif #include <windows.h> static void _cffi_init(void); diff --git a/pypy/module/_cffi_backend/misc.py b/pypy/module/_cffi_backend/misc.py --- a/pypy/module/_cffi_backend/misc.py +++ b/pypy/module/_cffi_backend/misc.py @@ -6,6 +6,7 @@ from rpython.rlib.objectmodel import specialize, we_are_translated from rpython.rlib.rarithmetic import r_uint, r_ulonglong from rpython.rlib.unroll import unrolling_iterable +from rpython.rlib.nonconst import NonConstant from rpython.rtyper.lltypesystem import lltype, llmemory, rffi from rpython.translator.tool.cbuild import ExternalCompilationInfo @@ -202,6 +203,9 @@ else: if strict and value < 0: raise OperationError(space.w_OverflowError, space.newtext(neg_msg)) + if not we_are_translated(): + if isinstance(value, NonConstant): # hack for test_ztranslation + return r_uint(0) return r_uint(value) # note that if not 'strict', then space.int() will round down floats bigint = space.bigint_w(space.int(w_ob), allow_conversion=False) diff --git a/pypy/module/_codecs/test/test_codecs.py b/pypy/module/_codecs/test/test_codecs.py --- a/pypy/module/_codecs/test/test_codecs.py +++ b/pypy/module/_codecs/test/test_codecs.py @@ -772,6 +772,26 @@ assert b"\\u3042\u3xxx".decode("unicode-escape", "test.handler1") == \ u"\u3042[<92><117><51>]xxx" + def test_unicode_internal_error_handler_infinite_loop(self): + import codecs + class MyException(Exception): + pass + seen = [0] + def handler_unicodeinternal(exc): + if not isinstance(exc, UnicodeDecodeError): + raise TypeError("don't know how to handle %r" % exc) + seen[0] += 1 + if seen[0] == 20: # stop the 20th time this is called + raise MyException + return (u"\x01", 4) # 4 < len(input), so will try and fail again + codecs.register_error("test.inf", handler_unicodeinternal) + try: + b"\x00\x00\x00\x00\x00".decode("unicode-internal", "test.inf") + except MyException: + pass + else: + raise AssertionError("should have gone into infinite loop") + def test_encode_error_bad_handler(self): import codecs codecs.register_error("test.bad_handler", lambda e: (repl, 1)) diff --git a/pypy/module/_io/interp_fileio.py b/pypy/module/_io/interp_fileio.py --- a/pypy/module/_io/interp_fileio.py +++ b/pypy/module/_io/interp_fileio.py @@ -196,12 +196,11 @@ wrap_oserror2(space, e, w_name, exception_name='w_IOError', eintr_retry=True) - if not rposix._WIN32: - try: - _open_inhcache.set_non_inheritable(self.fd) - except OSError as e: - raise wrap_oserror2(space, e, w_name, - eintr_retry=False) + try: + _open_inhcache.set_non_inheritable(self.fd) + except OSError as e: + raise wrap_oserror2(space, e, w_name, + eintr_retry=False) else: w_fd = space.call_function(w_opener, w_name, space.newint(flags)) @@ -225,6 +224,7 @@ raise wrap_oserror2(space, e, w_name, eintr_retry=False) + try: st = os.fstat(self.fd) except OSError as e: diff --git a/pypy/module/_io/test/test_fileio.py b/pypy/module/_io/test/test_fileio.py --- a/pypy/module/_io/test/test_fileio.py +++ b/pypy/module/_io/test/test_fileio.py @@ -279,31 +279,34 @@ raises(FileExistsError, _io.FileIO, filename, 'x') def test_non_inheritable(self): - import _io, posix + import _io + os = self.posix f = _io.FileIO(self.tmpfile, 'r') - assert posix.get_inheritable(f.fileno()) == False + assert os.get_inheritable(f.fileno()) == False f.close() def test_FileIO_fd_does_not_change_inheritable(self): - import _io, posix - fd1, fd2 = posix.pipe() - posix.set_inheritable(fd1, True) - posix.set_inheritable(fd2, False) + import _io + os = self.posix + fd1, fd2 = os.pipe() + os.set_inheritable(fd1, True) + os.set_inheritable(fd2, False) f1 = _io.FileIO(fd1, 'r') f2 = _io.FileIO(fd2, 'w') - assert posix.get_inheritable(fd1) == True - assert posix.get_inheritable(fd2) == False + assert os.get_inheritable(fd1) == True + assert os.get_inheritable(fd2) == False f1.close() f2.close() def test_close_upon_reinit(self): - import _io, posix + import _io + os = self.posix f = _io.FileIO(self.tmpfile, 'r') fd1 = f.fileno() f.__init__(self.tmpfile, 'w') fd2 = f.fileno() if fd1 != fd2: - raises(OSError, posix.close, fd1) + raises(OSError, os.close, fd1) def test_opener_negative(self): import _io 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 @@ -93,8 +93,11 @@ if sys.platform == 'win32': dash = '_' + WIN32 = True else: dash = '' + WIN32 = False + def fclose(fp): try: @@ -610,13 +613,9 @@ 'PyObject_CallMethod', 'PyObject_CallFunctionObjArgs', 'PyObject_CallMethodObjArgs', '_PyObject_CallFunction_SizeT', '_PyObject_CallMethod_SizeT', - 'PyObject_GetBuffer', 'PyBuffer_Release', + 'PyObject_DelItemString', 'PyObject_GetBuffer', 'PyBuffer_Release', '_Py_setfilesystemdefaultencoding', - 'PyCObject_FromVoidPtr', 'PyCObject_FromVoidPtrAndDesc', 'PyCObject_AsVoidPtr', - 'PyCObject_GetDesc', 'PyCObject_Import', 'PyCObject_SetVoidPtr', - 'PyCObject_Type', '_Py_get_cobject_type', - 'PyCapsule_New', 'PyCapsule_IsValid', 'PyCapsule_GetPointer', 'PyCapsule_GetName', 'PyCapsule_GetDestructor', 'PyCapsule_GetContext', 'PyCapsule_SetPointer', 'PyCapsule_SetName', 'PyCapsule_SetDestructor', @@ -672,7 +671,7 @@ 'PyObject*', 'space.w_None', header=pypy_decl) register_global('_Py_TrueStruct', 'PyObject*', 'space.w_True', header=pypy_decl) -register_global('_Py_ZeroStruct', +register_global('_Py_FalseStruct', 'PyObject*', 'space.w_False', header=pypy_decl) register_global('_Py_NotImplementedStruct', 'PyObject*', 'space.w_NotImplemented', header=pypy_decl) @@ -716,8 +715,8 @@ "PyByteArray_Type": "space.w_bytearray", "PyMemoryView_Type": "space.w_memoryview", "PyBaseObject_Type": "space.w_object", - 'PyNone_Type': 'space.type(space.w_None)', - 'PyNotImplemented_Type': 'space.type(space.w_NotImplemented)', + '_PyNone_Type': 'space.type(space.w_None)', + '_PyNotImplemented_Type': 'space.type(space.w_NotImplemented)', 'PyCell_Type': 'space.gettypeobject(Cell.typedef)', 'PyModule_Type': 'space.gettypeobject(Module.typedef)', 'PyProperty_Type': 'space.gettypeobject(W_Property.typedef)', @@ -1121,9 +1120,6 @@ # of the cpyext module. The C functions are called with no wrapper, # but must not do anything like calling back PyType_Ready(). We # use them just to get a pointer to the PyTypeObjects defined in C. - get_cobject_type = rffi.llexternal('_%s_get_cobject_type' % prefix, - [], PyTypeObjectPtr, - compilation_info=eci, _nowrapper=True) get_capsule_type = rffi.llexternal('_%s_get_capsule_type' % prefix, [], PyTypeObjectPtr, compilation_info=eci, _nowrapper=True) @@ -1134,7 +1130,6 @@ def init_types(space): from pypy.module.cpyext.typeobject import py_type_ready from pypy.module.sys.interp_encoding import getfilesystemencoding - py_type_ready(space, get_cobject_type()) py_type_ready(space, get_capsule_type()) s = space.text_w(getfilesystemencoding(space)) setdefenc(rffi.str2charp(s, track_allocation=False)) # "leaks" @@ -1495,7 +1490,6 @@ source_dir / "pythonrun.c", source_dir / "sysmodule.c", source_dir / "complexobject.c", - source_dir / "cobject.c", source_dir / "structseq.c", source_dir / "capsule.c", source_dir / "pysignals.c", @@ -1549,7 +1543,6 @@ if sys.platform == 'win32': get_pythonapi_source = ''' - #include <windows.h> RPY_EXTERN HANDLE pypy_get_pythonapi_handle() { MEMORY_BASIC_INFORMATION mi; @@ -1563,6 +1556,9 @@ } ''' separate_module_sources.append(get_pythonapi_source) + kwds['post_include_bits'] = ['#include <windows.h>', + 'RPY_EXTERN HANDLE pypy_get_pythonapi_handle();', + ] eci = ExternalCompilationInfo( include_dirs=include_dirs, @@ -1673,7 +1669,11 @@ try: ll_libname = rffi.str2charp(path) try: - dll = rdynload.dlopen(ll_libname, space.sys.dlopenflags) + if WIN32: + # Allow other DLLs in the same directory with "path" + dll = rdynload.dlopenex(ll_libname) + else: + dll = rdynload.dlopen(ll_libname, space.sys.dlopenflags) finally: lltype.free(ll_libname, flavor='raw') except rdynload.DLOpenError as e: diff --git a/pypy/module/cpyext/eval.py b/pypy/module/cpyext/eval.py --- a/pypy/module/cpyext/eval.py +++ b/pypy/module/cpyext/eval.py @@ -9,6 +9,7 @@ from pypy.module.cpyext.pyobject import PyObject from pypy.module.cpyext.pyerrors import PyErr_SetFromErrno from pypy.module.cpyext.funcobject import PyCodeObject +from pypy.module.cpyext.frameobject import PyFrameObject from pypy.module.__builtin__ import compiling PyCompilerFlags = cpython_struct( @@ -58,6 +59,11 @@ return None return caller.get_w_globals() # borrowed ref +@cpython_api([], PyFrameObject, error=CANNOT_FAIL, result_borrowed=True) +def PyEval_GetFrame(space): + caller = space.getexecutioncontext().gettopframe_nohidden() + return caller # borrowed ref, may be null + @cpython_api([PyCodeObject, PyObject, PyObject], PyObject) def PyEval_EvalCode(space, w_code, w_globals, w_locals): """This is a simplified interface to PyEval_EvalCodeEx(), with just diff --git a/pypy/module/cpyext/include/Python.h b/pypy/module/cpyext/include/Python.h --- a/pypy/module/cpyext/include/Python.h +++ b/pypy/module/cpyext/include/Python.h @@ -123,7 +123,6 @@ #include "memoryobject.h" #include "eval.h" #include "pymem.h" -#include "pycobject.h" #include "pycapsule.h" #include "bytesobject.h" #include "sliceobject.h" diff --git a/pypy/module/cpyext/include/abstract.h b/pypy/module/cpyext/include/abstract.h --- a/pypy/module/cpyext/include/abstract.h +++ b/pypy/module/cpyext/include/abstract.h @@ -4,6 +4,15 @@ extern "C" { #endif + PyAPI_FUNC(int) PyObject_DelItemString(PyObject *o, char *key); + + /* + Remove the mapping for object, key, from the object *o. + Returns -1 on failure. This is equivalent to + the Python statement: del o[key]. + */ + + /* new buffer API */ #define PyObject_CheckBuffer(obj) \ @@ -27,6 +36,27 @@ /* Releases a Py_buffer obtained from getbuffer ParseTuple's s*. */ +/* Mapping protocol:*/ + + /* implemented as a macro: + + int PyMapping_DelItemString(PyObject *o, char *key); + + Remove the mapping for object, key, from the object *o. + Returns -1 on failure. This is equivalent to + the Python statement: del o[key]. + */ +#define PyMapping_DelItemString(O,K) PyObject_DelItemString((O),(K)) + + /* implemented as a macro: + + int PyMapping_DelItem(PyObject *o, PyObject *key); + + Remove the mapping for object, key, from the object *o. + Returns -1 on failure. This is equivalent to + the Python statement: del o[key]. + */ +#define PyMapping_DelItem(O,K) PyObject_DelItem((O),(K)) #ifdef __cplusplus } diff --git a/pypy/module/cpyext/include/boolobject.h b/pypy/module/cpyext/include/boolobject.h --- a/pypy/module/cpyext/include/boolobject.h +++ b/pypy/module/cpyext/include/boolobject.h @@ -1,5 +1,4 @@ - -/* Bool object interface */ +/* Boolean object interface */ #ifndef Py_BOOLOBJECT_H #define Py_BOOLOBJECT_H @@ -7,15 +6,19 @@ extern "C" { #endif -#define Py_False ((PyObject *) &_Py_ZeroStruct) +#define PyBool_Check(x) (Py_TYPE(x) == &PyBool_Type) + +/* Py_False and Py_True are the only two bools in existence. +Don't forget to apply Py_INCREF() when returning either!!! */ + +/* Use these macros */ +#define Py_False ((PyObject *) &_Py_FalseStruct) #define Py_True ((PyObject *) &_Py_TrueStruct) /* Macros for returning Py_True or Py_False, respectively */ #define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True #define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False -#define PyBool_Check(op) ((op)->ob_type == &PyBool_Type) - #ifdef __cplusplus } #endif diff --git a/pypy/module/cpyext/include/pycobject.h b/pypy/module/cpyext/include/pycobject.h deleted file mode 100644 --- a/pypy/module/cpyext/include/pycobject.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef Py_COBJECT_H -#define Py_COBJECT_H -#ifdef __cplusplus -extern "C" { -#endif - -PyAPI_DATA(PyTypeObject) PyCObject_Type; - -#define PyCObject_Check(op) ((op)->ob_type == &PyCObject_Type) - -/* Create a PyCObject from a pointer to a C object and an optional - destructor function. If the second argument is non-null, then it - will be called with the first argument if and when the PyCObject is - destroyed. - -*/ -PyAPI_FUNC(PyObject *) PyCObject_FromVoidPtr( - void *cobj, void (*destruct)(void*)); - - -/* Create a PyCObject from a pointer to a C object, a description object, - and an optional destructor function. If the third argument is non-null, - then it will be called with the first and second arguments if and when - the PyCObject is destroyed. -*/ -PyAPI_FUNC(PyObject *) PyCObject_FromVoidPtrAndDesc( - void *cobj, void *desc, void (*destruct)(void*,void*)); - -/* Retrieve a pointer to a C object from a PyCObject. */ -PyAPI_FUNC(void *) PyCObject_AsVoidPtr(PyObject *); - -/* Retrieve a pointer to a description object from a PyCObject. */ -PyAPI_FUNC(void *) PyCObject_GetDesc(PyObject *); - -/* Import a pointer to a C object from a module using a PyCObject. */ -PyAPI_FUNC(void *) PyCObject_Import(const char *module_name, const char *cobject_name); - -/* Modify a C object. Fails (==0) if object has a destructor. */ -PyAPI_FUNC(int) PyCObject_SetVoidPtr(PyObject *self, void *cobj); - - -#if (PY_VERSION_HEX >= 0x02060000 || defined(Py_BUILD_CORE)) -typedef struct { - PyObject_HEAD - void *cobject; - void *desc; - void (*destructor)(void *); -} PyCObject; -#endif - -PyAPI_FUNC(PyTypeObject *) _Py_get_cobject_type(void); - -#ifdef __cplusplus -} -#endif -#endif /* !Py_COBJECT_H */ diff --git a/pypy/module/cpyext/pyfile.py b/pypy/module/cpyext/pyfile.py --- a/pypy/module/cpyext/pyfile.py +++ b/pypy/module/cpyext/pyfile.py @@ -41,19 +41,6 @@ w_mode = space.newtext(rffi.charp2str(mode)) return space.call_method(space.builtin, 'open', w_filename, w_mode) -@cpython_api([FILEP, CONST_STRING, CONST_STRING, rffi.VOIDP], PyObject) -def PyFile_FromFile(space, fp, name, mode, close): - """Create a new PyFileObject from the already-open standard C file - pointer, fp. The function close will be called when the file should be - closed. Return NULL on failure.""" - raise NotImplementedError - -@cpython_api([PyObject, rffi.INT_real], lltype.Void) -def PyFile_SetBufSize(space, w_file, n): - """Available on systems with setvbuf() only. This should only be called - immediately after file object creation.""" - raise NotImplementedError - @cpython_api([CONST_STRING, PyObject], rffi.INT_real, error=-1) def PyFile_WriteString(space, s, w_p): """Write string s to file object p. Return 0 on success or -1 on @@ -75,9 +62,3 @@ w_str = space.repr(w_obj) space.call_method(w_p, "write", w_str) return 0 - -@cpython_api([PyObject], PyObject) -def PyFile_Name(space, w_p): - """Return the name of the file specified by p as a string object.""" - w_name = space.getattr(w_p, space.newtext("name")) - return w_name # borrowed ref, should be a W_StringObject from the file diff --git a/pypy/module/cpyext/src/abstract.c b/pypy/module/cpyext/src/abstract.c --- a/pypy/module/cpyext/src/abstract.c +++ b/pypy/module/cpyext/src/abstract.c @@ -23,6 +23,23 @@ /* Operations on any object */ int +PyObject_DelItemString(PyObject *o, char *key) +{ + PyObject *okey; + int ret; + + if (o == NULL || key == NULL) { + null_error(); + return -1; + } + okey = PyUnicode_FromString(key); + if (okey == NULL) + return -1; + ret = PyObject_DelItem(o, okey); + Py_DECREF(okey); + return ret; +} +int PyObject_CheckReadBuffer(PyObject *obj) { PyBufferProcs *pb = obj->ob_type->tp_as_buffer; @@ -96,6 +113,20 @@ return 0; } +/* Buffer C-API for Python 3.0 */ + +int +PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags) +{ + if (!PyObject_CheckBuffer(obj)) { + PyErr_Format(PyExc_TypeError, + "'%100s' does not have the buffer interface", + Py_TYPE(obj)->tp_name); + return -1; + } + return (*(obj->ob_type->tp_as_buffer->bf_getbuffer))(obj, view, flags); +} + void* PyBuffer_GetPointer(Py_buffer *view, Py_ssize_t *indices) { @@ -111,6 +142,7 @@ return (void*)pointer; } + void _Py_add_one_to_index_F(int nd, Py_ssize_t *index, const Py_ssize_t *shape) { @@ -253,19 +285,6 @@ -/* Buffer C-API for Python 3.0 */ - -int -PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags) -{ - if (!PyObject_CheckBuffer(obj)) { - PyErr_Format(PyExc_TypeError, - "'%100s' does not have the buffer interface", - Py_TYPE(obj)->tp_name); - return -1; - } - return (*(obj->ob_type->tp_as_buffer->bf_getbuffer))(obj, view, flags); -} void PyBuffer_Release(Py_buffer *view) @@ -427,6 +446,7 @@ return retval; } + static PyObject * objargs_mktuple(va_list va) { diff --git a/pypy/module/cpyext/src/cobject.c b/pypy/module/cpyext/src/cobject.c deleted file mode 100644 --- a/pypy/module/cpyext/src/cobject.c +++ /dev/null @@ -1,162 +0,0 @@ - -/* Wrap void* pointers to be passed between C modules */ - -#include "Python.h" - - -/* Declarations for objects of type PyCObject */ - -typedef void (*destructor1)(void *); -typedef void (*destructor2)(void *, void*); - -PyObject * -PyCObject_FromVoidPtr(void *cobj, void (*destr)(void *)) -{ - PyCObject *self; - - self = PyObject_NEW(PyCObject, &PyCObject_Type); - if (self == NULL) - return NULL; - self->cobject=cobj; - self->destructor=destr; - self->desc=NULL; - - return (PyObject *)self; -} - -PyObject * -PyCObject_FromVoidPtrAndDesc(void *cobj, void *desc, - void (*destr)(void *, void *)) -{ - PyCObject *self; - - if (!desc) { - PyErr_SetString(PyExc_TypeError, - "PyCObject_FromVoidPtrAndDesc called with null" - " description"); - return NULL; - } - self = PyObject_NEW(PyCObject, &PyCObject_Type); - if (self == NULL) - return NULL; - self->cobject = cobj; - self->destructor = (destructor1)destr; - self->desc = desc; - - return (PyObject *)self; -} - -void * -PyCObject_AsVoidPtr(PyObject *self) -{ - if (self) { - if (PyCapsule_CheckExact(self)) { - const char *name = PyCapsule_GetName(self); - return (void *)PyCapsule_GetPointer(self, name); - } - if (self->ob_type == &PyCObject_Type) - return ((PyCObject *)self)->cobject; - PyErr_SetString(PyExc_TypeError, - "PyCObject_AsVoidPtr with non-C-object"); - } - if (!PyErr_Occurred()) - PyErr_SetString(PyExc_TypeError, - "PyCObject_AsVoidPtr called with null pointer"); - return NULL; -} - -void * -PyCObject_GetDesc(PyObject *self) -{ - if (self) { - if (self->ob_type == &PyCObject_Type) - return ((PyCObject *)self)->desc; - PyErr_SetString(PyExc_TypeError, - "PyCObject_GetDesc with non-C-object"); - } - if (!PyErr_Occurred()) - PyErr_SetString(PyExc_TypeError, - "PyCObject_GetDesc called with null pointer"); - return NULL; -} - -void * -PyCObject_Import(const char *module_name, const char *name) -{ - PyObject *m, *c; - void *r = NULL; - - if ((m = PyImport_ImportModule(module_name))) { - if ((c = PyObject_GetAttrString(m,name))) { - r = PyCObject_AsVoidPtr(c); - Py_DECREF(c); - } - Py_DECREF(m); - } - return r; -} - -int -PyCObject_SetVoidPtr(PyObject *self, void *cobj) -{ - PyCObject* cself = (PyCObject*)self; - if (cself == NULL || !PyCObject_Check(cself) || - cself->destructor != NULL) { - PyErr_SetString(PyExc_TypeError, - "Invalid call to PyCObject_SetVoidPtr"); - return 0; - } - cself->cobject = cobj; - return 1; -} - -static void -PyCObject_dealloc(PyCObject *self) -{ - if (self->destructor) { - if(self->desc) - ((destructor2)(self->destructor))(self->cobject, self->desc); - else - (self->destructor)(self->cobject); - } - PyObject_DEL(self); -} - - -PyDoc_STRVAR(PyCObject_Type__doc__, -"C objects to be exported from one extension module to another\n\ -\n\ -C objects are used for communication between extension modules. They\n\ -provide a way for an extension module to export a C interface to other\n\ -extension modules, so that extension modules can use the Python import\n\ -mechanism to link to one another."); - -PyTypeObject PyCObject_Type = { - PyVarObject_HEAD_INIT(NULL, 0) - "PyCObject", /*tp_name*/ - sizeof(PyCObject), /*tp_basicsize*/ - 0, /*tp_itemsize*/ - /* methods */ - (destructor)PyCObject_dealloc, /*tp_dealloc*/ - 0, /*tp_print*/ - 0, /*tp_getattr*/ - 0, /*tp_setattr*/ - 0, /*tp_compare*/ - 0, /*tp_repr*/ - 0, /*tp_as_number*/ - 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - 0, /*tp_getattro*/ - 0, /*tp_setattro*/ - 0, /*tp_as_buffer*/ - 0, /*tp_flags*/ - PyCObject_Type__doc__ /*tp_doc*/ -}; - -PyTypeObject *_Py_get_cobject_type(void) -{ - return &PyCObject_Type; -} diff --git a/pypy/module/cpyext/stubs-find-implemented.py b/pypy/module/cpyext/stubs-find-implemented.py new file mode 100644 --- /dev/null +++ b/pypy/module/cpyext/stubs-find-implemented.py @@ -0,0 +1,21 @@ +import re +import os + + +for line in open('stubs.py'): + if not line.strip(): + continue + if line.startswith(' '): + continue + if line.startswith('#'): + continue + if line.startswith('@cpython_api'): + continue + if line.endswith(' = rffi.VOIDP\n'): + continue + + #print line.rstrip() + m = re.match(r"def ([\w\d_]+)[(]", line) + assert m, line + funcname = m.group(1) + os.system('grep -w %s [a-r]*.py s[a-s]*.py str*.py stubsa*.py sy*.py [t-z]*.py' % funcname) 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 @@ -1,29 +1,10 @@ -from pypy.module.cpyext.api import ( - cpython_api, PyObject, PyObjectP, CANNOT_FAIL - ) -from pypy.module.cpyext.complexobject import Py_complex_ptr as Py_complex -from rpython.rtyper.lltypesystem import rffi, lltype +#----this file is not imported, only here for reference---- -CWCHARPP = lltype.Ptr(lltype.Array(rffi.CWCHARP, hints={'nolength': True})) - -# we don't really care -PyTypeObjectPtr = rffi.VOIDP -Py_ssize_t = rffi.SSIZE_T -PyModuleDef = rffi.VOIDP -PyMethodDef = rffi.VOIDP -PyGetSetDef = rffi.VOIDP -PyMemberDef = rffi.VOIDP -va_list = rffi.VOIDP -wrapperbase = rffi.VOIDP -FILE = rffi.VOIDP -PyFrameObject = rffi.VOIDP -_inittab = rffi.VOIDP -PyThreadState = rffi.VOIDP -PyInterpreterState = rffi.VOIDP -Py_UNICODE = lltype.UniChar -PyCompilerFlags = rffi.VOIDP -struct_node = rffi.VOIDP -Py_tracefunc = rffi.VOIDP +#from pypy.module.cpyext.api import ( +# cpython_api, PyObject, PyObjectP, CANNOT_FAIL +# ) +#from pypy.module.cpyext.complexobject import Py_complex_ptr as Py_complex +#from rpython.rtyper.lltypesystem import rffi, lltype @cpython_api([rffi.CCHARP], Py_ssize_t, error=-1) @@ -228,39 +209,6 @@ this method returns zero and sets errno to EDOM.""" raise NotImplementedError -@cpython_api([rffi.DOUBLE, lltype.Char, rffi.INT_real, rffi.INT_real, rffi.INTP], rffi.CCHARP) -def PyOS_double_to_string(space, val, format_code, precision, flags, ptype): - """Convert a double val to a string using supplied - format_code, precision, and flags. - - format_code must be one of 'e', 'E', 'f', 'F', - 'g', 'G' or 'r'. For 'r', the supplied precision - must be 0 and is ignored. The 'r' format code specifies the - standard repr() format. - - flags can be zero or more of the values Py_DTSF_SIGN, - Py_DTSF_ADD_DOT_0, or Py_DTSF_ALT, or-ed together: - - Py_DTSF_SIGN means to always precede the returned string with a sign - character, even if val is non-negative. - - Py_DTSF_ADD_DOT_0 means to ensure that the returned string will not look - like an integer. - - Py_DTSF_ALT means to apply "alternate" formatting rules. See the - documentation for the PyOS_snprintf() '#' specifier for - details. - - If ptype is non-NULL, then the value it points to will be set to one of - Py_DTST_FINITE, Py_DTST_INFINITE, or Py_DTST_NAN, signifying that - val is a finite number, an infinite number, or not a number, respectively. - - The return value is a pointer to buffer with the converted string or - NULL if the conversion failed. The caller is responsible for freeing the - returned string by calling PyMem_Free(). - """ - raise NotImplementedError - @cpython_api([rffi.CCHARP, rffi.CCHARP], rffi.CCHARP) def PyOS_stricmp(space, s1, s2): """Case insensitive comparison of strings. The function works almost @@ -275,24 +223,6 @@ """ raise NotImplementedError -@cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyTZInfo_Check(space, ob): - """Return true if ob is of type PyDateTime_TZInfoType or a subtype of - PyDateTime_TZInfoType. ob must not be NULL. - """ - raise NotImplementedError - -@cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL) -def PyTZInfo_CheckExact(space, ob): - """Return true if ob is of type PyDateTime_TZInfoType. ob must not be - NULL. - """ - raise NotImplementedError - -@cpython_api([PyTypeObjectPtr, PyGetSetDef], PyObject) -def PyDescr_NewGetSet(space, type, getset): - raise NotImplementedError - @cpython_api([PyTypeObjectPtr, PyMemberDef], PyObject) def PyDescr_NewMember(space, type, meth): raise NotImplementedError @@ -483,31 +413,6 @@ 0 on success, -1 on failure.""" raise NotImplementedError -@cpython_api([PyObject], rffi.INT_real, error=-1) -def Py_ReprEnter(space, object): - """Called at the beginning of the tp_repr implementation to - detect cycles. - - If the object has already been processed, the function returns a - positive integer. In that case the tp_repr implementation - should return a string object indicating a cycle. As examples, - dict objects return {...} and list objects - return [...]. - - The function will return a negative integer if the recursion limit - is reached. In that case the tp_repr implementation should - typically return NULL. - - Otherwise, the function returns zero and the tp_repr - implementation can continue normally.""" - raise NotImplementedError - -@cpython_api([PyObject], lltype.Void) -def Py_ReprLeave(space, object): - """Ends a Py_ReprEnter(). Must be called once for each - invocation of Py_ReprEnter() that returns zero.""" - raise NotImplementedError - @cpython_api([rffi.INT_real, rffi.CCHARP, rffi.CCHARP, rffi.INT_real, rffi.CCHARP, rffi.CCHARP, rffi.CCHARP, rffi.INT_real], PyObject) def PyFile_FromFd(space, fd, name, mode, buffering, encoding, errors, newline, closefd): """Create a Python file object from the file descriptor of an already @@ -1295,39 +1200,6 @@ """ raise NotImplementedError -@cpython_api([PyObject], rffi.VOIDP) -def PyModule_GetState(space, module): - """Return the "state" of the module, that is, a pointer to the block of memory - allocated at module creation time, or NULL. See - PyModuleDef.m_size.""" - raise NotImplementedError - -@cpython_api([PyObject], PyModuleDef) -def PyModule_GetDef(space, module): - """Return a pointer to the PyModuleDef struct from which the module was - created, or NULL if the module wasn't created with - PyModule_Create().""" - raise NotImplementedError - - -@cpython_api([PyModuleDef], PyObject) -def PyModule_Create(space, module): - """Create a new module object, given the definition in module. This behaves - like PyModule_Create2() with module_api_version set to - PYTHON_API_VERSION.""" - raise NotImplementedError - - -@cpython_api([PyModuleDef, rffi.INT_real], PyObject) -def PyModule_Create2(space, module, module_api_version): - """Create a new module object, given the definition in module, assuming the - API version module_api_version. If that version does not match the version - of the running interpreter, a RuntimeWarning is emitted. - - Most uses of this function should be using PyModule_Create() - instead; only use this if you are sure you need it.""" - raise NotImplementedError - @cpython_api([PyObject, rffi.INT_real], PyObject) def PyNumber_ToBase(space, n, base): """Returns the integer n converted to base base as a string. The base @@ -1337,23 +1209,6 @@ PyNumber_Index() first.""" raise NotImplementedError -@cpython_api([PyObject], PyObject) -def PyObject_Bytes(space, o): - """ - Compute a bytes representation of object o. NULL is returned on - failure and a bytes object on success. This is equivalent to the Python - expression bytes(o), when o is not an integer. Unlike bytes(o), - a TypeError is raised when o is an integer instead of a zero-initialized - bytes object.""" - raise NotImplementedError - -@cpython_api([], PyFrameObject) -def PyEval_GetFrame(space): - """Return the current thread state's frame, which is NULL if no frame is - currently executing.""" - raise NotImplementedError - borrow_from() - @cpython_api([PyFrameObject], rffi.INT_real, error=-1) def PyFrame_GetLineNumber(space, frame): """Return the line number that frame is currently executing.""" diff --git a/pypy/module/cpyext/test/test_eval.py b/pypy/module/cpyext/test/test_eval.py --- a/pypy/module/cpyext/test/test_eval.py +++ b/pypy/module/cpyext/test/test_eval.py @@ -510,3 +510,15 @@ assert run_async(list1()) == ([], [0, 1, 2]) assert run_async(list2()) == ([], [0, 1, 2]) """ + + def test_getframe(self): + import sys + module = self.import_extension('foo', [ + ("getframe1", "METH_NOARGS", + """ + PyFrameObject *x = PyEval_GetFrame(); + Py_INCREF(x); + return (PyObject *)x; + """),], prologue="#include <frameobject.h>\n") + res = module.getframe1() + assert res is sys._getframe(0) diff --git a/pypy/module/cpyext/test/test_pycobject.py b/pypy/module/cpyext/test/test_pycobject.py deleted file mode 100644 --- a/pypy/module/cpyext/test/test_pycobject.py +++ /dev/null @@ -1,30 +0,0 @@ -import py -from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase - -class AppTestStringObject(AppTestCpythonExtensionBase): - def test_pycobject_import(self): - module = self.import_extension('foo', [ - ("set_ptr", "METH_O", - """ - PyObject *pointer, *module; - void *ptr = PyLong_AsVoidPtr(args); - if (PyErr_Occurred()) return NULL; - pointer = PyCObject_FromVoidPtr(ptr, NULL); - if (PyErr_Occurred()) return NULL; - module = PyImport_ImportModule("foo"); - PyModule_AddObject(module, "_ptr", pointer); - Py_DECREF(module); - if (PyErr_Occurred()) return NULL; - Py_RETURN_NONE; - """), - ("get_ptr", "METH_NOARGS", - """ - void *ptr = PyCObject_Import("foo", "_ptr"); - if (PyErr_Occurred()) return NULL; - return PyLong_FromVoidPtr(ptr); - """)]) - module.set_ptr(1234) - assert "PyCObject object" in str(module._ptr) - import gc; gc.collect() - assert module.get_ptr() == 1234 - del module._ptr diff --git a/pypy/module/sys/initpath.py b/pypy/module/sys/initpath.py --- a/pypy/module/sys/initpath.py +++ b/pypy/module/sys/initpath.py @@ -231,7 +231,9 @@ if os.name == 'nt': _source_code = r""" +#ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0501 +#endif #include <windows.h> #include <stdio.h> diff --git a/rpython/rlib/jit.py b/rpython/rlib/jit.py --- a/rpython/rlib/jit.py +++ b/rpython/rlib/jit.py @@ -151,7 +151,7 @@ if getattr(func, '_elidable_function_', False): raise TypeError("it does not make sense for %s to be both elidable and unroll_safe" % func) if not getattr(func, '_jit_look_inside_', True): - raise TypeError("it does not make sense for %s to be both elidable and dont_look_inside" % func) + raise TypeError("it does not make sense for %s to be both unroll_safe and dont_look_inside" % func) func._jit_unroll_safe_ = True return func diff --git a/rpython/rlib/rdynload.py b/rpython/rlib/rdynload.py --- a/rpython/rlib/rdynload.py +++ b/rpython/rlib/rdynload.py @@ -233,6 +233,15 @@ raise DLOpenError(ustr.encode('utf-8')) return res + def dlopenex(name): + res = rwin32.LoadLibraryExA(name) + if not res: + err = rwin32.GetLastError_saved() + ustr = rwin32.FormatErrorW(err) + # DLOpenError unicode msg breaks translation of cpyext create_extension_module + raise DLOpenError(ustr.encode('utf-8')) + return res + def dlclose(handle): res = rwin32.FreeLibrary(handle) if res: diff --git a/rpython/rlib/rmmap.py b/rpython/rlib/rmmap.py --- a/rpython/rlib/rmmap.py +++ b/rpython/rlib/rmmap.py @@ -835,7 +835,7 @@ # assume -1 and 0 both mean invalid file descriptor # to 'anonymously' map memory. if fileno != -1 and fileno != 0: - fh = rwin32.get_osfhandle(fileno) + fh = rffi.cast(HANDLE, rwin32.get_osfhandle(fileno)) # Win9x appears to need us seeked to zero # SEEK_SET = 0 # libc._lseek(fileno, 0, SEEK_SET) diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py --- a/rpython/rlib/rposix.py +++ b/rpython/rlib/rposix.py @@ -137,7 +137,10 @@ RPY_EXTERN void exit_suppress_iph(void* handle) {}; #endif ''',] - post_include_bits=['RPY_EXTERN int _PyVerify_fd(int);'] + post_include_bits=['RPY_EXTERN int _PyVerify_fd(int);', + 'RPY_EXTERN void* enter_suppress_iph();', + 'RPY_EXTERN void exit_suppress_iph(void* handle);', + ] else: separate_module_sources = [] post_include_bits = [] @@ -235,7 +238,8 @@ rthread.tlfield_rpy_errno.setraw(_get_errno()) # ^^^ keep fork() up-to-date too, below if _WIN32: - includes = ['io.h', 'sys/utime.h', 'sys/types.h', 'process.h', 'time.h'] + includes = ['io.h', 'sys/utime.h', 'sys/types.h', 'process.h', 'time.h', + 'direct.h'] libraries = [] else: if sys.platform.startswith(('darwin', 'netbsd', 'openbsd')): @@ -730,16 +734,21 @@ length = rwin32.MAX_PATH + 1 traits = _preferred_traits(path) win32traits = make_win32_traits(traits) - with traits.scoped_alloc_buffer(length) as buf: - res = win32traits.GetFullPathName( - traits.as_str0(path), rffi.cast(rwin32.DWORD, length), - buf.raw, lltype.nullptr(win32traits.LPSTRP.TO)) - if res == 0: - raise rwin32.lastSavedWindowsError("_getfullpathname failed") - result = buf.str(intmask(res)) - assert result is not None - result = rstring.assert_str0(result) - return result + while True: # should run the loop body maximum twice + with traits.scoped_alloc_buffer(length) as buf: + res = win32traits.GetFullPathName( + traits.as_str0(path), rffi.cast(rwin32.DWORD, length), + buf.raw, lltype.nullptr(win32traits.LPSTRP.TO)) + res = intmask(res) + if res == 0: + raise rwin32.lastSavedWindowsError("_getfullpathname failed") + if res >= length: + length = res + 1 + continue + result = buf.str(res) + assert result is not None + result = rstring.assert_str0(result) + return result c_getcwd = external(UNDERSCORE_ON_WIN32 + 'getcwd', [rffi.CCHARP, rffi.SIZE_T], rffi.CCHARP, diff --git a/rpython/rlib/runicode.py b/rpython/rlib/runicode.py --- a/rpython/rlib/runicode.py +++ b/rpython/rlib/runicode.py @@ -1777,8 +1777,6 @@ "truncated input", s, pos, size) result.append(res) - if pos > size - unicode_bytes: - break continue t = r_uint(0) h = 0 diff --git a/rpython/rlib/rwin32.py b/rpython/rlib/rwin32.py --- a/rpython/rlib/rwin32.py +++ b/rpython/rlib/rwin32.py @@ -20,7 +20,7 @@ if WIN32: eci = ExternalCompilationInfo( - includes = ['windows.h', 'stdio.h', 'stdlib.h'], + includes = ['windows.h', 'stdio.h', 'stdlib.h', 'io.h'], libraries = ['kernel32'], ) else: @@ -113,6 +113,7 @@ MB_ERR_INVALID_CHARS ERROR_NO_UNICODE_TRANSLATION WC_NO_BEST_FIT_CHARS STD_INPUT_HANDLE STD_OUTPUT_HANDLE STD_ERROR_HANDLE HANDLE_FLAG_INHERIT FILE_TYPE_CHAR + LOAD_WITH_ALTERED_SEARCH_PATH """ from rpython.translator.platform import host_factory static_platform = host_factory() @@ -195,12 +196,28 @@ GetModuleHandle = winexternal('GetModuleHandleA', [rffi.CCHARP], HMODULE) LoadLibrary = winexternal('LoadLibraryA', [rffi.CCHARP], HMODULE, save_err=rffi.RFFI_SAVE_LASTERROR) + def wrap_loadlibraryex(func): + def loadlibrary(name, flags=LOAD_WITH_ALTERED_SEARCH_PATH): + # Requires a full path name with '/' -> '\\' + return func(name, NULL_HANDLE, flags) + return loadlibrary + + _LoadLibraryExA = winexternal('LoadLibraryExA', + [rffi.CCHARP, HANDLE, DWORD], HMODULE, + save_err=rffi.RFFI_SAVE_LASTERROR) + LoadLibraryExA = wrap_loadlibraryex(_LoadLibraryExA) + LoadLibraryW = winexternal('LoadLibraryW', [rffi.CWCHARP], HMODULE, + save_err=rffi.RFFI_SAVE_LASTERROR) + _LoadLibraryExW = winexternal('LoadLibraryExW', + [rffi.CWCHARP, HANDLE, DWORD], HMODULE, + save_err=rffi.RFFI_SAVE_LASTERROR) + LoadLibraryExW = wrap_loadlibraryex(_LoadLibraryExW) GetProcAddress = winexternal('GetProcAddress', [HMODULE, rffi.CCHARP], rffi.VOIDP) FreeLibrary = winexternal('FreeLibrary', [HMODULE], BOOL, releasegil=False) - LocalFree = winexternal('LocalFree', [HLOCAL], DWORD) + LocalFree = winexternal('LocalFree', [HLOCAL], HLOCAL) CloseHandle = winexternal('CloseHandle', [HANDLE], BOOL, releasegil=False, save_err=rffi.RFFI_SAVE_LASTERROR) CloseHandle_no_err = winexternal('CloseHandle', [HANDLE], BOOL, @@ -215,12 +232,12 @@ [DWORD, rffi.VOIDP, DWORD, DWORD, rffi.CWCHARP, DWORD, rffi.VOIDP], DWORD) - _get_osfhandle = rffi.llexternal('_get_osfhandle', [rffi.INT], HANDLE) + _get_osfhandle = rffi.llexternal('_get_osfhandle', [rffi.INT], rffi.INTP) def get_osfhandle(fd): from rpython.rlib.rposix import FdValidator with FdValidator(fd): - handle = _get_osfhandle(fd) + handle = rffi.cast(HANDLE, _get_osfhandle(fd)) if handle == INVALID_HANDLE_VALUE: raise WindowsError(ERROR_INVALID_HANDLE, "Invalid file handle") return handle diff --git a/rpython/rlib/test/loadtest/loadtest0.dll b/rpython/rlib/test/loadtest/loadtest0.dll new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..9bdcc33a1902f8e989d349c49c2cc08e633aa32b GIT binary patch [cut] diff --git a/rpython/rlib/test/loadtest/loadtest1.dll b/rpython/rlib/test/loadtest/loadtest1.dll new file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..cb83854875c876717371bdf90488eed9c6571f03 GIT binary patch [cut] diff --git a/rpython/rlib/test/test_rposix.py b/rpython/rlib/test/test_rposix.py --- a/rpython/rlib/test/test_rposix.py +++ b/rpython/rlib/test/test_rposix.py @@ -83,6 +83,14 @@ # the most intriguing failure of ntpath.py should not repeat, here: assert not data.endswith(stuff) + @win_only + def test__getfullpathname_long(self): + stuff = "C:" + "\\abcd" * 100 + py.test.raises(WindowsError, rposix.getfullpathname, stuff) + ustuff = u"C:" + u"\\abcd" * 100 + res = rposix.getfullpathname(ustuff) + assert res == ustuff + def test_getcwd(self): assert rposix.getcwd() == os.getcwd() diff --git a/rpython/rlib/test/test_rwin32.py b/rpython/rlib/test/test_rwin32.py --- a/rpython/rlib/test/test_rwin32.py +++ b/rpython/rlib/test/test_rwin32.py @@ -6,6 +6,44 @@ from rpython.rlib import rwin32 from rpython.tool.udir import udir +loadtest_dir = os.path.dirname(__file__) + '/loadtest' +test1 = os.path.abspath(loadtest_dir + '/loadtest1.dll') +test0 = os.path.abspath(loadtest_dir + '/loadtest0.dll') + +if not os.path.exists(test1) or not os.path.exists(test0): + # This is how the files, which are checked into the repo, were created + from rpython.translator.tool.cbuild import ExternalCompilationInfo + from rpython.translator.platform import platform + from rpython.translator import cdir + if not os.path.exists(loadtest_dir): + os.mkdir(loadtest_dir) + c_file = udir.ensure("test_rwin32", dir=1).join("test0.c") + c_file.write(py.code.Source(''' + #include "src/precommondefs.h" + RPY_EXPORTED + int internal_sum(int a, int b) { + return a + b; + } + ''')) + eci = ExternalCompilationInfo(include_dirs=[cdir]) + lib_name = str(platform.compile([c_file], eci, test0[:-4], + standalone=False)) + assert os.path.abspath(lib_name) == os.path.abspath(test0) + + c_file = udir.ensure("test_rwin32", dir=1).join("test1.c") + c_file.write(py.code.Source(''' + #include "src/precommondefs.h" + int internal_sum(int a, int b); + RPY_EXPORTED + int sum(int a, int b) { + return internal_sum(a, b); + } + ''')) + eci = ExternalCompilationInfo(include_dirs=[cdir], + libraries=[loadtest_dir + '/loadtest0']) + lib_name = str(platform.compile([c_file], eci, test1[:-4], + standalone=False, )) + assert os.path.abspath(lib_name) == os.path.abspath(test1) def test_get_osfhandle(): fid = open(str(udir.join('validate_test.txt')), 'w') @@ -28,13 +66,13 @@ "import time;" "time.sleep(10)", ], - ) + ) print proc.pid handle = rwin32.OpenProcess(rwin32.PROCESS_ALL_ACCESS, False, proc.pid) assert rwin32.TerminateProcess(handle, signal.SIGTERM) == 1 rwin32.CloseHandle(handle) assert proc.wait() == signal.SIGTERM - + @py.test.mark.dont_track_allocations('putenv intentionally keeps strings alive') def test_wenviron(): name, value = u'PYPY_TEST_日本', u'foobar日本' @@ -55,3 +93,48 @@ msg = rwin32.FormatErrorW(34) assert type(msg) is unicode assert u'%2' in msg + +def test_loadlibraryA(): + # test0 can be loaded alone, but test1 requires the modified search path + hdll = rwin32.LoadLibrary(test0) + assert hdll + faddr = rwin32.GetProcAddress(hdll, 'internal_sum') + assert faddr + assert rwin32.FreeLibrary(hdll) + + hdll = rwin32.LoadLibrary(test1) + assert not hdll + + assert os.path.exists(test1) + + hdll = rwin32.LoadLibraryExA(test1) + assert hdll + faddr = rwin32.GetProcAddress(hdll, 'sum') + assert faddr + assert rwin32.FreeLibrary(hdll) + +def test_loadlibraryW(): + # test0 can be loaded alone, but test1 requires the modified search path + hdll = rwin32.LoadLibraryW(unicode(test0)) + assert hdll + faddr = rwin32.GetProcAddress(hdll, 'internal_sum') + assert faddr + assert rwin32.FreeLibrary(hdll) + + hdll = rwin32.LoadLibraryW(unicode(test1)) + assert not hdll + + assert os.path.exists(unicode(test1)) + + hdll = rwin32.LoadLibraryExW(unicode(test1)) + assert hdll + faddr = rwin32.GetProcAddress(hdll, 'sum') + assert faddr + assert rwin32.FreeLibrary(hdll) + +def test_loadlibrary_unicode(): + import shutil + test0u = unicode(udir.join(u'load\u03betest.dll')) + shutil.copyfile(test0, test0u) + hdll = rwin32.LoadLibraryW(test0u) + assert hdll _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit