[pypy-commit] pypy py3k: merge default

pjenvey noreply at buildbot.pypy.org
Sun May 4 00:04:20 CEST 2014


Author: Philip Jenvey <pjenvey at underboss.org>
Branch: py3k
Changeset: r71241:2f47b24c4692
Date: 2014-05-02 11:37 -0700
http://bitbucket.org/pypy/pypy/changeset/2f47b24c4692/

Log:	merge default

diff --git a/pypy/doc/release-2.3.0.rst b/pypy/doc/release-2.3.0.rst
--- a/pypy/doc/release-2.3.0.rst
+++ b/pypy/doc/release-2.3.0.rst
@@ -18,17 +18,18 @@
     http://pypy.org/download.html
 
 We would like to thank our donors for the continued support of the PyPy
-project. We showed quite a bit of progress on all three projects (see below)
-and we're slowly running out of funds.
-Please consider donating more so we can finish those projects!  The three
-projects are:
+project, and for those who donate to our three sub-projects.
+We showed quite a bit of progress 
+but we're slowly running out of funds.
+Please consider donating more, or even better convince your employer to donate,
+so we can finish those projects!  The three sub-projects are:
 
 * `Py3k`_ (supporting Python 3.x): the release PyPy3 2.2 is imminent.
 
 * `STM`_ (software transactional memory): a preview will be released very soon,
   once we fix a few bugs
 
-* `NumPy`_ the work done is included in the PyPy 2.2 release. More details below.
+* `NumPy`_ which is included in the PyPy 2.3 release. More details below.
 
 .. _`Py3k`: http://pypy.org/py3donate.html
 .. _`STM`: http://pypy.org/tmdonate2.html
@@ -44,8 +45,8 @@
 =============
 
 PyPy is a very compliant Python interpreter, almost a drop-in replacement for
-CPython 2.7. It's fast (`pypy 2.2 and cpython 2.7.2`_ performance comparison;
-note that the latest cpython is not faster than cpython 2.7.2)
+CPython 2.7. It's fast (`pypy 2.3 and cpython 2.7.x`_ performance comparison;
+note that cpython's speed has not changed since 2.7.2)
 due to its integrated tracing JIT compiler.
 
 This release supports x86 machines running Linux 32/64, Mac OS X 64, Windows,
@@ -56,13 +57,13 @@
 bit python is still stalling, we would welcome a volunteer
 to `handle that`_.
 
-.. _`pypy 2.2 and cpython 2.7.2`: http://speed.pypy.org
+.. _`pypy 2.3 and cpython 2.7.x`: http://speed.pypy.org
 .. _`handle that`: http://doc.pypy.org/en/latest/windows.html#what-is-missing-for-a-full-64-bit-translation
 
 Highlights
 ==========
 
-Bugfixes
+Bugfixes 
 --------
 
 Many issues were cleaned up after being reported by users to https://bugs.pypy.org (ignore the bad SSL certificate) or on IRC at #pypy. Note that we consider
@@ -71,7 +72,7 @@
 * The ARM port no longer crashes on unaligned memory access to floats and doubles,
   and singlefloats are supported in the JIT.
 
-* Generators are faster since they now skip unecessary cleanup
+* Generators are faster since they now skip unnecessary cleanup
 
 * A first time contributor simplified JIT traces by adding integer bound
   propagation in indexing and logical operations.
@@ -84,6 +85,8 @@
 
 * Fix a rpython bug with loop-unrolling that appeared in the `HippyVM`_ PHP port
 
+* Support for corner cases on objects with __int__ and __float__ methods
+
 .. _`HippyVM`: http://www.hippyvm.com
 
 New Platforms and Features
@@ -97,8 +100,6 @@
 
 * Support for precompiled headers in the build process for MSVC
 
-* Support for objects with __int__ and __float__ methods
-
 * Tweak support of errno in cpyext (the PyPy implemenation of the capi)
 
 
@@ -127,8 +128,12 @@
 * A cffi-based ``numpy.random`` module is available as a branch in the numpy
   repository, it will be merged soon after this release.
 
-* enhancements to the PyPy JIT were made to support virtualizing the raw_store/raw_load memory operations used in numpy arrays. Further work remains here in virtualizing the alloc_raw_storage when possible. This will allow scalars to have storages but still be virtualized when possible in loops.
+* enhancements to the PyPy JIT were made to support virtualizing the raw_store/raw_load 
+  memory operations used in numpy arrays. Further work remains here in virtualizing the 
+  alloc_raw_storage when possible. This will allow scalars to have storages but still be 
+  virtualized when possible in loops.
 
 Cheers
