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

Reply via email to