Author: Stian Andreassen Branch: math-improvements Changeset: r95498:a344a7cb2d95 Date: 2018-12-15 03:59 +0100 http://bitbucket.org/pypy/pypy/changeset/a344a7cb2d95/
Log: merge heads diff too long, truncating to 2000 out of 3510 lines diff --git a/extra_tests/__init__.py b/extra_tests/__init__.py new file mode 100644 diff --git a/pypy/module/test_lib_pypy/cffi_tests/__init__.py b/extra_tests/cffi_tests/__init__.py rename from pypy/module/test_lib_pypy/cffi_tests/__init__.py rename to extra_tests/cffi_tests/__init__.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/__init__.py b/extra_tests/cffi_tests/cffi0/__init__.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/__init__.py rename to extra_tests/cffi_tests/cffi0/__init__.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py b/extra_tests/cffi_tests/cffi0/backend_tests.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py rename to extra_tests/cffi_tests/cffi0/backend_tests.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py +++ b/extra_tests/cffi_tests/cffi0/backend_tests.py @@ -3,7 +3,7 @@ import platform import sys, ctypes from cffi import FFI, CDefError, FFIError, VerificationMissing -from pypy.module.test_lib_pypy.cffi_tests.support import * +from extra_tests.cffi_tests.support import * SIZE_OF_INT = ctypes.sizeof(ctypes.c_int) SIZE_OF_LONG = ctypes.sizeof(ctypes.c_long) diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/callback_in_thread.py b/extra_tests/cffi_tests/cffi0/callback_in_thread.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/callback_in_thread.py rename to extra_tests/cffi_tests/cffi0/callback_in_thread.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/distutils_module/setup.py b/extra_tests/cffi_tests/cffi0/snippets/distutils_module/setup.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/distutils_module/setup.py rename to extra_tests/cffi_tests/cffi0/snippets/distutils_module/setup.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/distutils_module/snip_basic_verify.py b/extra_tests/cffi_tests/cffi0/snippets/distutils_module/snip_basic_verify.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/distutils_module/snip_basic_verify.py rename to extra_tests/cffi_tests/cffi0/snippets/distutils_module/snip_basic_verify.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/distutils_package_1/setup.py b/extra_tests/cffi_tests/cffi0/snippets/distutils_package_1/setup.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/distutils_package_1/setup.py rename to extra_tests/cffi_tests/cffi0/snippets/distutils_package_1/setup.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/distutils_package_1/snip_basic_verify1/__init__.py b/extra_tests/cffi_tests/cffi0/snippets/distutils_package_1/snip_basic_verify1/__init__.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/distutils_package_1/snip_basic_verify1/__init__.py rename to extra_tests/cffi_tests/cffi0/snippets/distutils_package_1/snip_basic_verify1/__init__.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/distutils_package_2/setup.py b/extra_tests/cffi_tests/cffi0/snippets/distutils_package_2/setup.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/distutils_package_2/setup.py rename to extra_tests/cffi_tests/cffi0/snippets/distutils_package_2/setup.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/distutils_package_2/snip_basic_verify2/__init__.py b/extra_tests/cffi_tests/cffi0/snippets/distutils_package_2/snip_basic_verify2/__init__.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/distutils_package_2/snip_basic_verify2/__init__.py rename to extra_tests/cffi_tests/cffi0/snippets/distutils_package_2/snip_basic_verify2/__init__.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/infrastructure/setup.py b/extra_tests/cffi_tests/cffi0/snippets/infrastructure/setup.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/infrastructure/setup.py rename to extra_tests/cffi_tests/cffi0/snippets/infrastructure/setup.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/infrastructure/snip_infrastructure/__init__.py b/extra_tests/cffi_tests/cffi0/snippets/infrastructure/snip_infrastructure/__init__.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/infrastructure/snip_infrastructure/__init__.py rename to extra_tests/cffi_tests/cffi0/snippets/infrastructure/snip_infrastructure/__init__.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/setuptools_module/setup.py b/extra_tests/cffi_tests/cffi0/snippets/setuptools_module/setup.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/setuptools_module/setup.py rename to extra_tests/cffi_tests/cffi0/snippets/setuptools_module/setup.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/setuptools_module/snip_setuptools_verify.py b/extra_tests/cffi_tests/cffi0/snippets/setuptools_module/snip_setuptools_verify.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/setuptools_module/snip_setuptools_verify.py rename to extra_tests/cffi_tests/cffi0/snippets/setuptools_module/snip_setuptools_verify.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/setuptools_package_1/setup.py b/extra_tests/cffi_tests/cffi0/snippets/setuptools_package_1/setup.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/setuptools_package_1/setup.py rename to extra_tests/cffi_tests/cffi0/snippets/setuptools_package_1/setup.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py b/extra_tests/cffi_tests/cffi0/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py rename to extra_tests/cffi_tests/cffi0/snippets/setuptools_package_1/snip_setuptools_verify1/__init__.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/setuptools_package_2/setup.py b/extra_tests/cffi_tests/cffi0/snippets/setuptools_package_2/setup.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/setuptools_package_2/setup.py rename to extra_tests/cffi_tests/cffi0/snippets/setuptools_package_2/setup.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py b/extra_tests/cffi_tests/cffi0/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py rename to extra_tests/cffi_tests/cffi0/snippets/setuptools_package_2/snip_setuptools_verify2/__init__.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_cdata.py b/extra_tests/cffi_tests/cffi0/test_cdata.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/test_cdata.py rename to extra_tests/cffi_tests/cffi0/test_cdata.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ctypes.py b/extra_tests/cffi_tests/cffi0/test_ctypes.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ctypes.py rename to extra_tests/cffi_tests/cffi0/test_ctypes.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ctypes.py +++ b/extra_tests/cffi_tests/cffi0/test_ctypes.py @@ -1,6 +1,6 @@ # Generated by pypy/tool/import_cffi.py import py, sys -from pypy.module.test_lib_pypy.cffi_tests.cffi0 import backend_tests +from extra_tests.cffi_tests.cffi0 import backend_tests from cffi.backend_ctypes import CTypesBackend diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py b/extra_tests/cffi_tests/cffi0/test_ffi_backend.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py rename to extra_tests/cffi_tests/cffi0/test_ffi_backend.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py +++ b/extra_tests/cffi_tests/cffi0/test_ffi_backend.py @@ -1,8 +1,8 @@ # Generated by pypy/tool/import_cffi.py import py, sys, platform import pytest -from pypy.module.test_lib_pypy.cffi_tests.cffi0 import backend_tests, test_function, test_ownlib -from pypy.module.test_lib_pypy.cffi_tests.support import u +from extra_tests.cffi_tests.cffi0 import backend_tests, test_function, test_ownlib +from extra_tests.cffi_tests.support import u from cffi import FFI import _cffi_backend diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_function.py b/extra_tests/cffi_tests/cffi0/test_function.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/test_function.py rename to extra_tests/cffi_tests/cffi0/test_function.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_function.py +++ b/extra_tests/cffi_tests/cffi0/test_function.py @@ -4,8 +4,8 @@ import math, os, sys import ctypes.util from cffi.backend_ctypes import CTypesBackend -from pypy.module.test_lib_pypy.cffi_tests.udir import udir -from pypy.module.test_lib_pypy.cffi_tests.support import FdWriteCapture +from extra_tests.cffi_tests.udir import udir +from extra_tests.cffi_tests.support import FdWriteCapture from .backend_tests import needs_dlopen_none try: diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_model.py b/extra_tests/cffi_tests/cffi0/test_model.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/test_model.py rename to extra_tests/cffi_tests/cffi0/test_model.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ownlib.py b/extra_tests/cffi_tests/cffi0/test_ownlib.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ownlib.py rename to extra_tests/cffi_tests/cffi0/test_ownlib.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ownlib.py +++ b/extra_tests/cffi_tests/cffi0/test_ownlib.py @@ -1,9 +1,9 @@ # Generated by pypy/tool/import_cffi.py -import py, sys +import py, sys, os import subprocess, weakref from cffi import FFI from cffi.backend_ctypes import CTypesBackend -from pypy.module.test_lib_pypy.cffi_tests.support import u +from extra_tests.cffi_tests.support import u SOURCE = """\ @@ -115,10 +115,9 @@ def setup_class(cls): cls.module = None - from pypy.module.test_lib_pypy.cffi_tests.udir import udir + from extra_tests.cffi_tests.udir import udir udir.join('testownlib.c').write(SOURCE) if sys.platform == 'win32': - import os # did we already build it? if cls.Backend is CTypesBackend: dll_path = str(udir) + '\\testownlib1.dll' # only ascii for the ctypes backend @@ -149,10 +148,23 @@ os.rename(str(udir) + '\\testownlib.dll', dll_path) cls.module = dll_path else: + encoded = None + if cls.Backend is not CTypesBackend: + try: + unicode_name = u+'testownlibcaf\xe9' + encoded = unicode_name.encode(sys.getfilesystemencoding()) + if sys.version_info >= (3,): + encoded = str(unicode_name) + except UnicodeEncodeError: + pass + if encoded is None: + unicode_name = u+'testownlib' + encoded = str(unicode_name) subprocess.check_call( - 'cc testownlib.c -shared -fPIC -o testownlib.so', + "cc testownlib.c -shared -fPIC -o '%s.so'" % (encoded,), cwd=str(udir), shell=True) - cls.module = str(udir.join('testownlib.so')) + cls.module = os.path.join(str(udir), unicode_name + (u+'.so')) + print(repr(cls.module)) def test_getting_errno(self): if self.module is None: diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_parsing.py b/extra_tests/cffi_tests/cffi0/test_parsing.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/test_parsing.py rename to extra_tests/cffi_tests/cffi0/test_parsing.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_platform.py b/extra_tests/cffi_tests/cffi0/test_platform.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/test_platform.py rename to extra_tests/cffi_tests/cffi0/test_platform.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_unicode_literals.py b/extra_tests/cffi_tests/cffi0/test_unicode_literals.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/test_unicode_literals.py rename to extra_tests/cffi_tests/cffi0/test_unicode_literals.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_verify.py b/extra_tests/cffi_tests/cffi0/test_verify.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/test_verify.py rename to extra_tests/cffi_tests/cffi0/test_verify.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_verify.py +++ b/extra_tests/cffi_tests/cffi0/test_verify.py @@ -2,7 +2,7 @@ import py, re import sys, os, math, weakref from cffi import FFI, VerificationError, VerificationMissing, model, FFIError -from pypy.module.test_lib_pypy.cffi_tests.support import * +from extra_tests.cffi_tests.support import * lib_m = ['m'] @@ -1408,7 +1408,7 @@ def test_tmpdir(): import tempfile, os - from pypy.module.test_lib_pypy.cffi_tests.udir import udir + from extra_tests.cffi_tests.udir import udir tmpdir = tempfile.mkdtemp(dir=str(udir)) ffi = FFI() ffi.cdef("int foo(int);") @@ -1418,7 +1418,7 @@ def test_relative_to(): import tempfile, os - from pypy.module.test_lib_pypy.cffi_tests.udir import udir + from extra_tests.cffi_tests.udir import udir tmpdir = tempfile.mkdtemp(dir=str(udir)) ffi = FFI() ffi.cdef("int foo(int);") diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_verify2.py b/extra_tests/cffi_tests/cffi0/test_verify2.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/test_verify2.py rename to extra_tests/cffi_tests/cffi0/test_verify2.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_version.py b/extra_tests/cffi_tests/cffi0/test_version.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/test_version.py rename to extra_tests/cffi_tests/cffi0/test_version.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_vgen.py b/extra_tests/cffi_tests/cffi0/test_vgen.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/test_vgen.py rename to extra_tests/cffi_tests/cffi0/test_vgen.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_vgen2.py b/extra_tests/cffi_tests/cffi0/test_vgen2.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/test_vgen2.py rename to extra_tests/cffi_tests/cffi0/test_vgen2.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_zdistutils.py b/extra_tests/cffi_tests/cffi0/test_zdistutils.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/test_zdistutils.py rename to extra_tests/cffi_tests/cffi0/test_zdistutils.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_zdistutils.py +++ b/extra_tests/cffi_tests/cffi0/test_zdistutils.py @@ -4,7 +4,7 @@ from cffi import FFI, FFIError from cffi.verifier import Verifier, _locate_engine_class, _get_so_suffixes from cffi.ffiplatform import maybe_relative_path -from pypy.module.test_lib_pypy.cffi_tests.udir import udir +from extra_tests.cffi_tests.udir import udir class DistUtilsTest(object): diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_zintegration.py b/extra_tests/cffi_tests/cffi0/test_zintegration.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi0/test_zintegration.py rename to extra_tests/cffi_tests/cffi0/test_zintegration.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_zintegration.py +++ b/extra_tests/cffi_tests/cffi0/test_zintegration.py @@ -1,7 +1,7 @@ # Generated by pypy/tool/import_cffi.py import py, os, sys, shutil import subprocess -from pypy.module.test_lib_pypy.cffi_tests.udir import udir +from extra_tests.cffi_tests.udir import udir if sys.platform == 'win32': py.test.skip('snippets do not run on win32') diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/__init__.py b/extra_tests/cffi_tests/cffi1/__init__.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi1/__init__.py rename to extra_tests/cffi_tests/cffi1/__init__.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_cffi_binary.py b/extra_tests/cffi_tests/cffi1/test_cffi_binary.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi1/test_cffi_binary.py rename to extra_tests/cffi_tests/cffi1/test_cffi_binary.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_commontypes.py b/extra_tests/cffi_tests/cffi1/test_commontypes.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi1/test_commontypes.py rename to extra_tests/cffi_tests/cffi1/test_commontypes.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_dlopen.py b/extra_tests/cffi_tests/cffi1/test_dlopen.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi1/test_dlopen.py rename to extra_tests/cffi_tests/cffi1/test_dlopen.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_dlopen.py +++ b/extra_tests/cffi_tests/cffi1/test_dlopen.py @@ -2,7 +2,7 @@ import py from cffi import FFI, VerificationError, CDefError from cffi.recompiler import make_py_source -from pypy.module.test_lib_pypy.cffi_tests.udir import udir +from extra_tests.cffi_tests.udir import udir def test_simple(): diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_dlopen_unicode_literals.py b/extra_tests/cffi_tests/cffi1/test_dlopen_unicode_literals.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi1/test_dlopen_unicode_literals.py rename to extra_tests/cffi_tests/cffi1/test_dlopen_unicode_literals.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_ffi_obj.py b/extra_tests/cffi_tests/cffi1/test_ffi_obj.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi1/test_ffi_obj.py rename to extra_tests/cffi_tests/cffi1/test_ffi_obj.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_new_ffi_1.py b/extra_tests/cffi_tests/cffi1/test_new_ffi_1.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi1/test_new_ffi_1.py rename to extra_tests/cffi_tests/cffi1/test_new_ffi_1.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_new_ffi_1.py +++ b/extra_tests/cffi_tests/cffi1/test_new_ffi_1.py @@ -3,8 +3,8 @@ import platform, imp import sys, os, ctypes import cffi -from pypy.module.test_lib_pypy.cffi_tests.udir import udir -from pypy.module.test_lib_pypy.cffi_tests.support import * +from extra_tests.cffi_tests.udir import udir +from extra_tests.cffi_tests.support import * from cffi.recompiler import recompile from cffi.cffi_opcode import PRIMITIVE_TO_INDEX diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_parse_c_type.py b/extra_tests/cffi_tests/cffi1/test_parse_c_type.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi1/test_parse_c_type.py rename to extra_tests/cffi_tests/cffi1/test_parse_c_type.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_parse_c_type.py +++ b/extra_tests/cffi_tests/cffi1/test_parse_c_type.py @@ -4,7 +4,12 @@ from cffi import cffi_opcode if '__pypy__' in sys.builtin_module_names: - py.test.skip("not available on pypy") + try: + # pytest >= 4.0 + py.test.skip("not available on pypy", allow_module_level=True) + except TypeError: + # older pytest + py.test.skip("not available on pypy") cffi_dir = os.path.dirname(cffi_opcode.__file__) diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_re_python.py b/extra_tests/cffi_tests/cffi1/test_re_python.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi1/test_re_python.py rename to extra_tests/cffi_tests/cffi1/test_re_python.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_re_python.py +++ b/extra_tests/cffi_tests/cffi1/test_re_python.py @@ -3,8 +3,8 @@ import py from cffi import FFI from cffi import recompiler, ffiplatform, VerificationMissing -from pypy.module.test_lib_pypy.cffi_tests.udir import udir -from pypy.module.test_lib_pypy.cffi_tests.support import u +from extra_tests.cffi_tests.udir import udir +from extra_tests.cffi_tests.support import u def setup_module(mod): @@ -37,13 +37,22 @@ 'globalconst42', 'globalconsthello'] ) outputfilename = ffiplatform.compile(str(tmpdir), ext) + + # test with a non-ascii char + ofn, oext = os.path.splitext(outputfilename) if sys.platform == "win32": - # test with a non-ascii char - outputfn1 = outputfilename - ofn, oext = os.path.splitext(outputfn1) - outputfilename = ofn + (u+'\u03be') + oext - #print(repr(outputfn1) + ' ==> ' + repr(outputfilename)) - os.rename(outputfn1, outputfilename) + unicode_name = ofn + (u+'\u03be') + oext + else: + unicode_name = ofn + (u+'\xe9') + oext + try: + unicode_name.encode(sys.getfilesystemencoding()) + except UnicodeEncodeError: + unicode_name = None + if unicode_name is not None: + print(repr(outputfilename) + ' ==> ' + repr(unicode_name)) + os.rename(outputfilename, unicode_name) + outputfilename = unicode_name + mod.extmod = outputfilename mod.tmpdir = tmpdir # diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_realize_c_type.py b/extra_tests/cffi_tests/cffi1/test_realize_c_type.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi1/test_realize_c_type.py rename to extra_tests/cffi_tests/cffi1/test_realize_c_type.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py b/extra_tests/cffi_tests/cffi1/test_recompiler.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py rename to extra_tests/cffi_tests/cffi1/test_recompiler.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py +++ b/extra_tests/cffi_tests/cffi1/test_recompiler.py @@ -3,9 +3,9 @@ import sys, os, py from cffi import FFI, VerificationError, FFIError, CDefError from cffi import recompiler -from pypy.module.test_lib_pypy.cffi_tests.udir import udir -from pypy.module.test_lib_pypy.cffi_tests.support import u, long -from pypy.module.test_lib_pypy.cffi_tests.support import FdWriteCapture, StdErrCapture +from extra_tests.cffi_tests.udir import udir +from extra_tests.cffi_tests.support import u, long +from extra_tests.cffi_tests.support import FdWriteCapture, StdErrCapture try: import importlib diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_unicode_literals.py b/extra_tests/cffi_tests/cffi1/test_unicode_literals.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi1/test_unicode_literals.py rename to extra_tests/cffi_tests/cffi1/test_unicode_literals.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py b/extra_tests/cffi_tests/cffi1/test_verify1.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py rename to extra_tests/cffi_tests/cffi1/test_verify1.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py +++ b/extra_tests/cffi_tests/cffi1/test_verify1.py @@ -3,7 +3,7 @@ from cffi import FFI, FFIError, VerificationError, VerificationMissing, model from cffi import CDefError from cffi import recompiler -from pypy.module.test_lib_pypy.cffi_tests.support import * +from extra_tests.cffi_tests.support import * import _cffi_backend lib_m = ['m'] @@ -1377,7 +1377,7 @@ def test_tmpdir(): import tempfile, os - from pypy.module.test_lib_pypy.cffi_tests.udir import udir + from extra_tests.cffi_tests.udir import udir tmpdir = tempfile.mkdtemp(dir=str(udir)) ffi = FFI() ffi.cdef("int foo(int);") @@ -1388,7 +1388,7 @@ def test_relative_to(): py.test.skip("not available") import tempfile, os - from pypy.module.test_lib_pypy.cffi_tests.udir import udir + from extra_tests.cffi_tests.udir import udir tmpdir = tempfile.mkdtemp(dir=str(udir)) ffi = FFI() ffi.cdef("int foo(int);") @@ -2234,7 +2234,7 @@ def test_windows_dllimport_data(): if sys.platform != 'win32': py.test.skip("Windows only") - from pypy.module.test_lib_pypy.cffi_tests.udir import udir + from extra_tests.cffi_tests.udir import udir tmpfile = udir.join('dllimport_data.c') tmpfile.write('int my_value = 42;\n') ffi = FFI() diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py b/extra_tests/cffi_tests/cffi1/test_zdist.py rename from pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py rename to extra_tests/cffi_tests/cffi1/test_zdist.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py +++ b/extra_tests/cffi_tests/cffi1/test_zdist.py @@ -2,7 +2,7 @@ import sys, os, py import subprocess import cffi -from pypy.module.test_lib_pypy.cffi_tests.udir import udir +from extra_tests.cffi_tests.udir import udir from shutil import rmtree from tempfile import mkdtemp diff --git a/pypy/module/test_lib_pypy/cffi_tests/conftest.py b/extra_tests/cffi_tests/conftest.py rename from pypy/module/test_lib_pypy/cffi_tests/conftest.py rename to extra_tests/cffi_tests/conftest.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/__init__.py b/extra_tests/cffi_tests/embedding/__init__.py rename from pypy/module/test_lib_pypy/cffi_tests/embedding/__init__.py rename to extra_tests/cffi_tests/embedding/__init__.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/add1-test.c b/extra_tests/cffi_tests/embedding/add1-test.c rename from pypy/module/test_lib_pypy/cffi_tests/embedding/add1-test.c rename to extra_tests/cffi_tests/embedding/add1-test.c diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/add1.py b/extra_tests/cffi_tests/embedding/add1.py rename from pypy/module/test_lib_pypy/cffi_tests/embedding/add1.py rename to extra_tests/cffi_tests/embedding/add1.py --- a/pypy/module/test_lib_pypy/cffi_tests/embedding/add1.py +++ b/extra_tests/cffi_tests/embedding/add1.py @@ -12,7 +12,7 @@ sys.stdout.write("preparing") for i in range(3): sys.stdout.flush() - time.sleep(0.02) + time.sleep(0.2) sys.stdout.write(".") sys.stdout.write("\n") diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/add2-test.c b/extra_tests/cffi_tests/embedding/add2-test.c rename from pypy/module/test_lib_pypy/cffi_tests/embedding/add2-test.c rename to extra_tests/cffi_tests/embedding/add2-test.c diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/add2.py b/extra_tests/cffi_tests/embedding/add2.py rename from pypy/module/test_lib_pypy/cffi_tests/embedding/add2.py rename to extra_tests/cffi_tests/embedding/add2.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/add3.py b/extra_tests/cffi_tests/embedding/add3.py rename from pypy/module/test_lib_pypy/cffi_tests/embedding/add3.py rename to extra_tests/cffi_tests/embedding/add3.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/add_recursive-test.c b/extra_tests/cffi_tests/embedding/add_recursive-test.c rename from pypy/module/test_lib_pypy/cffi_tests/embedding/add_recursive-test.c rename to extra_tests/cffi_tests/embedding/add_recursive-test.c diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/add_recursive.py b/extra_tests/cffi_tests/embedding/add_recursive.py rename from pypy/module/test_lib_pypy/cffi_tests/embedding/add_recursive.py rename to extra_tests/cffi_tests/embedding/add_recursive.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/empty.py b/extra_tests/cffi_tests/embedding/empty.py rename from pypy/module/test_lib_pypy/cffi_tests/embedding/empty.py rename to extra_tests/cffi_tests/embedding/empty.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/initerror.py b/extra_tests/cffi_tests/embedding/initerror.py rename from pypy/module/test_lib_pypy/cffi_tests/embedding/initerror.py rename to extra_tests/cffi_tests/embedding/initerror.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/perf-test.c b/extra_tests/cffi_tests/embedding/perf-test.c rename from pypy/module/test_lib_pypy/cffi_tests/embedding/perf-test.c rename to extra_tests/cffi_tests/embedding/perf-test.c diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/perf.py b/extra_tests/cffi_tests/embedding/perf.py rename from pypy/module/test_lib_pypy/cffi_tests/embedding/perf.py rename to extra_tests/cffi_tests/embedding/perf.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py b/extra_tests/cffi_tests/embedding/test_basic.py rename from pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py rename to extra_tests/cffi_tests/embedding/test_basic.py --- a/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py +++ b/extra_tests/cffi_tests/embedding/test_basic.py @@ -2,7 +2,7 @@ import py import sys, os, re import shutil, subprocess, time -from pypy.module.test_lib_pypy.cffi_tests.udir import udir +from extra_tests.cffi_tests.udir import udir import cffi diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/test_performance.py b/extra_tests/cffi_tests/embedding/test_performance.py rename from pypy/module/test_lib_pypy/cffi_tests/embedding/test_performance.py rename to extra_tests/cffi_tests/embedding/test_performance.py --- a/pypy/module/test_lib_pypy/cffi_tests/embedding/test_performance.py +++ b/extra_tests/cffi_tests/embedding/test_performance.py @@ -1,6 +1,6 @@ # Generated by pypy/tool/import_cffi.py import sys -from pypy.module.test_lib_pypy.cffi_tests.embedding.test_basic import EmbeddingTests +from extra_tests.cffi_tests.embedding.test_basic import EmbeddingTests if sys.platform == 'win32': import py diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/test_recursive.py b/extra_tests/cffi_tests/embedding/test_recursive.py rename from pypy/module/test_lib_pypy/cffi_tests/embedding/test_recursive.py rename to extra_tests/cffi_tests/embedding/test_recursive.py --- a/pypy/module/test_lib_pypy/cffi_tests/embedding/test_recursive.py +++ b/extra_tests/cffi_tests/embedding/test_recursive.py @@ -1,5 +1,5 @@ # Generated by pypy/tool/import_cffi.py -from pypy.module.test_lib_pypy.cffi_tests.embedding.test_basic import EmbeddingTests +from extra_tests.cffi_tests.embedding.test_basic import EmbeddingTests class TestRecursive(EmbeddingTests): diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/test_thread.py b/extra_tests/cffi_tests/embedding/test_thread.py rename from pypy/module/test_lib_pypy/cffi_tests/embedding/test_thread.py rename to extra_tests/cffi_tests/embedding/test_thread.py --- a/pypy/module/test_lib_pypy/cffi_tests/embedding/test_thread.py +++ b/extra_tests/cffi_tests/embedding/test_thread.py @@ -1,12 +1,12 @@ # Generated by pypy/tool/import_cffi.py -from pypy.module.test_lib_pypy.cffi_tests.embedding.test_basic import EmbeddingTests +from extra_tests.cffi_tests.embedding.test_basic import EmbeddingTests class TestThread(EmbeddingTests): def test_first_calls_in_parallel(self): add1_cffi = self.prepare_module('add1') self.compile('thread1-test', [add1_cffi], threads=True) - for i in range(50): + for i in range(20): output = self.execute('thread1-test') assert output == ("starting\n" "preparing...\n" + diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/test_tlocal.py b/extra_tests/cffi_tests/embedding/test_tlocal.py rename from pypy/module/test_lib_pypy/cffi_tests/embedding/test_tlocal.py rename to extra_tests/cffi_tests/embedding/test_tlocal.py --- a/pypy/module/test_lib_pypy/cffi_tests/embedding/test_tlocal.py +++ b/extra_tests/cffi_tests/embedding/test_tlocal.py @@ -1,5 +1,5 @@ # Generated by pypy/tool/import_cffi.py -from pypy.module.test_lib_pypy.cffi_tests.embedding.test_basic import EmbeddingTests +from extra_tests.cffi_tests.embedding.test_basic import EmbeddingTests class TestThreadLocal(EmbeddingTests): diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/thread-test.h b/extra_tests/cffi_tests/embedding/thread-test.h rename from pypy/module/test_lib_pypy/cffi_tests/embedding/thread-test.h rename to extra_tests/cffi_tests/embedding/thread-test.h diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/thread1-test.c b/extra_tests/cffi_tests/embedding/thread1-test.c rename from pypy/module/test_lib_pypy/cffi_tests/embedding/thread1-test.c rename to extra_tests/cffi_tests/embedding/thread1-test.c diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/thread2-test.c b/extra_tests/cffi_tests/embedding/thread2-test.c rename from pypy/module/test_lib_pypy/cffi_tests/embedding/thread2-test.c rename to extra_tests/cffi_tests/embedding/thread2-test.c diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/thread3-test.c b/extra_tests/cffi_tests/embedding/thread3-test.c rename from pypy/module/test_lib_pypy/cffi_tests/embedding/thread3-test.c rename to extra_tests/cffi_tests/embedding/thread3-test.c diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/tlocal-test.c b/extra_tests/cffi_tests/embedding/tlocal-test.c rename from pypy/module/test_lib_pypy/cffi_tests/embedding/tlocal-test.c rename to extra_tests/cffi_tests/embedding/tlocal-test.c diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/tlocal.py b/extra_tests/cffi_tests/embedding/tlocal.py rename from pypy/module/test_lib_pypy/cffi_tests/embedding/tlocal.py rename to extra_tests/cffi_tests/embedding/tlocal.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/support.py b/extra_tests/cffi_tests/support.py rename from pypy/module/test_lib_pypy/cffi_tests/support.py rename to extra_tests/cffi_tests/support.py --- a/pypy/module/test_lib_pypy/cffi_tests/support.py +++ b/extra_tests/cffi_tests/support.py @@ -9,7 +9,7 @@ return eval('u'+repr(other).replace(r'\\u', r'\u') .replace(r'\\U', r'\U')) u = U() - long = long # for further "from pypy.module.test_lib_pypy.cffi_tests.support import long" + long = long # for further "from extra_tests.cffi_tests.support import long" assert u+'a\x00b' == eval(r"u'a\x00b'") assert u+'a\u1234b' == eval(r"u'a\u1234b'") assert u+'a\U00012345b' == eval(r"u'a\U00012345b'") diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_egg_version.py b/extra_tests/cffi_tests/test_egg_version.py rename from pypy/module/test_lib_pypy/cffi_tests/test_egg_version.py rename to extra_tests/cffi_tests/test_egg_version.py diff --git a/pypy/module/test_lib_pypy/cffi_tests/udir.py b/extra_tests/cffi_tests/udir.py rename from pypy/module/test_lib_pypy/cffi_tests/udir.py rename to extra_tests/cffi_tests/udir.py diff --git a/extra_tests/test_interpreter.py b/extra_tests/test_interpreter.py new file mode 100644 --- /dev/null +++ b/extra_tests/test_interpreter.py @@ -0,0 +1,36 @@ +from __future__ import print_function +import pytest + +@pytest.fixture +def testfile(tmpdir): + tmpfile = tmpdir.join('test_execution_context') + tmpfile.write(""" +from __future__ import print_function +import gc +class X(object): + def __del__(self): + print("Called", self.num) +def f(): + x1 = X(); x1.num = 1 + x2 = X(); x2.num = 2 + x1.next = x2 +f() +gc.collect() +gc.collect() +""") + return tmpfile + + +def test_del_not_blocked(testfile): + # test the behavior fixed in r71420: before, only one __del__ + # would be called + import os, sys + if sys.platform == "win32": + cmdformat = '"%s" "%s"' + else: + cmdformat = "'%s' '%s'" + g = os.popen(cmdformat % (sys.executable, testfile), 'r') + data = g.read() + g.close() + assert 'Called 1' in data + assert 'Called 2' in data diff --git a/lib-python/2.7/threading.py b/lib-python/2.7/threading.py --- a/lib-python/2.7/threading.py +++ b/lib-python/2.7/threading.py @@ -36,6 +36,10 @@ _allocate_lock = thread.allocate_lock _get_ident = thread.get_ident ThreadError = thread.error +try: + _CRLock = thread.RLock +except AttributeError: + _CRLock = None del thread @@ -120,7 +124,9 @@ acquired it. """ - return _RLock(*args, **kwargs) + if _CRLock is None or args or kwargs: + return _PyRLock(*args, **kwargs) + return _CRLock(_active) class _RLock(_Verbose): """A reentrant lock must be released by the thread that acquired it. Once a @@ -238,6 +244,8 @@ def _is_owned(self): return self.__owner == _get_ident() +_PyRLock = _RLock + def Condition(*args, **kwargs): """Factory function that returns a new condition variable object. diff --git a/lib-python/2.7/warnings.py b/lib-python/2.7/warnings.py --- a/lib-python/2.7/warnings.py +++ b/lib-python/2.7/warnings.py @@ -182,6 +182,8 @@ module = category[:i] klass = category[i+1:] try: + if not module: + raise ImportError # instead of the ValueError we'd get m = __import__(module, None, None, [klass]) except ImportError: raise _OptionError("invalid module name: %r" % (module,)) diff --git a/lib_pypy/cffi/cparser.py b/lib_pypy/cffi/cparser.py --- a/lib_pypy/cffi/cparser.py +++ b/lib_pypy/cffi/cparser.py @@ -137,6 +137,14 @@ parts.append(csource) return ''.join(parts) +def _warn_for_string_literal(csource): + if '"' in csource: + import warnings + warnings.warn("String literal found in cdef() or type source. " + "String literals are ignored here, but you should " + "remove them anyway because some character sequences " + "confuse pre-parsing.") + def _preprocess(csource): # Remove comments. NOTE: this only work because the cdef() section # should not contain any string literal! @@ -148,6 +156,7 @@ macrovalue = macrovalue.replace('\\\n', '').strip() macros[macroname] = macrovalue csource = _r_define.sub('', csource) + _warn_for_string_literal(csource) # if pycparser.__version__ < '2.14': csource = _workaround_for_old_pycparser(csource) 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 @@ -26,6 +26,12 @@ from pyrepl.fancy_termios import tcgetattr, tcsetattr from pyrepl.console import Console, Event from pyrepl import unix_eventqueue +try: + from __pypy__ import pyos_inputhook +except ImportError: + def pyos_inputhook(): + pass + class InvalidTerminal(RuntimeError): pass @@ -416,6 +422,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), err: diff --git a/lib_pypy/resource.py b/lib_pypy/resource.py --- a/lib_pypy/resource.py +++ b/lib_pypy/resource.py @@ -4,8 +4,10 @@ from errno import EINVAL, EPERM import _structseq, os -try: from __pypy__ import builtinify -except ImportError: builtinify = lambda f: f +try: + from __pypy__ import builtinify +except ImportError: + builtinify = lambda f: f class error(Exception): @@ -35,7 +37,7 @@ ru_oublock = _structseq.structseqfield(10, "block output operations") ru_msgsnd = _structseq.structseqfield(11, "IPC messages sent") ru_msgrcv = _structseq.structseqfield(12, "IPC messages received") - ru_nsignals = _structseq.structseqfield(13,"signals received") + ru_nsignals = _structseq.structseqfield(13, "signals received") ru_nvcsw = _structseq.structseqfield(14, "voluntary context switches") ru_nivcsw = _structseq.structseqfield(15, "involuntary context switches") @@ -57,7 +59,7 @@ ru.ru_nsignals, ru.ru_nvcsw, ru.ru_nivcsw, - )) + )) @builtinify def getrusage(who): diff --git a/pypy/doc/architecture.rst b/pypy/doc/architecture.rst --- a/pypy/doc/architecture.rst +++ b/pypy/doc/architecture.rst @@ -4,7 +4,7 @@ .. contents:: This document gives an overview of the goals and architecture of PyPy. If you're -interested in :ref:`using PyPy <using-pypy>` or :ref:`hacking on it <developing-pypy>`, +interested in :ref:`using PyPy <using-pypy>` or hacking on it, have a look at our :ref:`getting started <getting-started-index>` section. diff --git a/pypy/doc/conf.py b/pypy/doc/conf.py --- a/pypy/doc/conf.py +++ b/pypy/doc/conf.py @@ -192,10 +192,10 @@ # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). -latex_documents = [ - ('temp_index', 'PyPy.tex', u'PyPy Documentation', - u'The PyPy Project', 'manual'), -] +#latex_documents = [ +# ('temp_index', 'PyPy.tex', u'PyPy Documentation', +# u'The PyPy Project', 'manual'), +#] # The name of an image file (relative to this directory) to place at the top of # the title page. @@ -212,7 +212,7 @@ #latex_appendices = [] # If false, no module index is generated. -latex_use_modindex = False +#latex_use_modindex = False # Example configuration for intersphinx: refer to the Python standard library. diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst --- a/pypy/doc/index.rst +++ b/pypy/doc/index.rst @@ -29,6 +29,7 @@ :maxdepth: 1 introduction + architecture install build windows @@ -59,7 +60,6 @@ :maxdepth: 2 contributing - architecture configuration project-ideas project-documentation diff --git a/pypy/doc/project-documentation.rst b/pypy/doc/project-documentation.rst --- a/pypy/doc/project-documentation.rst +++ b/pypy/doc/project-documentation.rst @@ -28,7 +28,6 @@ .. toctree:: :hidden: - architecture coding-guide sprint-reports extradoc diff --git a/pypy/doc/project-ideas.rst b/pypy/doc/project-ideas.rst --- a/pypy/doc/project-ideas.rst +++ b/pypy/doc/project-ideas.rst @@ -111,9 +111,12 @@ -------------- Our cpyext C-API compatiblity layer can now run upstream NumPy unmodified. -Release PyPy2.7-v5.4 still fails about 60 of the ~6000 test in the NumPy -test suite. We could use help analyzing the failures and fixing them either -as patches to upstream NumPy, or as fixes to PyPy. +Release PyPy2.7-v6.0 still fails about 10 of the ~6000 test in the NumPy +test suite. We need to improve our ctypes structure -> memoryview conversions_, +and to refactor the way `NumPy adds docstrings`_. + +.. _conversions: https://bitbucket.org/pypy/pypy/issues/2930 +.. _`NumPy adds docstrings`: https://github.com/numpy/numpy/issues/10167 We also are looking for help in how to hijack NumPy dtype conversion and ufunc calls to allow the JIT to make them fast, using our internal _numpypy @@ -165,8 +168,33 @@ Or maybe not. We can also play around with the idea of using a single representation: as a byte string in utf-8. (This idea needs some extra logic -for efficient indexing, like a cache.) +for efficient indexing, like a cache.) Work has begun on the ``unicode-utf`` +and ``unicode-utf8-py3`` branches. More is needed, for instance there are +SIMD optimizations that are not yet used. +Convert RPython to Python3 +-------------------------- + +The world is moving on, we should too. + +Improve performance +------------------- + +* Make uninlined Python-level calls faster +* Switch to a `sea-of-nodes`_ IR, or a `Lua-Jit`_-like IR which iterates on + on the sea-of-nodes approach +* Use real register-allocation +* Improve instruction selection / scheduling +* Create a hybrid tracing/method JIT + +.. _`sea-of-nodes`: https://darksi.de/d.sea-of-nodes/ +.. _`Lua-JIT`: http://wiki.luajit.org/SSA-IR-2.0 + +Improve warmup +-------------- +* Interpreter speed-ups +* Optimize while tracing +* Cache information between runs Translation Toolchain --------------------- @@ -234,6 +262,27 @@ .. _runner: http://speed.pypy.org .. _`CPython site`: https://speed.python.org/ + +Interfacing with C +------------------ + +While we could make ``cpyext`` faster_, we would also like to explore other +ideas. It seems cffi is only appropriate for small to medium-sized extensions, +and it is hard to imagine NumPy abandoning the C-API. Here are a few ideas: +* Extend Cython to have a backend that can be understood by the JIT +* Collaborate with C-extension authors to ensure full PyPy support (see below) +* Put PyPy compatible packages on PyPI and in conda + + +.. _faster: https://morepypy.blogspot.com/2018/09#next-steps + +Support more platforms +---------------------- + +We have a plan for a `Windows 64`_ port. + +.. _`Windows 64`: windows.html#what-is-missing-for-a-full-64-bit-translation + ====================================== Make more python modules pypy-friendly ====================================== 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 @@ -39,8 +39,27 @@ .. branch: fix-readme-typo +.. branch: avoid_shell_injection_in_shutil + +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` + + +.. branch: expose-gc-time + +Make GC hooks measure time in seconds (as opposed to an opaque unit). + .. math-improvements Improve performance of long operations where one of the operands fits into an int. + diff --git a/pypy/goal/targetpypystandalone.py b/pypy/goal/targetpypystandalone.py --- a/pypy/goal/targetpypystandalone.py +++ b/pypy/goal/targetpypystandalone.py @@ -368,7 +368,7 @@ def get_gchooks(self): from pypy.module.gc.hook import LowLevelGcHooks if self.space is None: - raise Exception("get_gchooks must be called afeter get_entry_point") + raise Exception("get_gchooks must be called after get_entry_point") return self.space.fromcache(LowLevelGcHooks) def get_entry_point(self, config): diff --git a/pypy/interpreter/app_main.py b/pypy/interpreter/app_main.py --- a/pypy/interpreter/app_main.py +++ b/pypy/interpreter/app_main.py @@ -609,8 +609,14 @@ warnoptions.extend(pythonwarnings.split(',')) if warnoptions: sys.warnoptions[:] = warnoptions - from warnings import _processoptions - _processoptions(sys.warnoptions) + try: + if 'warnings' in sys.modules: + from warnings import _processoptions + _processoptions(sys.warnoptions) + else: + import warnings + except ImportError as e: + pass # CPython just eats any exception here # set up the Ctrl-C => KeyboardInterrupt signal handler, if the # signal module is available diff --git a/pypy/interpreter/test/test_app_main.py b/pypy/interpreter/test/test_app_main.py --- a/pypy/interpreter/test/test_app_main.py +++ b/pypy/interpreter/test/test_app_main.py @@ -977,6 +977,7 @@ " foo = True\n") +@py.test.mark.skipif('config.getoption("runappdirect")') class AppTestAppMain: def setup_class(self): # ---------------------------------------- diff --git a/pypy/interpreter/test/test_executioncontext.py b/pypy/interpreter/test/test_executioncontext.py --- a/pypy/interpreter/test/test_executioncontext.py +++ b/pypy/interpreter/test/test_executioncontext.py @@ -43,7 +43,7 @@ class Action1(executioncontext.AsyncAction): def perform(self, ec, frame): events.append('one') - + class Action2(executioncontext.AsyncAction): def perform(self, ec, frame): events.append('two') @@ -76,7 +76,7 @@ class Action1(executioncontext.AsyncAction): _count = 0 - + def perform(self, ec, frame): events.append('one') if self._count == 0: @@ -139,11 +139,11 @@ def test_llprofile(self): l = [] - + def profile_func(space, w_arg, frame, event, w_aarg): assert w_arg is space.w_None l.append(event) - + space = self.space space.getexecutioncontext().setllprofile(profile_func, space.w_None) space.appexec([], """(): @@ -157,7 +157,7 @@ l = [] seen = [] space = self.space - + def profile_func(space, w_arg, frame, event, w_func): assert w_arg is space.w_None l.append(event) @@ -190,10 +190,10 @@ check_snippet('max(1, 2, **{})', 'builtin max') check_snippet('args = (1, 2); max(*args, **{})', 'builtin max') check_snippet('abs(val=0)', 'builtin abs') - + def test_llprofile_c_exception(self): l = [] - + def profile_func(space, w_arg, frame, event, w_aarg): assert w_arg is space.w_None l.append(event) @@ -308,7 +308,7 @@ space = self.space w_res = space.appexec([], """(): l = [] - + def profile(*args): l.append(sys.exc_info()[0]) @@ -327,45 +327,6 @@ """) -class AppTestDelNotBlocked: - - def setup_method(self, meth): - if not self.runappdirect: - py.test.skip("test is meant for running with py.test -A") - from rpython.tool.udir import udir - tmpfile = udir.join('test_execution_context') - tmpfile.write(""" -import gc -class X(object): - def __del__(self): - print "Called", self.num -def f(): - x1 = X(); x1.num = 1 - x2 = X(); x2.num = 2 - x1.next = x2 -f() -gc.collect() -gc.collect() -""") - self.tmpfile = str(tmpfile) - self.w_tmpfile = self.space.wrap(self.tmpfile) - - def test_del_not_blocked(self): - # test the behavior fixed in r71420: before, only one __del__ - # would be called - import os, sys - print sys.executable, self.tmpfile - if sys.platform == "win32": - cmdformat = '"%s" "%s"' - else: - cmdformat = "'%s' '%s'" - g = os.popen(cmdformat % (sys.executable, self.tmpfile), 'r') - data = g.read() - g.close() - assert 'Called 1' in data - assert 'Called 2' in data - - class AppTestProfile: def test_return(self): 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 @@ -109,6 +109,7 @@ '_promote' : 'interp_magic._promote', 'side_effects_ok' : 'interp_magic.side_effects_ok', 'stack_almost_full' : 'interp_magic.stack_almost_full', + 'pyos_inputhook' : 'interp_magic.pyos_inputhook', } if sys.platform == 'win32': interpleveldefs['get_console_cp'] = 'interp_magic.get_console_cp' 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 @@ -211,3 +211,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/_cppyy/test/conftest.py b/pypy/module/_cppyy/test/conftest.py --- a/pypy/module/_cppyy/test/conftest.py +++ b/pypy/module/_cppyy/test/conftest.py @@ -1,4 +1,7 @@ import py, sys +from os.path import abspath, commonprefix, dirname + +THIS_DIR = dirname(__file__) @py.test.mark.tryfirst def pytest_runtest_setup(item): @@ -29,10 +32,11 @@ py.test.skip(infomsg) def pytest_ignore_collect(path, config): + path = str(path) if py.path.local.sysfind('genreflex') is None and config.option.runappdirect: - return True # "can't run dummy tests in -A" + return commonprefix([path, THIS_DIR]) == THIS_DIR if disabled: - return True + return commonprefix([path, THIS_DIR]) == THIS_DIR disabled = None diff --git a/pypy/module/_rawffi/alt/test/test_ffitype.py b/pypy/module/_rawffi/alt/test/test_ffitype.py --- a/pypy/module/_rawffi/alt/test/test_ffitype.py +++ b/pypy/module/_rawffi/alt/test/test_ffitype.py @@ -1,6 +1,5 @@ -from pypy.module._rawffi.alt.test.test_funcptr import BaseAppTestFFI - -class AppTestFFIType(BaseAppTestFFI): +class AppTestFFIType(object): + spaceconfig = dict(usemodules=('_rawffi',)) def test_simple_types(self): from _rawffi.alt import types @@ -8,7 +7,7 @@ assert str(types.uint) == "<ffi type uint>" assert types.sint.name == 'sint' assert types.uint.name == 'uint' - + def test_sizeof(self): from _rawffi.alt import types assert types.sbyte.sizeof() == 1 @@ -36,4 +35,3 @@ assert x is types.char_p x = types.Pointer(types.unichar) assert x is types.unichar_p - diff --git a/pypy/module/_warnings/test/test_warnings.py b/pypy/module/_warnings/test/test_warnings.py --- a/pypy/module/_warnings/test/test_warnings.py +++ b/pypy/module/_warnings/test/test_warnings.py @@ -46,18 +46,22 @@ except ImportError: skip('no test, -A on cpython?') # With showarning() missing, make sure that output is okay. - del warnings.showwarning + saved = warnings.showwarning + try: + del warnings.showwarning - stderr = sys.stderr - try: - sys.stderr = StringIO.StringIO() - inner('test message') - result = sys.stderr.getvalue() + stderr = sys.stderr + try: + sys.stderr = StringIO.StringIO() + inner('test message') + result = sys.stderr.getvalue() + finally: + sys.stderr = stderr + + assert result.count('\n') == 2 + assert ' warnings.warn(message, ' in result finally: - sys.stderr = stderr - - assert result.count('\n') == 2 - assert ' warnings.warn(message, ' in result + warnings.showwarning = saved def test_filename_none(self): import _warnings 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 @@ -159,6 +159,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: @@ -171,14 +175,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), @@ -195,6 +198,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(). @@ -239,8 +247,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 @@ -644,6 +644,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', '_PyTraceMalloc_Track', '_PyTraceMalloc_Untrack', 'PyMem_Malloc', 'PyObject_Free', 'PyObject_GC_Del', 'PyType_GenericAlloc', '_PyObject_New', '_PyObject_NewVar', @@ -1180,6 +1181,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): @@ -1726,6 +1731,12 @@ w_mod = state.fixup_extension(name, path) return w_mod +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/include/pythonrun.h b/pypy/module/cpyext/include/pythonrun.h --- a/pypy/module/cpyext/include/pythonrun.h +++ b/pypy/module/cpyext/include/pythonrun.h @@ -47,6 +47,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/pyobject.py b/pypy/module/cpyext/pyobject.py --- a/pypy/module/cpyext/pyobject.py +++ b/pypy/module/cpyext/pyobject.py @@ -261,6 +261,7 @@ if w_obj is not None: if w_obj is not w_marker_deallocating: return w_obj + type_name = rffi.charp2str(cts.cast('char*', ref.c_ob_type.c_tp_name)) fatalerror( "*** Invalid usage of a dying CPython object ***\n" "\n" @@ -275,7 +276,8 @@ "freed, making that reference point to garbage.\n" ">>> PyPy could contain some workaround to still work if\n" "you are lucky, but it is not done so far; better fix the bug in\n" - "the CPython extension.") + "the CPython extension.\n" + ">>> This object is of type '%s'" % (type_name,)) # This reference is not yet a real interpreter object. # Realize it. 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/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 PyInt_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_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 @@ -421,6 +421,8 @@ with raises_w(space, TypeError): PyUnicode_FromEncodedObject( space, space.wrap(u_text), null_charp, None) + assert space.unicode_w(PyUnicode_FromEncodedObject( + space, space.wrap(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 @@ -366,10 +366,14 @@ 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.""" + return _pyunicode_decode(space, rffi.charpsize2str(s, size), + encoding, errors) + +def _pyunicode_decode(space, s, encoding, errors): 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_str = space.newbytes(s) w_encoding = space.newtext(rffi.charp2str(encoding)) if errors: w_errors = space.newbytes(rffi.charp2str(errors)) @@ -398,28 +402,12 @@ All other objects, including Unicode objects, cause a TypeError to be set.""" - if not encoding: + if space.isinstance_w(w_obj, space.w_unicode): 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) + 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.bufferstr_w(w_obj) + return _pyunicode_decode(space, s, encoding, errors) @cpython_api([CONST_STRING], PyObject) def PyUnicode_FromString(space, s): diff --git a/pypy/module/gc/app_referents.py b/pypy/module/gc/app_referents.py --- a/pypy/module/gc/app_referents.py +++ b/pypy/module/gc/app_referents.py @@ -57,12 +57,14 @@ 'total_allocated_memory', 'jit_backend_allocated', 'peak_memory', 'peak_allocated_memory', 'total_arena_memory', 'total_rawmalloced_memory', 'nursery_size', - 'peak_arena_memory', 'peak_rawmalloced_memory'): + 'peak_arena_memory', 'peak_rawmalloced_memory', + ): setattr(self, item, self._format(getattr(self._s, item))) self.memory_used_sum = self._format(self._s.total_gc_memory + self._s.total_memory_pressure + self._s.jit_backend_used) self.memory_allocated_sum = self._format(self._s.total_allocated_memory + self._s.total_memory_pressure + self._s.jit_backend_allocated) + self.total_gc_time = self._s.total_gc_time def _format(self, v): if v < 1000000: @@ -92,6 +94,8 @@ raw assembler allocated: %s%s ----------------------------- Total: %s + + Total time spent in GC: %s """ % (self.total_gc_memory, self.peak_memory, self.total_arena_memory, self.total_rawmalloced_memory, @@ -106,7 +110,8 @@ self.nursery_size, self.jit_backend_allocated, extra, - self.memory_allocated_sum) + self.memory_allocated_sum, + self.total_gc_time / 1000.0) def get_stats(memory_pressure=False): diff --git a/pypy/module/gc/hook.py b/pypy/module/gc/hook.py --- a/pypy/module/gc/hook.py +++ b/pypy/module/gc/hook.py @@ -7,6 +7,8 @@ from pypy.interpreter.typedef import TypeDef, interp_attrproperty, GetSetProperty from pypy.interpreter.executioncontext import AsyncAction +inf = float("inf") + class LowLevelGcHooks(GcHooks): """ These are the low-level hooks which are called directly from the GC. @@ -126,9 +128,9 @@ def reset(self): self.count = 0 - self.duration = r_longlong(0) - self.duration_min = r_longlong(longlongmax) - self.duration_max = r_longlong(0) + self.duration = 0.0 + self.duration_min = inf + self.duration_max = 0.0 def fix_annotation(self): # the annotation of the class and its attributes must be completed @@ -136,9 +138,9 @@ # annotated with the correct types if NonConstant(False): self.count = NonConstant(-42) - self.duration = NonConstant(r_longlong(-42)) - self.duration_min = NonConstant(r_longlong(-42)) - self.duration_max = NonConstant(r_longlong(-42)) + self.duration = NonConstant(-53.2) + self.duration_min = NonConstant(-53.2) + self.duration_max = NonConstant(-53.2) self.total_memory_used = NonConstant(r_uint(42)) self.pinned_objects = NonConstant(-42) self.fire() @@ -166,9 +168,9 @@ def reset(self): self.count = 0 - self.duration = r_longlong(0) - self.duration_min = r_longlong(longlongmax) - self.duration_max = r_longlong(0) + self.duration = 0.0 + self.duration_min = inf + self.duration_max = 0.0 def fix_annotation(self): # the annotation of the class and its attributes must be completed @@ -176,9 +178,9 @@ # annotated with the correct types if NonConstant(False): self.count = NonConstant(-42) - self.duration = NonConstant(r_longlong(-42)) - self.duration_min = NonConstant(r_longlong(-42)) - self.duration_max = NonConstant(r_longlong(-42)) + self.duration = NonConstant(-53.2) + self.duration_min = NonConstant(-53.2) + self.duration_max = NonConstant(-53.2) self.oldstate = NonConstant(-42) self.newstate = NonConstant(-42) self.fire() @@ -276,10 +278,14 @@ # just a shortcut to make the typedefs shorter -def wrap_many_ints(cls, names): +def wrap_many(cls, names): d = {} for name in names: - d[name] = interp_attrproperty(name, cls=cls, wrapfn="newint") + if "duration" in name: + wrapfn = "newfloat" + else: + wrapfn = "newint" + d[name] = interp_attrproperty(name, cls=cls, wrapfn=wrapfn) return d @@ -303,7 +309,7 @@ W_GcMinorStats.typedef = TypeDef( "GcMinorStats", - **wrap_many_ints(W_GcMinorStats, ( + **wrap_many(W_GcMinorStats, ( "count", "duration", "duration_min", @@ -319,7 +325,7 @@ STATE_SWEEPING = incminimark.STATE_SWEEPING, STATE_FINALIZING = incminimark.STATE_FINALIZING, GC_STATES = tuple(incminimark.GC_STATES), - **wrap_many_ints(W_GcCollectStepStats, ( + **wrap_many(W_GcCollectStepStats, ( "count", "duration", "duration_min", @@ -330,7 +336,7 @@ W_GcCollectStats.typedef = TypeDef( "GcCollectStats", - **wrap_many_ints(W_GcCollectStats, ( + **wrap_many(W_GcCollectStats, ( "count", "num_major_collects", "arenas_count_before", diff --git a/pypy/module/gc/referents.py b/pypy/module/gc/referents.py --- a/pypy/module/gc/referents.py +++ b/pypy/module/gc/referents.py @@ -189,6 +189,7 @@ self.peak_arena_memory = rgc.get_stats(rgc.PEAK_ARENA_MEMORY) self.peak_rawmalloced_memory = rgc.get_stats(rgc.PEAK_RAWMALLOCED_MEMORY) self.nursery_size = rgc.get_stats(rgc.NURSERY_SIZE) + self.total_gc_time = rgc.get_stats(rgc.TOTAL_GC_TIME) W_GcStats.typedef = TypeDef("GcStats", total_memory_pressure=interp_attrproperty("total_memory_pressure", @@ -215,6 +216,8 @@ cls=W_GcStats, wrapfn="newint"), nursery_size=interp_attrproperty("nursery_size", cls=W_GcStats, wrapfn="newint"), + total_gc_time=interp_attrproperty("total_gc_time", + cls=W_GcStats, wrapfn="newint"), ) @unwrap_spec(memory_pressure=bool) diff --git a/pypy/module/gc/test/test_hook.py b/pypy/module/gc/test/test_hook.py --- a/pypy/module/gc/test/test_hook.py +++ b/pypy/module/gc/test/test_hook.py @@ -26,11 +26,11 @@ @unwrap_spec(ObjSpace) def fire_many(space): - gchooks.fire_gc_minor(5, 0, 0) - gchooks.fire_gc_minor(7, 0, 0) - gchooks.fire_gc_collect_step(5, 0, 0) - gchooks.fire_gc_collect_step(15, 0, 0) - gchooks.fire_gc_collect_step(22, 0, 0) + gchooks.fire_gc_minor(5.0, 0, 0) + gchooks.fire_gc_minor(7.0, 0, 0) + gchooks.fire_gc_collect_step(5.0, 0, 0) + gchooks.fire_gc_collect_step(15.0, 0, 0) + gchooks.fire_gc_collect_step(22.0, 0, 0) gchooks.fire_gc_collect(1, 2, 3, 4, 5, 6) cls.w_fire_gc_minor = space.wrap(interp2app(fire_gc_minor)) 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 @@ -211,9 +211,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) @@ -303,7 +303,7 @@ try: fid = posix.fdopen(fd) fid.read(10) - except OSError as e: + except (IOError, OSError) as e: assert e.errno == errno.EBADF else: assert False, "using result of fdopen(fd) on closed file must raise" @@ -576,6 +576,12 @@ assert '\nOSError: [Errno 9]' in res else: assert res == 'test1\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): 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 @@ -188,8 +188,8 @@ #endif #include <windows.h> #include <stdio.h> +#include <stdlib.h> -RPY_EXPORTED char *_pypy_init_home(void) { HMODULE hModule = 0; @@ -225,7 +225,6 @@ #include <stdio.h> #include <stdlib.h> -RPY_EXPORTED char *_pypy_init_home(void) { Dl_info info; @@ -243,11 +242,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/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py --- a/pypy/module/test_lib_pypy/test_sqlite3.py +++ b/pypy/module/test_lib_pypy/test_sqlite3.py @@ -5,327 +5,321 @@ import pytest import sys +_sqlite3 = pytest.importorskip('_sqlite3') -def pytest_funcarg__con(request): +pypy_only = pytest.mark.skipif('__pypy__' not in sys.builtin_module_names, + reason="PyPy-only test") + + +@pytest.yield_fixture +def con(): con = _sqlite3.connect(':memory:') - request.addfinalizer(lambda: con.close()) - return con + yield con + con.close() -class BaseTestSQLite: - def test_list_ddl(self, con): - """From issue996. Mostly just looking for lack of exceptions.""" - cursor = con.cursor() - cursor.execute('CREATE TABLE foo (bar INTEGER)') - result = list(cursor) - assert result == [] - cursor.execute('INSERT INTO foo (bar) VALUES (42)') - result = list(cursor) - assert result == [] - cursor.execute('SELECT * FROM foo') - result = list(cursor) - assert result == [(42,)] +def test_list_ddl(con): + """From issue996. Mostly just looking for lack of exceptions.""" + cursor = con.cursor() + cursor.execute('CREATE TABLE foo (bar INTEGER)') + result = list(cursor) + assert result == [] + cursor.execute('INSERT INTO foo (bar) VALUES (42)') + result = list(cursor) + assert result == [] + cursor.execute('SELECT * FROM foo') + result = list(cursor) + assert result == [(42,)] - def test_connect_takes_same_positional_args_as_Connection(self, con): - if not hasattr(_sqlite3, '_ffi'): - pytest.skip("only works for lib_pypy _sqlite3") - from inspect import getargspec - clsargs = getargspec(_sqlite3.Connection.__init__).args[1:] # ignore self - conargs = getargspec(_sqlite3.connect).args - assert clsargs == conargs +@pypy_only +def test_connect_takes_same_positional_args_as_Connection(con): + from inspect import getargspec + clsargs = getargspec(_sqlite3.Connection.__init__).args[1:] # ignore self + conargs = getargspec(_sqlite3.connect).args + assert clsargs == conargs - def test_total_changes_after_close(self, con): - con.close() - pytest.raises(_sqlite3.ProgrammingError, "con.total_changes") +def test_total_changes_after_close(con): + con.close() + with pytest.raises(_sqlite3.ProgrammingError): + con.total_changes - def test_connection_check_init(self): - class Connection(_sqlite3.Connection): - def __init__(self, name): - pass +def test_connection_check_init(): + class Connection(_sqlite3.Connection): + def __init__(self, name): + pass - con = Connection(":memory:") - e = pytest.raises(_sqlite3.ProgrammingError, "con.cursor()") - assert '__init__' in e.value.message + con = Connection(":memory:") + with pytest.raises(_sqlite3.ProgrammingError) as excinfo: + con.cursor() + assert '__init__' in excinfo.value.message - def test_cursor_check_init(self, con): - class Cursor(_sqlite3.Cursor): - def __init__(self, name): - pass - cur = Cursor(con) - e = pytest.raises(_sqlite3.ProgrammingError, "cur.execute('select 1')") - assert '__init__' in e.value.message +def test_cursor_check_init(con): + class Cursor(_sqlite3.Cursor): + def __init__(self, name): + pass - def test_connection_after_close(self, con): - pytest.raises(TypeError, "con()") - con.close() - # raises ProgrammingError because should check closed before check args - pytest.raises(_sqlite3.ProgrammingError, "con()") + cur = Cursor(con) + with pytest.raises(_sqlite3.ProgrammingError) as excinfo: + cur.execute('select 1') + assert '__init__' in excinfo.value.message - def test_cursor_iter(self, con): +def test_connection_after_close(con): + with pytest.raises(TypeError): + con() + con.close() + # raises ProgrammingError because should check closed before check args + with pytest.raises(_sqlite3.ProgrammingError): + con() + +def test_cursor_iter(con): + cur = con.cursor() + with pytest.raises(StopIteration): + next(cur) + + cur.execute('select 1') + next(cur) + with pytest.raises(StopIteration): + next(cur) + + cur.execute('select 1') + con.commit() + next(cur) + with pytest.raises(StopIteration): + next(cur) + + with pytest.raises(_sqlite3.ProgrammingError): + cur.executemany('select 1', []) + with pytest.raises(StopIteration): + next(cur) + + cur.execute('select 1') + cur.execute('create table test(ing)') + with pytest.raises(StopIteration): + next(cur) + + cur.execute('select 1') + cur.execute('insert into test values(1)') + con.commit() + with pytest.raises(StopIteration): + next(cur) + +def test_cursor_after_close(con): + cur = con.execute('select 1') + cur.close() + con.close() + with pytest.raises(_sqlite3.ProgrammingError): + cur.close() + # raises ProgrammingError because should check closed before check args + with pytest.raises(_sqlite3.ProgrammingError): + cur.execute(1,2,3,4,5) + with pytest.raises(_sqlite3.ProgrammingError): + cur.executemany(1,2,3,4,5) + +@pypy_only +def test_connection_del(tmpdir): + """For issue1325.""" + import os + import gc + resource = pytest.importorskip('resource') + + limit = resource.getrlimit(resource.RLIMIT_NOFILE) + try: + fds = 0 + while True: + fds += 1 + resource.setrlimit(resource.RLIMIT_NOFILE, (fds, limit[1])) + try: + for p in os.pipe(): os.close(p) + except OSError: + assert fds < 100 + else: + break + + def open_many(cleanup): + con = [] + for i in range(3): + con.append(_sqlite3.connect(str(tmpdir.join('test.db')))) + if cleanup: + con[i] = None + gc.collect(); gc.collect() + + with pytest.raises(_sqlite3.OperationalError): + open_many(False) + sys.exc_clear() + gc.collect(); gc.collect() + open_many(True) + finally: + resource.setrlimit(resource.RLIMIT_NOFILE, limit) + +def test_on_conflict_rollback_executemany(con): + major, minor, micro = _sqlite3.sqlite_version.split('.')[:3] + if (int(major), int(minor), int(micro)) < (3, 2, 2): + pytest.skip("requires sqlite3 version >= 3.2.2") + con.execute("create table foo(x, unique(x) on conflict rollback)") + con.execute("insert into foo(x) values (1)") + try: + con.executemany("insert into foo(x) values (?)", [[1]]) + except _sqlite3.DatabaseError: + pass + con.execute("insert into foo(x) values (2)") + try: + con.commit() + except _sqlite3.OperationalError: + pytest.fail("_sqlite3 knew nothing about the implicit ROLLBACK") + +def test_statement_arg_checking(con): + with pytest.raises(_sqlite3.Warning) as e: + con(123) + assert str(e.value) == 'SQL is of wrong type. Must be string or unicode.' + with pytest.raises(ValueError) as e: + con.execute(123) + assert str(e.value) == 'operation parameter must be str or unicode' + with pytest.raises(ValueError) as e: + con.executemany(123, 123) + assert str(e.value) == 'operation parameter must be str or unicode' + with pytest.raises(ValueError) as e: + con.executescript(123) + assert str(e.value) == 'script argument must be unicode or string.' + +def test_statement_param_checking(con): + con.execute('create table foo(x)') + con.execute('insert into foo(x) values (?)', [2]) + con.execute('insert into foo(x) values (?)', (2,)) + class seq(object): + def __len__(self): + return 1 + def __getitem__(self, key): + return 2 + con.execute('insert into foo(x) values (?)', seq()) + del seq.__len__ + with pytest.raises(_sqlite3.ProgrammingError): + con.execute('insert into foo(x) values (?)', seq()) + with pytest.raises(_sqlite3.ProgrammingError): + con.execute('insert into foo(x) values (?)', {2:2}) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit