Author: Ronan Lamy <[email protected]>
Branch: kill-flowobjspace
Changeset: r60822:634f56eec5d6
Date: 2013-02-02 16:47 +0000
http://bitbucket.org/pypy/pypy/changeset/634f56eec5d6/

Log:    merge default

diff --git a/lib-python/2.7/collections.py b/lib-python/2.7/collections.py
--- a/lib-python/2.7/collections.py
+++ b/lib-python/2.7/collections.py
@@ -6,7 +6,6 @@
 __all__ += _abcoll.__all__
 
 from _collections import deque, defaultdict
-from operator import itemgetter as _itemgetter
 from keyword import iskeyword as _iskeyword
 import sys as _sys
 import heapq as _heapq
@@ -298,7 +297,7 @@
         _fields = %(field_names)r \n
         def __new__(_cls, %(argtxt)s):
             'Create new instance of %(typename)s(%(argtxt)s)'
-            return _tuple.__new__(_cls, (%(argtxt)s)) \n
+            return tuple.__new__(_cls, (%(argtxt)s)) \n
         @classmethod
         def _make(cls, iterable, new=tuple.__new__, len=len):
             'Make a new %(typename)s object from a sequence or iterable'
@@ -323,14 +322,13 @@
             'Return self as a plain tuple.  Used by copy and pickle.'
             return tuple(self) \n\n''' % locals()
     for i, name in enumerate(field_names):
-        template += "        %s = _property(_itemgetter(%d), doc='Alias for 
field number %d')\n" % (name, i, i)
+        template += "        %s = property(lambda self: self[%d], doc='Alias 
for field number %d')\n" % (name, i, i)
     if verbose:
         print template
 
     # Execute the template string in a temporary namespace and
     # support tracing utilities by setting a value for 
frame.f_globals['__name__']
-    namespace = dict(_itemgetter=_itemgetter, __name__='namedtuple_%s' % 
typename,
-                     OrderedDict=OrderedDict, _property=property, _tuple=tuple)
+    namespace = {'__name__': 'namedtuple_%s' % typename}
     try:
         exec template in namespace
     except SyntaxError, e:
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
@@ -27,10 +27,10 @@
         'data'   : '{base}',
         },
     'pypy': {
-        'stdlib': '{base}/lib-python',
-        'platstdlib': '{base}/lib-python',
-        'purelib': '{base}/lib-python',
-        'platlib': '{base}/lib-python',
+        'stdlib': '{base}/lib-python/{py_version_short}',
+        'platstdlib': '{base}/lib-python/{py_version_short}',
+        'purelib': '{base}/lib-python/{py_version_short}',
+        'platlib': '{base}/lib-python/{py_version_short}',
         'include': '{base}/include',
         'platinclude': '{base}/include',
         'scripts': '{base}/bin',
diff --git a/lib-python/2.7/test/test_capi.py b/lib-python/2.7/test/test_capi.py
--- a/lib-python/2.7/test/test_capi.py
+++ b/lib-python/2.7/test/test_capi.py
@@ -19,9 +19,6 @@
             'test_broken_memoryview',
             'test_capsule',
             'test_lazy_hash_inheritance',
-            'test_long_api',
-            'test_longlong_api',
-            'test_null_strings',
             'test_widechar',
             'TestThreadState',
             'TestPendingCalls',
diff --git a/lib-python/2.7/test/test_multiprocessing.py 
b/lib-python/2.7/test/test_multiprocessing.py
--- a/lib-python/2.7/test/test_multiprocessing.py
+++ b/lib-python/2.7/test/test_multiprocessing.py
@@ -1343,7 +1343,7 @@
 
         # Because we are using xmlrpclib for serialization instead of
         # pickle this will cause a serialization error.
-        self.assertRaises(Exception, queue.put, time.sleep)
+        self.assertRaises(Exception, queue.put, object)
 
         # Make queue finalizer run before the server is stopped
         del queue
@@ -1800,9 +1800,9 @@
         if not gc.isenabled():
             gc.enable()
             self.addCleanup(gc.disable)
-        thresholds = gc.get_threshold()
-        self.addCleanup(gc.set_threshold, *thresholds)
-        gc.set_threshold(10)
+        #thresholds = gc.get_threshold()
+        #self.addCleanup(gc.set_threshold, *thresholds)
+        #gc.set_threshold(10)
 
         # perform numerous block allocations, with cyclic references to make
         # sure objects are collected asynchronously by the gc
@@ -1865,6 +1865,7 @@
     def test_synchronize(self):
         self.test_sharedctypes(lock=True)
 
+    @unittest.skipUnless(test_support.check_impl_detail(pypy=False), "pypy 
ctypes differences")
     def test_copy(self):
         foo = _Foo(2, 5.0)
         bar = copy(foo)
diff --git a/lib-python/2.7/test/test_zipfile.py 
b/lib-python/2.7/test/test_zipfile.py
--- a/lib-python/2.7/test/test_zipfile.py
+++ b/lib-python/2.7/test/test_zipfile.py
@@ -1213,6 +1213,17 @@
             self.assertEqual(data1, '1'*FIXEDTEST_SIZE)
             self.assertEqual(data2, '2'*FIXEDTEST_SIZE)
 
+    def test_many_opens(self):
+        # Verify that read() and open() promptly close the file descriptor,
+        # and don't rely on the garbage collector to free resources.
+        with zipfile.ZipFile(TESTFN2, mode="r") as zipf:
+            for x in range(100):
+                zipf.read('ones')
+                with zipf.open('ones') as zopen1:
+                    pass
+        for x in range(10):
+            self.assertLess(open('/dev/null').fileno(), 100)
+
     def tearDown(self):
         unlink(TESTFN2)
 
diff --git a/lib-python/2.7/zipfile.py b/lib-python/2.7/zipfile.py
--- a/lib-python/2.7/zipfile.py
+++ b/lib-python/2.7/zipfile.py
@@ -475,9 +475,11 @@
     # Search for universal newlines or line chunks.
     PATTERN = re.compile(r'^(?P<chunk>[^\r\n]+)|(?P<newline>\n|\r\n?)')
 
-    def __init__(self, fileobj, mode, zipinfo, decrypter=None):
+    def __init__(self, fileobj, mode, zipinfo, decrypter=None,
+                 close_fileobj=False):
         self._fileobj = fileobj
         self._decrypter = decrypter
+        self._close_fileobj = close_fileobj
 
         self._compress_type = zipinfo.compress_type
         self._compress_size = zipinfo.compress_size
@@ -649,6 +651,12 @@
         self._offset += len(data)
         return data
 
+    def close(self):
+        try:
+            if self._close_fileobj:
+                self._fileobj.close()
+        finally:
+            super(ZipExtFile, self).close()
 
 
 class ZipFile:
@@ -866,7 +874,8 @@
 
     def read(self, name, pwd=None):
         """Return file bytes (as a string) for name."""
-        return self.open(name, "r", pwd).read()
+        with self.open(name, "r", pwd) as fp:
+            return fp.read()
 
     def open(self, name, mode="r", pwd=None):
         """Return file-like object for 'name'."""
@@ -889,8 +898,12 @@
             zinfo = name
         else:
             # Get info object for name
-            zinfo = self.getinfo(name)
-
+            try:
+                zinfo = self.getinfo(name)
+            except KeyError:
+                if not self._filePassed:
+                    zef_file.close()
+                raise
         zef_file.seek(zinfo.header_offset, 0)
 
         # Skip the file header:
@@ -904,6 +917,8 @@
             zef_file.read(fheader[_FH_EXTRA_FIELD_LENGTH])
 
         if fname != zinfo.orig_filename:
+            if not self._filePassed:
+                zef_file.close()
             raise BadZipfile, \
                       'File name in directory "%s" and header "%s" differ.' % (
                           zinfo.orig_filename, fname)
@@ -915,6 +930,8 @@
             if not pwd:
                 pwd = self.pwd
             if not pwd:
+                if not self._filePassed:
+                    zef_file.close()
                 raise RuntimeError, "File %s is encrypted, " \
                       "password required for extraction" % name
 
@@ -933,9 +950,12 @@
                 # compare against the CRC otherwise
                 check_byte = (zinfo.CRC >> 24) & 0xff
             if ord(h[11]) != check_byte:
+                if not self._filePassed:
+                    zef_file.close()
                 raise RuntimeError("Bad password for file", name)
 
-        return  ZipExtFile(zef_file, mode, zinfo, zd)
+        return ZipExtFile(zef_file, mode, zinfo, zd,
+                          close_fileobj=not self._filePassed)
 
     def extract(self, member, path=None, pwd=None):
         """Extract a member from the archive to the current working directory,
@@ -993,7 +1013,7 @@
             return targetpath
 
         source = self.open(member, pwd=pwd)
-        target = file(targetpath, "wb")
+        target = open(targetpath, "wb")
         shutil.copyfileobj(source, target)
         source.close()
         target.close()
diff --git a/lib-python/conftest.py b/lib-python/conftest.py
--- a/lib-python/conftest.py
+++ b/lib-python/conftest.py
@@ -310,7 +310,7 @@
     RegrTest('test_msilib.py'),
     RegrTest('test_multibytecodec.py', usemodules='_multibytecodec'),
     RegrTest('test_multifile.py'),
-    RegrTest('test_multiprocessing.py', skip=True),
+    RegrTest('test_multiprocessing.py'),
     RegrTest('test_mutants.py', core="possibly"),
     RegrTest('test_mutex.py'),
     RegrTest('test_netrc.py'),
diff --git a/lib_pypy/_ctypes_test.py b/lib_pypy/_ctypes_test.py
--- a/lib_pypy/_ctypes_test.py
+++ b/lib_pypy/_ctypes_test.py
@@ -1,6 +1,5 @@
 import os, sys
 import tempfile
-import gc
 
 def compile_shared():
     """Compile '_ctypes_test.c' into an extension module, and import it
@@ -19,7 +18,7 @@
     if sys.platform == 'win32':
         ccflags = ['-D_CRT_SECURE_NO_WARNINGS']
     else:
-        ccflags = ['-fPIC']
+        ccflags = ['-fPIC', '-Wimplicit-function-declaration']
     res = compiler.compile([os.path.join(thisdir, '_ctypes_test.c')],
                            include_dirs=[include_dir],
                            extra_preargs=ccflags)
@@ -35,10 +34,10 @@
             library = os.path.join(thisdir, '..', 'include', 'python27')
         if not os.path.exists(library + '.lib'):
             # For a local translation
-            library = os.path.join(thisdir, '..', 'pypy', 'translator',
-                    'goal', 'libpypy-c')
+            library = os.path.join(thisdir, '..', 'pypy', 'goal', 'libpypy-c')
         libraries = [library, 'oleaut32']
-        extra_ldargs = ['/MANIFEST'] # needed for VC10
+        extra_ldargs = ['/MANIFEST',  # needed for VC10
+                        '/EXPORT:init_ctypes_test']
     else:
         libraries = []
         extra_ldargs = []
diff --git a/lib_pypy/_testcapi.py b/lib_pypy/_testcapi.py
--- a/lib_pypy/_testcapi.py
+++ b/lib_pypy/_testcapi.py
@@ -34,8 +34,7 @@
             library = os.path.join(thisdir, '..', 'include', 'python27')
         if not os.path.exists(library + '.lib'):
             # For a local translation
-            library = os.path.join(thisdir, '..', 'pypy', 'translator',
-                    'goal', 'libpypy-c')
+            library = os.path.join(thisdir, '..', 'pypy', 'goal', 'libpypy-c')
         libraries = [library, 'oleaut32']
         extra_ldargs = ['/MANIFEST',  # needed for VC10
                         '/EXPORT:init_testcapi']
diff --git a/pypy/bin/checkmodule.py b/pypy/bin/checkmodule.py
--- a/pypy/bin/checkmodule.py
+++ b/pypy/bin/checkmodule.py
@@ -8,6 +8,8 @@
 """
 import sys, os
 
+sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..'))
+
 from pypy.objspace.fake.checkmodule import checkmodule
 
 def main(argv):
diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -318,10 +318,5 @@
   type and vice versa. For builtin types, a dictionary will be returned that
   cannot be changed (but still looks and behaves like a normal dictionary).
 
-* the ``__len__`` or ``__length_hint__`` special methods are sometimes
-  called by CPython to get a length estimate to preallocate internal arrays.
-  So far, PyPy never calls ``__len__`` for this purpose, and never calls
-  ``__length_hint__`` at all.
-
 
 .. include:: _ref.txt
diff --git a/pypy/doc/discussion/improve-rpython.rst 
b/pypy/doc/discussion/improve-rpython.rst
--- a/pypy/doc/discussion/improve-rpython.rst
+++ b/pypy/doc/discussion/improve-rpython.rst
@@ -15,7 +15,7 @@
     from pypy.interpreter.typedef import interp_attrproperty, 
interp_attrproperty_w
     from pypy.interpreter.gateway import interp2app
     from pypy.interpreter.error import OperationError
-    from pypy.rpython.lltypesystem import rffi, lltype
+    from rpython.rtyper.lltypesystem import rffi, lltype
 
 - A more direct declarative way to write Typedef::
 
diff --git a/pypy/doc/rffi.rst b/pypy/doc/rffi.rst
--- a/pypy/doc/rffi.rst
+++ b/pypy/doc/rffi.rst
@@ -17,7 +17,7 @@
 lltype.Signed or lltype.Array) and memory management must be done
 by hand. To declare a function, we write::
 
-  from pypy.rpython.lltypesystem import rffi
+  from rpython.rtyper.lltypesystem import rffi
 
   external_function = rffi.llexternal(name, args, result)
 
@@ -31,7 +31,7 @@
 libraries and sources by passing in the optional ``compilation_info``
 parameter::
 
-  from pypy.rpython.lltypesystem import rffi
+  from rpython.rtyper.lltypesystem import rffi
   from rpython.translator.tool.cbuild import ExternalCompilationInfo
 
   info = ExternalCompilationInfo(includes=[], libraries=[])
diff --git a/pypy/interpreter/executioncontext.py 
b/pypy/interpreter/executioncontext.py
--- a/pypy/interpreter/executioncontext.py
+++ b/pypy/interpreter/executioncontext.py
@@ -40,6 +40,7 @@
     def gettopframe(self):
         return self.topframeref()
 
+    @jit.unroll_safe
     def gettopframe_nohidden(self):
         frame = self.topframeref()
         while frame and frame.hide():
diff --git a/pypy/interpreter/miscutils.py b/pypy/interpreter/miscutils.py
--- a/pypy/interpreter/miscutils.py
+++ b/pypy/interpreter/miscutils.py
@@ -17,9 +17,8 @@
     def setvalue(self, value):
         self._value = value
 
-    def getmainthreadvalue(self):
-        return self._value
+    def ismainthread(self):
+        return True
 
     def getallvalues(self):
         return {0: self._value}
-
diff --git a/pypy/module/__pypy__/interp_identitydict.py 
b/pypy/module/__pypy__/interp_identitydict.py
--- a/pypy/module/__pypy__/interp_identitydict.py
+++ b/pypy/module/__pypy__/interp_identitydict.py
@@ -33,6 +33,11 @@
         except KeyError:
             raise OperationError(space.w_KeyError, w_key)
 
+    def descr_iter(self, space):
+        raise OperationError(space.w_TypeError,
+            space.wrap("'identity_dict' object does not support iteration; "
+                       "iterate over x.keys()"))
+
     def get(self, space, w_key, w_default=None):
         if w_default is None:
             w_default = space.w_None
@@ -50,8 +55,11 @@
 W_IdentityDict.typedef = TypeDef("identity_dict",
     __doc__="""\
 A dictionary that considers keys by object identity.
-Distinct objects that compare equal will have separate entries.
-All objects can be used as keys, even non-hashable ones.
+Distinct objects will have separate entries even if they
+compare equal.  All objects can be used as keys, even
+non-hashable ones --- but avoid using immutable objects
+like integers: two int objects 42 may or may not be
+internally the same object.
 """,
     __new__ = interp2app(W_IdentityDict.descr_new.im_func),
     __len__ = interp2app(W_IdentityDict.descr_len),
@@ -59,6 +67,7 @@
     __setitem__ = interp2app(W_IdentityDict.descr_setitem),
     __getitem__ = interp2app(W_IdentityDict.descr_getitem),
     __delitem__ = interp2app(W_IdentityDict.descr_delitem),
+    __iter__ = interp2app(W_IdentityDict.descr_iter),
     get = interp2app(W_IdentityDict.get),
     keys = interp2app(W_IdentityDict.keys),
     values = interp2app(W_IdentityDict.values),
diff --git a/pypy/module/__pypy__/test/test_identitydict.py 
b/pypy/module/__pypy__/test/test_identitydict.py
--- a/pypy/module/__pypy__/test/test_identitydict.py
+++ b/pypy/module/__pypy__/test/test_identitydict.py
@@ -56,3 +56,10 @@
 
         assert None in d
         assert [] not in d
+
+    def test_iterate(self):
+        from __pypy__ import identity_dict
+        d = identity_dict()
+        d[None] = 1
+        raises(TypeError, iter, d)
+        raises(TypeError, list, d)
diff --git a/pypy/module/_io/interp_fileio.py b/pypy/module/_io/interp_fileio.py
--- a/pypy/module/_io/interp_fileio.py
+++ b/pypy/module/_io/interp_fileio.py
@@ -153,41 +153,49 @@
 
         self.readable, self.writable, append, flags = decode_mode(space, mode)
 
-        if fd >= 0:
-            verify_fd(fd)
-            try:
-                os.fstat(fd)
-            except OSError, e:
-                if e.errno == errno.EBADF:
-                    raise wrap_oserror(space, e)
-                # else: pass
-            self.fd = fd
-            self.closefd = bool(closefd)
-        else:
-            if not closefd:
-                raise OperationError(space.w_ValueError, space.wrap(
-                    "Cannot use closefd=False with file name"))
-            self.closefd = True
+        fd_is_own = False
+        try:
+            if fd >= 0:
+                verify_fd(fd)
+                try:
+                    os.fstat(fd)
+                except OSError, e:
+                    if e.errno == errno.EBADF:
+                        raise wrap_oserror(space, e)
+                    # else: pass
+                self.fd = fd
+                self.closefd = bool(closefd)
+            else:
+                self.closefd = True
+                if not closefd:
+                    raise OperationError(space.w_ValueError, space.wrap(
+                        "Cannot use closefd=False with file name"))
 
-            from pypy.module.posix.interp_posix import (
-                dispatch_filename, rposix)
-            try:
-                self.fd = dispatch_filename(rposix.open)(
-                    space, w_name, flags, 0666)
-            except OSError, e:
-                raise wrap_oserror2(space, e, w_name,
-                                    exception_name='w_IOError')
+                from pypy.module.posix.interp_posix import (
+                    dispatch_filename, rposix)
+                try:
+                    self.fd = dispatch_filename(rposix.open)(
+                        space, w_name, flags, 0666)
+                except OSError, e:
+                    raise wrap_oserror2(space, e, w_name,
+                                        exception_name='w_IOError')
+                finally:
+                    fd_is_own = True
 
             self._dircheck(space, w_name)
-        self.w_name = w_name
+            self.w_name = w_name
 
-        if append:
-            # For consistent behaviour, we explicitly seek to the end of file
-            # (otherwise, it might be done only on the first write()).
-            try:
-                os.lseek(self.fd, 0, os.SEEK_END)
-            except OSError, e:
-                raise wrap_oserror(space, e, exception_name='w_IOError')
+            if append:
+                # For consistent behaviour, we explicitly seek to the end of 
file
+                # (otherwise, it might be done only on the first write()).
+                try:
+                    os.lseek(self.fd, 0, os.SEEK_END)
+                except OSError, e:
+                    raise wrap_oserror(space, e, exception_name='w_IOError')
+        except:
+            if not fd_is_own:
+                self.fd = -1
+            raise
 
     def _mode(self):
         if self.readable:
@@ -253,7 +261,6 @@
         except OSError:
             return
         if stat.S_ISDIR(st.st_mode):
-            self._close(space)
             raise wrap_oserror2(space, OSError(errno.EISDIR, "fstat"),
                                 w_filename, exception_name='w_IOError')
 
diff --git a/pypy/module/_io/test/test_fileio.py 
b/pypy/module/_io/test/test_fileio.py
--- a/pypy/module/_io/test/test_fileio.py
+++ b/pypy/module/_io/test/test_fileio.py
@@ -41,7 +41,12 @@
 
     def test_open_directory(self):
         import _io
+        import os
         raises(IOError, _io.FileIO, self.tmpdir, "rb")
+        if os.name != 'nt':
+            fd = os.open(self.tmpdir, os.O_RDONLY)
+            raises(IOError, _io.FileIO, fd, "rb")
+            os.close(fd)
 
     def test_readline(self):
         import _io
diff --git a/pypy/module/cpyext/longobject.py b/pypy/module/cpyext/longobject.py
--- a/pypy/module/cpyext/longobject.py
+++ b/pypy/module/cpyext/longobject.py
@@ -47,7 +47,12 @@
     Return a C unsigned long representation of the contents of pylong.
     If pylong is greater than ULONG_MAX, an OverflowError is
     raised."""
-    return rffi.cast(rffi.ULONG, space.uint_w(w_long))
+    try:
+        return rffi.cast(rffi.ULONG, space.uint_w(w_long))
+    except OperationError, e:
+        if e.match(space, space.w_ValueError):
+            e.w_type = space.w_OverflowError
+        raise
 
 @cpython_api([PyObject], rffi.ULONG, error=-1)
 def PyLong_AsUnsignedLongMask(space, w_long):
@@ -86,7 +91,12 @@
     Return a C unsigned long representation of the contents of pylong.
     If pylong is greater than ULONG_MAX, an OverflowError is
     raised."""
-    return rffi.cast(rffi.ULONGLONG, space.r_ulonglong_w(w_long))
+    try:
+        return rffi.cast(rffi.ULONGLONG, space.r_ulonglong_w(w_long))
+    except OperationError, e:
+        if e.match(space, space.w_ValueError):
+            e.w_type = space.w_OverflowError
+        raise
 
 @cpython_api([PyObject], rffi.ULONGLONG, error=-1)
 def PyLong_AsUnsignedLongLongMask(space, w_long):
diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py
--- a/pypy/module/cpyext/object.py
+++ b/pypy/module/cpyext/object.py
@@ -218,6 +218,8 @@
 
 @cpython_api([PyObject], PyObject)
 def PyObject_Str(space, w_obj):
+    if w_obj is None:
+        return space.wrap("<NULL>")
     return space.str(w_obj)
 
 @cpython_api([PyObject], PyObject)
@@ -226,6 +228,8 @@
     representation on success, NULL on failure.  This is the equivalent of the
     Python expression repr(o).  Called by the repr() built-in function and
     by reverse quotes."""
+    if w_obj is None:
+        return space.wrap("<NULL>")
     return space.repr(w_obj)
 
 @cpython_api([PyObject], PyObject)
@@ -234,6 +238,8 @@
     string representation on success, NULL on failure. This is the equivalent 
of
     the Python expression unicode(o).  Called by the unicode() built-in
     function."""
+    if w_obj is None:
+        return space.wrap(u"<NULL>")
     return space.call_function(space.w_unicode, w_obj)
 
 @cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
diff --git a/pypy/module/cpyext/test/test_longobject.py 
b/pypy/module/cpyext/test/test_longobject.py
--- a/pypy/module/cpyext/test/test_longobject.py
+++ b/pypy/module/cpyext/test/test_longobject.py
@@ -31,6 +31,8 @@
         value = api.PyLong_AsUnsignedLong(w_value)
         assert value == (sys.maxint - 1) * 2
 
+        self.raises(space, api, OverflowError, api.PyLong_AsUnsignedLong, 
space.wrap(-1))
+
     def test_as_ssize_t(self, space, api):
         w_value = space.newlong(2)
         value = api.PyLong_AsSsize_t(w_value)
@@ -46,11 +48,11 @@
         w_l = space.wrap(sys.maxint + 1)
         assert api.PyLong_Check(w_l)
         assert api.PyLong_CheckExact(w_l)
-        
+
         w_i = space.wrap(sys.maxint)
         assert not api.PyLong_Check(w_i)
         assert not api.PyLong_CheckExact(w_i)
-        
+
         L = space.appexec([], """():
             class L(long):
                 pass
@@ -73,6 +75,8 @@
         assert api.PyLong_AsUnsignedLongLongMask(
             space.wrap(1<<64)) == 0
 
+        self.raises(space, api, OverflowError, api.PyLong_AsUnsignedLongLong, 
space.wrap(-1))
+
     def test_as_long_and_overflow(self, space, api):
         overflow = lltype.malloc(rffi.CArrayPtr(rffi.INT_real).TO, 1, 
flavor='raw')
         assert api.PyLong_AsLongAndOverflow(
diff --git a/pypy/module/cpyext/test/test_object.py 
b/pypy/module/cpyext/test/test_object.py
--- a/pypy/module/cpyext/test/test_object.py
+++ b/pypy/module/cpyext/test/test_object.py
@@ -94,27 +94,30 @@
 
     def test_size(self, space, api):
         assert api.PyObject_Size(space.newlist([space.w_None])) == 1
-        
+
+    def test_str(self, space, api):
+        w_list = space.newlist([space.w_None, space.wrap(42)])
+        assert space.str_w(api.PyObject_Str(None)) == "<NULL>"
+        assert space.str_w(api.PyObject_Str(w_list)) == "[None, 42]"
+        assert space.str_w(api.PyObject_Str(space.wrap("a"))) == "a"
+
     def test_repr(self, space, api):
         w_list = space.newlist([space.w_None, space.wrap(42)])
+        assert space.str_w(api.PyObject_Repr(None)) == "<NULL>"
         assert space.str_w(api.PyObject_Repr(w_list)) == "[None, 42]"
         assert space.str_w(api.PyObject_Repr(space.wrap("a"))) == "'a'"
-        
-        w_list = space.newlist([space.w_None, space.wrap(42)])
-        assert space.str_w(api.PyObject_Str(w_list)) == "[None, 42]"
-        assert space.str_w(api.PyObject_Str(space.wrap("a"))) == "a"
-        
+
     def test_RichCompare(self, space, api):
         def compare(w_o1, w_o2, opid):
             res = api.PyObject_RichCompareBool(w_o1, w_o2, opid)
             w_res = api.PyObject_RichCompare(w_o1, w_o2, opid)
             assert space.is_true(w_res) == res
             return res
-        
+
         def test_compare(o1, o2):
             w_o1 = space.wrap(o1)
             w_o2 = space.wrap(o2)
-            
+
             for opid, expected in [
                     (Py_LT, o1 <  o2), (Py_LE, o1 <= o2),
                     (Py_NE, o1 != o2), (Py_EQ, o1 == o2),
@@ -190,6 +193,7 @@
             api.PyErr_Clear()
 
     def test_unicode(self, space, api):
+        assert space.unwrap(api.PyObject_Unicode(None)) == u"<NULL>"
         assert space.unwrap(api.PyObject_Unicode(space.wrap([]))) == u"[]"
         assert space.unwrap(api.PyObject_Unicode(space.wrap("e"))) == u"e"
         assert api.PyObject_Unicode(space.wrap("\xe9")) is None
diff --git a/pypy/module/signal/interp_signal.py 
b/pypy/module/signal/interp_signal.py
--- a/pypy/module/signal/interp_signal.py
+++ b/pypy/module/signal/interp_signal.py
@@ -60,7 +60,6 @@
     def __init__(self, space):
         "NOT_RPYTHON"
         AsyncAction.__init__(self, space)
-        self.handlers_w = {}
         self.pending_signal = -1
         self.fire_in_main_thread = False
         if self.space.config.objspace.usemodules.thread:
@@ -91,7 +90,7 @@
                 # If we are in the main thread, report the signal now,
                 # and poll more
                 self.pending_signal = -1
-                self._report_signal(n)
+                report_signal(self.space, n)
                 n = self.pending_signal
                 if n < 0: n = pypysig_poll()
             else:
@@ -110,20 +109,31 @@
             pypysig_pushback(cpy_signal.SIGINT)
         self.fire_in_main_thread = True
 
-    def _report_signal(self, n):
-        try:
-            w_handler = self.handlers_w[n]
-        except KeyError:
-            return    # no handler, ignore signal
-        space = self.space
-        if not space.is_true(space.callable(w_handler)):
-            return    # w_handler is SIG_IGN or SIG_DFL?
-        # re-install signal handler, for OSes that clear it
-        pypysig_reinstall(n)
-        # invoke the app-level handler
-        ec = space.getexecutioncontext()
-        w_frame = space.wrap(ec.gettopframe_nohidden())
-        space.call_function(w_handler, space.wrap(n), w_frame)
+# ____________________________________________________________
+
+
+class Handlers:
+    def __init__(self, space):
+        self.handlers_w = {}
+
+def _get_handlers(space):
+    return space.fromcache(Handlers).handlers_w
+
+
+def report_signal(space, n):
+    handlers_w = _get_handlers(space)
+    try:
+        w_handler = handlers_w[n]
+    except KeyError:
+        return    # no handler, ignore signal
+    if not space.is_true(space.callable(w_handler)):
+        return    # w_handler is SIG_IGN or SIG_DFL?
+    # re-install signal handler, for OSes that clear it
+    pypysig_reinstall(n)
+    # invoke the app-level handler
+    ec = space.getexecutioncontext()
+    w_frame = space.wrap(ec.gettopframe_nohidden())
+    space.call_function(w_handler, space.wrap(n), w_frame)
 
 
 @unwrap_spec(signum=int)
@@ -141,9 +151,9 @@
         check_signum_exists(space, signum)
     else:
         check_signum_in_range(space, signum)
-    action = space.check_signal_action
-    if signum in action.handlers_w:
-        return action.handlers_w[signum]
+    handlers_w = _get_handlers(space)
+    if signum in handlers_w:
+        return handlers_w[signum]
     return space.wrap(SIG_DFL)
 
 
@@ -198,16 +208,12 @@
     A signal handler function is called with two arguments:
     the first is the signal number, the second is the interrupted stack frame.
     """
-    ec = space.getexecutioncontext()
-    main_ec = space.threadlocals.getmainthreadvalue()
-
-    old_handler = getsignal(space, signum)
-
-    if ec is not main_ec:
+    if not space.threadlocals.ismainthread():
         raise OperationError(space.w_ValueError,
                              space.wrap("signal() must be called from the "
                                         "main thread"))
-    action = space.check_signal_action
+    old_handler = getsignal(space, signum)
+
     if space.eq_w(w_handler, space.wrap(SIG_DFL)):
         pypysig_default(signum)
     elif space.eq_w(w_handler, space.wrap(SIG_IGN)):
@@ -218,7 +224,8 @@
                                  space.wrap("'handler' must be a callable "
                                             "or SIG_DFL or SIG_IGN"))
         pypysig_setflag(signum)
-    action.handlers_w[signum] = w_handler
+    handlers_w = _get_handlers(space)
+    handlers_w[signum] = w_handler
     return old_handler
 
 
@@ -231,13 +238,10 @@
 
     The fd must be non-blocking.
     """
-    if space.config.objspace.usemodules.thread:
-        main_ec = space.threadlocals.getmainthreadvalue()
-        ec = space.getexecutioncontext()
-        if ec is not main_ec:
-            raise OperationError(
-                space.w_ValueError,
-                space.wrap("set_wakeup_fd only works in main thread"))
+    if not space.threadlocals.ismainthread():
+        raise OperationError(
+            space.w_ValueError,
+            space.wrap("set_wakeup_fd only works in main thread"))
     old_fd = pypysig_set_wakeup_fd(fd)
     return space.wrap(intmask(old_fd))
 
diff --git a/pypy/module/thread/os_lock.py b/pypy/module/thread/os_lock.py
--- a/pypy/module/thread/os_lock.py
+++ b/pypy/module/thread/os_lock.py
@@ -38,10 +38,10 @@
 
     @unwrap_spec(waitflag=int)
     def descr_lock_acquire(self, space, waitflag=1):
-        """Lock the lock.  Without argument, this blocks if the lock is already
-locked (even by the same thread), waiting for another thread to release
-the lock, and return None once the lock is acquired.
-With an argument, this will only block if the argument is true,
+        """Lock the lock.  With the default argument of True, this blocks
+if the lock is already locked (even by the same thread), waiting for
+another thread to release the lock, and returns True once the lock is
+acquired.  With an argument of False, this will always return immediately
 and the return value reflects whether the lock is acquired.
 The blocking operation is not interruptible."""
         mylock = self.lock
@@ -113,4 +113,4 @@
 def allocate_lock(space):
     """Create a new lock object.  (allocate() is an obsolete synonym.)
 See LockType.__doc__ for information about locks."""
-    return space.wrap(Lock(space))
\ No newline at end of file
+    return space.wrap(Lock(space))
diff --git a/pypy/module/thread/test/test_lock.py 
b/pypy/module/thread/test/test_lock.py
--- a/pypy/module/thread/test/test_lock.py
+++ b/pypy/module/thread/test/test_lock.py
@@ -12,7 +12,10 @@
         assert lock.locked() is False
         raises(thread.error, lock.release)
         assert lock.locked() is False
-        lock.acquire()
+        r = lock.acquire()
+        assert r is True
+        r = lock.acquire(False)
+        assert r is False
         assert lock.locked() is True
         lock.release()
         assert lock.locked() is False
diff --git a/pypy/module/thread/threadlocals.py 
b/pypy/module/thread/threadlocals.py
--- a/pypy/module/thread/threadlocals.py
+++ b/pypy/module/thread/threadlocals.py
@@ -44,10 +44,6 @@
         self._mostrecentkey = ident
         self._mostrecentvalue = value
 
-    def getmainthreadvalue(self):
-        ident = self._mainthreadident
-        return self._valuedict.get(ident, None)
-
     def ismainthread(self):
         return thread.get_ident() == self._mainthreadident
 
diff --git a/rpython/rlib/rthread.py b/rpython/rlib/rthread.py
--- a/rpython/rlib/rthread.py
+++ b/rpython/rlib/rthread.py
@@ -126,10 +126,11 @@
         return bool(res)
 
     def acquire_timed(self, timeout):
-        "timeout is in microseconds."
+        """Timeout is in microseconds.  Returns 0 in case of failure,
+        1 in case it works, 2 if interrupted by a signal."""
         res = c_thread_acquirelock_timed(self._lock, timeout, 1)
         res = rffi.cast(lltype.Signed, res)
-        return bool(res)
+        return res
 
     def release(self):
         # Sanity check: the lock must be locked
diff --git a/rpython/rlib/test/test_rpath.py b/rpython/rlib/test/test_rpath.py
--- a/rpython/rlib/test/test_rpath.py
+++ b/rpython/rlib/test/test_rpath.py
@@ -6,7 +6,7 @@
 
 def test_rabspath_relative(tmpdir):
     tmpdir.chdir()
-    assert rpath.rabspath('foo') == tmpdir.join('foo')
+    assert rpath.rabspath('foo') == os.path.realpath(str(tmpdir.join('foo')))
 
 @py.test.mark.skipif("IS_WINDOWS")
 def test_rabspath_absolute_posix():
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
@@ -159,17 +159,46 @@
             l = allocate_lock()
             l.acquire(True)
             t1 = time.time()
-            ok = l.acquire_timed(1000000)
+            ok = l.acquire_timed(1000001)
             t2 = time.time()
             delay = t2 - t1
-            if ok:
+            if ok == 0:        # RPY_LOCK_FAILURE
+                return -delay
+            elif ok == 2:      # RPY_LOCK_INTR
                 return delay
-            else:
-                return -delay
+            else:              # RPY_LOCK_ACQUIRED
+                return 0.0
         fn = self.getcompiled(f, [])
         res = fn()
         assert res < -1.0
 
+    def test_acquire_timed_alarm(self):
+        import sys
+        if not sys.platform.startswith('linux'):
+            py.test.skip("skipped on non-linux")
+        import time
+        from rpython.rlib import rsignal
+        def f():
+            l = allocate_lock()
+            l.acquire(True)
+            #
+            rsignal.pypysig_setflag(rsignal.SIGALRM)
+            rsignal.c_alarm(1)
+            #
+            t1 = time.time()
+            ok = l.acquire_timed(2500000)
+            t2 = time.time()
+            delay = t2 - t1
+            if ok == 0:        # RPY_LOCK_FAILURE
+                return -delay
+            elif ok == 2:      # RPY_LOCK_INTR
+                return delay
+            else:              # RPY_LOCK_ACQUIRED
+                return 0.0
+        fn = self.getcompiled(f, [])
+        res = fn()
+        assert res >= 0.95
+
 #class TestRunDirectly(AbstractThreadTests):
 #    def getcompiled(self, f, argtypes):
 #        return f
diff --git a/rpython/rtyper/memory/gc/minimark.py 
b/rpython/rtyper/memory/gc/minimark.py
--- a/rpython/rtyper/memory/gc/minimark.py
+++ b/rpython/rtyper/memory/gc/minimark.py
@@ -47,7 +47,7 @@
 from rpython.rtyper.lltypesystem.lloperation import llop
 from rpython.rtyper.lltypesystem.llmemory import raw_malloc_usage
 from rpython.rtyper.memory.gc.base import GCBase, MovingGCBase
-from rpython.rtyper.memory.gc import minimarkpage, env
+from rpython.rtyper.memory.gc import env
 from rpython.rtyper.memory.support import mangle_hash
 from rpython.rlib.rarithmetic import ovfcheck, LONG_BIT, intmask, r_uint
 from rpython.rlib.rarithmetic import LONG_BIT_SHIFT
@@ -254,6 +254,7 @@
         #
         # The ArenaCollection() handles the nonmovable objects allocation.
         if ArenaCollectionClass is None:
+            from rpython.rtyper.memory.gc import minimarkpage
             ArenaCollectionClass = minimarkpage.ArenaCollection
         self.ac = ArenaCollectionClass(arena_size, page_size,
                                        small_request_threshold)
@@ -2033,43 +2034,3 @@
                 (obj + offset).address[0] = llmemory.NULL
         self.old_objects_with_weakrefs.delete()
         self.old_objects_with_weakrefs = new_with_weakref
-
-
-# ____________________________________________________________
-
-# For testing, a simple implementation of ArenaCollection.
-# This version could be used together with obmalloc.c, but
-# it requires an extra word per object in the 'all_objects'
-# list.
-
-class SimpleArenaCollection(object):
-
-    def __init__(self, arena_size, page_size, small_request_threshold):
-        self.arena_size = arena_size   # ignored
-        self.page_size = page_size
-        self.small_request_threshold = small_request_threshold
-        self.all_objects = []
-        self.total_memory_used = 0
-
-    def malloc(self, size):
-        nsize = raw_malloc_usage(size)
-        ll_assert(nsize > 0, "malloc: size is null or negative")
-        ll_assert(nsize <= self.small_request_threshold,"malloc: size too big")
-        ll_assert((nsize & (WORD-1)) == 0, "malloc: size is not aligned")
-        #
-        result = llarena.arena_malloc(nsize, False)
-        llarena.arena_reserve(result, size)
-        self.all_objects.append((result, nsize))
-        self.total_memory_used += nsize
-        return result
-
-    def mass_free(self, ok_to_free_func):
-        objs = self.all_objects
-        self.all_objects = []
-        self.total_memory_used = 0
-        for rawobj, nsize in objs:
-            if ok_to_free_func(rawobj):
-                llarena.arena_free(rawobj)
-            else:
-                self.all_objects.append((rawobj, nsize))
-                self.total_memory_used += nsize
diff --git a/rpython/rtyper/memory/gc/minimarktest.py 
b/rpython/rtyper/memory/gc/minimarktest.py
new file mode 100644
--- /dev/null
+++ b/rpython/rtyper/memory/gc/minimarktest.py
@@ -0,0 +1,44 @@
+from rpython.rtyper.lltypesystem import llarena
+from rpython.rtyper.lltypesystem.llmemory import raw_malloc_usage
+from rpython.rlib.debug import ll_assert
+from rpython.rlib.rarithmetic import LONG_BIT
+
+# For testing, a simple implementation of ArenaCollection.
+# This version could be used together with obmalloc.c, but
+# it requires an extra word per object in the 'all_objects'
+# list.
+
+WORD = LONG_BIT // 8
+
+
+class SimpleArenaCollection(object):
+
+    def __init__(self, arena_size, page_size, small_request_threshold):
+        self.arena_size = arena_size   # ignored
+        self.page_size = page_size
+        self.small_request_threshold = small_request_threshold
+        self.all_objects = []
+        self.total_memory_used = 0
+
+    def malloc(self, size):
+        nsize = raw_malloc_usage(size)
+        ll_assert(nsize > 0, "malloc: size is null or negative")
+        ll_assert(nsize <= self.small_request_threshold,"malloc: size too big")
+        ll_assert((nsize & (WORD-1)) == 0, "malloc: size is not aligned")
+        #
+        result = llarena.arena_malloc(nsize, False)
+        llarena.arena_reserve(result, size)
+        self.all_objects.append((result, nsize))
+        self.total_memory_used += nsize
+        return result
+
+    def mass_free(self, ok_to_free_func):
+        objs = self.all_objects
+        self.all_objects = []
+        self.total_memory_used = 0
+        for rawobj, nsize in objs:
+            if ok_to_free_func(rawobj):
+                llarena.arena_free(rawobj)
+            else:
+                self.all_objects.append((rawobj, nsize))
+                self.total_memory_used += nsize
diff --git a/rpython/rtyper/memory/gc/test/test_direct.py 
b/rpython/rtyper/memory/gc/test/test_direct.py
--- a/rpython/rtyper/memory/gc/test/test_direct.py
+++ b/rpython/rtyper/memory/gc/test/test_direct.py
@@ -481,7 +481,7 @@
 
 class TestMiniMarkGCSimple(DirectGCTest):
     from rpython.rtyper.memory.gc.minimark import MiniMarkGC as GCClass
-    from rpython.rtyper.memory.gc.minimark import SimpleArenaCollection
+    from rpython.rtyper.memory.gc.minimarktest import SimpleArenaCollection
     # test the GC itself, providing a simple class for ArenaCollection
     GC_PARAMS = {'ArenaCollectionClass': SimpleArenaCollection}
 
diff --git a/rpython/rtyper/memory/gc/test/test_inspector.py 
b/rpython/rtyper/memory/gc/test/test_inspector.py
--- a/rpython/rtyper/memory/gc/test/test_inspector.py
+++ b/rpython/rtyper/memory/gc/test/test_inspector.py
@@ -43,6 +43,6 @@
 
 class TestMiniMarkGCSimple(InspectorTest):
     from rpython.rtyper.memory.gc.minimark import MiniMarkGC as GCClass
-    from rpython.rtyper.memory.gc.minimark import SimpleArenaCollection
+    from rpython.rtyper.memory.gc.minimarktest import SimpleArenaCollection
     GC_PARAMS = {'ArenaCollectionClass': SimpleArenaCollection,
                  "card_page_indices": 4}
diff --git a/rpython/translator/c/src/profiling.c 
b/rpython/translator/c/src/profiling.c
--- a/rpython/translator/c/src/profiling.c
+++ b/rpython/translator/c/src/profiling.c
@@ -8,8 +8,8 @@
 #include <sched.h>
 #endif
 
-cpu_set_t base_cpu_set;
-int profiling_setup = 0;
+static cpu_set_t base_cpu_set;
+static int profiling_setup = 0;
 
 void pypy_setup_profiling()
 {
@@ -37,8 +37,8 @@
 
 #include <windows.h>
 
-DWORD_PTR base_affinity_mask;
-int profiling_setup = 0;
+static DWORD_PTR base_affinity_mask;
+static int profiling_setup = 0;
 
 void pypy_setup_profiling() { 
     if (!profiling_setup) {
diff --git a/rpython/translator/c/src/thread.h 
b/rpython/translator/c/src/thread.h
--- a/rpython/translator/c/src/thread.h
+++ b/rpython/translator/c/src/thread.h
@@ -7,7 +7,7 @@
 typedef enum RPyLockStatus {
     RPY_LOCK_FAILURE = 0,
     RPY_LOCK_ACQUIRED = 1,
-    RPY_LOCK_INTR
+    RPY_LOCK_INTR = 2
 } RPyLockStatus;
 
 #ifdef _WIN32
diff --git a/rpython/translator/platform/__init__.py 
b/rpython/translator/platform/__init__.py
--- a/rpython/translator/platform/__init__.py
+++ b/rpython/translator/platform/__init__.py
@@ -53,9 +53,18 @@
         ofiles = self._compile_o_files(cfiles, eci, standalone)
         return self._finish_linking(ofiles, eci, outputfilename, standalone)
 
+    def _all_cfiles(self, cfiles, eci):
+        seen = set()
+        result = []
+        for cfile in list(cfiles) + list(eci.separate_module_files):
+            cfile = py.path.local(cfile)
+            if cfile not in seen:
+                seen.add(cfile)
+                result.append(cfile)
+        return result
+
     def _compile_o_files(self, cfiles, eci, standalone=True):
-        cfiles = [py.path.local(f) for f in cfiles]
-        cfiles += [py.path.local(f) for f in eci.separate_module_files]
+        cfiles = self._all_cfiles(cfiles, eci)
         compile_args = self._compile_args_from_eci(eci, standalone)
         ofiles = []
         for cfile in cfiles:
diff --git a/rpython/translator/platform/posix.py 
b/rpython/translator/platform/posix.py
--- a/rpython/translator/platform/posix.py
+++ b/rpython/translator/platform/posix.py
@@ -84,8 +84,7 @@
 
     def gen_makefile(self, cfiles, eci, exe_name=None, path=None,
                      shared=False):
-        cfiles = [py.path.local(f) for f in cfiles]
-        cfiles += [py.path.local(f) for f in eci.separate_module_files]
+        cfiles = self._all_cfiles(cfiles, eci)
 
         if path is None:
             path = cfiles[0].dirpath()
diff --git a/rpython/translator/platform/windows.py 
b/rpython/translator/platform/windows.py
--- a/rpython/translator/platform/windows.py
+++ b/rpython/translator/platform/windows.py
@@ -248,8 +248,7 @@
 
     def gen_makefile(self, cfiles, eci, exe_name=None, path=None,
                      shared=False):
-        cfiles = [py.path.local(f) for f in cfiles]
-        cfiles += [py.path.local(f) for f in eci.separate_module_files]
+        cfiles = self._all_cfiles(cfiles, eci)
 
         if path is None:
             path = cfiles[0].dirpath()
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to