+
 The PyPy Team
 
diff --git a/pypy/doc/whatsnew-2.3.0.rst b/pypy/doc/whatsnew-2.3.0.rst
--- a/pypy/doc/whatsnew-2.3.0.rst
+++ b/pypy/doc/whatsnew-2.3.0.rst
@@ -161,3 +161,7 @@
 
 .. branch: refactor-buffer-api
 Properly implement old/new buffer API for objects and start work on replacing bufferstr usage
+
+.. branch: issue1430
+Add a lock for unsafe calls to gethostbyname and gethostbyaddr
+
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
@@ -3,6 +3,5 @@
 =======================
 
 .. this is a revision shortly after release-2.3.x
-.. startrev: 0524dae88c75
+.. startrev: 0f75ad4d14ce
 
-.. branch: reflex-support
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -705,23 +705,17 @@
     def allocate_lock(self):
         """Return an interp-level Lock object if threads are enabled,
         and a dummy object if they are not."""
-        if self.config.objspace.usemodules.thread:
-            # we use a sub-function to avoid putting the 'import' statement
-            # here, where the flow space would see it even if thread=False
-            return self.__allocate_lock()
-        else:
-            return dummy_lock
-
-    def __allocate_lock(self):
-        from rpython.rlib.rthread import allocate_lock, error
+        from rpython.rlib import rthread
+        if not self.config.objspace.usemodules.thread:
+            return rthread.dummy_lock
         # hack: we can't have prebuilt locks if we're translating.
         # In this special situation we should just not lock at all
         # (translation is not multithreaded anyway).
         if not we_are_translated() and self.config.translating:
             raise CannotHaveLock()
         try:
-            return allocate_lock()
-        except error:
+            return rthread.allocate_lock()
+        except rthread.error:
             raise OperationError(self.w_RuntimeError,
                                  self.wrap("out of resources"))
 
@@ -1765,24 +1759,6 @@
         return space.getitem(w_glob, space.wrap('anonymous'))
 
 
-class DummyLock(object):
-    def acquire(self, flag):
-        return True
-
-    def release(self):
-        pass
-
-    def _freeze_(self):
-        return True
-
-    def __enter__(self):
-        pass
-
-    def __exit__(self, *args):
-        pass
-
-dummy_lock = DummyLock()
-
 # Table describing the regular part of the interface of object spaces,
 # namely all methods which only take w_ arguments and return a w_ result
 # (if any).
diff --git a/pypy/module/_ast/test/test_ast.py b/pypy/module/_ast/test/test_ast.py
--- a/pypy/module/_ast/test/test_ast.py
+++ b/pypy/module/_ast/test/test_ast.py
@@ -20,6 +20,11 @@
         ast = self.ast
         assert isinstance(ast.__version__, str)
 
+    def test_flags(self):
+        skip("broken")
+        from copy_reg import _HEAPTYPE
+        assert self.ast.Module.__flags__ & _HEAPTYPE
+
     def test_build_ast(self):
         ast = self.ast
         mod = self.get_ast("x = 4")
@@ -234,19 +239,19 @@
         x = ast.Num()
         assert x._fields == ('n',)
         exc = raises(AttributeError, getattr, x, 'n')
-        assert exc.value.args[0] == "'Num' object has no attribute 'n'"
+        assert "Num' object has no attribute 'n'" in exc.value.args[0]
 
         x = ast.Num(42)
         assert x.n == 42
         exc = raises(AttributeError, getattr, x, 'lineno')
-        assert exc.value.args[0] == "'Num' object has no attribute 'lineno'"
+        assert "Num' object has no attribute 'lineno'" in exc.value.args[0]
 
         y = ast.Num()
         x.lineno = y
         assert x.lineno == y
 
         exc = raises(AttributeError, getattr, x, 'foobar')
-        assert exc.value.args[0] == "'Num' object has no attribute 'foobar'"
+        assert "Num' object has no attribute 'foobar'" in exc.value.args[0]
 
         x = ast.Num(lineno=2)
         assert x.lineno == 2
@@ -260,9 +265,8 @@
         raises(TypeError, ast.Num, 1, 2, lineno=0)
 
     def test_issue1680_nonseq(self):
+        # Test deleting an attribute manually
 
-        # Test deleting an attribute manually
-         
         _ast = self.ast
         mod = self.get_ast("self.attr")
         assert isinstance(mod, _ast.Module)
@@ -303,9 +307,8 @@
         assert not hasattr(mod.body[0], 'name')
 
     def test_issue1680_seq(self):
+        # Test deleting an attribute manually
 
-        # Test deleting an attribute manually
-         
         _ast = self.ast
         mod = self.get_ast("self.attr")
         assert isinstance(mod, _ast.Module)
@@ -408,9 +411,8 @@
         import ast
         num_node = ast.Num(n=2, lineno=2, col_offset=3)
         dict_res = num_node.__dict__
-        
         assert dict_res == {'n':2, 'lineno':2, 'col_offset':3}
-    
+
     def test_issue1673_Num_notfullinit(self):
         import ast
         import copy
@@ -418,7 +420,7 @@
         assert num_node.n == 2
         assert num_node.lineno == 2
         num_node2 = copy.deepcopy(num_node)
-    
+
     def test_issue1673_Num_fullinit(self):
         import ast
         import copy 
@@ -429,7 +431,7 @@
         assert num_node.col_offset == num_node2.col_offset
         dict_res = num_node2.__dict__
         assert dict_res == {'n':2, 'lineno':2, 'col_offset':3}
-          
+
     def test_issue1673_Str(self):
         import ast
         import copy
@@ -439,4 +441,3 @@
         str_node2 = copy.deepcopy(str_node)
         dict_res = str_node2.__dict__
         assert dict_res == {'n':2, 'lineno':2}
-    
\ No newline at end of file
diff --git a/pypy/module/_lsprof/test/test_cprofile.py b/pypy/module/_lsprof/test/test_cprofile.py
--- a/pypy/module/_lsprof/test/test_cprofile.py
+++ b/pypy/module/_lsprof/test/test_cprofile.py
@@ -43,7 +43,7 @@
         )
         by_id = set()
         for entry in stats:
-            if entry.code == f1.func_code:
+            if entry.code == f1.__code__:
                 assert len(entry.calls) == 2
                 for subentry in entry.calls:
                     assert subentry.code in expected
@@ -219,10 +219,10 @@
                             lines.remove(line)
                             break
                     else:
-                        print('NOT FOUND:', pattern.rstrip('\n'))
+                        print('NOT FOUND: %s' % pattern.rstrip('\n'))
                         print('--- GOT ---')
                         print(got)
-                        print()
+                        print('')
                         print('--- EXPECTED ---')
                         print(expected)
                         assert False
diff --git a/pypy/module/_socket/__init__.py b/pypy/module/_socket/__init__.py
--- a/pypy/module/_socket/__init__.py
+++ b/pypy/module/_socket/__init__.py
@@ -17,6 +17,8 @@
     def startup(self, space):
         from rpython.rlib.rsocket import rsocket_startup
         rsocket_startup()
+        from pypy.module._socket.interp_func import State
+        space.fromcache(State).startup(space)
 
     def buildloaders(cls):
         from rpython.rlib import rsocket
diff --git a/pypy/module/_socket/interp_func.py b/pypy/module/_socket/interp_func.py
--- a/pypy/module/_socket/interp_func.py
+++ b/pypy/module/_socket/interp_func.py
@@ -43,8 +43,9 @@
     Return the true host name, a list of aliases, and a list of IP addresses,
     for a host.  The host argument is a string giving a host name or IP number.
     """
+    lock = space.fromcache(State).netdb_lock
     try:
-        res = rsocket.gethostbyname_ex(host)
+        res = rsocket.gethostbyname_ex(host, lock)
     except SocketError, e:
         raise converted_error(space, e)
     return common_wrapgethost(space, res)
@@ -56,8 +57,9 @@
     Return the true host name, a list of aliases, and a list of IP addresses,
     for a host.  The host argument is a string giving a host name or IP number.
     """
+    lock = space.fromcache(State).netdb_lock
     try:
-        res = rsocket.gethostbyaddr(host)
+        res = rsocket.gethostbyaddr(host, lock)
     except SocketError, e:
         raise converted_error(space, e)
     return common_wrapgethost(space, res)
@@ -316,3 +318,10 @@
             raise OperationError(space.w_ValueError,
                                  space.wrap('Timeout value out of range'))
     rsocket.setdefaulttimeout(timeout)
+
+class State(object):
+    def __init__(self, space):
+        self.netdb_lock = None
+
+    def startup(self, space):
+        self.netdb_lock = space.allocate_lock()
diff --git a/pypy/module/cppyy/test/test_datatypes.py b/pypy/module/cppyy/test/test_datatypes.py
--- a/pypy/module/cppyy/test/test_datatypes.py
+++ b/pypy/module/cppyy/test/test_datatypes.py
@@ -7,6 +7,8 @@
 def setup_module(mod):
     if sys.platform == 'win32':
         py.test.skip("win32 not supported so far")
+    if sys.maxsize < 2 ** 31:
+        py.test.skip("32 bit not supported so far")
     err = os.system("cd '%s' && make datatypesDict.so" % currpath)
     if err:
         raise OSError("'make' failed (see stderr)")
@@ -30,7 +32,7 @@
     def test02_instance_data_read_access(self):
         """Test read access to instance public data and verify values"""
 
-        import cppyy, sys
+        import cppyy
         cppyy_test_data = cppyy.gbl.cppyy_test_data
 
         c = cppyy_test_data()
@@ -117,7 +119,7 @@
     def test03_instance_data_write_access(self):
         """Test write access to instance public data and verify values"""
 
-        import cppyy, sys
+        import cppyy
         cppyy_test_data = cppyy.gbl.cppyy_test_data
 
         c = cppyy_test_data()
@@ -489,14 +491,14 @@
 
         import cppyy
         four_vector = cppyy.gbl.four_vector
-        
+
         t1 = four_vector(1., 2., 3., -4.)
         t2 = four_vector(0., 0., 0.,  0.)
         t3 = four_vector(t1)
-  
+
         assert t1 == t3
         assert t1 != t2
-        
+
         for i in range(4):
             assert t1[i] == t3[i]
 
@@ -625,8 +627,8 @@
 
     def test18_object_and_pointer_comparisons(self):
         """Verify object and pointer comparisons"""
-    
-        import cppyy 
+
+        import cppyy
         gbl = cppyy.gbl
 
         c1 = cppyy.bind_object(0, gbl.cppyy_test_data)
@@ -662,11 +664,11 @@
 
     def test19_object_validity(self):
         """Test object validity checking"""
-        
+
         from cppyy import gbl
 
         d = gbl.cppyy_test_pod()
-                     
+
         assert d
         assert not not d
 
diff --git a/pypy/module/micronumpy/__init__.py b/pypy/module/micronumpy/__init__.py
--- a/pypy/module/micronumpy/__init__.py
+++ b/pypy/module/micronumpy/__init__.py
@@ -23,7 +23,7 @@
 
         'set_string_function': 'appbridge.set_string_function',
         'typeinfo': 'descriptor.get_dtype_cache(space).w_typeinfo',
-        'nditer': 'nditer.nditer',
+        'nditer': 'nditer.W_NDIter',
     }
     for c in ['MAXDIMS', 'CLIP', 'WRAP', 'RAISE']:
         interpleveldefs[c] = 'space.wrap(constants.%s)' % c
diff --git a/pypy/module/micronumpy/descriptor.py b/pypy/module/micronumpy/descriptor.py
--- a/pypy/module/micronumpy/descriptor.py
+++ b/pypy/module/micronumpy/descriptor.py
@@ -131,12 +131,13 @@
         return dtype
 
     def get_name(self):
-        return self.w_box_type.name
+        name = self.w_box_type.name
+        if name.endswith('_'):
+            name = name[:-1]
+        return name
 
     def descr_get_name(self, space):
         name = self.get_name()
-        if name[-1] == '_':
-            name = name[:-1]
         if self.is_flexible() and self.elsize != 0:
             return space.wrap(name + str(self.elsize * 8))
         return space.wrap(name)
@@ -820,7 +821,7 @@
             w_box_type=space.gettypefor(boxes.W_ULongBox),
         )
         aliases = {
-            NPY.BOOL:        ['bool', 'bool8'],
+            NPY.BOOL:        ['bool_', 'bool8'],
             NPY.BYTE:        ['byte'],
             NPY.UBYTE:       ['ubyte'],
             NPY.SHORT:       ['short'],
@@ -835,8 +836,8 @@
             NPY.CFLOAT:      ['csingle'],
             NPY.CDOUBLE:     ['complex', 'cfloat', 'cdouble'],
             NPY.CLONGDOUBLE: ['clongdouble', 'clongfloat'],
-            NPY.STRING:      ['string', 'str'],
-            NPY.UNICODE:     ['unicode'],
+            NPY.STRING:      ['string_', 'str'],
+            NPY.UNICODE:     ['unicode_'],
         }
         self.alternate_constructors = {
             NPY.BOOL:     [space.w_bool],
diff --git a/pypy/module/micronumpy/nditer.py b/pypy/module/micronumpy/nditer.py
--- a/pypy/module/micronumpy/nditer.py
+++ b/pypy/module/micronumpy/nditer.py
@@ -492,13 +492,15 @@
              w_op_dtypes=WrappedDefault(None), order=str,
              w_casting=WrappedDefault(None), w_op_axes=WrappedDefault(None),
              w_itershape=WrappedDefault(None), w_buffersize=WrappedDefault(None))
-def nditer(space, w_seq, w_flags, w_op_flags, w_op_dtypes, w_casting, w_op_axes,
-           w_itershape, w_buffersize, order='K'):
+def descr__new__(space, w_subtype, w_seq, w_flags, w_op_flags, w_op_dtypes,
+                 w_casting, w_op_axes, w_itershape, w_buffersize, order='K'):
     return W_NDIter(space, w_seq, w_flags, w_op_flags, w_op_dtypes, w_casting, w_op_axes,
                     w_itershape, w_buffersize, order)
 
-W_NDIter.typedef = TypeDef(
-    'nditer',
+W_NDIter.typedef = TypeDef('nditer',
+    __module__ = 'numpy',
+    __new__ = interp2app(descr__new__),
+
     __iter__ = interp2app(W_NDIter.descr_iter),
     __getitem__ = interp2app(W_NDIter.descr_getitem),
     __setitem__ = interp2app(W_NDIter.descr_setitem),
@@ -530,3 +532,4 @@
     shape = GetSetProperty(W_NDIter.descr_get_shape),
     value = GetSetProperty(W_NDIter.descr_get_value),
 )
+W_NDIter.typedef.acceptable_as_base_class = False
diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py
--- a/pypy/module/micronumpy/test/test_dtypes.py
+++ b/pypy/module/micronumpy/test/test_dtypes.py
@@ -47,6 +47,7 @@
         assert d.kind == 'b'
         assert dtype(d) is d
         assert dtype('bool') is d
+        assert dtype('bool_') is d
         assert dtype('|b1') is d
         b = '>' if sys.byteorder == 'little' else '<'
         assert dtype(b + 'i4') is not dtype(b + 'i4')
@@ -63,10 +64,12 @@
         assert dtype(int).names is None
         assert dtype(int).hasobject is False
         assert dtype(int).subdtype is None
+        assert dtype(str) is dtype('string') is dtype('string_')
+        assert dtype(unicode) is dtype('unicode') is dtype('unicode_')
 
         assert dtype(None) is dtype(float)
 
-        for d in [dtype('<c8'), dtype('>i4')]:
+        for d in [dtype('<c8'), dtype('>i4'), dtype('bool')]:
             for key in ["d[2]", "d['z']", "d[None]"]:
                 exc = raises(KeyError, key)
                 assert exc.value[0] == "There are no fields in dtype %s." % str(d)
diff --git a/pypy/module/micronumpy/test/test_nditer.py b/pypy/module/micronumpy/test/test_nditer.py
--- a/pypy/module/micronumpy/test/test_nditer.py
+++ b/pypy/module/micronumpy/test/test_nditer.py
@@ -3,6 +3,19 @@
 
 
 class AppTestNDIter(BaseNumpyAppTest):
+    def test_type(self):
+        import numpy as np
+        assert type(np.nditer) is type
+        assert np.nditer.__name__ == 'nditer'
+        assert np.nditer.__module__ == 'numpy'
+        try:
+            class Sub(np.nditer):
+                pass
+        except TypeError as e:
+            assert "not an acceptable base" in str(e)
+        else:
+            assert False
+
     def test_basic(self):
         from numpy import arange, nditer, ndarray
         a = arange(6).reshape(2,3)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_cprofile.py b/pypy/module/pypyjit/test_pypy_c/test_cprofile.py
--- a/pypy/module/pypyjit/test_pypy_c/test_cprofile.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_cprofile.py
@@ -1,4 +1,4 @@
-import py
+import py, sys
 from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC
 
 class TestCProfile(BaseTestPyPyC):
@@ -26,6 +26,10 @@
         for method in ['append', 'pop']:
             loop, = log.loops_by_id(method)
             print loop.ops_by_id(method)
-            assert ' call(' not in repr(loop.ops_by_id(method))
+            # on 32-bit, there is f1=read_timestamp(); ...;
+            # f2=read_timestamp(); f3=call(llong_sub,f1,f2)
+            # which should turn into a single PADDQ/PSUBQ
+            if sys.maxint != 2147483647:
+                assert ' call(' not in repr(loop.ops_by_id(method))
             assert ' call_may_force(' not in repr(loop.ops_by_id(method))
             assert ' cond_call(' in repr(loop.ops_by_id(method))
diff --git a/pypy/objspace/fake/checkmodule.py b/pypy/objspace/fake/checkmodule.py
--- a/pypy/objspace/fake/checkmodule.py
+++ b/pypy/objspace/fake/checkmodule.py
@@ -10,6 +10,7 @@
         mod = __import__('pypy.module.%s' % modname, None, None, ['__doc__'])
         # force computation and record what we wrap
         module = mod.Module(space, W_Root())
+        module.startup(space)
         for name in module.loaders:
             seeobj_w.append(module._load_lazily(space, name))
         if hasattr(module, 'submodules'):
diff --git a/pypy/objspace/std/test/test_typeobject.py b/pypy/objspace/std/test/test_typeobject.py
--- a/pypy/objspace/std/test/test_typeobject.py
+++ b/pypy/objspace/std/test/test_typeobject.py
@@ -61,7 +61,6 @@
 
 
 class AppTestTypeObject:
-
     def test_abstract_methods(self):
         class X(object):
             pass
@@ -72,6 +71,13 @@
         raises(AttributeError, getattr, type, "__abstractmethods__")
         raises(TypeError, "int.__abstractmethods__ = ('abc', )")
 
+    def test_attribute_error(self):
+        class X(object):
+            __module__ = 'test'
+        x = X()
+        exc = raises(AttributeError, "x.a")
+        assert str(exc.value) == "'X' object has no attribute 'a'"
+
     def test_call_type(self):
         assert type(42) is int
         C = type('C', (object,), {'x': lambda: 42})
@@ -410,8 +416,7 @@
         assert f.__call__() == ((), {})
         assert f.__call__("hello", "world") == (("hello", "world"), {})
         assert f.__call__(5, bla=6) == ((5,), {"bla": 6})
-        assert f.__call__(a=1, b=2, c=3) == ((), {"a": 1, "b": 2,
-                                                           "c": 3})
+        assert f.__call__(a=1, b=2, c=3) == ((), {"a": 1, "b": 2, "c": 3})
 
     def test_multipleinheritance_fail(self):
         try:
@@ -529,7 +534,7 @@
     def test_metaclass_choice(self):
         """
         events = []
-        
+
         class T1(type):
             def __new__(*args):
                 events.append(args)
@@ -552,7 +557,7 @@
         assert type(C) is T1
         assert type(G) is T1
         """
-    
+
     def test_descr_typecheck(self):
         raises(TypeError,type.__dict__['__name__'].__get__,1)
         raises(TypeError,type.__dict__['__mro__'].__get__,1)
@@ -797,7 +802,7 @@
         z2 = Z2()
         z2.__class__ = Z1
         assert z2.__class__ == Z1
-        
+
         class I(int):
             pass
         class F(float):
@@ -816,13 +821,12 @@
             pass
 
         i = I()
-        
         i2 = I()
         i.__class__ = I2
         i2.__class__ = I
         assert i.__class__ ==  I2
         assert i2.__class__ == I
-        
+
         i3 = I3()
         raises(TypeError, "i3.__class__ = I2")
         i3.__class__ = I4
@@ -873,6 +877,12 @@
         Abc.__name__ = 'Def'
         assert Abc.__name__ == 'Def'
         raises(TypeError, "Abc.__name__ = 42")
+        try:
+            Abc.__name__ = 'G\x00hi'
+        except ValueError as e:
+            assert str(e) == "__name__ must not contain null bytes"
+        else:
+            assert False
 
     def test_compare(self):
         class A(object):
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -487,11 +487,12 @@
 
     def get_module_type_name(w_self):
         space = w_self.space
-        w_mod = w_self.get_module()
-        if space.isinstance_w(w_mod, space.w_unicode):
-            mod = space.unicode_w(w_mod)
-            if mod != u'builtins':
-                return u'%s.%s' % (mod, w_self.name.decode('utf-8'))
+        if not w_self.is_heaptype():
+            w_mod = w_self.get_module()
+            if space.isinstance_w(w_mod, space.w_unicode):
+                mod = space.unicode_w(w_mod)
+                if mod != u'builtins':
+                    return u'%s.%s' % (mod, w_self.name.decode('utf-8'))
         return w_self.name.decode('utf-8')
 
     def getname(w_self, space):
@@ -631,7 +632,10 @@
     w_type = _check(space, w_type)
     if not w_type.is_heaptype():
         raise oefmt(space.w_TypeError, "can't set %N.__name__", w_type)
-    w_type.name = space.str_w(w_value)
+    name = space.str_w(w_value)
+    if '\x00' in name:
+        raise oefmt(space.w_ValueError, "__name__ must not contain null bytes")
+    w_type.name = name
 
 def descr_get__mro__(space, w_type):
     w_type = _check(space, w_type)
diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py
--- a/rpython/jit/metainterp/optimizeopt/optimizer.py
+++ b/rpython/jit/metainterp/optimizeopt/optimizer.py
@@ -351,7 +351,7 @@
         arg_consts = []
         for i in range(op.numargs()):
             arg = op.getarg(i)
-            const = self.get_constant_box(arg)
+            const = self.optimizer.get_constant_box(arg)
             if const is None:
                 return None
             arg_consts.append(const)
diff --git a/rpython/rlib/_rsocket_rffi.py b/rpython/rlib/_rsocket_rffi.py
--- a/rpython/rlib/_rsocket_rffi.py
+++ b/rpython/rlib/_rsocket_rffi.py
@@ -30,7 +30,7 @@
                 'stdio.h',
                 'netdb.h',
                 'arpa/inet.h',
-                'stdint.h', 
+                'stdint.h',
                 'errno.h',
                 )
     if _HAS_AF_PACKET:
@@ -139,7 +139,7 @@
 EAI_SOCKTYPE EAI_SYSTEM
 
 IPPROTO_AH IPPROTO_BIP IPPROTO_DSTOPTS IPPROTO_EGP IPPROTO_EON IPPROTO_ESP
-IPPROTO_FRAGMENT IPPROTO_GGP IPPROTO_GRE IPPROTO_HELLO IPPROTO_HOPOPTS 
+IPPROTO_FRAGMENT IPPROTO_GGP IPPROTO_GRE IPPROTO_HELLO IPPROTO_HOPOPTS
 IPPROTO_ICMPV6 IPPROTO_IDP IPPROTO_IGMP IPPROTO_IPCOMP IPPROTO_IPIP
 IPPROTO_IPV4 IPPROTO_IPV6 IPPROTO_MAX IPPROTO_MOBILE IPPROTO_ND IPPROTO_NONE
 IPPROTO_PIM IPPROTO_PUP IPPROTO_ROUTING IPPROTO_RSVP IPPROTO_TCP IPPROTO_TP
@@ -174,7 +174,7 @@
 
 SOCK_DGRAM SOCK_RAW SOCK_RDM SOCK_SEQPACKET SOCK_STREAM
 
-SOL_SOCKET SOL_IPX SOL_AX25 SOL_ATALK SOL_NETROM SOL_ROSE 
+SOL_SOCKET SOL_IPX SOL_AX25 SOL_ATALK SOL_NETROM SOL_ROSE
 
 SO_ACCEPTCONN SO_BROADCAST SO_DEBUG SO_DONTROUTE SO_ERROR SO_EXCLUSIVEADDRUSE
 SO_KEEPALIVE SO_LINGER SO_OOBINLINE SO_RCVBUF SO_RCVLOWAT SO_RCVTIMEO
@@ -286,7 +286,7 @@
                                               ('nl_pid', rffi.INT),
                                               ('nl_groups', rffi.INT)],
                                              ifdef='AF_NETLINK')
-                                             
+
 CConfig.addrinfo = platform.Struct('struct addrinfo',
                                      [('ai_flags', rffi.INT),
                                       ('ai_family', rffi.INT),
diff --git a/rpython/rlib/rsocket.py b/rpython/rlib/rsocket.py
--- a/rpython/rlib/rsocket.py
+++ b/rpython/rlib/rsocket.py
@@ -18,6 +18,7 @@
 from rpython.rlib.objectmodel import instantiate, keepalive_until_here
 from rpython.rlib import _rsocket_rffi as _c
 from rpython.rlib.rarithmetic import intmask, r_uint
+from rpython.rlib.rthread import dummy_lock
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.rtyper.lltypesystem.rffi import sizeof, offsetof
 INVALID_SOCKET = _c.INVALID_SOCKET
@@ -1124,22 +1125,24 @@
         paddr = h_addr_list[i]
     return (rffi.charp2str(hostent.c_h_name), aliases, address_list)
 
-def gethostbyname_ex(name):
-    # XXX use gethostbyname_r() if available, and/or use locks if not
+def gethostbyname_ex(name, lock=dummy_lock):
+    # XXX use gethostbyname_r() if available instead of locks
     addr = gethostbyname(name)
-    hostent = _c.gethostbyname(name)
-    return gethost_common(name, hostent, addr)
+    with lock:
+        hostent = _c.gethostbyname(name)
+        return gethost_common(name, hostent, addr)
 
-def gethostbyaddr(ip):
-    # XXX use gethostbyaddr_r() if available, and/or use locks if not
+def gethostbyaddr(ip, lock=dummy_lock):
+    # XXX use gethostbyaddr_r() if available, instead of locks
     addr = makeipaddr(ip)
     assert isinstance(addr, IPAddress)
-    p, size = addr.lock_in_addr()
-    try:
-        hostent = _c.gethostbyaddr(p, size, addr.family)
-    finally:
-        addr.unlock()
-    return gethost_common(ip, hostent, addr)
+    with lock:
+        p, size = addr.lock_in_addr()
+        try:
+            hostent = _c.gethostbyaddr(p, size, addr.family)
+        finally:
+            addr.unlock()
+        return gethost_common(ip, hostent, addr)
 
 def getaddrinfo(host, port_or_service,
                 family=AF_UNSPEC, socktype=0, proto=0, flags=0,
diff --git a/rpython/rlib/rthread.py b/rpython/rlib/rthread.py
--- a/rpython/rlib/rthread.py
+++ b/rpython/rlib/rthread.py
@@ -1,4 +1,3 @@
-
 from rpython.rtyper.lltypesystem import rffi, lltype, llmemory
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
 from rpython.conftest import cdir
@@ -113,6 +112,24 @@
     assert len(y) == 0
     return rffi.cast(lltype.Signed, ll_start_new_thread(x))
 
+class DummyLock(object):
+    def acquire(self, flag):
+        return True
+
+    def release(self):
+        pass
+
+    def _freeze_(self):
+        return True
+
+    def __enter__(self):
+        pass
+
+    def __exit__(self, *args):
+        pass
+
+dummy_lock = DummyLock()
+
 class Lock(object):
     """ Container for low-level implementation
     of a lock object
diff --git a/rpython/rlib/test/test_rsocket.py b/rpython/rlib/test/test_rsocket.py
--- a/rpython/rlib/test/test_rsocket.py
+++ b/rpython/rlib/test/test_rsocket.py
@@ -3,6 +3,7 @@
 from rpython.rlib.rsocket import *
 import socket as cpy_socket
 
+
 def setup_module(mod):
     rsocket_startup()
 
@@ -61,6 +62,43 @@
             py.test.fail("could not find the localhost address in %r"
                          % (address_list,))
 
+def test_thread_safe_gethostbyname_ex():
+    import threading
+    nthreads = 10
+    domain = 'google.com'
+    result = [0] * nthreads
+    threads = [None] * nthreads
+    lock = threading.Lock()
+    def lookup_name(i):
+        name, aliases, address_list = gethostbyname_ex(domain, lock)
+        if name == domain:
+            result[i] += 1
+    for i in range(nthreads):
+        threads[i] = threading.Thread(target = lookup_name, args=[i])
+        threads[i].start()
+    for i in range(nthreads):
+        threads[i].join()
+    assert sum(result) == nthreads
+
+def test_thread_safe_gethostbyaddr():
+    import threading
+    nthreads = 10
+    ip = '8.8.8.8'
+    domain = gethostbyaddr(ip)[0]
+    result = [0] * nthreads
+    threads = [None] * nthreads
+    lock = threading.Lock()
+    def lookup_addr(ip, i):
+        name, aliases, address_list = gethostbyaddr(ip, lock)
+        if name == domain:
+            result[i] += 1
+    for i in range(nthreads):
+        threads[i] = threading.Thread(target = lookup_addr, args=[ip, i])
+        threads[i].start()
+    for i in range(nthreads):
+        threads[i].join()
+    assert sum(result) == nthreads
+
 def test_gethostbyaddr():
     try:
         cpy_socket.gethostbyaddr("::1")


More information about the pypy-commit mailing list