Author: Richard Plangger <planri...@gmail.com> Branch: vmprof-native Changeset: r90790:dd7413118eca Date: 2017-03-22 11:45 -0300 http://bitbucket.org/pypy/pypy/changeset/dd7413118eca/
Log: merge default diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -80,5 +80,6 @@ .hypothesis/ ^release/ ^rpython/_cache$ +^\.cache$ pypy/module/cppyy/.+/*\.pcm diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -34,3 +34,5 @@ 050d84dd78997f021acf0e133934275d63547cc0 release-pypy2.7-v5.4.1 0e2d9a73f5a1818d0245d75daccdbe21b2d5c3ef release-pypy2.7-v5.4.1 aff251e543859ce4508159dd9f1a82a2f553de00 release-pypy2.7-v5.6.0 +fa3249d55d15b9829e1be69cdf45b5a44cec902d release-pypy2.7-v5.7.0 +b16a4363e930f6401bceb499b9520955504c6cb0 release-pypy3.5-v5.7.0 diff --git a/README.rst b/README.rst --- a/README.rst +++ b/README.rst @@ -27,14 +27,19 @@ Building ======== -build with: +First switch to or download the correct branch. The basic choices are +``default`` for Python 2.7 and, for Python 3.X, the corresponding py3.X +branch (e.g. ``py3.5``). + +Build with: .. code-block:: console $ rpython/bin/rpython -Ojit pypy/goal/targetpypystandalone.py -This ends up with ``pypy-c`` binary in the main pypy directory. We suggest -to use virtualenv with the resulting pypy-c as the interpreter; you can -find more details about various installation schemes here: +This ends up with a ``pypy-c`` or ``pypy3-c`` binary in the main pypy +directory. We suggest to use virtualenv with the resulting +pypy-c/pypy3-c as the interpreter; you can find more details about +various installation schemes here: http://doc.pypy.org/en/latest/install.html diff --git a/lib-python/2.7/sysconfig.py b/lib-python/2.7/sysconfig.py --- a/lib-python/2.7/sysconfig.py +++ b/lib-python/2.7/sysconfig.py @@ -29,8 +29,8 @@ 'pypy': { 'stdlib': '{base}/lib-{implementation_lower}/{py_version_short}', 'platstdlib': '{base}/lib-{implementation_lower}/{py_version_short}', - 'purelib': '{base}/lib-{implementation_lower}/{py_version_short}', - 'platlib': '{base}/lib-{implementation_lower}/{py_version_short}', + 'purelib': '{base}/site-packages', + 'platlib': '{base}/site-packages', 'include': '{base}/include', 'platinclude': '{base}/include', 'scripts': '{base}/bin', diff --git a/lib-python/2.7/weakref.py b/lib-python/2.7/weakref.py --- a/lib-python/2.7/weakref.py +++ b/lib-python/2.7/weakref.py @@ -36,9 +36,9 @@ except ImportError: def _delitem_if_value_is(d, key, value): try: - if self.data[key] is value: # fall-back: there is a potential + if d[key] is value: # fall-back: there is a potential # race condition in multithreaded programs HERE - del self.data[key] + del d[key] except KeyError: pass diff --git a/pypy/doc/build.rst b/pypy/doc/build.rst --- a/pypy/doc/build.rst +++ b/pypy/doc/build.rst @@ -110,22 +110,22 @@ 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 \ + tk-dev libgc-dev python-cffi \ liblzma-dev # For lzma on PyPy3. On Fedora:: dnf install gcc make libffi-devel pkgconfig zlib-devel bzip2-devel \ sqlite-devel ncurses-devel expat-devel openssl-devel tk-devel \ - gdbm-devel \ + gdbm-devel python-cffi\ 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 \ - xz-devel # For lzma on PyPy3. + libexpat-devel libffi-devel python-curses python-cffi \ + xz-devel # For lzma on PyPy3. (XXX plus the SLES11 version of libgdbm-dev and tk-dev) On Mac OS X, most of these build-time dependencies are installed alongside diff --git a/pypy/doc/release-v5.7.0.rst b/pypy/doc/release-v5.7.0.rst --- a/pypy/doc/release-v5.7.0.rst +++ b/pypy/doc/release-v5.7.0.rst @@ -2,23 +2,27 @@ PyPy2.7 and PyPy3.5 v5.7 - two in one release ============================================= -We have released PyPy2.7 and a beta-quality PyPy3.5 v5.7. +The PyPy team is proud to release both PyPy2.7 v5.7 (an interpreter supporting +Python v2.7 syntax), and a beta-quality PyPy3.5 v5.7 (an interpreter for Python +v3.5 syntax). The two releases are both based on much the same codebase, thus +the dual release. Note that PyPy3.5 supports Linux 64bit only for now. + This new PyPy2.7 release includes the upstream stdlib version 2.7.13, and -PyPy 3.5 (our first in the 3.5 series) includes the upstream stdlib version +PyPy3.5 (our first in the 3.5 series) includes the upstream stdlib version 3.5.3. We continue to make incremental improvements to our C-API -compatibility layer (cpyext). PyPy2 can now import and run many c-extension -packages, among the most notable are numpy, cython, and pandas. Performance may +compatibility layer (cpyext). PyPy2 can now import and run many C-extension +packages, among the most notable are Numpy, Cython, and Pandas. Performance may be slower than CPython, especially for frequently-called short C functions. Please let us know if your use case is slow, we have ideas how to make things faster but need real-world examples (not micro-benchmarks) of problematic code. Work proceeds at a good pace on the PyPy3.5 version due to a grant_ from the Mozilla Foundation, hence our first 3.5.3 beta -release. Thanks Mozilla !!! While we do not pass all tests, asyncio works and +release. Thanks Mozilla !!! While we do not pass all tests yet, asyncio works and as `these benchmarks show`_ it already gives a nice speed bump. -We also backported the ``f""`` formatting from 3.6 (as an expection; otherwise +We also backported the ``f""`` formatting from 3.6 (as an exception; otherwise "PyPy3.5" supports the Python 3.5 language). CFFI_ has been updated to 1.10, improving an already great package for @@ -65,7 +69,7 @@ We also welcome developers of other `dynamic languages`_ to see what RPython can do for them. -This release supports: +The PyPy 2.7 release supports: * **x86** machines on most common operating systems (Linux 32/64 bits, Mac OS X 64 bits, Windows 32 bits, OpenBSD, FreeBSD) @@ -80,63 +84,60 @@ .. _`dynamic languages`: http://rpython.readthedocs.io/en/latest/examples.html Highlights of the PyPy2.7, cpyext, and RPython changes (since 5.6 released Nov, 2016) -============================================================================================= +===================================================================================== See also issues that were resolved_ * New features and cleanups * update the format of the PYPYLOG file and improvements to vmprof - * improve the consistency of RPython annotation unions - * emit more sysconfig values for downstream cextension packages - * add PyAnySet_Check, PyModule_GetName, PyWeakref_Check*, - _PyImport_{Acquire,Release}Lock, PyGen_Check*, PyOS_AfterFork, - * add translation option --keepgoing to continue after the first AnnotationError + * emit more sysconfig values for downstream cextension packages including + properly setting purelib and platlib to site-packages + * add ``PyAnySet_Check``, ``PyModule_GetName``, ``PyWeakref_Check*``, + ``_PyImport_{Acquire,Release}Lock``, ``PyGen_Check*``, ``PyOS_AfterFork``, * detect and raise on recreation of a PyPy object from a PyObject during tp_dealloc * refactor and clean up poor handling of unicode exposed in work on py3.5 - * builtin cppyy_ supports C++ 11, 14, etc. via cling (reflex has been removed) - * add translation time --disable_entrypoints option for embedding PyPy together - with another RPython VM - * adapt ``weakref`` according to Python issue #19542, will be in CPython 2.7.14 + * builtin module cppyy_ supports C++ 11, 14, etc. via cling (reflex has been removed) + * adapt ``weakref`` according to CPython issue #19542_, will be in CPython 2.7.14 * support translations with cpyext and the Boehm GC (for special cases like - revdb + RevDB_ * implement ``StringBuffer.get_raw_address`` for the buffer protocol, it is now possible to obtain the address of any readonly object without pinning it * refactor the initialization code in translating cpyext - * fix ``"".replace("", "x", num)`` to give the same result as CPython * use a cffi-style C parser to create rffi objects in cpyext, now the - translating python must have cffi available - * add a rpython implementation of siphash24, allow choosing hash algorithm - randomizing the seed - * make ``attach_gdb`` work on Windows (with Visual Studio Debugger) + translating Python must have either ``cffi`` or ``pycparser`` available * implement ``move_to_end(last=True/False)`` on RPython ordered dicts, make available as ``__pypy__.move_to_end`` and, on py3.5, ``OrderedDict.move_to_end()`` * remove completely RPython ``space.wrap`` in a major cleanup, differentiate between ``space.newtext`` and ``space.newbytes`` on py3.5 - * improve shadowstack to where it is now the default in place of asmgcc + * any uncaught RPython exception in the interpreter is turned into a + SystemError (rather than a segfault) + * add translation time --disable_entrypoints option for embedding PyPy together + with another RPython VM + * Bug Fixes - * any uncaught RPython exception in the interpreter is turned into a - SystemError (rather than a segfault) + * fix ``"".replace("", "x", num)`` to give the same result as CPython * create log files without the executable bit - * disable clock_gettime() on OS/X, since we support 10.11 and it was only + * disable ``clock_gettime()`` on OS/X, since we support 10.11 and it was only added in 10.12 - * support HAVE_FSTATVFS which was unintentionally always false - * fix user-created C-API heaptype, issue #2434 - * fix PyDict_Update is not actually the same as dict.update - * assign tp_doc on PyTypeObject and tie it to the app-level __doc__ attribute - issue #2446 + * support ``HAVE_FSTATVFS`` which was unintentionally always false + * fix user-created C-API heaptype, issue #2434_ + * fix ``PyDict_Update`` is not actually the same as ``dict.update`` + * assign ``tp_doc`` on ``PyTypeObject`` and tie it to the app-level ``__doc__`` attribute + issue #2446_ * clean up memory leaks around ``PyObject_GetBuffer``, ``PyMemoryView_GET_BUFFER``, ``PyMemoryView_FromBuffer``, and ``PyBuffer_Release`` - * improve support for creating c-extension objects from app-level classes, - filling more slots especially ``tp_new`` and ``tp_dealloc`` - * add rstack.stack_almost_full() and use it to avoid stack overflow due to - the JIT where possible - * fix for ctypes.c_bool returning bool restype issue #2475 + * improve support for creating C-extension objects from app-level classes, + filling more slots, especially ``tp_new`` and ``tp_dealloc`` + * fix for ``ctypes.c_bool`` returning ``bool`` restype, issue #2475_ * fix in corner cases with the GIL and C-API functions + * allow overriding thread.local.__init__ in a subclass, issue #2501_ + * allow ``PyClass_New`` to be called with NULL as the first arguemnt, issue #2504_ + * Performance improvements: @@ -158,17 +159,28 @@ information across failing guards * add optimized "zero-copy" path for ``io.FileIO.readinto`` +* RPython improvements + + * improve the consistency of RPython annotation unions + * add translation option --keepgoing to continue after the first AnnotationError + * improve shadowstack to where it is now the default in place of asmgcc + * add a rpython implementation of siphash24, allow choosing hash algorithm + randomizing the seed + * add rstack.stack_almost_full() and use it to avoid stack overflow due to + the JIT where possible + Highlights of the PyPy3.5 release (since 5.5 alpha released Oct, 2016) -========================================================= +========================================================================== -Development moved from the py3k branch to the py3.5 branch in the pypy bitbucket repo +Development moved from the py3k branch to the py3.5 branch in the PyPy bitbucket repo. * New features - * this first PyPy3.5 release implements much, but not all, of Python 3.5.3 + * this first PyPy3.5 release implements most of Python 3.5.3, exceptions are listed below * PEP 456 allowing secure and interchangable hash algorithms * use cryptography_'s cffi backend for SSL + * Bug Fixes * implement fixes for some CPython issues that arose since the last release @@ -176,12 +188,21 @@ * Performance improvements: - * do not create a list whenever descr_new of a bytesobject is called - * - * - * + * do not create a list whenever ``descr_new`` of a ``bytesobject`` is called + +* The following features of Python 3.5 are not implemented yet in PyPy: + + * PEP 442: Safe object finalization + * PEP 489: Multi-phase extension module initialization .. _resolved: whatsnew-pypy2-5.7.0.html +.. _19542: https://bugs.python.org/issue19542 +.. _2434: https://bitbucket.org/pypy/pypy/issues/2434/support-pybind11-in-conjunction-with-pypys +.. _2446: https://bitbucket.org/pypy/pypy/issues/2446/cpyext-tp_doc-field-not-reflected-on +.. _2475: https://bitbucket.org/pypy/pypy/issues/2475 +.. _2501: https://bitbucket.org/pypy/pypy/issues/2501 +.. _2504: https://bitbucket.org/pypy/pypy/issues/2504 +.. _RevDB: https://bitbucket.org/pypy/revdb .. _cryptography: https://cryptography.io .. _cppyy: cppyy.html diff --git a/pypy/module/_cffi_backend/cffi1_module.py b/pypy/module/_cffi_backend/cffi1_module.py --- a/pypy/module/_cffi_backend/cffi1_module.py +++ b/pypy/module/_cffi_backend/cffi1_module.py @@ -48,3 +48,4 @@ w_modules_dict = space.sys.get('modules') space.setitem(w_modules_dict, w_name, module) space.setitem(w_modules_dict, space.newtext(name + '.lib'), lib) + return module 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 @@ -1469,10 +1469,6 @@ copy_header_files(cts, trunk_include, use_micronumpy) -def _load_from_cffi(space, name, path, initptr): - from pypy.module._cffi_backend import cffi1_module - cffi1_module.load_cffi1_module(space, name, path, initptr) - @unwrap_spec(path='text', name='text') def load_extension_module(space, path, name): # note: this is used both to load CPython-API-style C extension @@ -1505,11 +1501,11 @@ pass else: try: - _load_from_cffi(space, name, path, initptr) + from pypy.module._cffi_backend import cffi1_module + return cffi1_module.load_cffi1_module(space, name, path, initptr) except: rdynload.dlclose(dll) raise - return # if space.config.objspace.usemodules.cpyext: also_look_for = 'init%s' % (basename,) @@ -1518,8 +1514,7 @@ except KeyError: pass else: - load_cpyext_module(space, name, path, dll, initptr) - return + return load_cpyext_module(space, name, path, dll, initptr) if look_for is not None: look_for += ' or ' + also_look_for else: @@ -1535,9 +1530,10 @@ space.getbuiltinmodule("cpyext") # mandatory to init cpyext state = space.fromcache(State) - if state.find_extension(name, path) is not None: + w_mod = state.find_extension(name, path) + if w_mod is not None: rdynload.dlclose(dll) - return + return w_mod old_context = state.package_context state.package_context = name, path try: @@ -1546,7 +1542,8 @@ state.check_and_raise_exception() finally: state.package_context = old_context - state.fixup_extension(name, path) + w_mod = state.fixup_extension(name, path) + return w_mod @specialize.ll() def generic_cpy_call(space, func, *args): diff --git a/pypy/module/cpyext/classobject.py b/pypy/module/cpyext/classobject.py --- a/pypy/module/cpyext/classobject.py +++ b/pypy/module/cpyext/classobject.py @@ -39,6 +39,8 @@ @cpython_api([PyObject, PyObject, PyObject], PyObject) def PyClass_New(space, w_bases, w_dict, w_name): + if w_bases is None: + w_bases = space.newtuple([]) w_classobj = space.gettypefor(W_ClassObject) return space.call_function(w_classobj, w_name, w_bases, w_dict) diff --git a/pypy/module/cpyext/modsupport.py b/pypy/module/cpyext/modsupport.py --- a/pypy/module/cpyext/modsupport.py +++ b/pypy/module/cpyext/modsupport.py @@ -10,6 +10,14 @@ from pypy.module.cpyext.state import State from pypy.interpreter.error import oefmt +@cpython_api([rffi.CCHARP], PyObject) +def PyModule_New(space, name): + """ + Return a new module object with the __name__ attribute set to name. + Only the module's __doc__ and __name__ attributes are filled in; + the caller is responsible for providing a __file__ attribute.""" + return Module(space, space.newtext(rffi.charp2str(name))) + #@cpython_api([rffi.CCHARP], PyObject) def PyImport_AddModule(space, name): """Return the module object corresponding to a module name. The name argument diff --git a/pypy/module/cpyext/state.py b/pypy/module/cpyext/state.py --- a/pypy/module/cpyext/state.py +++ b/pypy/module/cpyext/state.py @@ -165,6 +165,7 @@ w_dict = w_mod.getdict(space) w_copy = space.call_method(w_dict, 'copy') self.extensions[path] = w_copy + return w_mod def _rawrefcount_perform(space): diff --git a/pypy/module/cpyext/stubs.py b/pypy/module/cpyext/stubs.py --- a/pypy/module/cpyext/stubs.py +++ b/pypy/module/cpyext/stubs.py @@ -1365,13 +1365,6 @@ """ raise NotImplementedError -@cpython_api([rffi.CCHARP], PyObject) -def PyModule_New(space, name): - """Return a new module object with the __name__ attribute set to name. Only - the module's __doc__ and __name__ attributes are filled in; the caller is - responsible for providing a __file__ attribute.""" - raise NotImplementedError - @cpython_api([PyObject], rffi.CCHARP) def PyModule_GetFilename(space, module): """Return the name of the file from which module was loaded using module's diff --git a/pypy/module/cpyext/test/test_classobject.py b/pypy/module/cpyext/test/test_classobject.py --- a/pypy/module/cpyext/test/test_classobject.py +++ b/pypy/module/cpyext/test/test_classobject.py @@ -77,3 +77,15 @@ class C: pass assert module.get_classtype() is type(C) + + def test_pyclass_new_no_bases(self): + module = self.import_extension('foo', [ + ("new_foo", "METH_O", + """ + return PyClass_New(NULL, PyDict_New(), args); + """)]) + FooClass = module.new_foo("FooClass") + class Cls1: + pass + assert type(FooClass) is type(Cls1) + assert FooClass.__bases__ == Cls1.__bases__ diff --git a/pypy/module/cpyext/test/test_module.py b/pypy/module/cpyext/test/test_module.py --- a/pypy/module/cpyext/test/test_module.py +++ b/pypy/module/cpyext/test/test_module.py @@ -1,8 +1,15 @@ +from pypy.module.cpyext.modsupport import PyModule_New from pypy.module.cpyext.test.test_api import BaseApiTest from rpython.rtyper.lltypesystem import rffi class TestModuleObject(BaseApiTest): + def test_module_new(self, space): + with rffi.scoped_str2charp('testname') as buf: + w_mod = PyModule_New(space, buf) + assert space.eq_w(space.getattr(w_mod, space.newtext('__name__')), + space.newtext('testname')) + def test_module_getname(self, space, api): w_sys = space.wrap(space.sys) p = api.PyModule_GetName(w_sys) diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py --- a/pypy/module/imp/importing.py +++ b/pypy/module/imp/importing.py @@ -616,7 +616,7 @@ from pypy.module.cpyext.api import load_extension_module log_pyverbose(space, 1, "import %s # from %s\n" % (modulename, filename)) - load_extension_module(space, filename, modulename) + return load_extension_module(space, filename, modulename) # NB. cpyext.api.load_extension_module() can also delegate to _cffi_backend @jit.dont_look_inside @@ -680,8 +680,8 @@ pass return w_mod elif find_info.modtype == C_EXTENSION and has_so_extension(space): - load_c_extension(space, find_info.filename, space.text_w(w_modulename)) - return check_sys_modules(space, w_modulename) + return load_c_extension(space, find_info.filename, + space.text_w(w_modulename)) except OperationError: w_mods = space.sys.get('modules') space.call_method(w_mods, 'pop', w_modulename, space.w_None) diff --git a/pypy/module/imp/interp_imp.py b/pypy/module/imp/interp_imp.py --- a/pypy/module/imp/interp_imp.py +++ b/pypy/module/imp/interp_imp.py @@ -136,8 +136,8 @@ def load_dynamic(space, w_modulename, filename, w_file=None): if not importing.has_so_extension(space): raise oefmt(space.w_ImportError, "Not implemented") - importing.load_c_extension(space, filename, space.text_w(w_modulename)) - return importing.check_sys_modules(space, w_modulename) + return importing.load_c_extension(space, filename, + space.text_w(w_modulename)) def new_module(space, w_name): return Module(space, w_name, add_package=False) diff --git a/pypy/module/thread/os_local.py b/pypy/module/thread/os_local.py --- a/pypy/module/thread/os_local.py +++ b/pypy/module/thread/os_local.py @@ -1,6 +1,7 @@ import weakref from rpython.rlib import jit from pypy.interpreter.baseobjspace import W_Root +from pypy.interpreter.error import oefmt from pypy.interpreter.executioncontext import ExecutionContext from pypy.interpreter.typedef import (TypeDef, interp2app, GetSetProperty, descr_get_dict) @@ -74,18 +75,20 @@ return w_dict def descr_local__new__(space, w_subtype, __args__): + from pypy.objspace.std.typeobject import _precheck_for_new + w_subtype = _precheck_for_new(space, w_subtype) + if __args__.arguments_w or __args__.keywords: + w_parent_init, _ = space.lookup_in_type_where(w_subtype, '__init__') + if w_parent_init is space.w_object: + raise oefmt(space.w_TypeError, + "Initialization arguments are not supported") local = space.allocate_instance(Local, w_subtype) Local.__init__(local, space, __args__) return local - def descr_local__init__(self, space): - # No arguments allowed - pass - Local.typedef = TypeDef("thread._local", __doc__ = "Thread-local data", __new__ = interp2app(Local.descr_local__new__.im_func), - __init__ = interp2app(Local.descr_local__init__), __dict__ = GetSetProperty(descr_get_dict, cls=Local), ) diff --git a/pypy/module/thread/test/test_local.py b/pypy/module/thread/test/test_local.py --- a/pypy/module/thread/test/test_local.py +++ b/pypy/module/thread/test/test_local.py @@ -72,6 +72,19 @@ assert seen1 == [1, 2, 3, 4, 5] assert tags == ['???'] + def test_local_init2(self): + import thread + + class A(object): + def __init__(self, n): + assert n == 42 + self.n = n + class X(thread._local, A): + pass + + x = X(42) + assert x.n == 42 + def test_local_setdict(self): import thread x = thread._local() diff --git a/pypy/module/zipimport/interp_zipimport.py b/pypy/module/zipimport/interp_zipimport.py --- a/pypy/module/zipimport/interp_zipimport.py +++ b/pypy/module/zipimport/interp_zipimport.py @@ -263,11 +263,18 @@ if compiled: w_result = self.import_pyc_file(space, fullname, fname, buf, pkgpath) - if w_result is not None: - return w_result + if w_result is None: + continue else: - return self.import_py_file(space, fullname, fname, + w_result = self.import_py_file(space, fullname, fname, buf, pkgpath) + if space.sys.get_flag('verbose') >= 1: + w_stderr = space.sys.get('stderr') + message = "import %s # loaded from Zip %s%s%s\n" % ( + fullname, self.filename, os.path.sep, fname) + space.call_method(w_stderr, "write", + space.newtext(message)) + return w_result except: w_mods = space.sys.get('modules') space.call_method(w_mods, 'pop', space.newtext(fullname), space.w_None) diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py --- a/pypy/objspace/std/dictmultiobject.py +++ b/pypy/objspace/std/dictmultiobject.py @@ -1049,6 +1049,8 @@ else: return d.pop(key, w_default) elif self._never_equal_to(space.type(w_key)): + if w_default is not None: + return w_default raise KeyError else: self.switch_to_object_strategy(w_dict) diff --git a/pypy/objspace/std/test/test_dictmultiobject.py b/pypy/objspace/std/test/test_dictmultiobject.py --- a/pypy/objspace/std/test/test_dictmultiobject.py +++ b/pypy/objspace/std/test/test_dictmultiobject.py @@ -161,7 +161,7 @@ w_d.initialize_content([(w(1), wb("a")), (w(2), wb("b"))]) w_l = self.space.call_method(w_d, "keys") assert sorted(self.space.listview_int(w_l)) == [1,2] - + # make sure that .keys() calls newlist_bytes for string dicts def not_allowed(*args): assert False, 'should not be called' @@ -174,7 +174,7 @@ # XXX: it would be nice if the test passed without monkeypatch.undo(), # but we need space.newlist_unicode for it - monkeypatch.undo() + monkeypatch.undo() w_d = self.space.newdict() w_d.initialize_content([(w(u"a"), w(1)), (w(u"b"), w(6))]) w_l = self.space.call_method(w_d, "keys") @@ -223,6 +223,10 @@ assert len(dd) == 1 raises(KeyError, dd.pop, 33) + assert d.pop("abc", None) is None + raises(KeyError, d.pop, "abc") + assert len(d) == 2 + def test_has_key(self): d = {1: 2, 3: 4} assert d.has_key(1) @@ -1466,4 +1470,3 @@ fakespace = FakeSpace() d = fakespace.newdict(module=True) assert type(d.get_strategy()) is BytesDictStrategy - diff --git a/pypy/tool/release/repackage.sh b/pypy/tool/release/repackage.sh --- a/pypy/tool/release/repackage.sh +++ b/pypy/tool/release/repackage.sh @@ -1,6 +1,6 @@ # Edit these appropriately before running this script maj=5 -min=6 +min=7 rev=0 branchname=release-pypy2.7-5.x # ==OR== release-$maj.x # ==OR== release-$maj.$min.x tagname=release-pypy2.7-v$maj.$min.$rev # ==OR== release-$maj.$min diff --git a/rpython/rlib/rthread.py b/rpython/rlib/rthread.py --- a/rpython/rlib/rthread.py +++ b/rpython/rlib/rthread.py @@ -429,7 +429,11 @@ gc._trace_callback(callback, arg, p + offset) llop.threadlocalref_release(lltype.Void) _lambda_trace_tlref = lambda: _trace_tlref - TRACETLREF = lltype.GcStruct('TRACETLREF') + # WAAAH obscurity: can't use a name that may be non-unique, + # otherwise the types compare equal, even though we call + # register_custom_trace_hook() to register different trace + # functions... + TRACETLREF = lltype.GcStruct('TRACETLREF%d' % unique_id) _tracetlref_obj = lltype.malloc(TRACETLREF, immortal=True) @staticmethod diff --git a/rpython/rlib/rurandom.py b/rpython/rlib/rurandom.py --- a/rpython/rlib/rurandom.py +++ b/rpython/rlib/rurandom.py @@ -99,8 +99,11 @@ eci = eci.merge(ExternalCompilationInfo(includes=['linux/random.h'])) class CConfig: _compilation_info_ = eci - GRND_NONBLOCK = rffi_platform.ConstantInteger('GRND_NONBLOCK') + GRND_NONBLOCK = rffi_platform.DefinedConstantInteger( + 'GRND_NONBLOCK') globals().update(rffi_platform.configure(CConfig)) + if GRND_NONBLOCK is None: + GRND_NONBLOCK = 0x0001 # from linux/random.h # On Linux, use the syscall() function because the GNU libc doesn't # expose the Linux getrandom() syscall yet. diff --git a/rpython/rlib/test/test_rthread.py b/rpython/rlib/test/test_rthread.py --- a/rpython/rlib/test/test_rthread.py +++ b/rpython/rlib/test/test_rthread.py @@ -262,15 +262,23 @@ py.test.skip("no __thread support here") class FooBar(object): - pass + def __init__(self, a, b): + self.lst = [a, b] t = ThreadLocalReference(FooBar) + t2 = ThreadLocalReference(FooBar) def tset(): - x1 = FooBar() + x1 = FooBar(40, 2) t.set(x1) return weakref.ref(x1) tset._dont_inline_ = True + def t2set(): + x1 = FooBar(50, 3) + t2.set(x1) + return weakref.ref(x1) + t2set._dont_inline_ = True + class WrFromThread: pass wr_from_thread = WrFromThread() @@ -279,22 +287,30 @@ config = objectmodel.fetch_translated_config() assert t.automatic_keepalive(config) is True wr = tset() - import gc; gc.collect() # 'x1' should not be collected - x2 = t.get() + wr2 = t2set() + import gc; gc.collect() # the two 'x1' should not be collected + x1 = t.get() + assert x1 is not None + assert wr() is not None + assert wr() is x1 + assert x1.lst == [40, 2] + x2 = t2.get() assert x2 is not None - assert wr() is not None - assert wr() is x2 - return wr + assert wr2() is not None + assert wr2() is x2 + assert x2.lst == [50, 3] + return wr, wr2 def thread_entry_point(): - wr = f() + wr, wr2 = f() wr_from_thread.wr = wr + wr_from_thread.wr2 = wr2 wr_from_thread.seen = True def main(): wr_from_thread.seen = False start_new_thread(thread_entry_point, ()) - wr1 = f() + wr1, wr2 = f() count = 0 while True: time.sleep(0.5) @@ -302,10 +318,15 @@ break count += 1 assert wr_from_thread.seen is True - wr2 = wr_from_thread.wr - import gc; gc.collect() # wr2() should be collected here + wr_other_1 = wr_from_thread.wr + wr_other_2 = wr_from_thread.wr2 + import gc; gc.collect() # wr_other_*() should be collected here assert wr1() is not None # this thread, still running - assert wr2() is None # other thread, not running any more + assert wr2() is not None # this thread, still running + assert wr_other_1() is None # other thread, not running any more + assert wr_other_2() is None # other thread, not running any more + assert wr1().lst == [40, 2] + assert wr2().lst == [50, 3] return 42 extra_options = {'no__thread': no__thread, 'shared': True} _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit