Author: Matti Picus <matti.pi...@gmail.com> Branch: py3.6 Changeset: r95329:18106031c176 Date: 2018-11-17 23:33 -0800 http://bitbucket.org/pypy/pypy/changeset/18106031c176/
Log: merge py3.5 into branch diff too long, truncating to 2000 out of 2161 lines diff --git a/lib-python/3/distutils/sysconfig_pypy.py b/lib-python/3/distutils/sysconfig_pypy.py --- a/lib-python/3/distutils/sysconfig_pypy.py +++ b/lib-python/3/distutils/sysconfig_pypy.py @@ -8,11 +8,9 @@ available. """ -__revision__ = "$Id: sysconfig.py 85358 2010-10-10 09:54:59Z antoine.pitrou $" - import sys import os -import imp +import imp, _imp from distutils.errors import DistutilsPlatformError @@ -71,9 +69,17 @@ def _init_nt(): """Initialize the module as appropriate for NT""" g = {} + # set basic install directories + g['LIBDEST'] = get_python_lib(plat_specific=0, standard_lib=1) + g['BINLIBDEST'] = get_python_lib(plat_specific=1, standard_lib=1) + + # XXX hmmm.. a normal install puts include files here + g['INCLUDEPY'] = get_python_inc(plat_specific=0) + + g['EXT_SUFFIX'] = _imp.extension_suffixes()[0] g['EXE'] = ".exe" - g['SO'] = ".pyd" - g['SOABI'] = g['SO'].rsplit('.')[0] # xxx? + g['VERSION'] = get_python_version().replace(".", "") + g['BINDIR'] = os.path.dirname(os.path.abspath(sys.executable)) global _config_vars _config_vars = g 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 @@ -190,7 +190,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/lib_pypy/pyrepl/unix_console.py b/lib_pypy/pyrepl/unix_console.py --- a/lib_pypy/pyrepl/unix_console.py +++ b/lib_pypy/pyrepl/unix_console.py @@ -27,6 +27,12 @@ from .console import Console, Event from .unix_eventqueue import EventQueue from .trace import trace +try: + from __pypy__ import pyos_inputhook +except ImportError: + def pyos_inputhook(): + pass + class InvalidTerminal(RuntimeError): pass @@ -76,8 +82,8 @@ pass def register(self, fd, flag): self.fd = fd - def poll(self, timeout=None): - r,w,e = select.select([self.fd],[],[],timeout) + def poll(self): # note: a 'timeout' argument would be *milliseconds* + r,w,e = select.select([self.fd],[],[]) return r POLLIN = getattr(select, "POLLIN", None) @@ -407,6 +413,7 @@ def get_event(self, block=1): while self.event_queue.empty(): while 1: # All hail Unix! + pyos_inputhook() try: self.push_char(os.read(self.input_fd, 1)) except (IOError, OSError) as err: diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -42,3 +42,16 @@ .. branch: py3.6-wordcode implement new wordcode instruction encoding on the 3.6 branch + +.. branch: socket_default_timeout_blockingness + +Backport CPython fix for possible shell injection issue in `distutils.spawn`, +https://bugs.python.org/issue34540 + +.. branch: cffi_dlopen_unicode + +Enable use of unicode file names in `dlopen` + +.. branch: rlock-in-rpython + +Backport CPython fix for `thread.RLock` diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py --- a/pypy/module/__pypy__/__init__.py +++ b/pypy/module/__pypy__/__init__.py @@ -110,6 +110,7 @@ 'stack_almost_full' : 'interp_magic.stack_almost_full', 'fsencode' : 'interp_magic.fsencode', 'fsdecode' : 'interp_magic.fsdecode', + 'pyos_inputhook' : 'interp_magic.pyos_inputhook', } submodules = { diff --git a/pypy/module/__pypy__/interp_magic.py b/pypy/module/__pypy__/interp_magic.py --- a/pypy/module/__pypy__/interp_magic.py +++ b/pypy/module/__pypy__/interp_magic.py @@ -209,3 +209,13 @@ def revdb_stop(space): from pypy.interpreter.reverse_debugging import stop_point stop_point() + +def pyos_inputhook(space): + """Call PyOS_InputHook() from the CPython C API.""" + if not space.config.objspace.usemodules.cpyext: + return + w_modules = space.sys.get('modules') + if space.finditem_str(w_modules, 'cpyext') is None: + return # cpyext not imported yet, ignore + from pypy.module.cpyext.api import invoke_pyos_inputhook + invoke_pyos_inputhook(space) 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/cdlopen.py b/pypy/module/_cffi_backend/cdlopen.py --- a/pypy/module/_cffi_backend/cdlopen.py +++ b/pypy/module/_cffi_backend/cdlopen.py @@ -1,31 +1,24 @@ from rpython.rtyper.lltypesystem import lltype, llmemory, rffi from rpython.rlib.objectmodel import specialize, we_are_translated -from rpython.rlib.rdynload import DLLHANDLE, dlopen, dlsym, dlclose, DLOpenError +from rpython.rlib.rdynload import DLLHANDLE, dlsym, dlclose from pypy.interpreter.error import oefmt -from pypy.module._rawffi.interp_rawffi import wrap_dlopenerror from pypy.module._cffi_backend.parse_c_type import ( _CFFI_OPCODE_T, GLOBAL_S, CDL_INTCONST_S, STRUCT_UNION_S, FIELD_S, ENUM_S, TYPENAME_S, ll_set_cdl_realize_global_int) from pypy.module._cffi_backend.realize_c_type import getop from pypy.module._cffi_backend.lib_obj import W_LibObject -from pypy.module._cffi_backend import cffi_opcode, cffi1_module - +from pypy.module._cffi_backend import cffi_opcode, cffi1_module, misc class W_DlOpenLibObject(W_LibObject): - def __init__(self, ffi, filename, flags): - with rffi.scoped_str2charp(filename) as ll_libname: - if filename is None: - filename = "<None>" - try: - handle = dlopen(ll_libname, flags) - except DLOpenError as e: - raise wrap_dlopenerror(ffi.space, e, filename) - W_LibObject.__init__(self, ffi, filename) + def __init__(self, ffi, w_filename, flags): + space = ffi.space + fname, handle = misc.dlopen_w(space, w_filename, flags) + W_LibObject.__init__(self, ffi, fname) self.libhandle = handle - self.register_finalizer(ffi.space) + self.register_finalizer(space) def _finalize_(self): h = self.libhandle 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/ffi_obj.py b/pypy/module/_cffi_backend/ffi_obj.py --- a/pypy/module/_cffi_backend/ffi_obj.py +++ b/pypy/module/_cffi_backend/ffi_obj.py @@ -572,8 +572,8 @@ return self.ffi_type(w_arg, ACCEPT_STRING | ACCEPT_CDATA) - @unwrap_spec(filename="fsencode_or_none", flags=int) - def descr_dlopen(self, filename, flags=0): + @unwrap_spec(flags=int) + def descr_dlopen(self, w_filename, flags=0): """\ Load and return a dynamic library identified by 'name'. The standard C library can be loaded by passing None. @@ -584,7 +584,7 @@ first access.""" # from pypy.module._cffi_backend import cdlopen - return cdlopen.W_DlOpenLibObject(self, filename, flags) + return cdlopen.W_DlOpenLibObject(self, w_filename, flags) def descr_dlclose(self, w_lib): diff --git a/pypy/module/_cffi_backend/libraryobj.py b/pypy/module/_cffi_backend/libraryobj.py --- a/pypy/module/_cffi_backend/libraryobj.py +++ b/pypy/module/_cffi_backend/libraryobj.py @@ -4,28 +4,21 @@ from pypy.interpreter.error import oefmt from pypy.interpreter.gateway import interp2app, unwrap_spec from pypy.interpreter.typedef import TypeDef -from pypy.module._rawffi.interp_rawffi import wrap_dlopenerror from rpython.rtyper.lltypesystem import rffi -from rpython.rlib.rdynload import DLLHANDLE, dlopen, dlsym, dlclose, DLOpenError +from rpython.rlib.rdynload import DLLHANDLE, dlsym, dlclose from pypy.module._cffi_backend.cdataobj import W_CData from pypy.module._cffi_backend.ctypeobj import W_CType +from pypy.module._cffi_backend import misc class W_Library(W_Root): _immutable_ = True - def __init__(self, space, filename, flags): + def __init__(self, space, w_filename, flags): self.space = space - with rffi.scoped_str2charp(filename) as ll_libname: - if filename is None: - filename = "<None>" - try: - self.handle = dlopen(ll_libname, flags) - except DLOpenError as e: - raise wrap_dlopenerror(space, e, filename) - self.name = filename + self.name, self.handle = misc.dlopen_w(space, w_filename, flags) self.register_finalizer(space) def _finalize_(self): @@ -104,7 +97,7 @@ W_Library.typedef.acceptable_as_base_class = False -@unwrap_spec(filename="fsencode_or_none", flags=int) -def load_library(space, filename, flags=0): - lib = W_Library(space, filename, flags) +@unwrap_spec(flags=int) +def load_library(space, w_filename, flags=0): + lib = W_Library(space, w_filename, flags) return lib 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 @@ -1,14 +1,24 @@ from __future__ import with_statement +import sys from pypy.interpreter.error import OperationError, oefmt +from pypy.module._rawffi.interp_rawffi import wrap_dlopenerror from rpython.rlib import jit 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.rdynload import dlopen, DLOpenError +from rpython.rlib.nonconst import NonConstant from rpython.rtyper.lltypesystem import lltype, llmemory, rffi from rpython.translator.tool.cbuild import ExternalCompilationInfo +if sys.platform == 'win32': + from rpython.rlib.rdynload import dlopenU + WIN32 = True +else: + WIN32 = False + # ____________________________________________________________ @@ -202,6 +212,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) @@ -389,3 +402,28 @@ ptr = rffi.cast(rffi.FLOATP, source) for i in range(len(float_list)): float_list[i] = rffi.cast(lltype.Float, ptr[i]) + +# ____________________________________________________________ + +def dlopen_w(space, w_filename, flags): + if WIN32 and space.isinstance_w(w_filename, space.w_unicode): + fname = space.text_w(space.repr(w_filename)) + unicode_name = space.unicode_w(w_filename) + with rffi.scoped_unicode2wcharp(unicode_name) as ll_libname: + try: + handle = dlopenU(ll_libname, flags) + except DLOpenError as e: + raise wrap_dlopenerror(space, e, fname) + else: + if space.is_none(w_filename): + fname = None + else: + fname = space.fsencode_w(w_filename) + with rffi.scoped_str2charp(fname) as ll_libname: + if fname is None: + fname = "<None>" + try: + handle = dlopen(ll_libname, flags) + except DLOpenError as e: + raise wrap_dlopenerror(space, e, fname) + return fname, handle diff --git a/pypy/module/_cffi_backend/test/test_re_python.py b/pypy/module/_cffi_backend/test/test_re_python.py --- a/pypy/module/_cffi_backend/test/test_re_python.py +++ b/pypy/module/_cffi_backend/test/test_re_python.py @@ -1,8 +1,13 @@ import py +import sys, shutil, os from rpython.tool.udir import udir from pypy.interpreter.gateway import interp2app from pypy.module._cffi_backend.newtype import _clean_cache +if sys.platform == 'win32': + WIN32 = True +else: + WIN32 = False class AppTestRecompilerPython: spaceconfig = dict(usemodules=['_cffi_backend']) @@ -40,6 +45,18 @@ 'globalconst42', 'globalconsthello']) outputfilename = ffiplatform.compile(str(tmpdir), ext) cls.w_extmod = space.wrap(outputfilename) + if WIN32: + unicode_name = u'load\u03betest.dll' + else: + unicode_name = u'load_caf\xe9' + os.path.splitext(outputfilename)[1] + try: + unicode_name.encode(sys.getfilesystemencoding()) + except UnicodeEncodeError: + unicode_name = None # skip test_dlopen_unicode + if unicode_name is not None: + outputfileUname = os.path.join(unicode(udir), unicode_name) + shutil.copyfile(outputfilename, outputfileUname) + cls.w_extmodU = space.wrap(outputfileUname) #mod.tmpdir = tmpdir # ffi = FFI() @@ -108,6 +125,16 @@ assert lib.add42(-10) == 32 assert type(lib.add42) is _cffi_backend.FFI.CData + def test_dlopen_unicode(self): + if not getattr(self, 'extmodU', None): + skip("no unicode file name") + import _cffi_backend, sys + sys.pypy_initfsencoding() # initialize space.sys.filesystemencoding + self.fix_path() + from re_python_pysrc import ffi + lib = ffi.dlopen(self.extmodU) + assert lib.add42(-10) == 32 + def test_dlclose(self): import _cffi_backend self.fix_path() 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/_cppyy/capi/loadable_capi.py b/pypy/module/_cppyy/capi/loadable_capi.py --- a/pypy/module/_cppyy/capi/loadable_capi.py +++ b/pypy/module/_cppyy/capi/loadable_capi.py @@ -308,10 +308,10 @@ dldflags = rdynload.RTLD_LOCAL | rdynload.RTLD_LAZY if os.environ.get('CPPYY_BACKEND_LIBRARY'): libname = os.environ['CPPYY_BACKEND_LIBRARY'] - state.backend = W_Library(space, libname, dldflags) + state.backend = W_Library(space, space.newtext(libname), dldflags) else: # try usual lookups - state.backend = W_Library(space, backend_library, dldflags) + state.backend = W_Library(space, space.newtext(backend_library), dldflags) if state.backend: # fix constants 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 @@ -197,12 +197,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)) @@ -226,6 +225,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_bufferedio.py b/pypy/module/_io/test/test_bufferedio.py --- a/pypy/module/_io/test/test_bufferedio.py +++ b/pypy/module/_io/test/test_bufferedio.py @@ -169,12 +169,12 @@ # exc = raises(TypeError, readinto, u"hello") msg = str(exc.value) - print(msg) + # print(msg) assert " read-write b" in msg and msg.endswith(", not str") # exc = raises(TypeError, readinto, memoryview(b"hello")) msg = str(exc.value) - print(msg) + # print(msg) assert " read-write b" in msg and msg.endswith(", not memoryview") # f.close() diff --git a/pypy/module/_io/test/test_bytesio.py b/pypy/module/_io/test/test_bytesio.py --- a/pypy/module/_io/test/test_bytesio.py +++ b/pypy/module/_io/test/test_bytesio.py @@ -111,12 +111,12 @@ # exc = raises(TypeError, readinto, u"hello") msg = str(exc.value) - print(msg) + # print(msg) assert " read-write b" in msg and msg.endswith(", not str") # exc = raises(TypeError, readinto, memoryview(b"hello")) msg = str(exc.value) - print(msg) + # print(msg) assert " read-write b" in msg and msg.endswith(", not memoryview") # b.close() 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 @@ -173,12 +173,12 @@ # exc = raises(TypeError, f.readinto, u"hello") msg = str(exc.value) - print(msg) + # print(msg) assert " read-write b" in msg and msg.endswith(", not str") # exc = raises(TypeError, f.readinto, memoryview(b"hello")) msg = str(exc.value) - print(msg) + # print(msg) assert " read-write b" in msg and msg.endswith(", not memoryview") # f.close() @@ -288,31 +288,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/array/interp_array.py b/pypy/module/array/interp_array.py --- a/pypy/module/array/interp_array.py +++ b/pypy/module/array/interp_array.py @@ -179,6 +179,10 @@ lltype.free(self._buffer, flavor='raw') def setlen(self, size, zero=False, overallocate=True): + if self._buffer: + delta_memory_pressure = -self.allocated * self.itemsize + else: + delta_memory_pressure = 0 if size > 0: if size > self.allocated or size < self.allocated / 2: if overallocate: @@ -191,14 +195,13 @@ some = 0 self.allocated = size + some byte_size = self.allocated * self.itemsize + delta_memory_pressure += byte_size if zero: new_buffer = lltype.malloc( - rffi.CCHARP.TO, byte_size, flavor='raw', - add_memory_pressure=True, zero=True) + rffi.CCHARP.TO, byte_size, flavor='raw', zero=True) else: new_buffer = lltype.malloc( - rffi.CCHARP.TO, byte_size, flavor='raw', - add_memory_pressure=True) + rffi.CCHARP.TO, byte_size, flavor='raw') copy_bytes = min(size, self.len) * self.itemsize rffi.c_memcpy(rffi.cast(rffi.VOIDP, new_buffer), rffi.cast(rffi.VOIDP, self._buffer), @@ -215,6 +218,11 @@ lltype.free(self._buffer, flavor='raw') self._buffer = new_buffer self.len = size + # adds the difference between the old and the new raw-malloced + # size. If setlen() is called a lot on the same array object, + # it is important to take into account the fact that we also do + # lltype.free() above. + rgc.add_memory_pressure(delta_memory_pressure) def _fromiterable(self, w_seq): # used by fromsequence(). @@ -259,8 +267,10 @@ return None oldbuffer = self._buffer self._buffer = lltype.malloc(rffi.CCHARP.TO, - (self.len - (j - i)) * self.itemsize, flavor='raw', - add_memory_pressure=True) + (self.len - (j - i)) * self.itemsize, flavor='raw') + # Issue #2913: don't pass add_memory_pressure here, otherwise + # memory pressure grows but actual raw memory usage doesn't---we + # are freeing the old buffer at the end of this function. if i: rffi.c_memcpy( rffi.cast(rffi.VOIDP, self._buffer), diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py --- a/pypy/module/cpyext/api.py +++ b/pypy/module/cpyext/api.py @@ -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', @@ -648,6 +647,7 @@ 'Py_FrozenFlag', 'Py_TabcheckFlag', 'Py_UnicodeFlag', 'Py_IgnoreEnvironmentFlag', 'Py_DivisionWarningFlag', 'Py_DontWriteBytecodeFlag', 'Py_NoUserSiteDirectory', '_Py_QnewFlag', 'Py_Py3kWarningFlag', 'Py_HashRandomizationFlag', '_Py_PackageContext', + 'PyOS_InputHook', 'PyMem_RawMalloc', 'PyMem_RawCalloc', 'PyMem_RawRealloc', 'PyMem_RawFree', 'PyMem_Malloc', 'PyMem_Calloc', 'PyMem_Realloc', 'PyMem_Free', @@ -672,7 +672,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 +716,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 +1121,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 +1131,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" @@ -1188,6 +1184,10 @@ state.C._PyPy_object_dealloc = rffi.llexternal( '_PyPy_object_dealloc', [PyObject], lltype.Void, compilation_info=eci, _nowrapper=True) + FUNCPTR = lltype.Ptr(lltype.FuncType([], rffi.INT)) + state.C.get_pyos_inputhook = rffi.llexternal( + '_PyPy_get_PyOS_InputHook', [], FUNCPTR, + compilation_info=eci, _nowrapper=True) def init_function(func): @@ -1495,7 +1495,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 +1548,6 @@ if sys.platform == 'win32': get_pythonapi_source = ''' - #include <windows.h> RPY_EXTERN HANDLE pypy_get_pythonapi_handle() { MEMORY_BASIC_INFORMATION mi; @@ -1563,6 +1561,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 +1674,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: @@ -1789,6 +1794,12 @@ return return exec_def(space, w_mod, mod_as_pyobj) +def invoke_pyos_inputhook(space): + state = space.fromcache(State) + c_inputhook = state.C.get_pyos_inputhook() + if c_inputhook: + generic_cpy_call(space, c_inputhook) + @specialize.ll() def generic_cpy_call(space, func, *args): FT = lltype.typeOf(func).TO 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/include/pythonrun.h b/pypy/module/cpyext/include/pythonrun.h --- a/pypy/module/cpyext/include/pythonrun.h +++ b/pypy/module/cpyext/include/pythonrun.h @@ -41,6 +41,11 @@ #define Py_CompileString(str, filename, start) Py_CompileStringFlags(str, filename, start, NULL) +/* Stuff with no proper home (yet) */ +PyAPI_DATA(int) (*PyOS_InputHook)(void); +typedef int (*_pypy_pyos_inputhook)(void); +PyAPI_FUNC(_pypy_pyos_inputhook) _PyPy_get_PyOS_InputHook(void); + #ifdef __cplusplus } #endif 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/src/missing.c b/pypy/module/cpyext/src/missing.c --- a/pypy/module/cpyext/src/missing.c +++ b/pypy/module/cpyext/src/missing.c @@ -31,3 +31,7 @@ void _Py_setfilesystemdefaultencoding(const char *enc) { Py_FileSystemDefaultEncoding = enc; } +int (*PyOS_InputHook)(void) = 0; /* only ever filled in by C extensions */ +PyAPI_FUNC(_pypy_pyos_inputhook) _PyPy_get_PyOS_InputHook(void) { + return PyOS_InputHook; +} 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_misc.py b/pypy/module/cpyext/test/test_misc.py new file mode 100644 --- /dev/null +++ b/pypy/module/cpyext/test/test_misc.py @@ -0,0 +1,35 @@ +from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase + + +class AppTestMisc(AppTestCpythonExtensionBase): + + def test_pyos_inputhook(self): + module = self.import_extension('foo', [ + ("set_pyos_inputhook", "METH_NOARGS", + ''' + PyOS_InputHook = &my_callback; + Py_RETURN_NONE; + '''), + ("fetch_value", "METH_NOARGS", + ''' + return PyLong_FromLong(my_flag); + '''), + ], prologue=''' + static long my_flag = 0; + static int my_callback(void) { return ++my_flag; } + ''') + + try: + import __pypy__ + except ImportError: + skip("only runs on top of pypy") + assert module.fetch_value() == 0 + __pypy__.pyos_inputhook() + assert module.fetch_value() == 0 + module.set_pyos_inputhook() # <= set + assert module.fetch_value() == 0 + __pypy__.pyos_inputhook() + assert module.fetch_value() == 1 + __pypy__.pyos_inputhook() + assert module.fetch_value() == 2 + assert module.fetch_value() == 2 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/cpyext/test/test_pyfile.py b/pypy/module/cpyext/test/test_pyfile.py --- a/pypy/module/cpyext/test/test_pyfile.py +++ b/pypy/module/cpyext/test/test_pyfile.py @@ -48,17 +48,6 @@ space.call_method(w_file, "close") - def test_file_name(self, space, api): - name = str(udir / "_test_file") - with rffi.scoped_str2charp(name) as filename: - with rffi.scoped_str2charp("wb") as mode: - w_file = api.PyFile_FromString(filename, mode) - assert space.str_w(api.PyFile_Name(w_file)) == name - - @pytest.mark.xfail - def test_file_setbufsize(self, space, api): - api.PyFile_SetBufSize() - def test_file_writestring(self, space, api, capfd): w_stdout = space.sys.get("stdout") with rffi.scoped_str2charp("test\n") as s: diff --git a/pypy/module/cpyext/test/test_unicodeobject.py b/pypy/module/cpyext/test/test_unicodeobject.py --- a/pypy/module/cpyext/test/test_unicodeobject.py +++ b/pypy/module/cpyext/test/test_unicodeobject.py @@ -677,13 +677,15 @@ def test_decode_null_encoding(self, space): null_charp = lltype.nullptr(rffi.CCHARP.TO) u_text = u'abcdefg' - s_text = space.str_w(PyUnicode_AsEncodedString(space, space.wrap(u_text), null_charp, null_charp)) + s_text = space.bytes_w(PyUnicode_AsEncodedString(space, space.wrap(u_text), null_charp, null_charp)) b_text = rffi.str2charp(s_text) assert space.unicode_w(PyUnicode_Decode( space, b_text, len(s_text), null_charp, null_charp)) == u_text with raises_w(space, TypeError): PyUnicode_FromEncodedObject( space, space.wrap(u_text), null_charp, None) + assert space.unicode_w(PyUnicode_FromEncodedObject( + space, space.newbytes(s_text), null_charp, None)) == u_text rffi.free_charp(b_text) def test_mbcs(self, space): diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py --- a/pypy/module/cpyext/unicodeobject.py +++ b/pypy/module/cpyext/unicodeobject.py @@ -486,11 +486,16 @@ in the unicode() built-in function. The codec to be used is looked up using the Python codec registry. Return NULL if an exception was raised by the codec.""" - if not encoding: - # This tracks CPython 2.7, in CPython 3.4 'utf-8' is hardcoded instead - encoding = PyUnicode_GetDefaultEncoding(space) - w_str = space.newbytes(rffi.charpsize2str(s, size)) - w_encoding = space.newtext(rffi.charp2str(encoding)) + return _pyunicode_decode(space, rffi.charpsize2str(s, size), + encoding, errors) + +def _pyunicode_decode(space, s, encoding, errors): + if encoding: + w_encoding = space.newtext(rffi.charp2str(encoding)) + else: + # python 3.4 changed to this from defaultencoding + w_encoding = space.newtext('utf-8') + w_str = space.newbytes(s) if errors: w_errors = space.newtext(rffi.charp2str(errors)) else: @@ -525,28 +530,12 @@ All other objects, including Unicode objects, cause a TypeError to be set.""" - if not encoding: - raise oefmt(space.w_TypeError, "decoding Unicode is not supported") - w_encoding = space.newtext(rffi.charp2str(encoding)) - if errors: - w_errors = space.newtext(rffi.charp2str(errors)) - else: - w_errors = None - - # - unicode is disallowed - # - raise TypeError for non-string types if space.isinstance_w(w_obj, space.w_unicode): - w_meth = None - else: - try: - w_meth = space.getattr(w_obj, space.newtext('decode')) - except OperationError as e: - if not e.match(space, space.w_AttributeError): - raise - w_meth = None - if w_meth is None: - raise oefmt(space.w_TypeError, "decoding Unicode is not supported") - return space.call_function(w_meth, w_encoding, w_errors) + raise oefmt(space.w_TypeError, "decoding str is not supported") + if space.isinstance_w(w_obj, space.w_bytearray): # Python 2.x specific + raise oefmt(space.w_TypeError, "decoding bytearray is not supported") + s = space.charbuf_w(w_obj) + return _pyunicode_decode(space, s, encoding, errors) @cpython_api([PyObject, PyObjectP], rffi.INT_real, error=0) diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py --- a/pypy/module/posix/test/test_posix2.py +++ b/pypy/module/posix/test/test_posix2.py @@ -232,9 +232,9 @@ def test_pickle(self): import pickle, os st = self.posix.stat(os.curdir) - print(type(st).__module__) + # print(type(st).__module__) s = pickle.dumps(st) - print(repr(s)) + # print(repr(s)) new = pickle.loads(s) assert new == st assert type(new) is type(st) @@ -578,6 +578,12 @@ res = fp.read() assert res == '1\n' + if sys.platform == "win32": + # using startfile in app_startfile creates global state + test_popen.dont_track_allocations = True + test_popen_with.dont_track_allocations = True + test_popen_child_fds.dont_track_allocations = True + if hasattr(__import__(os.name), '_getfullpathname'): def test__getfullpathname(self): # nt specific diff --git a/pypy/module/pwd/interp_pwd.py b/pypy/module/pwd/interp_pwd.py --- a/pypy/module/pwd/interp_pwd.py +++ b/pypy/module/pwd/interp_pwd.py @@ -37,7 +37,8 @@ passwd_p = lltype.Ptr(config['passwd']) def external(name, args, result, **kwargs): - return rffi.llexternal(name, args, result, compilation_info=eci, **kwargs) + return rffi.llexternal(name, args, result, compilation_info=eci, + releasegil=False, **kwargs) c_getpwuid = external("getpwuid", [uid_t], passwd_p) c_getpwnam = external("getpwnam", [rffi.CCHARP], passwd_p) 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,11 +231,13 @@ if os.name == 'nt': _source_code = r""" +#ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0501 +#endif #include <windows.h> #include <stdio.h> +#include <stdlib.h> -RPY_EXPORTED char *_pypy_init_home(void) { HMODULE hModule = 0; @@ -271,7 +273,6 @@ #include <stdio.h> #include <stdlib.h> -RPY_EXPORTED char *_pypy_init_home(void) { Dl_info info; @@ -289,11 +290,27 @@ } """ +_source_code += """ +inline +void _pypy_init_free(char *p) +{ + free(p); +} +""" + +if we_are_translated(): + post_include_bits = [] +else: + # for tests + post_include_bits=['RPY_EXPORTED char *_pypy_init_home(void);', + 'RPY_EXPORTED void _pypy_init_free(char*);', + ] + _eci = ExternalCompilationInfo(separate_module_sources=[_source_code], - post_include_bits=['RPY_EXPORTED char *_pypy_init_home(void);']) + post_include_bits=post_include_bits) _eci = _eci.merge(rdynload.eci) pypy_init_home = rffi.llexternal("_pypy_init_home", [], rffi.CCHARP, _nowrapper=True, compilation_info=_eci) -pypy_init_free = rffi.llexternal("free", [rffi.CCHARP], lltype.Void, +pypy_init_free = rffi.llexternal("_pypy_init_free", [rffi.CCHARP], lltype.Void, _nowrapper=True, compilation_info=_eci) diff --git a/pypy/module/thread/os_lock.py b/pypy/module/thread/os_lock.py --- a/pypy/module/thread/os_lock.py +++ b/pypy/module/thread/os_lock.py @@ -49,7 +49,8 @@ # Run signal handlers if we were interrupted space.getexecutioncontext().checksignals() if microseconds >= 0: - microseconds = r_longlong(endtime - (time.time() * 1e6)) + microseconds = r_longlong((endtime - (time.time() * 1e6)) + + 0.999) # Check for negative values, since those mean block # forever if microseconds <= 0: @@ -247,7 +248,7 @@ "cannot release un-acquired lock") self.rlock_count -= 1 if self.rlock_count == 0: - self.rlock_owner == 0 + self.rlock_owner = 0 self.lock.release() def is_owned_w(self, space): diff --git a/pypy/module/thread/test/test_lock.py b/pypy/module/thread/test/test_lock.py --- a/pypy/module/thread/test/test_lock.py +++ b/pypy/module/thread/test/test_lock.py @@ -306,6 +306,9 @@ finally: signal.signal(signal.SIGALRM, oldalrm) + +class AppTestLockRepr(GenericTestThread): + def test_lock_repr(self): import _thread lock = _thread.allocate_lock() 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,25 @@ 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 dlopenU(name, mode=-1): + # mode is unused on windows, but a consistant signature + res = rwin32.LoadLibraryW(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 @@ -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 @@ -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] _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit