[pypy-commit] pypy py3.5: hg merge default

arigo pypy.commits at gmail.com
Mon Oct 8 14:33:43 EDT 2018


Author: Armin Rigo <arigo at tunes.org>
Branch: py3.5
Changeset: r95194:248ed5fa4ded
Date: 2018-10-08 20:30 +0200
http://bitbucket.org/pypy/pypy/changeset/248ed5fa4ded/

Log:	hg merge default

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
@@ -761,6 +761,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/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,7 +613,7 @@
     'PyObject_CallMethod', 'PyObject_CallFunctionObjArgs', 'PyObject_CallMethodObjArgs',
     '_PyObject_CallFunction_SizeT', '_PyObject_CallMethod_SizeT',
 
-    'PyObject_GetBuffer', 'PyBuffer_Release',
+    'PyObject_DelItemString', 'PyObject_GetBuffer', 'PyBuffer_Release',
     '_Py_setfilesystemdefaultencoding',
 
     'PyCapsule_New', 'PyCapsule_IsValid', 'PyCapsule_GetPointer',
@@ -1664,7 +1667,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
 
+ at 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/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/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/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
 
- at 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
 
- at 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
-
- at 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
-
- at 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
 
- at 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
-
- at 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
 
- at 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
-
- at 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
-
-
- at 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
-
-
- at 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
 
- at 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
-
- at 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/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/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -730,16 +730,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
@@ -1775,8 +1775,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
@@ -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,6 +196,22 @@
     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, handle=None, flags=LOAD_WITH_ALTERED_SEARCH_PATH):
+            # Requires a full path name with '/' -> '\\'
+            return func(name, 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)
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


More information about the pypy-commit mailing list