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