Author: Raffael Tfirst <[email protected]>
Branch: py3.5-async
Changeset: r85968:2688a6d60ce4
Date: 2016-08-01 20:41 +0200
http://bitbucket.org/pypy/pypy/changeset/2688a6d60ce4/
Log: Merge with py3k
diff too long, truncating to 2000 out of 43939 lines
diff --git a/.hgtags b/.hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -26,3 +26,4 @@
40497617ae91caa1a394d8be6f9cd2de31cb0628 release-pypy3.3-v5.2
40497617ae91caa1a394d8be6f9cd2de31cb0628 release-pypy3.3-v5.2
c09c19272c990a0611b17569a0085ad1ab00c8ff release-pypy2.7-v5.3
+7e8df3df96417c16c2d55b41352ec82c9c69c978 release-pypy2.7-v5.3.1
diff --git a/dotviewer/graphparse.py b/dotviewer/graphparse.py
--- a/dotviewer/graphparse.py
+++ b/dotviewer/graphparse.py
@@ -85,10 +85,11 @@
pass
def splitline(line, re_word = re.compile(r'[^\s"]\S*|["]["]|["].*?[^\\]["]')):
+ import ast
result = []
for word in re_word.findall(line):
if word.startswith('"'):
- word = eval(word)
+ word = ast.literal_eval(word)
result.append(word)
return result
diff --git a/lib-python/2.7/test/test_hash.py b/lib-python/2.7/test/test_hash.py
--- a/lib-python/2.7/test/test_hash.py
+++ b/lib-python/2.7/test/test_hash.py
@@ -174,7 +174,7 @@
class StringlikeHashRandomizationTests(HashRandomizationTests):
if check_impl_detail(pypy=True):
- EMPTY_STRING_HASH = -1
+ EMPTY_STRING_HASH = -2
else:
EMPTY_STRING_HASH = 0
diff --git a/lib-python/3/test/test_unicode.py
b/lib-python/3/test/test_unicode.py
--- a/lib-python/3/test/test_unicode.py
+++ b/lib-python/3/test/test_unicode.py
@@ -2604,7 +2604,8 @@
def test_getnewargs(self):
text = 'abc'
args = text.__getnewargs__()
- self.assertIsNot(args[0], text)
+ if support.check_impl_detail():
+ self.assertIsNot(args[0], text)
self.assertEqual(args[0], text)
self.assertEqual(len(args), 1)
diff --git a/lib-python/conftest.py b/lib-python/conftest.py
--- a/lib-python/conftest.py
+++ b/lib-python/conftest.py
@@ -418,7 +418,7 @@
RegrTest('test_threading.py', usemodules="thread", core=True),
RegrTest('test_threading_local.py', usemodules="thread", core=True),
RegrTest('test_threadsignals.py', usemodules="thread"),
- RegrTest('test_time.py', core=True, usemodules="struct"),
+ RegrTest('test_time.py', core=True, usemodules="struct thread _rawffi"),
RegrTest('test_timeit.py'),
RegrTest('test_timeout.py'),
RegrTest('test_tk.py'),
@@ -452,7 +452,7 @@
RegrTest('test_userstring.py', core=True),
RegrTest('test_uu.py'),
RegrTest('test_uuid.py'),
- RegrTest('test_venv.py'),
+ RegrTest('test_venv.py', usemodules="struct"),
RegrTest('test_wait3.py', usemodules="thread"),
RegrTest('test_wait4.py', usemodules="thread"),
RegrTest('test_warnings.py', core=True),
diff --git a/lib_pypy/_ctypes/basics.py b/lib_pypy/_ctypes/basics.py
--- a/lib_pypy/_ctypes/basics.py
+++ b/lib_pypy/_ctypes/basics.py
@@ -198,10 +198,13 @@
return tp._alignmentofinstances()
@builtinify
-def byref(cdata):
+def byref(cdata, offset=0):
# "pointer" is imported at the end of this module to avoid circular
# imports
- return pointer(cdata)
+ ptr = pointer(cdata)
+ if offset != 0:
+ ptr._buffer[0] += offset
+ return ptr
def cdata_from_address(self, address):
# fix the address: turn it into as unsigned, in case it's a negative number
diff --git a/lib_pypy/_pypy_winbase_build.py b/lib_pypy/_pypy_winbase_build.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_pypy_winbase_build.py
@@ -0,0 +1,91 @@
+# Note: uses the CFFI out-of-line ABI mode. We can't use the API
+# mode because ffi.compile() needs to run the compiler, which
+# needs 'subprocess', which needs 'msvcrt' and '_subprocess',
+# which depend on '_pypy_winbase_cffi' already.
+#
+# Note that if you need to regenerate _pypy_winbase_cffi and
+# can't use a preexisting PyPy to do that, then running this
+# file should work as long as 'subprocess' is not imported
+# by cffi. I had to hack in 'cffi._pycparser' to move an
+#'import subprocess' to the inside of a function. (Also,
+# CPython+CFFI should work as well.)
+#
+# This module supports both msvcrt.py and _subprocess.py.
+
+from cffi import FFI
+
+ffi = FFI()
+
+ffi.set_source("_pypy_winbase_cffi", None)
+
+# ---------- MSVCRT ----------
+
+ffi.cdef("""
+typedef unsigned short wint_t;
+
+int _open_osfhandle(intptr_t osfhandle, int flags);
+intptr_t _get_osfhandle(int fd);
+int _setmode(int fd, int mode);
+int _locking(int fd, int mode, long nbytes);
+
+int _kbhit(void);
+int _getch(void);
+wint_t _getwch(void);
+int _getche(void);
+wint_t _getwche(void);
+int _putch(int);
+wint_t _putwch(wchar_t);
+int _ungetch(int);
+wint_t _ungetwch(wint_t);
+""")
+
+# ---------- SUBPROCESS ----------
+
+ffi.cdef("""
+typedef struct {
+ DWORD cb;
+ char * lpReserved;
+ char * lpDesktop;
+ char * lpTitle;
+ DWORD dwX;
+ DWORD dwY;
+ DWORD dwXSize;
+ DWORD dwYSize;
+ DWORD dwXCountChars;
+ DWORD dwYCountChars;
+ DWORD dwFillAttribute;
+ DWORD dwFlags;
+ WORD wShowWindow;
+ WORD cbReserved2;
+ LPBYTE lpReserved2;
+ HANDLE hStdInput;
+ HANDLE hStdOutput;
+ HANDLE hStdError;
+} STARTUPINFO, *LPSTARTUPINFO;
+
+typedef struct {
+ HANDLE hProcess;
+ HANDLE hThread;
+ DWORD dwProcessId;
+ DWORD dwThreadId;
+} PROCESS_INFORMATION, *LPPROCESS_INFORMATION;
+
+DWORD WINAPI GetVersion(void);
+BOOL WINAPI CreatePipe(PHANDLE, PHANDLE, void *, DWORD);
+BOOL WINAPI CloseHandle(HANDLE);
+HANDLE WINAPI GetCurrentProcess(void);
+BOOL WINAPI DuplicateHandle(HANDLE, HANDLE, HANDLE, LPHANDLE,
+ DWORD, BOOL, DWORD);
+BOOL WINAPI CreateProcessA(char *, char *, void *,
+ void *, BOOL, DWORD, char *,
+ char *, LPSTARTUPINFO, LPPROCESS_INFORMATION);
+DWORD WINAPI WaitForSingleObject(HANDLE, DWORD);
+BOOL WINAPI GetExitCodeProcess(HANDLE, LPDWORD);
+BOOL WINAPI TerminateProcess(HANDLE, UINT);
+HANDLE WINAPI GetStdHandle(DWORD);
+""")
+
+# --------------------
+
+if __name__ == "__main__":
+ ffi.compile()
diff --git a/lib_pypy/_pypy_winbase_cffi.py b/lib_pypy/_pypy_winbase_cffi.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_pypy_winbase_cffi.py
@@ -0,0 +1,10 @@
+# auto-generated file
+import _cffi_backend
+
+ffi = _cffi_backend.FFI('_pypy_winbase_cffi',
+ _version = 0x2601,
+ _types =
b'\x00\x00\x01\x0D\x00\x00\x07\x01\x00\x00\x00\x0F\x00\x00\x01\x0D\x00\x00\x07\x01\x00\x00\x07\x01\x00\x00\x00\x0F\x00\x00\x01\x0D\x00\x00\x07\x01\x00\x00\x07\x01\x00\x00\x09\x01\x00\x00\x00\x0F\x00\x00\x01\x0D\x00\x00\x19\x01\x00\x00\x07\x01\x00\x00\x00\x0F\x00\x00\x01\x0D\x00\x00\x00\x0F\x00\x00\x01\x0D\x00\x00\x50\x03\x00\x00\x13\x11\x00\x00\x53\x03\x00\x00\x15\x11\x00\x00\x07\x01\x00\x00\x0A\x01\x00\x00\x13\x11\x00\x00\x13\x11\x00\x00\x4F\x03\x00\x00\x4E\x03\x00\x00\x02\x0F\x00\x00\x01\x0D\x00\x00\x15\x03\x00\x00\x1F\x11\x00\x00\x15\x11\x00\x00\x0A\x01\x00\x00\x02\x0F\x00\x00\x01\x0D\x00\x00\x15\x11\x00\x00\x02\x0F\x00\x00\x01\x0D\x00\x00\x15\x11\x00\x00\x08\x01\x00\x00\x02\x0F\x00\x00\x01\x0D\x00\x00\x15\x11\x00\x00\x18\x03\x00\x00\x02\x0F\x00\x00\x01\x0D\x00\x00\x15\x11\x00\x00\x15\x11\x00\x00\x15\x11\x00\x00\x1F\x11\x00\x00\x0A\x01\x00\x00\x07\x01\x00\x00\x0A\x01\x00\x00\x02\x0F\x00\x00\x0D\x0D\x00\x00\x07\x01\x00\x00\x00\x0F\x00\x00\x18\x0D\x00\x00\x15\x11\x00\x
00\x0A\x01\x00\x00\x02\x0F\x00\x00\x18\x0D\x00\x00\x02\x0F\x00\x00\x42\x0D\x00\x00\x06\x01\x00\x00\x00\x0F\x00\x00\x42\x0D\x00\x00\x00\x0F\x00\x00\x42\x0D\x00\x00\x10\x01\x00\x00\x00\x0F\x00\x00\x15\x0D\x00\x00\x0A\x01\x00\x00\x02\x0F\x00\x00\x15\x0D\x00\x00\x02\x0F\x00\x00\x00\x09\x00\x00\x01\x09\x00\x00\x02\x01\x00\x00\x52\x03\x00\x00\x04\x01\x00\x00\x00\x01',
+ _globals =
(b'\x00\x00\x24\x23CloseHandle',0,b'\x00\x00\x1E\x23CreatePipe',0,b'\x00\x00\x12\x23CreateProcessA',0,b'\x00\x00\x2F\x23DuplicateHandle',0,b'\x00\x00\x4C\x23GetCurrentProcess',0,b'\x00\x00\x2B\x23GetExitCodeProcess',0,b'\x00\x00\x49\x23GetStdHandle',0,b'\x00\x00\x3F\x23GetVersion',0,b'\x00\x00\x27\x23TerminateProcess',0,b'\x00\x00\x3B\x23WaitForSingleObject',0,b'\x00\x00\x38\x23_get_osfhandle',0,b'\x00\x00\x10\x23_getch',0,b'\x00\x00\x10\x23_getche',0,b'\x00\x00\x44\x23_getwch',0,b'\x00\x00\x44\x23_getwche',0,b'\x00\x00\x10\x23_kbhit',0,b'\x00\x00\x07\x23_locking',0,b'\x00\x00\x0C\x23_open_osfhandle',0,b'\x00\x00\x00\x23_putch',0,b'\x00\x00\x46\x23_putwch',0,b'\x00\x00\x03\x23_setmode',0,b'\x00\x00\x00\x23_ungetch',0,b'\x00\x00\x41\x23_ungetwch',0),
+ _struct_unions =
((b'\x00\x00\x00\x4E\x00\x00\x00\x02$PROCESS_INFORMATION',b'\x00\x00\x15\x11hProcess',b'\x00\x00\x15\x11hThread',b'\x00\x00\x18\x11dwProcessId',b'\x00\x00\x18\x11dwThreadId'),(b'\x00\x00\x00\x4F\x00\x00\x00\x02$STARTUPINFO',b'\x00\x00\x18\x11cb',b'\x00\x00\x13\x11lpReserved',b'\x00\x00\x13\x11lpDesktop',b'\x00\x00\x13\x11lpTitle',b'\x00\x00\x18\x11dwX',b'\x00\x00\x18\x11dwY',b'\x00\x00\x18\x11dwXSize',b'\x00\x00\x18\x11dwYSize',b'\x00\x00\x18\x11dwXCountChars',b'\x00\x00\x18\x11dwYCountChars',b'\x00\x00\x18\x11dwFillAttribute',b'\x00\x00\x18\x11dwFlags',b'\x00\x00\x42\x11wShowWindow',b'\x00\x00\x42\x11cbReserved2',b'\x00\x00\x51\x11lpReserved2',b'\x00\x00\x15\x11hStdInput',b'\x00\x00\x15\x11hStdOutput',b'\x00\x00\x15\x11hStdError')),
+ _typenames =
(b'\x00\x00\x00\x1CLPPROCESS_INFORMATION',b'\x00\x00\x00\x1BLPSTARTUPINFO',b'\x00\x00\x00\x4EPROCESS_INFORMATION',b'\x00\x00\x00\x4FSTARTUPINFO',b'\x00\x00\x00\x42wint_t'),
+)
diff --git a/lib_pypy/_winapi.py b/lib_pypy/_winapi.py
--- a/lib_pypy/_winapi.py
+++ b/lib_pypy/_winapi.py
@@ -10,152 +10,99 @@
# Declare external Win32 functions
-import ctypes
-
-_kernel32 = ctypes.WinDLL('kernel32')
-
-_CloseHandle = _kernel32.CloseHandle
-_CloseHandle.argtypes = [ctypes.c_int]
-_CloseHandle.restype = ctypes.c_int
-
-_CreatePipe = _kernel32.CreatePipe
-_CreatePipe.argtypes = [ctypes.POINTER(ctypes.c_int),
ctypes.POINTER(ctypes.c_int),
- ctypes.c_void_p, ctypes.c_int]
-_CreatePipe.restype = ctypes.c_int
-
-_GetCurrentProcess = _kernel32.GetCurrentProcess
-_GetCurrentProcess.argtypes = []
-_GetCurrentProcess.restype = ctypes.c_int
+from _pypy_winbase_cffi import ffi as _ffi
+_kernel32 = _ffi.dlopen('kernel32')
GetVersion = _kernel32.GetVersion
-GetVersion.argtypes = []
-GetVersion.restype = ctypes.c_int
-_DuplicateHandle = _kernel32.DuplicateHandle
-_DuplicateHandle.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_int,
- ctypes.POINTER(ctypes.c_int),
- ctypes.c_int, ctypes.c_int, ctypes.c_int]
-_DuplicateHandle.restype = ctypes.c_int
-_WaitForSingleObject = _kernel32.WaitForSingleObject
-_WaitForSingleObject.argtypes = [ctypes.c_int, ctypes.c_uint]
-_WaitForSingleObject.restype = ctypes.c_int
+# Now the _subprocess module implementation
-_GetExitCodeProcess = _kernel32.GetExitCodeProcess
-_GetExitCodeProcess.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_int)]
-_GetExitCodeProcess.restype = ctypes.c_int
+def _WinError():
+ code, message = _ffi.getwinerror()
+ raise WindowsError(code, message)
-_TerminateProcess = _kernel32.TerminateProcess
-_TerminateProcess.argtypes = [ctypes.c_int, ctypes.c_int]
-_TerminateProcess.restype = ctypes.c_int
+_INVALID_HANDLE_VALUE = _ffi.cast("HANDLE", -1)
-_GetStdHandle = _kernel32.GetStdHandle
-_GetStdHandle.argtypes = [ctypes.c_int]
-_GetStdHandle.restype = ctypes.c_int
-
-_GetModuleFileNameW = _kernel32.GetModuleFileNameW
-_GetModuleFileNameW.argtypes = [ctypes.c_int, ctypes.c_wchar_p, ctypes.c_uint]
-_GetModuleFileNameW.restype = ctypes.c_int
-
-class _STARTUPINFO(ctypes.Structure):
- _fields_ = [('cb', ctypes.c_int),
- ('lpReserved', ctypes.c_void_p),
- ('lpDesktop', ctypes.c_char_p),
- ('lpTitle', ctypes.c_char_p),
- ('dwX', ctypes.c_int),
- ('dwY', ctypes.c_int),
- ('dwXSize', ctypes.c_int),
- ('dwYSize', ctypes.c_int),
- ('dwXCountChars', ctypes.c_int),
- ('dwYCountChars', ctypes.c_int),
- ("dwFillAttribute", ctypes.c_int),
- ("dwFlags", ctypes.c_int),
- ("wShowWindow", ctypes.c_short),
- ("cbReserved2", ctypes.c_short),
- ("lpReserved2", ctypes.c_void_p),
- ("hStdInput", ctypes.c_int),
- ("hStdOutput", ctypes.c_int),
- ("hStdError", ctypes.c_int)
- ]
-
-class _PROCESS_INFORMATION(ctypes.Structure):
- _fields_ = [("hProcess", ctypes.c_int),
- ("hThread", ctypes.c_int),
- ("dwProcessID", ctypes.c_int),
- ("dwThreadID", ctypes.c_int)]
-
-_CreateProcess = _kernel32.CreateProcessW
-_CreateProcess.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p,
ctypes.c_void_p, ctypes.c_void_p,
- ctypes.c_int, ctypes.c_int, ctypes.c_wchar_p,
ctypes.c_wchar_p,
- ctypes.POINTER(_STARTUPINFO),
ctypes.POINTER(_PROCESS_INFORMATION)]
-_CreateProcess.restype = ctypes.c_int
-
-del ctypes
-
-# Now the _winapi module implementation
-
-from ctypes import c_int as _c_int, byref as _byref, WinError as _WinError
-
-class _handle:
- def __init__(self, handle):
- self.handle = handle
+class _handle(object):
+ def __init__(self, c_handle):
+ # 'c_handle' is a cffi cdata of type HANDLE, which is basically 'void
*'
+ self.c_handle = c_handle
+ if int(self) != -1:
+ self.c_handle = _ffi.gc(self.c_handle, _kernel32.CloseHandle)
def __int__(self):
- return self.handle
+ return int(_ffi.cast("intptr_t", self.c_handle))
- def __del__(self):
- if self.handle is not None:
- _CloseHandle(self.handle)
+ def __repr__(self):
+ return '<_subprocess.handle %d at 0x%x>' % (int(self), id(self))
def Detach(self):
- handle, self.handle = self.handle, None
- return handle
+ h = int(self)
+ if h != -1:
+ c_handle = self.c_handle
+ self.c_handle = _INVALID_HANDLE_VALUE
+ _ffi.gc(c_handle, None)
+ return h
def Close(self):
- if self.handle not in (-1, None):
- _CloseHandle(self.handle)
- self.handle = None
+ if int(self) != -1:
+ c_handle = self.c_handle
+ self.c_handle = _INVALID_HANDLE_VALUE
+ _ffi.gc(c_handle, None)
+ _kernel32.CloseHandle(c_handle)
def CreatePipe(attributes, size):
- read = _c_int()
- write = _c_int()
+ handles = _ffi.new("HANDLE[2]")
- res = _CreatePipe(_byref(read), _byref(write), None, size)
+ res = _kernel32.CreatePipe(handles, handles + 1, _ffi.NULL, size)
if not res:
raise _WinError()
- return _handle(read.value), _handle(write.value)
+ return _handle(handles[0]), _handle(handles[1])
def GetCurrentProcess():
- return _handle(_GetCurrentProcess())
+ return _handle(_kernel32.GetCurrentProcess())
def DuplicateHandle(source_process, source, target_process, access, inherit,
options=0):
- target = _c_int()
+ # CPython: the first three arguments are expected to be integers
+ target = _ffi.new("HANDLE[1]")
- res = _DuplicateHandle(int(source_process), int(source),
int(target_process),
- _byref(target),
- access, inherit, options)
+ res = _kernel32.DuplicateHandle(
+ _ffi.cast("HANDLE", source_process),
+ _ffi.cast("HANDLE", source),
+ _ffi.cast("HANDLE", target_process),
+ target, access, inherit, options)
if not res:
raise _WinError()
- return _handle(target.value)
+ return _handle(target[0])
+
+def _z(input):
+ if input is None:
+ return _ffi.NULL
+ if isinstance(input, basestring):
+ return str(input)
+ raise TypeError("string/unicode/None expected, got %r" % (
+ type(input).__name__,))
def CreateProcess(name, command_line, process_attr, thread_attr,
inherit, flags, env, start_dir, startup_info):
- si = _STARTUPINFO()
+ si = _ffi.new("STARTUPINFO *")
if startup_info is not None:
si.dwFlags = startup_info.dwFlags
si.wShowWindow = startup_info.wShowWindow
+ # CPython: these three handles are expected to be _handle objects
if startup_info.hStdInput:
- si.hStdInput = int(startup_info.hStdInput)
+ si.hStdInput = startup_info.hStdInput.c_handle
if startup_info.hStdOutput:
- si.hStdOutput = int(startup_info.hStdOutput)
+ si.hStdOutput = startup_info.hStdOutput.c_handle
if startup_info.hStdError:
- si.hStdError = int(startup_info.hStdError)
+ si.hStdError = startup_info.hStdError.c_handle
- pi = _PROCESS_INFORMATION()
+ pi = _ffi.new("PROCESS_INFORMATION *")
flags |= CREATE_UNICODE_ENVIRONMENT
if env is not None:
@@ -164,47 +111,55 @@
envbuf += "%s=%s\0" % (k, v)
envbuf += '\0'
else:
- envbuf = None
+ envbuf = _ffi.NULL
- res = _CreateProcess(name, command_line, None, None, inherit, flags,
envbuf,
- start_dir, _byref(si), _byref(pi))
+ res = _kernel32.CreateProcessA(_z(name), _z(command_line), _ffi.NULL,
+ _ffi.NULL, inherit, flags, envbuf,
+ _z(start_dir), si, pi)
if not res:
raise _WinError()
- return _handle(pi.hProcess), _handle(pi.hThread), pi.dwProcessID,
pi.dwThreadID
+ return _handle(pi.hProcess), _handle(pi.hThread), pi.dwProcessId,
pi.dwThreadId
def WaitForSingleObject(handle, milliseconds):
- res = _WaitForSingleObject(int(handle), milliseconds)
-
+ # CPython: the first argument is expected to be an integer.
+ res = _kernel32.WaitForSingleObject(_ffi.cast("HANDLE", handle),
+ milliseconds)
if res < 0:
raise _WinError()
return res
def GetExitCodeProcess(handle):
- code = _c_int()
+ # CPython: the first argument is expected to be an integer.
+ code = _ffi.new("DWORD[1]")
- res = _GetExitCodeProcess(int(handle), _byref(code))
+ res = _kernel32.GetExitCodeProcess(_ffi.cast("HANDLE", handle), code)
if not res:
raise _WinError()
- return code.value
+ return code[0]
def TerminateProcess(handle, exitcode):
- res = _TerminateProcess(int(handle), exitcode)
+ # CPython: the first argument is expected to be an integer.
+ # The second argument is silently wrapped in a UINT.
+ res = _kernel32.TerminateProcess(_ffi.cast("HANDLE", handle),
+ _ffi.cast("UINT", exitcode))
if not res:
raise _WinError()
def GetStdHandle(stdhandle):
- res = _GetStdHandle(stdhandle)
+ stdhandle = _ffi.cast("DWORD", stdhandle)
+ res = _kernel32.GetStdHandle(stdhandle)
if not res:
return None
else:
- return res
+ # note: returns integer, not handle object
+ return int(_ffi.cast("intptr_t", res))
def CloseHandle(handle):
res = _CloseHandle(handle)
diff --git a/lib_pypy/cffi/_pycparser/__init__.py
b/lib_pypy/cffi/_pycparser/__init__.py
--- a/lib_pypy/cffi/_pycparser/__init__.py
+++ b/lib_pypy/cffi/_pycparser/__init__.py
@@ -10,7 +10,6 @@
__all__ = ['c_lexer', 'c_parser', 'c_ast']
__version__ = '2.14'
-from subprocess import Popen, PIPE
from .c_parser import CParser
@@ -28,6 +27,7 @@
When successful, returns the preprocessed file's contents.
Errors from cpp will be printed out.
"""
+ from subprocess import Popen, PIPE
path_list = [cpp_path]
if isinstance(cpp_args, list):
path_list += cpp_args
diff --git a/lib_pypy/greenlet.egg-info b/lib_pypy/greenlet.egg-info
--- a/lib_pypy/greenlet.egg-info
+++ b/lib_pypy/greenlet.egg-info
@@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: greenlet
-Version: 0.4.9
+Version: 0.4.10
Summary: Lightweight in-process concurrent programming
Home-page: https://github.com/python-greenlet/greenlet
Author: Ralf Schmitt (for CPython), PyPy team
diff --git a/lib_pypy/greenlet.py b/lib_pypy/greenlet.py
--- a/lib_pypy/greenlet.py
+++ b/lib_pypy/greenlet.py
@@ -2,7 +2,7 @@
import __pypy__
import _continuation
-__version__ = "0.4.9"
+__version__ = "0.4.10"
# ____________________________________________________________
# Exceptions
diff --git a/lib_pypy/msvcrt.py b/lib_pypy/msvcrt.py
--- a/lib_pypy/msvcrt.py
+++ b/lib_pypy/msvcrt.py
@@ -7,26 +7,39 @@
# XXX incomplete: implemented only functions needed by subprocess.py
# PAC: 2010/08 added MS locking for Whoosh
-import ctypes
+# 07/2016: rewrote in CFFI
+
+import sys
+if sys.platform != 'win32':
+ raise ImportError("The 'msvcrt' module is only available on Windows")
+
+import _rawffi
+from _pypy_winbase_cffi import ffi as _ffi
+_lib = _ffi.dlopen(_rawffi.get_libc().name)
+
import errno
-from ctypes_support import standard_c_lib as _c
-from ctypes_support import get_errno
-
-try:
- open_osfhandle = _c._open_osfhandle
-except AttributeError: # we are not on windows
- raise ImportError
try: from __pypy__ import builtinify, validate_fd
except ImportError: builtinify = validate_fd = lambda f: f
-open_osfhandle.argtypes = [ctypes.c_int, ctypes.c_int]
-open_osfhandle.restype = ctypes.c_int
+def _ioerr():
+ e = _ffi.errno
+ raise IOError(e, errno.errorcode[e])
-_get_osfhandle = _c._get_osfhandle
-_get_osfhandle.argtypes = [ctypes.c_int]
-_get_osfhandle.restype = ctypes.c_int
+
+@builtinify
+def open_osfhandle(fd, flags):
+ """"open_osfhandle(handle, flags) -> file descriptor
+
+ Create a C runtime file descriptor from the file handle handle. The
+ flags parameter should be a bitwise OR of os.O_APPEND, os.O_RDONLY,
+ and os.O_TEXT. The returned file descriptor may be used as a parameter
+ to os.fdopen() to create a file object."""
+ fd = _lib._open_osfhandle(fd, flags)
+ if fd == -1:
+ _ioerr()
+ return fd
@builtinify
def get_osfhandle(fd):
@@ -38,62 +51,74 @@
validate_fd(fd)
except OSError as e:
raise IOError(*e.args)
- return _get_osfhandle(fd)
+ result = _lib._get_osfhandle(fd)
+ if result == -1:
+ _ioerr()
+ return result
-setmode = _c._setmode
-setmode.argtypes = [ctypes.c_int, ctypes.c_int]
-setmode.restype = ctypes.c_int
+@builtinify
+def setmode(fd, flags):
+ """setmode(fd, mode) -> Previous mode
+
+ Set the line-end translation mode for the file descriptor fd. To set
+ it to text mode, flags should be os.O_TEXT; for binary, it should be
+ os.O_BINARY."""
+ flags = _lib._setmode(fd, flags)
+ if flags == -1:
+ _ioerr()
+ return flags
LK_UNLCK, LK_LOCK, LK_NBLCK, LK_RLCK, LK_NBRLCK = range(5)
-_locking = _c._locking
-_locking.argtypes = [ctypes.c_int, ctypes.c_int, ctypes.c_int]
-_locking.restype = ctypes.c_int
-
@builtinify
def locking(fd, mode, nbytes):
- '''lock or unlock a number of bytes in a file.'''
- rv = _locking(fd, mode, nbytes)
+ """"locking(fd, mode, nbytes) -> None
+
+ Lock part of a file based on file descriptor fd from the C runtime.
+ Raises IOError on failure. The locked region of the file extends from
+ the current file position for nbytes bytes, and may continue beyond
+ the end of the file. mode must be one of the LK_* constants listed
+ below. Multiple regions in a file may be locked at the same time, but
+ may not overlap. Adjacent regions are not merged; they must be unlocked
+ individually."""
+ rv = _lib._locking(fd, mode, nbytes)
if rv != 0:
- e = get_errno()
- raise IOError(e, errno.errorcode[e])
+ _ioerr()
# Console I/O routines
-kbhit = _c._kbhit
-kbhit.argtypes = []
-kbhit.restype = ctypes.c_int
+kbhit = _lib._kbhit
-getch = _c._getch
-getch.argtypes = []
-getch.restype = ctypes.c_char
+@builtinify
+def getch():
+ return chr(_lib._getch())
-getwch = _c._getwch
-getwch.argtypes = []
-getwch.restype = ctypes.c_wchar
+@builtinify
+def getwch():
+ return unichr(_lib._getwch())
-getche = _c._getche
-getche.argtypes = []
-getche.restype = ctypes.c_char
+@builtinify
+def getche():
+ return chr(_lib._getche())
-getwche = _c._getwche
-getwche.argtypes = []
-getwche.restype = ctypes.c_wchar
+@builtinify
+def getwche():
+ return unichr(_lib._getwche())
-putch = _c._putch
-putch.argtypes = [ctypes.c_char]
-putch.restype = None
+@builtinify
+def putch(ch):
+ _lib._putch(ord(ch))
-putwch = _c._putwch
-putwch.argtypes = [ctypes.c_wchar]
-putwch.restype = None
+@builtinify
+def putwch(ch):
+ _lib._putwch(ord(ch))
-ungetch = _c._ungetch
-ungetch.argtypes = [ctypes.c_char]
-ungetch.restype = None
+@builtinify
+def ungetch(ch):
+ if _lib._ungetch(ord(ch)) == -1: # EOF
+ _ioerr()
-ungetwch = _c._ungetwch
-ungetwch.argtypes = [ctypes.c_wchar]
-ungetwch.restype = None
-
-del ctypes
+@builtinify
+def ungetwch(ch):
+ if _lib._ungetwch(ord(ch)) == -1: # EOF
+ _ioerr()
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -40,7 +40,7 @@
"binascii", "_multiprocessing", '_warnings', "_collections",
"_multibytecodec", "_continuation", "_cffi_backend",
"_csv", "_pypyjson", "_posixsubprocess", # "cppyy", "micronumpy"
- "faulthandler",
+ "faulthandler", "_jitlog",
])
from rpython.jit.backend import detect_cpu
diff --git a/pypy/conftest.py b/pypy/conftest.py
--- a/pypy/conftest.py
+++ b/pypy/conftest.py
@@ -94,6 +94,20 @@
def pytest_pycollect_makemodule(path, parent):
return PyPyModule(path, parent)
+def is_applevel(item):
+ from pypy.tool.pytest.apptest import AppTestFunction
+ return isinstance(item, AppTestFunction)
+
+def pytest_collection_modifyitems(config, items):
+ if config.option.runappdirect:
+ return
+ for item in items:
+ if isinstance(item, py.test.Function):
+ if is_applevel(item):
+ item.add_marker('applevel')
+ else:
+ item.add_marker('interplevel')
+
class PyPyModule(py.test.collect.Module):
""" we take care of collecting classes both at app level
and at interp-level (because we need to stick a space
@@ -128,9 +142,6 @@
if name.startswith('AppTest'):
from pypy.tool.pytest.apptest import AppClassCollector
return AppClassCollector(name, parent=self)
- else:
- from pypy.tool.pytest.inttest import IntClassCollector
- return IntClassCollector(name, parent=self)
elif hasattr(obj, 'func_code') and self.funcnamefilter(name):
if name.startswith('app_test_'):
@@ -138,11 +149,7 @@
"generator app level functions? you must be joking"
from pypy.tool.pytest.apptest import AppTestFunction
return AppTestFunction(name, parent=self)
- elif obj.func_code.co_flags & 32: # generator function
- return pytest.Generator(name, parent=self)
- else:
- from pypy.tool.pytest.inttest import IntTestFunction
- return IntTestFunction(name, parent=self)
+ return super(PyPyModule, self).makeitem(name, obj)
def skip_on_missing_buildoption(**ropts):
__tracebackhide__ = True
@@ -171,28 +178,19 @@
def pytest_runtest_setup(__multicall__, item):
if isinstance(item, py.test.collect.Function):
- appclass = item.getparent(PyPyClassCollector)
+ appclass = item.getparent(py.test.Class)
if appclass is not None:
# Make cls.space and cls.runappdirect available in tests.
spaceconfig = getattr(appclass.obj, 'spaceconfig', None)
if spaceconfig is not None:
from pypy.tool.pytest.objspace import gettestobjspace
appclass.obj.space = gettestobjspace(**spaceconfig)
+ else:
+ appclass.obj.space = LazyObjSpaceGetter()
appclass.obj.runappdirect = option.runappdirect
__multicall__.execute()
-class PyPyClassCollector(py.test.collect.Class):
- # All pypy Test classes have a "space" member.
- def setup(self):
- cls = self.obj
- if not hasattr(cls, 'spaceconfig'):
- cls.space = LazyObjSpaceGetter()
- else:
- assert hasattr(cls, 'space') # set by pytest_runtest_setup
- super(PyPyClassCollector, self).setup()
-
-
def pytest_ignore_collect(path):
return path.check(link=1)
diff --git a/pypy/doc/build.rst b/pypy/doc/build.rst
--- a/pypy/doc/build.rst
+++ b/pypy/doc/build.rst
@@ -104,27 +104,24 @@
apt-get install gcc make libffi-dev pkg-config libz-dev libbz2-dev \
libsqlite3-dev libncurses-dev libexpat1-dev libssl-dev libgdbm-dev \
- tk-dev libgc-dev liblzma-dev
-
-For the optional lzma module on PyPy3 you will also need ``liblzma-dev``.
+ tk-dev libgc-dev \
+ liblzma-dev # For lzma on PyPy3.
On Fedora::
dnf install gcc make libffi-devel pkgconfig zlib-devel bzip2-devel \
lib-sqlite3-devel ncurses-devel expat-devel openssl-devel tk-devel \
- gdbm-devel
-
-For the optional lzma module on PyPy3 you will also need ``xz-devel``.
+ gdbm-devel \
+ xz-devel # For lzma on PyPy3.
On SLES11::
zypper install gcc make python-devel pkg-config \
zlib-devel libopenssl-devel libbz2-devel sqlite3-devel \
- libexpat-devel libffi-devel python-curses
+ libexpat-devel libffi-devel python-curses \
+ xz-devel # For lzma on PyPy3.
(XXX plus the SLES11 version of libgdbm-dev and tk-dev)
-For the optional lzma module on PyPy3 you will also need ``xz-devel``.
-
On Mac OS X, most of these build-time dependencies are installed alongside
the Developer Tools. However, note that in order for the installation to
find them you may need to run::
diff --git a/pypy/doc/config/commandline.txt b/pypy/doc/config/commandline.txt
--- a/pypy/doc/config/commandline.txt
+++ b/pypy/doc/config/commandline.txt
@@ -9,7 +9,7 @@
PyPy Python interpreter options
-------------------------------
-The following options can be used after ``translate.py
+The following options can be used after ``rpython
targetpypystandalone`` or as options to ``py.py``.
.. GENERATE: objspace
@@ -22,7 +22,7 @@
General translation options
---------------------------
-The following are options of ``translate.py``. They must be
+The following are options of ``bin/rpython``. They must be
given before the ``targetxxx`` on the command line.
* `--opt -O:`__ set the optimization level `[0, 1, size, mem, 2, 3]`
diff --git a/pypy/doc/config/index.rst b/pypy/doc/config/index.rst
--- a/pypy/doc/config/index.rst
+++ b/pypy/doc/config/index.rst
@@ -15,12 +15,12 @@
./py.py <`objspace options`_>
-and the ``translate.py`` translation entry
+and the ``rpython/bin/rpython`` translation entry
point which takes arguments of this form:
.. parsed-literal::
- ./translate.py <`translation options`_> <target>
+ ./rpython/bin/rpython <`translation options`_> <target>
For the common case of ``<target>`` being ``targetpypystandalone.py``,
you can then pass the `object space options`_ after
@@ -28,7 +28,7 @@
.. parsed-literal::
- ./translate.py <`translation options`_> targetpypystandalone.py <`objspace
options`_>
+ ./rpython/bin/rpython <`translation options`_> targetpypystandalone.py
<`objspace options`_>
There is an `overview`_ of all command line arguments that can be
passed in either position.
diff --git a/pypy/doc/config/opt.rst b/pypy/doc/config/opt.rst
--- a/pypy/doc/config/opt.rst
+++ b/pypy/doc/config/opt.rst
@@ -4,8 +4,8 @@
This meta-option selects a default set of optimization
settings to use during a translation. Usage::
- translate.py --opt=#
- translate.py -O#
+ bin/rpython --opt=#
+ bin/rpython -O#
where ``#`` is the desired optimization level. The valid choices are:
diff --git a/pypy/doc/config/translation.dont_write_c_files.txt
b/pypy/doc/config/translation.dont_write_c_files.txt
--- a/pypy/doc/config/translation.dont_write_c_files.txt
+++ b/pypy/doc/config/translation.dont_write_c_files.txt
@@ -1,4 +1,4 @@
write the generated C files to ``/dev/null`` instead of to the disk. Useful if
-you want to use translate.py as a benchmark and don't want to access the disk.
+you want to use translation as a benchmark and don't want to access the disk.
.. _`translation documentation`: ../translation.html
diff --git a/pypy/doc/config/translation.fork_before.txt
b/pypy/doc/config/translation.fork_before.txt
--- a/pypy/doc/config/translation.fork_before.txt
+++ b/pypy/doc/config/translation.fork_before.txt
@@ -1,4 +1,4 @@
This is an option mostly useful when working on the PyPy toolchain. If you use
-it, translate.py will fork before the specified phase. If the translation
+it, translation will fork before the specified phase. If the translation
crashes after that fork, you can fix the bug in the toolchain, and continue
translation at the fork-point.
diff --git a/pypy/doc/cppyy.rst b/pypy/doc/cppyy.rst
--- a/pypy/doc/cppyy.rst
+++ b/pypy/doc/cppyy.rst
@@ -122,7 +122,7 @@
$ hg up reflex-support # optional
# This example shows python, but using pypy-c is faster and uses less
memory
- $ python rpython/translator/goal/translate.py --opt=jit
pypy/goal/targetpypystandalone --withmod-cppyy
+ $ python rpython/bin/rpython --opt=jit pypy/goal/targetpypystandalone
--withmod-cppyy
This will build a ``pypy-c`` that includes the cppyy module, and through that,
Reflex support.
diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -315,13 +315,28 @@
- ``complex``
+ - ``str`` (empty or single-character strings only)
+
+ - ``unicode`` (empty or single-character strings only)
+
+ - ``tuple`` (empty tuples only)
+
+ - ``frozenset`` (empty frozenset only)
+
This change requires some changes to ``id`` as well. ``id`` fulfills the
following condition: ``x is y <=> id(x) == id(y)``. Therefore ``id`` of the
above types will return a value that is computed from the argument, and can
thus be larger than ``sys.maxint`` (i.e. it can be an arbitrary long).
-Notably missing from the list above are ``str`` and ``unicode``. If your
-code relies on comparing strings with ``is``, then it might break in PyPy.
+Note that strings of length 2 or greater can be equal without being
+identical. Similarly, ``x is (2,)`` is not necessarily true even if
+``x`` contains a tuple and ``x == (2,)``. The uniqueness rules apply
+only to the particular cases described above. The ``str``, ``unicode``,
+``tuple`` and ``frozenset`` rules were added in PyPy 5.4; before that, a
+test like ``if x is "?"`` or ``if x is ()`` could fail even if ``x`` was
+equal to ``"?"`` or ``()``. The new behavior added in PyPy 5.4 is
+closer to CPython's, which caches precisely the empty tuple/frozenset,
+and (generally but not always) the strings and unicodes of length <= 1.
Note that for floats there "``is``" only one object per "bit pattern"
of the float. So ``float('nan') is float('nan')`` is true on PyPy,
diff --git a/pypy/doc/faq.rst b/pypy/doc/faq.rst
--- a/pypy/doc/faq.rst
+++ b/pypy/doc/faq.rst
@@ -335,3 +335,60 @@
This will disable SELinux's protection and allow PyPy to configure correctly.
Be sure to enable it again if you need it!
+
+
+How should I report a bug?
+--------------------------
+
+Our bug tracker is here: https://bitbucket.org/pypy/pypy/issues/
+
+Missing features or incompatibilities with CPython are considered
+bugs, and they are welcome. (See also our list of `known
+incompatibilities`__.)
+
+.. __: http://pypy.org/compat.html
+
+For bugs of the kind "I'm getting a PyPy crash or a strange
+exception", please note that: **We can't do anything without
+reproducing the bug ourselves**. We cannot do anything with
+tracebacks from gdb, or core dumps. This is not only because the
+standard PyPy is compiled without debug symbols. The real reason is
+that a C-level traceback is usually of no help at all in PyPy.
+Debugging PyPy can be annoying.
+
+In more details:
+
+* First, please give the exact PyPy version, and the OS.
+
+* It might help focus our search if we know if the bug can be
+ reproduced on a "``pypy --jit off``" or not. If "``pypy --jit
+ off``" always works, then the problem might be in the JIT.
+ Otherwise, we know we can ignore that part.
+
+* If you got the bug using only Open Source components, please give a
+ step-by-step guide that we can follow to reproduce the problem
+ ourselves. Don't assume we know anything about any program other
+ than PyPy. We would like a guide that we can follow point by point
+ (without guessing or having to figure things out)
+ on a machine similar to yours, starting from a bare PyPy, until we
+ see the same problem. (If you can, you can try to reduce the number
+ of steps and the time it needs to run, but that is not mandatory.)
+
+* If the bug involves Closed Source components, or just too many Open
+ Source components to install them all ourselves, then maybe you can
+ give us some temporary ssh access to a machine where the bug can be
+ reproduced. Or, maybe we can download a VirtualBox or VMWare
+ virtual machine where the problem occurs.
+
+* If giving us access would require us to use tools other than ssh,
+ make appointments, or sign a NDA, then we can consider a commerical
+ support contract for a small sum of money.
+
+* If even that is not possible for you, then sorry, we can't help.
+
+Of course, you can try to debug the problem yourself, and we can help
+you get started if you ask on the #pypy IRC channel, but be prepared:
+debugging an annoying PyPy problem usually involves quite a lot of gdb
+in auto-generated C code, and at least some knowledge about the
+various components involved, from PyPy's own RPython source code to
+the GC and possibly the JIT.
diff --git a/pypy/doc/index-of-release-notes.rst
b/pypy/doc/index-of-release-notes.rst
--- a/pypy/doc/index-of-release-notes.rst
+++ b/pypy/doc/index-of-release-notes.rst
@@ -6,6 +6,7 @@
.. toctree::
+ release-pypy2.7-v5.3.1.rst
release-pypy2.7-v5.3.0.rst
release-5.1.1.rst
release-5.1.0.rst
diff --git a/pypy/doc/index-of-whatsnew.rst b/pypy/doc/index-of-whatsnew.rst
--- a/pypy/doc/index-of-whatsnew.rst
+++ b/pypy/doc/index-of-whatsnew.rst
@@ -7,6 +7,7 @@
.. toctree::
whatsnew-head.rst
+ whatsnew-pypy2-5.3.1.rst
whatsnew-pypy2-5.3.0.rst
whatsnew-5.1.0.rst
whatsnew-5.0.0.rst
diff --git a/pypy/doc/install.rst b/pypy/doc/install.rst
--- a/pypy/doc/install.rst
+++ b/pypy/doc/install.rst
@@ -39,17 +39,16 @@
library.
If you want to install 3rd party libraries, the most convenient way is
-to install pip_ (unless you want to install virtualenv as explained
-below; then you can directly use pip inside virtualenvs):
+to install pip_ using ensurepip_ (unless you want to install virtualenv as
+explained below; then you can directly use pip inside virtualenvs):
.. code-block:: console
- $ curl -O https://bootstrap.pypa.io/get-pip.py
- $ ./pypy-2.1/bin/pypy get-pip.py
- $ ./pypy-2.1/bin/pip install pygments # for example
+ $ ./pypy-xxx/bin/pypy -m ensurepip
+ $ ./pypy-xxx/bin/pip install pygments # for example
-Third party libraries will be installed in ``pypy-2.1/site-packages``, and
-the scripts in ``pypy-2.1/bin``.
+Third party libraries will be installed in ``pypy-xxx/site-packages``, and
+the scripts in ``pypy-xxx/bin``.
Installing using virtualenv
@@ -61,7 +60,7 @@
checkout::
# from a tarball
- $ virtualenv -p /opt/pypy-c-jit-41718-3fb486695f20-linux/bin/pypy
my-pypy-env
+ $ virtualenv -p /opt/pypy-xxx/bin/pypy my-pypy-env
# from the mercurial checkout
$ virtualenv -p /path/to/pypy/pypy/translator/goal/pypy-c my-pypy-env
@@ -69,7 +68,7 @@
Note that bin/python is now a symlink to bin/pypy.
.. _pip: http://pypi.python.org/pypi/pip
-
+.. _ensurepip: https://docs.python.org/2.7/library/ensurepip.html
Building PyPy yourself
~~~~~~~~~~~~~~~~~~~~~~
diff --git a/pypy/doc/release-pypy2.7-v5.3.1.rst
b/pypy/doc/release-pypy2.7-v5.3.1.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-pypy2.7-v5.3.1.rst
@@ -0,0 +1,41 @@
+==========
+PyPy 5.3.1
+==========
+
+We have released a bugfix for PyPy2.7-v5.3.0, released last week,
+due to issues_ reported by users.
+
+Thanks to those who reported the issues.
+
+.. _issues: http://doc.pypy.org/en/latest/whatsnew-pypy2-5.3.1.html
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7. It's fast (`PyPy and CPython 2.7.x`_ performance comparison)
+due to its integrated tracing JIT compiler.
+
+We also welcome developers of other
+`dynamic languages`_ to see what RPython can do for them.
+
+This release supports:
+
+ * **x86** machines on most common operating systems
+ (Linux 32/64, Mac OS X 64, Windows 32, OpenBSD, FreeBSD),
+
+ * newer **ARM** hardware (ARMv6 or ARMv7, with VFPv3) running Linux,
+
+ * big- and little-endian variants of **PPC64** running Linux,
+
+ * **s390x** running Linux
+
+.. _`PyPy and CPython 2.7.x`: http://speed.pypy.org
+.. _`dynamic languages`: http://pypyjs.org
+
+Please update, and continue to help us make PyPy better.
+
+Cheers
+
+The PyPy Team
+
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
@@ -5,6 +5,13 @@
.. this is a revision shortly after release-pypy2.7-v5.3
.. startrev: 873218a739f1
+.. 418b05f95db5
+Improve CPython compatibility for ``is``. Now code like ``if x is ():``
+works the same way as it does on CPython. See
http://pypy.readthedocs.io/en/latest/cpython_differences.html#object-identity-of-primitive-values-is-and-id
.
+
+.. pull request #455
+Add sys.{get,set}dlopenflags, for cpyext extensions.
+
.. branch: fix-gen-dfa
Resolves an issue with the generator script to build the dfa for Python syntax.
@@ -19,3 +26,82 @@
.. branch: s390x-5.3-catchup
Implement the backend related changes for s390x.
+
+.. branch: incminimark-ll_assert
+.. branch: vmprof-openbsd
+
+.. branch: testing-cleanup
+
+Simplify handling of interp-level tests and make it more forward-
+compatible.
+
+.. branch: pyfile-tell
+Sync w_file with the c-level FILE* before returning FILE* in PyFile_AsFile
+
+.. branch: rw-PyString_AS_STRING
+Allow rw access to the char* returned from PyString_AS_STRING, also refactor
+PyStringObject to look like cpython's and allow subclassing PyString_Type and
+PyUnicode_Type
+
+.. branch: save_socket_errno
+
+Bug fix: if ``socket.socket()`` failed, the ``socket.error`` did not show
+the errno of the failing system call, but instead some random previous
+errno.
+
+.. branch: PyTuple_Type-subclass
+
+Refactor PyTupleObject to look like cpython's and allow subclassing
+PyTuple_Type
+
+.. branch: call-via-pyobj
+
+Use offsets from PyTypeObject to find actual c function to call rather than
+fixed functions, allows function override after PyType_Ready is called
+
+.. branch: issue2335
+
+Avoid exhausting the stack in the JIT due to successive guard
+failures in the same Python function ending up as successive levels of
+RPython functions, while at app-level the traceback is very short
+
+.. branch: use-madv-free
+
+Try harder to memory to the OS. See e.g. issue #2336. Note that it does
+not show up as a reduction of the VIRT column in ``top``, and the RES
+column might also not show the reduction, particularly on Linux >= 4.5 or
+on OS/X: it uses MADV_FREE, which only marks the pages as returnable to
+the OS if the memory is low.
+
+.. branch: cpyext-slotdefs2
+
+Fill in more slots when creating a PyTypeObject from a W_TypeObject
+More slots are still TBD, like tp_print and richcmp
+
+.. branch: json-surrogates
+
+Align json module decode with the cpython's impl, fixes issue 2345
+
+.. branch: issue2343
+
+Copy CPython's logic more closely for handling of ``__instancecheck__()``
+and ``__subclasscheck__()``. Fixes issue 2343.
+
+.. branch: msvcrt-cffi
+
+Rewrite the Win32 dependencies of 'subprocess' to use cffi instead
+of ctypes. This avoids importing ctypes in many small programs and
+scripts, which in turn avoids enabling threads (because ctypes
+creates callbacks at import time, and callbacks need threads).
+
+.. branch: new-jit-log
+
+The new logging facility that integrates with and adds features to vmprof.com.
+
+.. branch: jitlog-32bit
+
+Resolve issues to use the new logging facility on a 32bit system
+
+.. branch: ep2016sprint
+
+Trying harder to make hash(-1) return -2, like it does on CPython
diff --git a/pypy/doc/whatsnew-pypy2-5.3.1.rst
b/pypy/doc/whatsnew-pypy2-5.3.1.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/whatsnew-pypy2-5.3.1.rst
@@ -0,0 +1,15 @@
+===========================
+What's new in PyPy2.7 5.3.1
+===========================
+
+.. this is a revision shortly after release-pypy2.7-v5.3.0
+.. startrev: f4d726d1a010
+
+
+A bug-fix release, merging these changes:
+
+ * Add include guards to pymem.h, fixes issue #2321
+
+ * Make vmprof build on OpenBSD, from pull request #456
+
+ * Fix ``bytearray('').replace('a', 'ab')``, issue #2324
diff --git a/pypy/interpreter/astcompiler/astbuilder.py
b/pypy/interpreter/astcompiler/astbuilder.py
--- a/pypy/interpreter/astcompiler/astbuilder.py
+++ b/pypy/interpreter/astcompiler/astbuilder.py
@@ -416,28 +416,12 @@
try_node.get_lineno(), try_node.get_column())
def handle_with_stmt(self, with_node, is_async):
- body = self.handle_suite(with_node.get_child(-1))
- i = with_node.num_children() - 1
- while True:
- i -= 2
- item = with_node.get_child(i)
- test = self.handle_expr(item.get_child(0))
- if item.num_children() == 3:
- target = self.handle_expr(item.get_child(2))
- self.set_context(target, ast.Store)
- else:
- target = None
if is_async:
wi = ast.AsyncWith(test, target, body, with_node.get_lineno(),
with_node.get_column())
else:
wi = ast.With(test, target, body, with_node.get_lineno(),
with_node.get_column())
- if i == 1:
- break
- body = [wi]
- return wi
-
def handle_with_item(self, item_node):
test = self.handle_expr(item_node.get_child(0))
if item_node.num_children() == 3:
diff --git a/pypy/interpreter/astcompiler/test/test_astbuilder.py
b/pypy/interpreter/astcompiler/test/test_astbuilder.py
--- a/pypy/interpreter/astcompiler/test/test_astbuilder.py
+++ b/pypy/interpreter/astcompiler/test/test_astbuilder.py
@@ -1129,7 +1129,7 @@
assert space.eq_w(s.s, space.wrap("hi implicitly extra"))
s = self.get_first_expr("b'hi' b' implicitly' b' extra'")
assert isinstance(s, ast.Bytes)
- assert space.eq_w(s.s, space.wrapbytes("hi implicitly extra"))
+ assert space.eq_w(s.s, space.newbytes("hi implicitly extra"))
raises(SyntaxError, self.get_first_expr, "b'hello' 'world'")
sentence = u"Die Männer ärgen sich!"
source = u"# coding: utf-7\nstuff = '%s'" % (sentence,)
@@ -1184,7 +1184,7 @@
s = ast_from_node(space, tree, info).body[0].value
assert isinstance(s, ast.Str)
assert space.eq_w(s.s, space.wrap(u'Ç'))
-
+
def test_string_bug(self):
space = self.space
source = '# -*- encoding: utf8 -*-\nstuff = "x \xc3\xa9 \\n"\n'
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py
b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -965,7 +965,20 @@
"""
self.simple_test(source, 'ok', 1)
- def test_remove_docstring(self):
+ @py.test.mark.parametrize('expr, result', [
+ ("f1.__doc__", None),
+ ("f2.__doc__", 'docstring'),
+ ("f2()", 'docstring'),
+ ("f3.__doc__", None),
+ ("f3()", 'bar'),
+ ("C1.__doc__", None),
+ ("C2.__doc__", 'docstring'),
+ ("C3.field", 'not docstring'),
+ ("C4.field", 'docstring'),
+ ("C4.__doc__", 'docstring'),
+ ("C4.__doc__", 'docstring'),
+ ("__doc__", None),])
+ def test_remove_docstring(self, expr, result):
source = '"module_docstring"\n' + """if 1:
def f1():
'docstring'
@@ -989,19 +1002,7 @@
code_w.remove_docstrings(self.space)
dict_w = self.space.newdict();
code_w.exec_code(self.space, dict_w, dict_w)
-
- yield self.check, dict_w, "f1.__doc__", None
- yield self.check, dict_w, "f2.__doc__", 'docstring'
- yield self.check, dict_w, "f2()", 'docstring'
- yield self.check, dict_w, "f3.__doc__", None
- yield self.check, dict_w, "f3()", 'bar'
- yield self.check, dict_w, "C1.__doc__", None
- yield self.check, dict_w, "C2.__doc__", 'docstring'
- yield self.check, dict_w, "C3.field", 'not docstring'
- yield self.check, dict_w, "C4.field", 'docstring'
- yield self.check, dict_w, "C4.__doc__", 'docstring'
- yield self.check, dict_w, "C4.__doc__", 'docstring'
- yield self.check, dict_w, "__doc__", None
+ self.check(dict_w, expr, result)
def test_assert_skipping(self):
space = self.space
diff --git a/pypy/interpreter/astcompiler/tools/asdl_py.py
b/pypy/interpreter/astcompiler/tools/asdl_py.py
--- a/pypy/interpreter/astcompiler/tools/asdl_py.py
+++ b/pypy/interpreter/astcompiler/tools/asdl_py.py
@@ -422,7 +422,7 @@
if not (space.isinstance_w(w_obj, space.w_str) or
space.isinstance_w(w_obj, space.w_unicode)):
raise oefmt(space.w_TypeError,
- "AST string must be of type str or unicode")
+ "AST string must be of type str or unicode")
return w_obj
def get_field(space, w_node, name, optional):
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1056,7 +1056,7 @@
return (None, None)
def newlist_bytes(self, list_s):
- return self.newlist([self.wrapbytes(s) for s in list_s])
+ return self.newlist([self.newbytes(s) for s in list_s])
def newlist_unicode(self, list_u):
return self.newlist([self.wrap(u) for u in list_u])
@@ -1072,7 +1072,7 @@
return make_empty_list_with_size(self, sizehint)
def wrap_fsdecoded(self, x):
- return self.fsdecode(self.wrapbytes(x))
+ return self.fsdecode(self.newbytes(x))
@jit.unroll_safe
def exception_match(self, w_exc_type, w_check_class):
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -958,7 +958,7 @@
elif name != '__args__' and name != 'args_w':
spec = unwrap_spec[i]
if isinstance(defaultval, str) and spec not in [str]:
- defs_w.append(space.wrapbytes(defaultval))
+ defs_w.append(space.newbytes(defaultval))
else:
defs_w.append(space.wrap(defaultval))
if self._code._unwrap_spec:
@@ -978,7 +978,7 @@
if isinstance(spec, WrappedDefault):
default_value = spec.default_value
if isinstance(default_value, str):
- w_default = space.wrapbytes(default_value)
+ w_default = space.newbytes(default_value)
else:
w_default = space.wrap(default_value)
assert isinstance(w_default, W_Root)
diff --git a/pypy/interpreter/main.py b/pypy/interpreter/main.py
--- a/pypy/interpreter/main.py
+++ b/pypy/interpreter/main.py
@@ -19,7 +19,7 @@
def compilecode(space, source, filename, cmd='exec'):
w = space.wrap
w_code = space.builtin.call(
- 'compile', space.wrapbytes(source), space.wrap_fsdecoded(filename),
+ 'compile', space.newbytes(source), space.wrap_fsdecoded(filename),
w(cmd), w(0), w(0))
pycode = space.interp_w(eval.Code, w_code)
return pycode
diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py
--- a/pypy/interpreter/pycode.py
+++ b/pypy/interpreter/pycode.py
@@ -28,6 +28,7 @@
def unpack_str_tuple(space,w_str_tuple):
return [space.str_w(w_el) for w_el in space.unpackiterable(w_str_tuple)]
+
# Magic numbers for the bytecode version in code objects.
# See comments in pypy/module/imp/importing.
cpython_magic, = struct.unpack("<i", imp.get_magic()) # host magic number
@@ -420,14 +421,14 @@
w(self.co_nlocals),
w(self.co_stacksize),
w(self.co_flags),
- space.wrapbytes(self.co_code),
+ space.newbytes(self.co_code),
space.newtuple(self.co_consts_w),
space.newtuple(self.co_names_w),
space.newtuple([w(v) for v in self.co_varnames]),
w(self.co_filename),
w(self.co_name),
w(self.co_firstlineno),
- space.wrapbytes(self.co_lnotab),
+ space.newbytes(self.co_lnotab),
space.newtuple([w(v) for v in self.co_freevars]),
space.newtuple([w(v) for v in self.co_cellvars]),
w(self.magic),
@@ -448,7 +449,7 @@
space = self.space
# co_name should be an identifier
name = self.co_name.decode('utf-8')
- fn = space.fsdecode_w(space.wrapbytes(self.co_filename))
+ fn = space.fsdecode_w(space.newbytes(self.co_filename))
return space.wrap(u'<code object %s at 0x%s, file "%s", line %d>' % (
name, unicode(self.getaddrstring(space)), fn,
-1 if self.co_firstlineno == 0 else self.co_firstlineno))
diff --git a/pypy/interpreter/pyparser/automata.py
b/pypy/interpreter/pyparser/automata.py
--- a/pypy/interpreter/pyparser/automata.py
+++ b/pypy/interpreter/pyparser/automata.py
@@ -13,12 +13,11 @@
# PYPY Modification: removed the EMPTY class as it's not needed here
-# PYPY Modification: we don't need a particuliar DEFAULT class here
-# a simple None works fine.
-# (Having a DefaultClass inheriting from str makes
-# the annotator crash)
-DEFAULT = "\00default" # XXX hack, the rtyper does not support dict of with
str|None keys
- # anyway using dicts doesn't seem the best final way to
store these char indexed tables
+# PYPY Modification: DEFAULT is a singleton, used only in the pre-RPython
+# dicts (see pytokenize.py). Then DFA.__init__() turns these dicts into
+# more compact strings.
+DEFAULT = object()
+
# PYPY Modification : removed all automata functions (any, maybe,
# newArcPair, etc.)
diff --git a/pypy/interpreter/pyparser/error.py
b/pypy/interpreter/pyparser/error.py
--- a/pypy/interpreter/pyparser/error.py
+++ b/pypy/interpreter/pyparser/error.py
@@ -25,7 +25,7 @@
'replace')
w_text = space.wrap(text)
if self.filename is not None:
- w_filename = space.fsdecode(space.wrapbytes(self.filename))
+ w_filename = space.fsdecode(space.newbytes(self.filename))
return space.newtuple([space.wrap(self.msg),
space.newtuple([w_filename,
space.wrap(self.lineno),
diff --git a/pypy/interpreter/pyparser/gendfa.py
b/pypy/interpreter/pyparser/gendfa.py
--- a/pypy/interpreter/pyparser/gendfa.py
+++ b/pypy/interpreter/pyparser/gendfa.py
@@ -294,7 +294,7 @@
i = 0
for k, v in sorted(state.items()):
i += 1
- if k == '\x00default':
+ if k == DEFAULT:
k = "automata.DEFAULT"
else:
k = repr(k)
diff --git a/pypy/interpreter/pyparser/parsestring.py
b/pypy/interpreter/pyparser/parsestring.py
--- a/pypy/interpreter/pyparser/parsestring.py
+++ b/pypy/interpreter/pyparser/parsestring.py
@@ -85,13 +85,13 @@
if rawmode or '\\' not in substr:
if not unicode_literal:
- return space.wrapbytes(substr)
+ return space.newbytes(substr)
else:
v = unicodehelper.decode_utf8(space, substr)
return space.wrap(v)
v = PyString_DecodeEscape(space, substr, 'strict', encoding)
- return space.wrapbytes(v)
+ return space.newbytes(v)
def decode_unicode_utf8(space, s, ps, q):
# ****The Python 2.7 version, producing UTF-32 escapes****
diff --git a/pypy/interpreter/pyparser/pyparse.py
b/pypy/interpreter/pyparser/pyparse.py
--- a/pypy/interpreter/pyparser/pyparse.py
+++ b/pypy/interpreter/pyparser/pyparse.py
@@ -7,7 +7,7 @@
def recode_to_utf8(space, bytes, encoding):
if encoding == 'utf-8':
return bytes
- w_text = space.call_method(space.wrapbytes(bytes), "decode",
+ w_text = space.call_method(space.newbytes(bytes), "decode",
space.wrap(encoding))
w_recoded = space.call_method(w_text, "encode", space.wrap("utf-8"))
return space.bytes_w(w_recoded)
diff --git a/pypy/interpreter/test/test_gateway.py
b/pypy/interpreter/test/test_gateway.py
--- a/pypy/interpreter/test/test_gateway.py
+++ b/pypy/interpreter/test/test_gateway.py
@@ -471,12 +471,12 @@
space = self.space
w = space.wrap
def f(filename):
- return space.wrapbytes(filename)
+ return space.newbytes(filename)
app_f = gateway.interp2app_temp(f, unwrap_spec=['fsencode'])
w_app_f = space.wrap(app_f)
assert space.eq_w(
space.call_function(w_app_f, w(u'\udc80')),
- space.wrapbytes('\x80'))
+ space.newbytes('\x80'))
def test_interp2app_unwrap_spec_typechecks(self):
from rpython.rlib.rarithmetic import r_longlong
@@ -801,7 +801,7 @@
w_g = space.wrap(gateway.interp2app_temp(g))
args = argument.Arguments(space, [])
w_res = space.call_args(w_g, args)
- assert space.eq_w(w_res, space.wrapbytes('foo'))
+ assert space.eq_w(w_res, space.newbytes('foo'))
class AppTestPyTestMark:
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -345,13 +345,13 @@
def interp_attrproperty_bytes(name, cls, doc=None):
"NOT_RPYTHON: initialization-time only"
def fget(space, obj):
- return space.wrapbytes(getattr(obj, name))
+ return space.newbytes(getattr(obj, name))
return GetSetProperty(fget, cls=cls, doc=doc)
def interp_attrproperty_fsdecode(name, cls, doc=None):
"NOT_RPYTHON: initialization-time only"
def fget(space, obj):
- return space.fsdecode(space.wrapbytes(getattr(obj, name)))
+ return space.fsdecode(space.newbytes(getattr(obj, name)))
return GetSetProperty(fget, cls=cls, doc=doc)
def interp_attrproperty_w(name, cls, doc=None):
diff --git a/pypy/interpreter/unicodehelper.py
b/pypy/interpreter/unicodehelper.py
--- a/pypy/interpreter/unicodehelper.py
+++ b/pypy/interpreter/unicodehelper.py
@@ -18,7 +18,7 @@
startingpos, endingpos):
raise OperationError(space.w_UnicodeDecodeError,
space.newtuple([space.wrap(encoding),
- space.wrapbytes(s),
+ space.newbytes(s),
space.wrap(startingpos),
space.wrap(endingpos),
space.wrap(msg)]))
@@ -111,7 +111,7 @@
return space.call_method(w_uni, 'encode',
getfilesystemencoding(space),
space.wrap('surrogateescape'))
- return space.wrapbytes(bytes)
+ return space.newbytes(bytes)
def encode(space, w_data, encoding=None, errors='strict'):
from pypy.objspace.std.unicodeobject import encode_object
@@ -141,9 +141,7 @@
return result
def encode_utf8(space, uni, allow_surrogates=False):
- # Note that this function never raises UnicodeEncodeError,
- # since surrogate pairs are allowed.
- # This is not the case with Python3.
+ # Note that Python3 tends to forbid lone surrogates
return runicode.unicode_encode_utf_8(
uni, len(uni), "strict",
errorhandler=encode_error_handler(space),
diff --git a/pypy/module/__builtin__/abstractinst.py
b/pypy/module/__builtin__/abstractinst.py
--- a/pypy/module/__builtin__/abstractinst.py
+++ b/pypy/module/__builtin__/abstractinst.py
@@ -43,9 +43,61 @@
raise # propagate other errors
return space.type(w_obj)
+
+# ---------- isinstance ----------
+
+
+def p_recursive_isinstance_w(space, w_inst, w_cls):
+ # Copied straight from CPython 2.7. Does not handle 'cls' being a tuple.
+ if space.isinstance_w(w_cls, space.w_type):
+ return p_recursive_isinstance_type_w(space, w_inst, w_cls)
+
+ check_class(space, w_cls, "isinstance() arg 2 must be a class, type,"
+ " or tuple of classes and types")
+ try:
+ w_abstractclass = space.getattr(w_inst, space.wrap('__class__'))
+ except OperationError as e:
+ if not e.match(space, space.w_AttributeError):
+ raise # propagate other errors
+ return False
+ else:
+ return p_abstract_issubclass_w(space, w_abstractclass, w_cls)
+
+
+def p_recursive_isinstance_type_w(space, w_inst, w_type):
+ # subfunctionality of p_recursive_isinstance_w(): assumes that w_type is
+ # a type object. Copied straight from CPython 2.7.
+ if space.isinstance_w(w_inst, w_type):
+ return True
+ try:
+ w_abstractclass = space.getattr(w_inst, space.wrap('__class__'))
+ except OperationError as e:
+ if not e.match(space, space.w_AttributeError):
+ raise # propagate other errors
+ else:
+ if w_abstractclass is not space.type(w_inst):
+ if space.isinstance_w(w_abstractclass, space.w_type):
+ return space.issubtype_w(w_abstractclass, w_type)
+ return False
+
+
@jit.unroll_safe
def abstract_isinstance_w(space, w_obj, w_klass_or_tuple,
allow_override=False):
"""Implementation for the full 'isinstance(obj, klass_or_tuple)'."""
+ # Copied from CPython 2.7's PyObject_Isinstance(). Additionally,
+ # if 'allow_override' is False (the default), then don't try to
+ # use a custom __instancecheck__ method.
+
+ # WARNING: backward compatibility function name here. CPython
+ # uses the name "abstract" to refer to the logic of handling
+ # class-like objects, with a "__bases__" attribute. This function
+ # here is not related to that and implements the full
+ # PyObject_IsInstance() logic.
+
+ # Quick test for an exact match
+ if space.type(w_obj) is w_klass_or_tuple:
+ return True
+
# -- case (anything, tuple)
# XXX it might be risky that the JIT sees this
if space.isinstance_w(w_klass_or_tuple, space.w_tuple):
@@ -55,64 +107,55 @@
return False
# -- case (anything, type)
- try:
- if allow_override:
- w_result = space.isinstance_allow_override(w_obj, w_klass_or_tuple)
- else:
- w_result = space.isinstance(w_obj, w_klass_or_tuple)
- except OperationError as e: # if w_klass_or_tuple was not a type, ignore
it
- if not e.match(space, space.w_TypeError):
- raise # propagate other errors
- else:
- if space.is_true(w_result):
- return True
- # From now on we know that w_klass_or_tuple is indeed a type.
- # Try also to compare it with obj.__class__, if this is not
- # the same as type(obj).
- w_pretendtype = abstract_getclass(space, w_obj)
- try:
- if space.is_w(w_pretendtype, space.type(w_obj)):
- return False # common case: obj.__class__ is type(obj)
- if not allow_override:
- return space.issubtype_w(w_pretendtype, w_klass_or_tuple)
- w_result = space.issubtype_allow_override(w_pretendtype,
- w_klass_or_tuple)
- except OperationError as e:
- if e.async(space):
- raise
- return False # ignore most exceptions
- else:
- return space.is_true(w_result)
+ if allow_override:
+ w_check = space.lookup(w_klass_or_tuple, "__instancecheck__")
+ if w_check is not None:
+ # this is the common case: all type objects have a method
+ # __instancecheck__. The one in the base 'type' type calls
+ # back p_recursive_isinstance_type_w() from the present module.
+ return space.is_true(space.get_and_call_function(
+ w_check, w_klass_or_tuple, w_obj))
- return _abstract_isinstance_w_helper(space, w_obj, w_klass_or_tuple)
+ return p_recursive_isinstance_w(space, w_obj, w_klass_or_tuple)
-def _abstract_isinstance_w_helper(space, w_obj, w_klass_or_tuple):
- # -- case (anything, abstract-class)
- check_class(space, w_klass_or_tuple,
- "isinstance() arg 2 must be a class, type,"
- " or tuple of classes and types")
- try:
- w_abstractclass = space.getattr(w_obj, space.wrap('__class__'))
- except OperationError as e:
- if e.async(space): # ignore most exceptions
- raise
- return False
- else:
- return _issubclass_recurse(space, w_abstractclass, w_klass_or_tuple)
+# ---------- issubclass ----------
@jit.unroll_safe
-def _issubclass_recurse(space, w_derived, w_top):
- """Internal helper for abstract cases. Here, w_top cannot be a tuple."""
- if space.is_w(w_derived, w_top):
- return True
- w_bases = _get_bases(space, w_derived)
- if w_bases is not None:
- for w_base in space.fixedview(w_bases):
- if _issubclass_recurse(space, w_base, w_top):
+def p_abstract_issubclass_w(space, w_derived, w_cls):
+ # Copied straight from CPython 2.7, function abstract_issubclass().
+ # Don't confuse this with the function abstract_issubclass_w() below.
+ # Here, w_cls cannot be a tuple.
+ while True:
+ if space.is_w(w_derived, w_cls):
+ return True
+ w_bases = _get_bases(space, w_derived)
+ if w_bases is None:
+ return False
+ bases_w = space.fixedview(w_bases)
+ last_index = len(bases_w) - 1
+ if last_index < 0:
+ return False
+ # Avoid recursivity in the single inheritance case; in general,
+ # don't recurse on the last item in the tuple (loop instead).
+ for i in range(last_index):
+ if p_abstract_issubclass_w(space, bases_w[i], w_cls):
return True
- return False
+ w_derived = bases_w[last_index]
+
+
+def p_recursive_issubclass_w(space, w_derived, w_cls):
+ # From CPython's function of the same name (which as far as I can tell
+ # is not recursive). Copied straight from CPython 2.7.
+ if (space.isinstance_w(w_cls, space.w_type) and
+ space.isinstance_w(w_derived, space.w_type)):
+ return space.issubtype_w(w_derived, w_cls)
+ #
+ check_class(space, w_derived, "issubclass() arg 1 must be a class")
+ check_class(space, w_cls, "issubclass() arg 2 must be a class"
+ " or tuple of classes")
+ return p_abstract_issubclass_w(space, w_derived, w_cls)
@jit.unroll_safe
@@ -120,32 +163,46 @@
allow_override=False):
"""Implementation for the full 'issubclass(derived, klass_or_tuple)'."""
- # -- case (class-like-object, tuple-of-classes)
+ # WARNING: backward compatibility function name here. CPython
+ # uses the name "abstract" to refer to the logic of handling
+ # class-like objects, with a "__bases__" attribute. This function
+ # here is not related to that and implements the full
+ # PyObject_IsSubclass() logic. There is also p_abstract_issubclass_w().
+
+ # -- case (anything, tuple-of-classes)
if space.isinstance_w(w_klass_or_tuple, space.w_tuple):
for w_klass in space.fixedview(w_klass_or_tuple):
if abstract_issubclass_w(space, w_derived, w_klass,
allow_override):
return True
return False
- # -- case (type, type)
- try:
- if not allow_override:
- return space.issubtype_w(w_derived, w_klass_or_tuple)
- w_result = space.issubtype_allow_override(w_derived, w_klass_or_tuple)
- except OperationError as e: # if one of the args was not a type, ignore
it
- if not e.match(space, space.w_TypeError):
- raise # propagate other errors
- else:
- return space.is_true(w_result)
+ # -- case (anything, type)
+ if allow_override:
+ w_check = space.lookup(w_klass_or_tuple, "__subclasscheck__")
+ if w_check is not None:
+ # this is the common case: all type objects have a method
+ # __subclasscheck__. The one in the base 'type' type calls
+ # back p_recursive_issubclass_w() from the present module.
+ return space.is_true(space.get_and_call_function(
+ w_check, w_klass_or_tuple, w_derived))
- check_class(space, w_derived, "issubclass() arg 1 must be a class")
- # from here on, we are sure that w_derived is a class-like object
+ return p_recursive_issubclass_w(space, w_derived, w_klass_or_tuple)
- # -- case (class-like-object, abstract-class)
- check_class(space, w_klass_or_tuple,
- "issubclass() arg 2 must be a class, type,"
- " or tuple of classes and types")
- return _issubclass_recurse(space, w_derived, w_klass_or_tuple)
+
+# ------------------------------------------------------------
+# Exception helpers
+
+def exception_is_valid_obj_as_class_w(space, w_obj):
+ return BaseObjSpace.exception_is_valid_obj_as_class_w(space, w_obj)
+
+def exception_is_valid_class_w(space, w_cls):
+ return BaseObjSpace.exception_is_valid_class_w(space, w_cls)
+
+def exception_getclass(space, w_obj):
+ return BaseObjSpace.exception_getclass(space, w_obj)
+
+def exception_issubclass_w(space, w_cls1, w_cls2):
+ return BaseObjSpace.exception_issubclass_w(space, w_cls1, w_cls2)
# ____________________________________________________________
# App-level interface
diff --git a/pypy/module/__builtin__/test/test_abstractinst.py
b/pypy/module/__builtin__/test/test_abstractinst.py
--- a/pypy/module/__builtin__/test/test_abstractinst.py
+++ b/pypy/module/__builtin__/test/test_abstractinst.py
@@ -226,3 +226,26 @@
c = C()
assert isinstance(c, C)
assert not called
+
+ def test_instancecheck_exception_not_eaten(self):
+ class M(object):
+ def __instancecheck__(self, obj):
+ raise TypeError("foobar")
+
+ e = raises(TypeError, isinstance, 42, M())
+ assert str(e.value) == "foobar"
+
+ def test_issubclass_exception_not_eaten(self):
+ class M(object):
+ def __subclasscheck__(self, subcls):
+ raise TypeError("foobar")
+
+ e = raises(TypeError, issubclass, 42, M())
+ assert str(e.value) == "foobar"
+
+ def test_issubclass_no_fallback(self):
+ class M(object):
+ def __subclasscheck__(self, subcls):
+ return False
+
+ assert issubclass(42, M()) is False
diff --git a/pypy/module/__pypy__/interp_builders.py
b/pypy/module/__pypy__/interp_builders.py
--- a/pypy/module/__pypy__/interp_builders.py
+++ b/pypy/module/__pypy__/interp_builders.py
@@ -40,7 +40,7 @@
s = self.builder.build()
self.builder = None
if strtype is str:
- return space.wrapbytes(s)
+ return space.newbytes(s)
else:
return space.wrap(s)
diff --git a/pypy/module/__pypy__/interp_intop.py
b/pypy/module/__pypy__/interp_intop.py
--- a/pypy/module/__pypy__/interp_intop.py
+++ b/pypy/module/__pypy__/interp_intop.py
@@ -2,21 +2,10 @@
from rpython.rtyper.lltypesystem import lltype
from rpython.rtyper.lltypesystem.lloperation import llop
from rpython.rlib.rarithmetic import r_uint, intmask
+from rpython.rlib.rarithmetic import int_c_div, int_c_mod
from rpython.rlib import jit
-# XXX maybe temporary: hide llop.int_{floordiv,mod} from the JIT,
-# because now it expects only Python-style divisions, not the
-# C-style divisions of these two ll operations
[email protected]_look_inside
-def _int_floordiv(n, m):
- return llop.int_floordiv(lltype.Signed, n, m)
-
[email protected]_look_inside
-def _int_mod(n, m):
- return llop.int_mod(lltype.Signed, n, m)
-
-
@unwrap_spec(n=int, m=int)
def int_add(space, n, m):
return space.wrap(llop.int_add(lltype.Signed, n, m))
@@ -31,11 +20,11 @@
@unwrap_spec(n=int, m=int)
def int_floordiv(space, n, m):
- return space.wrap(_int_floordiv(n, m))
+ return space.wrap(int_c_div(n, m))
@unwrap_spec(n=int, m=int)
def int_mod(space, n, m):
- return space.wrap(_int_mod(n, m))
+ return space.wrap(int_c_mod(n, m))
@unwrap_spec(n=int, m=int)
def int_lshift(space, n, m):
diff --git a/pypy/module/_cffi_backend/cbuffer.py
b/pypy/module/_cffi_backend/cbuffer.py
--- a/pypy/module/_cffi_backend/cbuffer.py
+++ b/pypy/module/_cffi_backend/cbuffer.py
@@ -55,9 +55,9 @@
start, stop, step, size = space.decode_index4(w_index,
self.buffer.getlength())
if step == 0:
- return space.wrapbytes(self.buffer.getitem(start))
+ return space.newbytes(self.buffer.getitem(start))
res = self.buffer.getslice(start, stop, step, size)
- return space.wrapbytes(res)
+ return space.newbytes(res)
def descr_setitem(self, space, w_index, w_newstring):
start, stop, step, size = space.decode_index4(w_index,
diff --git a/pypy/module/_cffi_backend/ccallback.py
b/pypy/module/_cffi_backend/ccallback.py
--- a/pypy/module/_cffi_backend/ccallback.py
+++ b/pypy/module/_cffi_backend/ccallback.py
@@ -220,6 +220,11 @@
if rffi.cast(lltype.Signed, res) != clibffi.FFI_OK:
raise oefmt(space.w_SystemError,
"libffi failed to build this callback")
+ if closure_ptr.c_user_data != unique_id:
+ raise oefmt(space.w_SystemError,
+ "ffi_prep_closure(): bad user_data (it seems that the "
+ "version of the libffi library seen at runtime is "
+ "different from the 'ffi.h' file seen at compile-time)")
def py_invoke(self, ll_res, ll_args):
jitdriver1.jit_merge_point(callback=self,
diff --git a/pypy/module/_cffi_backend/ctypeprim.py
b/pypy/module/_cffi_backend/ctypeprim.py
--- a/pypy/module/_cffi_backend/ctypeprim.py
+++ b/pypy/module/_cffi_backend/ctypeprim.py
@@ -84,7 +84,7 @@
if self.size == 1:
with cdataobj as ptr:
s = ptr[0]
- return self.space.wrapbytes(s)
+ return self.space.newbytes(s)
return W_CType.string(self, cdataobj, maxlen)
def unpack_ptr(self, w_ctypeptr, ptr, length):
@@ -126,7 +126,7 @@
return self.space.wrap(ord(cdata[0]))
def convert_to_object(self, cdata):
- return self.space.wrapbytes(cdata[0])
+ return self.space.newbytes(cdata[0])
def _convert_to_char(self, w_ob):
space = self.space
@@ -146,7 +146,7 @@
def unpack_ptr(self, w_ctypeptr, ptr, length):
s = rffi.charpsize2str(ptr, length)
- return self.space.wrapbytes(s)
+ return self.space.newbytes(s)
# XXX explicitly use an integer type instead of lltype.UniChar here,
diff --git a/pypy/module/_cffi_backend/ctypeptr.py
b/pypy/module/_cffi_backend/ctypeptr.py
--- a/pypy/module/_cffi_backend/ctypeptr.py
+++ b/pypy/module/_cffi_backend/ctypeptr.py
@@ -122,7 +122,7 @@
s = rffi.charp2str(ptr)
else:
s = rffi.charp2strn(ptr, length)
- return space.wrapbytes(s)
+ return space.newbytes(s)
#
# pointer to a wchar_t: builds and returns a unicode
if self.is_unichar_ptr_or_array():
@@ -131,7 +131,7 @@
u = rffi.wcharp2unicode(cdata)
else:
u = rffi.wcharp2unicoden(cdata, length)
- return space.wrap(u)
+ return space.newunicode(u)
#
return W_CType.string(self, cdataobj, maxlen)
diff --git a/pypy/module/_cffi_backend/ctypestruct.py
b/pypy/module/_cffi_backend/ctypestruct.py
--- a/pypy/module/_cffi_backend/ctypestruct.py
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit