Author: Armin Rigo <ar...@tunes.org> Branch: use-gc-del-3 Changeset: r84324:7b8178ec0f5b Date: 2016-05-09 10:29 +0200 http://bitbucket.org/pypy/pypy/changeset/7b8178ec0f5b/
Log: hg merge default diff --git a/dotviewer/graphserver.py b/dotviewer/graphserver.py --- a/dotviewer/graphserver.py +++ b/dotviewer/graphserver.py @@ -143,6 +143,11 @@ if __name__ == '__main__': if len(sys.argv) != 2: + if len(sys.argv) == 1: + # start locally + import sshgraphserver + sshgraphserver.ssh_graph_server(['LOCAL']) + sys.exit(0) print >> sys.stderr, __doc__ sys.exit(2) if sys.argv[1] == '--stdio': diff --git a/dotviewer/sshgraphserver.py b/dotviewer/sshgraphserver.py --- a/dotviewer/sshgraphserver.py +++ b/dotviewer/sshgraphserver.py @@ -4,11 +4,14 @@ Usage: sshgraphserver.py hostname [more args for ssh...] + sshgraphserver.py LOCAL This logs in to 'hostname' by passing the arguments on the command-line to ssh. No further configuration is required: it works for all programs using the dotviewer library as long as they run on 'hostname' under the same username as the one sshgraphserver logs as. + +If 'hostname' is the string 'LOCAL', then it starts locally without ssh. """ import graphserver, socket, subprocess, random @@ -18,12 +21,19 @@ s1 = socket.socket() s1.bind(('127.0.0.1', socket.INADDR_ANY)) localhost, localport = s1.getsockname() - remoteport = random.randrange(10000, 20000) - # ^^^ and just hope there is no conflict - args = ['ssh', '-S', 'none', '-C', '-R%d:127.0.0.1:%d' % (remoteport, localport)] - args = args + sshargs + ['python -u -c "exec input()"'] - print ' '.join(args[:-1]) + if sshargs[0] != 'LOCAL': + remoteport = random.randrange(10000, 20000) + # ^^^ and just hope there is no conflict + + args = ['ssh', '-S', 'none', '-C', '-R%d:127.0.0.1:%d' % ( + remoteport, localport)] + args = args + sshargs + ['python -u -c "exec input()"'] + else: + remoteport = localport + args = ['python', '-u', '-c', 'exec input()'] + + print ' '.join(args) p = subprocess.Popen(args, bufsize=0, stdin=subprocess.PIPE, stdout=subprocess.PIPE) diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py --- a/lib_pypy/cffi/api.py +++ b/lib_pypy/cffi/api.py @@ -397,20 +397,7 @@ data. Later, when this new cdata object is garbage-collected, 'destructor(old_cdata_object)' will be called. """ - try: - gcp = self._backend.gcp - except AttributeError: - pass - else: - return gcp(cdata, destructor) - # - with self._lock: - try: - gc_weakrefs = self.gc_weakrefs - except AttributeError: - from .gc_weakref import GcWeakrefs - gc_weakrefs = self.gc_weakrefs = GcWeakrefs(self) - return gc_weakrefs.build(cdata, destructor) + return self._backend.gcp(cdata, destructor) def _get_cached_btype(self, type): assert self._lock.acquire(False) is False diff --git a/lib_pypy/cffi/backend_ctypes.py b/lib_pypy/cffi/backend_ctypes.py --- a/lib_pypy/cffi/backend_ctypes.py +++ b/lib_pypy/cffi/backend_ctypes.py @@ -460,6 +460,11 @@ return x._value raise TypeError("character expected, got %s" % type(x).__name__) + def __nonzero__(self): + return ord(self._value) != 0 + else: + def __nonzero__(self): + return self._value != 0 if kind == 'float': @staticmethod @@ -993,6 +998,31 @@ assert onerror is None # XXX not implemented return BType(source, error) + def gcp(self, cdata, destructor): + BType = self.typeof(cdata) + + if destructor is None: + if not (hasattr(BType, '_gcp_type') and + BType._gcp_type is BType): + raise TypeError("Can remove destructor only on a object " + "previously returned by ffi.gc()") + cdata._destructor = None + return None + + try: + gcp_type = BType._gcp_type + except AttributeError: + class CTypesDataGcp(BType): + __slots__ = ['_orig', '_destructor'] + def __del__(self): + if self._destructor is not None: + self._destructor(self._orig) + gcp_type = BType._gcp_type = CTypesDataGcp + new_cdata = self.cast(gcp_type, cdata) + new_cdata._orig = cdata + new_cdata._destructor = destructor + return new_cdata + typeof = type def getcname(self, BType, replace_with): 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 @@ -68,3 +68,19 @@ CPython). .. branch: oefmt + +.. branch: cpyext-werror + +Compile c snippets with -Werror in cpyext + +.. branch: gc-del-3 + +Add rgc.FinalizerQueue, documented in pypy/doc/discussion/finalizer-order.rst. +It is a more flexible way to make RPython finalizers. + +.. branch: unpacking-cpython-shortcut + +.. branch: cleanups + +.. branch: cpyext-more-slots + diff --git a/pypy/interpreter/test/test_argument.py b/pypy/interpreter/test/test_argument.py --- a/pypy/interpreter/test/test_argument.py +++ b/pypy/interpreter/test/test_argument.py @@ -688,3 +688,21 @@ def f(x): pass e = raises(TypeError, "f(**{u'ü' : 19})") assert "?" in str(e.value) + + def test_starstarargs_dict_subclass(self): + def f(**kwargs): + return kwargs + class DictSubclass(dict): + def __iter__(self): + yield 'x' + # CPython, as an optimization, looks directly into dict internals when + # passing one via **kwargs. + x =DictSubclass() + assert f(**x) == {} + x['a'] = 1 + assert f(**x) == {'a': 1} + + def test_starstarargs_module_dict(self): + def f(**kwargs): + return kwargs + assert f(**globals()) == globals() diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py --- a/pypy/module/_cffi_backend/cdataobj.py +++ b/pypy/module/_cffi_backend/cdataobj.py @@ -71,7 +71,7 @@ def nonzero(self): with self as ptr: - nonzero = bool(ptr) + nonzero = self.ctype.nonzero(ptr) return self.space.wrap(nonzero) def int(self, space): @@ -365,8 +365,16 @@ return self.ctype.size def with_gc(self, w_destructor): + space = self.space + if space.is_none(w_destructor): + if isinstance(self, W_CDataGCP): + self.w_destructor = None + return space.w_None + raise oefmt(space.w_TypeError, + "Can remove destructor only on a object " + "previously returned by ffi.gc()") with self as ptr: - return W_CDataGCP(self.space, ptr, self.ctype, self, w_destructor) + return W_CDataGCP(space, ptr, self.ctype, self, w_destructor) def unpack(self, length): from pypy.module._cffi_backend.ctypeptr import W_CTypePtrOrArray @@ -527,7 +535,7 @@ class W_CDataGCP(W_CData): """For ffi.gc().""" _attrs_ = ['w_original_cdata', 'w_destructor'] - _immutable_fields_ = ['w_original_cdata', 'w_destructor'] + _immutable_fields_ = ['w_original_cdata'] def __init__(self, space, cdata, ctype, w_original_cdata, w_destructor): W_CData.__init__(self, space, cdata, ctype) @@ -536,7 +544,10 @@ self.register_finalizer(space) def _finalize_(self): - self.space.call_function(self.w_destructor, self.w_original_cdata) + w_destructor = self.w_destructor + if w_destructor is not None: + self.w_destructor = None + self.space.call_function(w_destructor, self.w_original_cdata) W_CData.typedef = TypeDef( diff --git a/pypy/module/_cffi_backend/ctypeobj.py b/pypy/module/_cffi_backend/ctypeobj.py --- a/pypy/module/_cffi_backend/ctypeobj.py +++ b/pypy/module/_cffi_backend/ctypeobj.py @@ -147,6 +147,9 @@ raise oefmt(space.w_TypeError, "cannot add a cdata '%s' and a number", self.name) + def nonzero(self, cdata): + return bool(cdata) + def insert_name(self, extra, extra_position): name = '%s%s%s' % (self.name[:self.name_position], extra, diff --git a/pypy/module/_cffi_backend/ctypeprim.py b/pypy/module/_cffi_backend/ctypeprim.py --- a/pypy/module/_cffi_backend/ctypeprim.py +++ b/pypy/module/_cffi_backend/ctypeprim.py @@ -93,6 +93,18 @@ return self.space.newlist_int(result) return W_CType.unpack_ptr(self, w_ctypeptr, ptr, length) + def nonzero(self, cdata): + if self.size <= rffi.sizeof(lltype.Signed): + value = misc.read_raw_long_data(cdata, self.size) + return value != 0 + else: + return self._nonzero_longlong(cdata) + + def _nonzero_longlong(self, cdata): + # in its own function: LONGLONG may make the whole function jit-opaque + value = misc.read_raw_signed_data(cdata, self.size) + return bool(value) + class W_CTypePrimitiveCharOrUniChar(W_CTypePrimitive): _attrs_ = [] @@ -435,6 +447,9 @@ return self.space.newlist_float(result) return W_CType.unpack_ptr(self, w_ctypeptr, ptr, length) + def nonzero(self, cdata): + return misc.is_nonnull_float(cdata, self.size) + class W_CTypePrimitiveLongDouble(W_CTypePrimitiveFloat): _attrs_ = [] @@ -501,3 +516,7 @@ rffi.LONGDOUBLE, rffi.LONGDOUBLEP) return True return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob) + + @jit.dont_look_inside + def nonzero(self, cdata): + return misc.is_nonnull_longdouble(cdata) diff --git a/pypy/module/_cffi_backend/misc.py b/pypy/module/_cffi_backend/misc.py --- a/pypy/module/_cffi_backend/misc.py +++ b/pypy/module/_cffi_backend/misc.py @@ -256,7 +256,7 @@ def is_nonnull_longdouble(cdata): return _is_nonnull_longdouble(read_raw_longdouble_data(cdata)) def is_nonnull_float(cdata, size): - return read_raw_float_data(cdata, size) != 0.0 + return read_raw_float_data(cdata, size) != 0.0 # note: True if a NaN def object_as_bool(space, w_ob): # convert and cast a Python object to a boolean. Accept an integer diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -141,9 +141,13 @@ INF = 1E200 * 1E200 for name in ["float", "double"]: p = new_primitive_type(name) - assert bool(cast(p, 0)) + assert bool(cast(p, 0)) is False # since 1.7 + assert bool(cast(p, -0.0)) is False # since 1.7 + assert bool(cast(p, 1e-42)) is True + assert bool(cast(p, -1e-42)) is True assert bool(cast(p, INF)) assert bool(cast(p, -INF)) + assert bool(cast(p, float("nan"))) assert int(cast(p, -150)) == -150 assert int(cast(p, 61.91)) == 61 assert long(cast(p, 61.91)) == 61 @@ -202,7 +206,8 @@ def test_character_type(): p = new_primitive_type("char") - assert bool(cast(p, '\x00')) + assert bool(cast(p, 'A')) is True + assert bool(cast(p, '\x00')) is False # since 1.7 assert cast(p, '\x00') != cast(p, -17*256) assert int(cast(p, 'A')) == 65 assert long(cast(p, 'A')) == 65 @@ -2558,7 +2563,8 @@ BBoolP = new_pointer_type(BBool) assert int(cast(BBool, False)) == 0 assert int(cast(BBool, True)) == 1 - assert bool(cast(BBool, False)) is True # warning! + assert bool(cast(BBool, False)) is False # since 1.7 + assert bool(cast(BBool, True)) is True assert int(cast(BBool, 3)) == 1 assert int(cast(BBool, long(3))) == 1 assert int(cast(BBool, long(10)**4000)) == 1 diff --git a/pypy/module/_cffi_backend/test/test_ffi_obj.py b/pypy/module/_cffi_backend/test/test_ffi_obj.py --- a/pypy/module/_cffi_backend/test/test_ffi_obj.py +++ b/pypy/module/_cffi_backend/test/test_ffi_obj.py @@ -331,6 +331,25 @@ gc.collect() assert seen == [1] + def test_ffi_gc_disable(self): + import _cffi_backend as _cffi1_backend + ffi = _cffi1_backend.FFI() + p = ffi.new("int *", 123) + raises(TypeError, ffi.gc, p, None) + seen = [] + q1 = ffi.gc(p, lambda p: seen.append(1)) + q2 = ffi.gc(q1, lambda p: seen.append(2)) + import gc; gc.collect() + assert seen == [] + assert ffi.gc(q1, None) is None + del q1, q2 + for i in range(5): + if seen: + break + import gc + gc.collect() + assert seen == [2] + def test_ffi_new_allocator_1(self): import _cffi_backend as _cffi1_backend ffi = _cffi1_backend.FFI() diff --git a/pypy/module/_multibytecodec/app_multibytecodec.py b/pypy/module/_multibytecodec/app_multibytecodec.py --- a/pypy/module/_multibytecodec/app_multibytecodec.py +++ b/pypy/module/_multibytecodec/app_multibytecodec.py @@ -44,8 +44,10 @@ self, data)) def reset(self): - self.stream.write(MultibyteIncrementalEncoder.encode( - self, '', final=True)) + data = MultibyteIncrementalEncoder.encode( + self, '', final=True) + if len(data) > 0: + self.stream.write(data) MultibyteIncrementalEncoder.reset(self) def writelines(self, lines): diff --git a/pypy/module/_multibytecodec/test/test_app_stream.py b/pypy/module/_multibytecodec/test/test_app_stream.py --- a/pypy/module/_multibytecodec/test/test_app_stream.py +++ b/pypy/module/_multibytecodec/test/test_app_stream.py @@ -90,3 +90,15 @@ w.write(u'\u304b') w.write(u'\u309a') assert w.stream.output == ['\x83m', '', '\x82\xf5'] + + def test_writer_seek_no_empty_write(self): + # issue #2293: codecs.py will sometimes issue a reset() + # on a StreamWriter attached to a file that is not opened + # for writing at all. We must not emit a "write('')"! + class FakeFile: + def write(self, data): + raise IOError("can't write!") + # + w = self.ShiftJisx0213StreamWriter(FakeFile()) + w.reset() + # assert did not crash diff --git a/pypy/module/cpyext/ndarrayobject.py b/pypy/module/cpyext/ndarrayobject.py --- a/pypy/module/cpyext/ndarrayobject.py +++ b/pypy/module/cpyext/ndarrayobject.py @@ -248,7 +248,7 @@ w_signature = rffi.charp2str(signature) return do_ufunc(space, funcs, data, types, ntypes, nin, nout, identity, name, doc, check_return, w_signature) - + def do_ufunc(space, funcs, data, types, ntypes, nin, nout, identity, name, doc, check_return, w_signature): diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py --- a/pypy/module/cpyext/slotdefs.py +++ b/pypy/module/cpyext/slotdefs.py @@ -374,7 +374,75 @@ header = pypy_decl if mangle_name('', typedef.name) is None: header = None - if name == 'tp_setattro': + handled = False + # unary functions + for tp_name, attr in [('tp_as_number.c_nb_int', '__int__'), + ('tp_as_number.c_nb_long', '__long__'), + ('tp_as_number.c_nb_float', '__float__'), + ('tp_as_number.c_nb_negative', '__neg__'), + ('tp_as_number.c_nb_positive', '__pos__'), + ('tp_as_number.c_nb_absolute', '__abs__'), + ('tp_as_number.c_nb_invert', '__invert__'), + ('tp_as_number.c_nb_index', '__index__'), + ('tp_str', '__str__'), + ('tp_repr', '__repr__'), + ('tp_iter', '__iter__'), + ]: + if name == tp_name: + slot_fn = w_type.getdictvalue(space, attr) + if slot_fn is None: + return + + @cpython_api([PyObject], PyObject, header=header) + @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name)) + def slot_func(space, w_self): + return space.call_function(slot_fn, w_self) + api_func = slot_func.api_func + handled = True + + # binary functions + for tp_name, attr in [('tp_as_number.c_nb_add', '__add__'), + ('tp_as_number.c_nb_subtract', '__subtract__'), + ('tp_as_number.c_nb_multiply', '__mul__'), + ('tp_as_number.c_nb_divide', '__div__'), + ('tp_as_number.c_nb_remainder', '__mod__'), + ('tp_as_number.c_nb_divmod', '__divmod__'), + ('tp_as_number.c_nb_lshift', '__lshift__'), + ('tp_as_number.c_nb_rshift', '__rshift__'), + ('tp_as_number.c_nb_and', '__and__'), + ('tp_as_number.c_nb_xor', '__xor__'), + ('tp_as_number.c_nb_or', '__or__'), + ]: + if name == tp_name: + slot_fn = w_type.getdictvalue(space, attr) + if slot_fn is None: + return + + @cpython_api([PyObject, PyObject], PyObject, header=header) + @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name)) + def slot_func(space, w_self, w_arg): + return space.call_function(slot_fn, w_self, w_arg) + api_func = slot_func.api_func + handled = True + + # ternary functions + for tp_name, attr in [('tp_as_number.c_nb_power', ''), + ]: + if name == tp_name: + slot_fn = w_type.getdictvalue(space, attr) + if slot_fn is None: + return + + @cpython_api([PyObject, PyObject, PyObject], PyObject, header=header) + @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name)) + def slot_func(space, w_self, w_arg1, w_arg2): + return space.call_function(slot_fn, w_self, w_arg1, w_arg2) + api_func = slot_func.api_func + handled = True + + if handled: + pass + elif name == 'tp_setattro': setattr_fn = w_type.getdictvalue(space, '__setattr__') delattr_fn = w_type.getdictvalue(space, '__delattr__') if setattr_fn is None: @@ -401,28 +469,6 @@ return space.call_function(getattr_fn, w_self, w_name) api_func = slot_tp_getattro.api_func - elif name == 'tp_as_number.c_nb_int': - int_fn = w_type.getdictvalue(space, '__int__') - if int_fn is None: - return - - @cpython_api([PyObject], PyObject, header=header) - @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name)) - def slot_nb_int(space, w_self): - return space.call_function(int_fn, w_self) - api_func = slot_nb_int.api_func - - elif name == 'tp_as_number.c_nb_float': - float_fn = w_type.getdictvalue(space, '__float__') - if float_fn is None: - return - - @cpython_api([PyObject], PyObject, header=header) - @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name)) - def slot_nb_float(space, w_self): - return space.call_function(float_fn, w_self) - api_func = slot_nb_float.api_func - elif name == 'tp_call': call_fn = w_type.getdictvalue(space, '__call__') if call_fn is None: @@ -436,28 +482,6 @@ return space.call_args(call_fn, args) api_func = slot_tp_call.api_func - elif name == 'tp_str': - str_fn = w_type.getdictvalue(space, '__str__') - if str_fn is None: - return - - @cpython_api([PyObject], PyObject, header=header) - @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name)) - def slot_tp_str(space, w_self): - return space.call_function(str_fn, w_self) - api_func = slot_tp_str.api_func - - elif name == 'tp_iter': - iter_fn = w_type.getdictvalue(space, '__iter__') - if iter_fn is None: - return - - @cpython_api([PyObject], PyObject, header=header) - @func_renamer("cpyext_%s_%s" % (name.replace('.', '_'), typedef.name)) - def slot_tp_iter(space, w_self): - return space.call_function(iter_fn, w_self) - api_func = slot_tp_iter.api_func - elif name == 'tp_iternext': iternext_fn = w_type.getdictvalue(space, 'next') if iternext_fn is None: @@ -501,6 +525,7 @@ return space.call_args(space.get(new_fn, w_self), args) api_func = slot_tp_new.api_func else: + # missing: tp_as_number.nb_nonzero, tp_as_number.nb_coerce return return lambda: llhelper(api_func.functype, api_func.get_wrapper(space)) diff --git a/pypy/module/cpyext/test/test_api.py b/pypy/module/cpyext/test/test_api.py --- a/pypy/module/cpyext/test/test_api.py +++ b/pypy/module/cpyext/test/test_api.py @@ -1,4 +1,4 @@ -import py +import py, pytest from rpython.rtyper.lltypesystem import rffi, lltype from pypy.interpreter.baseobjspace import W_Root from pypy.module.cpyext.state import State @@ -100,7 +100,8 @@ PyPy_TypedefTest2(space, ppos) lltype.free(ppos, flavor='raw') - +@pytest.mark.skipif(os.environ.get('USER')=='root', + reason='root can write to all files') def test_copy_header_files(tmpdir): api.copy_header_files(tmpdir, True) def check(name): diff --git a/pypy/module/cpyext/test/test_borrow.py b/pypy/module/cpyext/test/test_borrow.py --- a/pypy/module/cpyext/test/test_borrow.py +++ b/pypy/module/cpyext/test/test_borrow.py @@ -12,13 +12,13 @@ PyObject *t = PyTuple_New(1); PyObject *f = PyFloat_FromDouble(42.0); PyObject *g = NULL; - printf("Refcnt1: %i\\n", f->ob_refcnt); + printf("Refcnt1: %zd\\n", f->ob_refcnt); PyTuple_SetItem(t, 0, f); // steals reference - printf("Refcnt2: %i\\n", f->ob_refcnt); + printf("Refcnt2: %zd\\n", f->ob_refcnt); f = PyTuple_GetItem(t, 0); // borrows reference - printf("Refcnt3: %i\\n", f->ob_refcnt); + printf("Refcnt3: %zd\\n", f->ob_refcnt); g = PyTuple_GetItem(t, 0); // borrows reference again - printf("Refcnt4: %i\\n", f->ob_refcnt); + printf("Refcnt4: %zd\\n", f->ob_refcnt); printf("COMPARE: %i\\n", f == g); fflush(stdout); Py_DECREF(t); diff --git a/pypy/module/cpyext/test/test_bytesobject.py b/pypy/module/cpyext/test/test_bytesobject.py --- a/pypy/module/cpyext/test/test_bytesobject.py +++ b/pypy/module/cpyext/test/test_bytesobject.py @@ -40,7 +40,7 @@ #endif if(s->ob_type->tp_basicsize != expected_size) { - printf("tp_basicsize==%ld\\n", s->ob_type->tp_basicsize); + printf("tp_basicsize==%zd\\n", s->ob_type->tp_basicsize); result = 0; } Py_DECREF(s); @@ -162,7 +162,10 @@ module = self.import_extension('foo', [ ("string_None", "METH_VARARGS", ''' - return PyString_AsString(Py_None); + if (PyString_AsString(Py_None)) { + Py_RETURN_NONE; + } + return NULL; ''' )]) raises(TypeError, module.string_None) diff --git a/pypy/module/cpyext/test/test_classobject.py b/pypy/module/cpyext/test/test_classobject.py --- a/pypy/module/cpyext/test/test_classobject.py +++ b/pypy/module/cpyext/test/test_classobject.py @@ -29,7 +29,6 @@ assert space.unwrap(space.getattr(w_instance, space.wrap('x'))) == 1 assert space.unwrap(space.getattr(w_instance, space.wrap('y'))) == 2 assert space.unwrap(space.getattr(w_instance, space.wrap('args'))) == (3,) - def test_lookup(self, space, api): w_instance = space.appexec([], """(): @@ -68,7 +67,7 @@ ("get_classtype", "METH_NOARGS", """ Py_INCREF(&PyClass_Type); - return &PyClass_Type; + return (PyObject*)&PyClass_Type; """)]) class C: pass assert module.get_classtype() is type(C) diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py --- a/pypy/module/cpyext/test/test_cpyext.py +++ b/pypy/module/cpyext/test/test_cpyext.py @@ -72,8 +72,7 @@ else: kwds["link_files"] = [str(api_library + '.so')] if sys.platform.startswith('linux'): - kwds["compile_extra"]=["-Werror=implicit-function-declaration", - "-g", "-O0"] + kwds["compile_extra"]=["-Werror", "-g", "-O0"] kwds["link_extra"]=["-g"] modname = modname.split('.')[-1] @@ -747,7 +746,7 @@ refcnt_after = true_obj->ob_refcnt; Py_DECREF(true_obj); Py_DECREF(true_obj); - fprintf(stderr, "REFCNT %i %i\\n", refcnt, refcnt_after); + fprintf(stderr, "REFCNT %zd %zd\\n", refcnt, refcnt_after); return PyBool_FromLong(refcnt_after == refcnt + 2); } static PyObject* foo_bar(PyObject* self, PyObject *args) @@ -763,7 +762,7 @@ return NULL; refcnt_after = true_obj->ob_refcnt; Py_DECREF(tup); - fprintf(stderr, "REFCNT2 %i %i %i\\n", refcnt, refcnt_after, + fprintf(stderr, "REFCNT2 %zd %zd %zd\\n", refcnt, refcnt_after, true_obj->ob_refcnt); return PyBool_FromLong(refcnt_after == refcnt + 1 && refcnt == true_obj->ob_refcnt); 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 @@ -171,7 +171,7 @@ int little_endian, is_signed; if (!PyArg_ParseTuple(args, "ii", &little_endian, &is_signed)) return NULL; - return _PyLong_FromByteArray("\x9A\xBC", 2, + return _PyLong_FromByteArray((unsigned char*)"\x9A\xBC", 2, little_endian, is_signed); """), ]) @@ -187,7 +187,7 @@ int little_endian, is_signed; if (!PyArg_ParseTuple(args, "ii", &little_endian, &is_signed)) return NULL; - return _PyLong_FromByteArray("\x9A\xBC\x41", 3, + return _PyLong_FromByteArray((unsigned char*)"\x9A\xBC\x41", 3, little_endian, is_signed); """), ]) diff --git a/pypy/module/cpyext/test/test_pyerrors.py b/pypy/module/cpyext/test/test_pyerrors.py --- a/pypy/module/cpyext/test/test_pyerrors.py +++ b/pypy/module/cpyext/test/test_pyerrors.py @@ -168,14 +168,14 @@ PyErr_NormalizeException(&type, &val, &tb); if (type != PyExc_TypeError) Py_RETURN_FALSE; - if (val->ob_type != PyExc_TypeError) + if ((PyObject*)Py_TYPE(val) != PyExc_TypeError) Py_RETURN_FALSE; /* Normalize again */ PyErr_NormalizeException(&type, &val, &tb); if (type != PyExc_TypeError) Py_RETURN_FALSE; - if (val->ob_type != PyExc_TypeError) + if ((PyObject*)Py_TYPE(val) != PyExc_TypeError) Py_RETURN_FALSE; PyErr_Restore(type, val, tb); diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py --- a/pypy/module/cpyext/test/test_typeobject.py +++ b/pypy/module/cpyext/test/test_typeobject.py @@ -437,14 +437,14 @@ ("test_tp_getattro", "METH_VARARGS", ''' PyObject *name, *obj = PyTuple_GET_ITEM(args, 0); - PyIntObject *attr, *value = PyTuple_GET_ITEM(args, 1); + PyIntObject *attr, *value = (PyIntObject*) PyTuple_GET_ITEM(args, 1); if (!obj->ob_type->tp_getattro) { PyErr_SetString(PyExc_ValueError, "missing tp_getattro"); return NULL; } name = PyString_FromString("attr1"); - attr = obj->ob_type->tp_getattro(obj, name); + attr = (PyIntObject*) obj->ob_type->tp_getattro(obj, name); if (attr->ob_ival != value->ob_ival) { PyErr_SetString(PyExc_ValueError, @@ -454,7 +454,7 @@ Py_DECREF(name); Py_DECREF(attr); name = PyString_FromString("attr2"); - attr = obj->ob_type->tp_getattro(obj, name); + attr = (PyIntObject*) obj->ob_type->tp_getattro(obj, name); if (attr == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) { PyErr_Clear(); @@ -758,8 +758,9 @@ } IntLikeObject; static int - intlike_nb_nonzero(IntLikeObject *v) + intlike_nb_nonzero(PyObject *o) { + IntLikeObject *v = (IntLikeObject*)o; if (v->value == -42) { PyErr_SetNone(PyExc_ValueError); return -1; @@ -920,3 +921,59 @@ ' multiple bases have instance lay-out conflict') else: raise AssertionError("did not get TypeError!") + + def test_call_tp_dealloc_when_created_from_python(self): + module = self.import_extension('foo', [ + ("fetchFooType", "METH_VARARGS", + """ + PyObject *o; + Foo_Type.tp_dealloc = &dealloc_foo; + Foo_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE; + Foo_Type.tp_new = &new_foo; + Foo_Type.tp_free = &PyObject_Del; + if (PyType_Ready(&Foo_Type) < 0) return NULL; + + o = PyObject_New(PyObject, &Foo_Type); + Py_DECREF(o); /* calls dealloc_foo immediately */ + + Py_INCREF(&Foo_Type); + return (PyObject *)&Foo_Type; + """), + ("getCounter", "METH_VARARGS", + """ + return PyInt_FromLong(foo_counter); + """)], prologue= + """ + static int foo_counter = 1000; + static void dealloc_foo(PyObject *foo) { + foo_counter += 10; + } + static PyObject *new_foo(PyTypeObject *t, PyObject *a, PyObject *k) + { + foo_counter += 1000; + return t->tp_alloc(t, 0); + } + static PyTypeObject Foo_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "foo.foo", + }; + """) + Foo = module.fetchFooType() + assert module.getCounter() == 1010 + Foo(); Foo() + for i in range(10): + if module.getCounter() >= 3030: + break + # NB. use self.debug_collect() instead of gc.collect(), + # otherwise rawrefcount's dealloc callback doesn't trigger + self.debug_collect() + assert module.getCounter() == 3030 + # + class Bar(Foo): + pass + Bar(); Bar() + for i in range(10): + if module.getCounter() >= 5050: + break + self.debug_collect() + assert module.getCounter() == 5050 diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py --- a/pypy/module/cpyext/typeobject.py +++ b/pypy/module/cpyext/typeobject.py @@ -556,7 +556,14 @@ typedescr = get_typedescr(w_type.layout.typedef) # dealloc - pto.c_tp_dealloc = typedescr.get_dealloc(space) + if space.gettypeobject(w_type.layout.typedef) is w_type: + # only for the exact type, like 'space.w_tuple' or 'space.w_list' + pto.c_tp_dealloc = typedescr.get_dealloc(space) + else: + # for all subtypes, use subtype_dealloc() + pto.c_tp_dealloc = llhelper( + subtype_dealloc.api_func.functype, + subtype_dealloc.api_func.get_wrapper(space)) # buffer protocol if space.is_w(w_type, space.w_str): setup_string_buffer_procs(space, pto) diff --git a/pypy/module/micronumpy/concrete.py b/pypy/module/micronumpy/concrete.py --- a/pypy/module/micronumpy/concrete.py +++ b/pypy/module/micronumpy/concrete.py @@ -258,7 +258,6 @@ elif space.is_w(w_idx, space.w_None): return [NewAxisChunk(), EllipsisChunk()] result = [] - i = 0 has_ellipsis = False has_filter = False for w_item in space.fixedview(w_idx): @@ -274,7 +273,6 @@ result.append(NewAxisChunk()) elif space.isinstance_w(w_item, space.w_slice): result.append(SliceChunk(w_item)) - i += 1 elif isinstance(w_item, W_NDimArray) and w_item.get_dtype().is_bool(): if has_filter: # in CNumPy, the support for this is incomplete @@ -287,7 +285,6 @@ result.append(IntegerChunk(w_item.descr_int(space))) else: result.append(IntegerChunk(w_item)) - i += 1 if not has_ellipsis: result.append(EllipsisChunk()) return result diff --git a/pypy/module/micronumpy/loop.py b/pypy/module/micronumpy/loop.py --- a/pypy/module/micronumpy/loop.py +++ b/pypy/module/micronumpy/loop.py @@ -199,7 +199,7 @@ reds='auto') def call_many_to_many(space, shape, func, in_dtypes, out_dtypes, in_args, out_args): - # out must hav been built. func needs no calc_type, is usually an + # out must have been built. func needs no calc_type, is usually an # external ufunc nin = len(in_args) in_iters = [None] * nin @@ -806,7 +806,6 @@ indexlen = len(indexes_w) dtype = arr.get_dtype() iter = PureShapeIter(iter_shape, indexes_w) - indexlen = len(indexes_w) while not iter.done(): getitem_int_driver.jit_merge_point(shapelen=shapelen, indexlen=indexlen, dtype=dtype, prefixlen=prefixlen) diff --git a/pypy/module/micronumpy/ndarray.py b/pypy/module/micronumpy/ndarray.py --- a/pypy/module/micronumpy/ndarray.py +++ b/pypy/module/micronumpy/ndarray.py @@ -231,11 +231,11 @@ dim = i idx = c.w_idx chunks.pop(i) - chunks.insert(0, SliceChunk(space.newslice(space.wrap(0), + chunks.insert(0, SliceChunk(space.newslice(space.wrap(0), space.w_None, space.w_None))) break if dim > 0: - view = self.implementation.swapaxes(space, self, 0, dim) + view = self.implementation.swapaxes(space, self, 0, dim) if dim >= 0: view = new_view(space, self, chunks) view.setitem_filter(space, idx, val_arr) @@ -563,7 +563,7 @@ l_w = [] for i in range(self.get_shape()[0]): item_w = self.descr_getitem(space, space.wrap(i)) - if (isinstance(item_w, W_NDimArray) or + if (isinstance(item_w, W_NDimArray) or isinstance(item_w, boxes.W_GenericBox)): l_w.append(space.call_method(item_w, "tolist")) else: @@ -740,7 +740,7 @@ space.str_w(self.get_dtype().descr_repr(space)), space.str_w(new_dtype.descr_repr(space)), casting) order = order_converter(space, space.wrap(order), self.get_order()) - if (not copy and new_dtype == self.get_dtype() + if (not copy and new_dtype == self.get_dtype() and (order in (NPY.KEEPORDER, NPY.ANYORDER) or order == self.get_order()) and (subok or type(self) is W_NDimArray)): return self diff --git a/pypy/module/micronumpy/strides.py b/pypy/module/micronumpy/strides.py --- a/pypy/module/micronumpy/strides.py +++ b/pypy/module/micronumpy/strides.py @@ -1,14 +1,13 @@ from pypy.interpreter.error import oefmt from rpython.rlib import jit -from pypy.module.micronumpy import support, constants as NPY +from pypy.module.micronumpy import constants as NPY from pypy.module.micronumpy.base import W_NDimArray # structures to describe slicing class BaseChunk(object): - _attrs_ = ['step','out_dim'] - pass + _attrs_ = ['step', 'out_dim'] class Chunk(BaseChunk): @@ -36,6 +35,7 @@ class IntegerChunk(BaseChunk): input_dim = 1 out_dim = 0 + def __init__(self, w_idx): self.w_idx = w_idx @@ -70,6 +70,7 @@ class EllipsisChunk(BaseChunk): input_dim = 0 out_dim = 0 + def __init__(self): pass @@ -80,6 +81,7 @@ class BooleanChunk(BaseChunk): input_dim = 1 out_dim = 1 + def __init__(self, w_idx): self.w_idx = w_idx diff --git a/pypy/module/micronumpy/ufuncs.py b/pypy/module/micronumpy/ufuncs.py --- a/pypy/module/micronumpy/ufuncs.py +++ b/pypy/module/micronumpy/ufuncs.py @@ -1521,7 +1521,7 @@ # Instantiated in cpyext/ndarrayobject. It is here since ufunc calls # set_dims_and_steps, otherwise ufunc, ndarrayobject would have circular # imports -npy_intpp = rffi.LONGP +npy_intpp = rffi.INTPTR_T LONG_SIZE = LONG_BIT / 8 CCHARP_SIZE = _get_bitsize('P') / 8 diff --git a/pypy/module/select/interp_epoll.py b/pypy/module/select/interp_epoll.py --- a/pypy/module/select/interp_epoll.py +++ b/pypy/module/select/interp_epoll.py @@ -53,6 +53,10 @@ EPOLL_CTL_MOD = cconfig["EPOLL_CTL_MOD"] EPOLL_CTL_DEL = cconfig["EPOLL_CTL_DEL"] +DEF_REGISTER_EVENTMASK = (public_symbols["EPOLLIN"] | + public_symbols["EPOLLOUT"] | + public_symbols["EPOLLPRI"]) + epoll_create = rffi.llexternal( "epoll_create", [rffi.INT], rffi.INT, compilation_info=eci, save_err=rffi.RFFI_SAVE_ERRNO @@ -133,7 +137,7 @@ self.close() @unwrap_spec(eventmask=int) - def descr_register(self, space, w_fd, eventmask=-1): + def descr_register(self, space, w_fd, eventmask=DEF_REGISTER_EVENTMASK): self.check_closed(space) self.epoll_ctl(space, EPOLL_CTL_ADD, w_fd, eventmask) @@ -142,7 +146,7 @@ self.epoll_ctl(space, EPOLL_CTL_DEL, w_fd, 0, ignore_ebadf=True) @unwrap_spec(eventmask=int) - def descr_modify(self, space, w_fd, eventmask=-1): + def descr_modify(self, space, w_fd, eventmask): self.check_closed(space) self.epoll_ctl(space, EPOLL_CTL_MOD, w_fd, eventmask) diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py b/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py +++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py @@ -56,7 +56,7 @@ max = int(max) p = ffi.cast(c_decl, min) assert p != min # no __eq__(int) - assert bool(p) is True + assert bool(p) is bool(min) assert int(p) == min p = ffi.cast(c_decl, max) assert int(p) == max @@ -285,7 +285,9 @@ assert ffi.new("char*", b"\xff")[0] == b'\xff' assert ffi.new("char*")[0] == b'\x00' assert int(ffi.cast("char", 300)) == 300 - 256 - assert bool(ffi.cast("char", 0)) + assert not bool(ffi.cast("char", 0)) + assert bool(ffi.cast("char", 1)) + assert bool(ffi.cast("char", 255)) py.test.raises(TypeError, ffi.new, "char*", 32) py.test.raises(TypeError, ffi.new, "char*", u+"x") py.test.raises(TypeError, ffi.new, "char*", b"foo") @@ -326,7 +328,11 @@ py.test.raises(TypeError, ffi.new, "wchar_t*", u+'\U00012345') assert ffi.new("wchar_t*")[0] == u+'\x00' assert int(ffi.cast("wchar_t", 300)) == 300 - assert bool(ffi.cast("wchar_t", 0)) + assert not bool(ffi.cast("wchar_t", 0)) + assert bool(ffi.cast("wchar_t", 1)) + assert bool(ffi.cast("wchar_t", 65535)) + if SIZE_OF_WCHAR > 2: + assert bool(ffi.cast("wchar_t", 65536)) py.test.raises(TypeError, ffi.new, "wchar_t*", 32) py.test.raises(TypeError, ffi.new, "wchar_t*", "foo") # @@ -1523,21 +1529,30 @@ import gc; gc.collect(); gc.collect(); gc.collect() assert seen == [3] + def test_gc_disable(self): + ffi = FFI(backend=self.Backend()) + p = ffi.new("int *", 123) + py.test.raises(TypeError, ffi.gc, p, None) + seen = [] + q1 = ffi.gc(p, lambda p: seen.append(1)) + q2 = ffi.gc(q1, lambda p: seen.append(2)) + import gc; gc.collect() + assert seen == [] + assert ffi.gc(q1, None) is None + del q1, q2 + import gc; gc.collect(); gc.collect(); gc.collect() + assert seen == [2] + def test_gc_finite_list(self): ffi = FFI(backend=self.Backend()) - public = not hasattr(ffi._backend, 'gcp') p = ffi.new("int *", 123) keepalive = [] for i in range(10): keepalive.append(ffi.gc(p, lambda p: None)) - if public: - assert len(ffi.gc_weakrefs.data) == i + 1 del keepalive[:] import gc; gc.collect(); gc.collect() for i in range(10): keepalive.append(ffi.gc(p, lambda p: None)) - if public: - assert len(ffi.gc_weakrefs.data) == 10 def test_CData_CType(self): ffi = FFI(backend=self.Backend()) diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py +++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_ffi_backend.py @@ -467,12 +467,12 @@ def test_introspect_order(self): ffi = FFI() - ffi.cdef("union aaa { int a; }; typedef struct ccc { int a; } b;") - ffi.cdef("union g { int a; }; typedef struct cc { int a; } bbb;") - ffi.cdef("union aa { int a; }; typedef struct a { int a; } bb;") - assert ffi.list_types() == (['b', 'bb', 'bbb'], - ['a', 'cc', 'ccc'], - ['aa', 'aaa', 'g']) + ffi.cdef("union CFFIaaa { int a; }; typedef struct CFFIccc { int a; } CFFIb;") + ffi.cdef("union CFFIg { int a; }; typedef struct CFFIcc { int a; } CFFIbbb;") + ffi.cdef("union CFFIaa { int a; }; typedef struct CFFIa { int a; } CFFIbb;") + assert ffi.list_types() == (['CFFIb', 'CFFIbb', 'CFFIbbb'], + ['CFFIa', 'CFFIcc', 'CFFIccc'], + ['CFFIaa', 'CFFIaaa', 'CFFIg']) def test_unpack(self): ffi = FFI() diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_new_ffi_1.py b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_new_ffi_1.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_new_ffi_1.py +++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_new_ffi_1.py @@ -139,7 +139,7 @@ max = int(max) p = ffi.cast(c_decl, min) assert p != min # no __eq__(int) - assert bool(p) is True + assert bool(p) is bool(min) assert int(p) == min p = ffi.cast(c_decl, max) assert int(p) == max @@ -351,7 +351,9 @@ assert ffi.new("char*", b"\xff")[0] == b'\xff' assert ffi.new("char*")[0] == b'\x00' assert int(ffi.cast("char", 300)) == 300 - 256 - assert bool(ffi.cast("char", 0)) + assert not bool(ffi.cast("char", 0)) + assert bool(ffi.cast("char", 1)) + assert bool(ffi.cast("char", 255)) py.test.raises(TypeError, ffi.new, "char*", 32) py.test.raises(TypeError, ffi.new, "char*", u+"x") py.test.raises(TypeError, ffi.new, "char*", b"foo") @@ -391,7 +393,11 @@ py.test.raises(TypeError, ffi.new, "wchar_t*", u+'\U00012345') assert ffi.new("wchar_t*")[0] == u+'\x00' assert int(ffi.cast("wchar_t", 300)) == 300 - assert bool(ffi.cast("wchar_t", 0)) + assert not bool(ffi.cast("wchar_t", 0)) + assert bool(ffi.cast("wchar_t", 1)) + assert bool(ffi.cast("wchar_t", 65535)) + if SIZE_OF_WCHAR > 2: + assert bool(ffi.cast("wchar_t", 65536)) py.test.raises(TypeError, ffi.new, "wchar_t*", 32) py.test.raises(TypeError, ffi.new, "wchar_t*", "foo") # diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py +++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py @@ -1898,14 +1898,14 @@ def test_introspect_order(): ffi = FFI() - ffi.cdef("union aaa { int a; }; typedef struct ccc { int a; } b;") - ffi.cdef("union g { int a; }; typedef struct cc { int a; } bbb;") - ffi.cdef("union aa { int a; }; typedef struct a { int a; } bb;") + ffi.cdef("union CFFIaaa { int a; }; typedef struct CFFIccc { int a; } CFFIb;") + ffi.cdef("union CFFIg { int a; }; typedef struct CFFIcc { int a; } CFFIbbb;") + ffi.cdef("union CFFIaa { int a; }; typedef struct CFFIa { int a; } CFFIbb;") verify(ffi, "test_introspect_order", """ - union aaa { int a; }; typedef struct ccc { int a; } b; - union g { int a; }; typedef struct cc { int a; } bbb; - union aa { int a; }; typedef struct a { int a; } bb; + union CFFIaaa { int a; }; typedef struct CFFIccc { int a; } CFFIb; + union CFFIg { int a; }; typedef struct CFFIcc { int a; } CFFIbbb; + union CFFIaa { int a; }; typedef struct CFFIa { int a; } CFFIbb; """) - assert ffi.list_types() == (['b', 'bb', 'bbb'], - ['a', 'cc', 'ccc'], - ['aa', 'aaa', 'g']) + assert ffi.list_types() == (['CFFIb', 'CFFIbb', 'CFFIbbb'], + ['CFFIa', 'CFFIcc', 'CFFIccc'], + ['CFFIaa', 'CFFIaaa', 'CFFIg']) diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py +++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py @@ -280,6 +280,14 @@ pass with open("setup.py", "w") as f: f.write("""if 1: + # https://bugs.python.org/issue23246 + import sys + if sys.platform == 'win32': + try: + import setuptools + except ImportError: + pass + import cffi ffi = cffi.FFI() ffi.set_source("pack1.mymod", "/*code would be here*/") diff --git a/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py b/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py --- a/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py +++ b/pypy/module/test_lib_pypy/cffi_tests/embedding/test_basic.py @@ -80,8 +80,21 @@ # find a solution to that: we could hack sys.path inside the # script run here, but we can't hack it in the same way in # execute(). - output = self._run([sys.executable, - os.path.join(local_dir, filename)]) + pathname = os.path.join(path, filename) + with open(pathname, 'w') as g: + g.write(''' +# https://bugs.python.org/issue23246 +import sys +if sys.platform == 'win32': + try: + import setuptools + except ImportError: + pass +''') + with open(os.path.join(local_dir, filename), 'r') as f: + g.write(f.read()) + + output = self._run([sys.executable, pathname]) match = re.compile(r"\bFILENAME: (.+)").search(output) assert match dynamic_lib_name = match.group(1) diff --git a/pypy/module/test_lib_pypy/cffi_tests/udir.py b/pypy/module/test_lib_pypy/cffi_tests/udir.py --- a/pypy/module/test_lib_pypy/cffi_tests/udir.py +++ b/pypy/module/test_lib_pypy/cffi_tests/udir.py @@ -1,4 +1,14 @@ # Generated by pypy/tool/import_cffi.py import py +import sys udir = py.path.local.make_numbered_dir(prefix = 'ffi-') + + +# Windows-only workaround for some configurations: see +# https://bugs.python.org/issue23246 (Python 2.7.9) +if sys.platform == 'win32': + try: + import setuptools + except ImportError: + pass diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py --- a/pypy/objspace/std/objspace.py +++ b/pypy/objspace/std/objspace.py @@ -484,7 +484,12 @@ return None def view_as_kwargs(self, w_dict): - if type(w_dict) is W_DictObject: + # Tries to return (keys_list, values_list), or (None, None) if + # it fails. It can fail on some dict implementations, so don't + # rely on it. For dict subclasses, though, it never fails; + # this emulates CPython's behavior which often won't call + # custom __iter__() or keys() methods in dict subclasses. + if isinstance(w_dict, W_DictObject): return w_dict.view_as_kwargs() return (None, None) diff --git a/pypy/tool/release/repackage.sh b/pypy/tool/release/repackage.sh --- a/pypy/tool/release/repackage.sh +++ b/pypy/tool/release/repackage.sh @@ -3,7 +3,7 @@ min=1 rev=1 branchname=release-$maj.x # ==OR== release-$maj.$min.x -tagname=release-$maj.$min # ==OR== release-$maj.$min.$rev +tagname=release-$maj.$min.$rev # ==OR== release-$maj.$min hg log -r $branchname || exit 1 hg log -r $tagname || exit 1 diff --git a/rpython/jit/metainterp/optimizeopt/intutils.py b/rpython/jit/metainterp/optimizeopt/intutils.py --- a/rpython/jit/metainterp/optimizeopt/intutils.py +++ b/rpython/jit/metainterp/optimizeopt/intutils.py @@ -1,5 +1,8 @@ +import sys from rpython.rlib.rarithmetic import ovfcheck, LONG_BIT, maxint, is_valid_int from rpython.rlib.objectmodel import we_are_translated +from rpython.rtyper.lltypesystem import lltype +from rpython.rtyper.lltypesystem.lloperation import llop from rpython.jit.metainterp.resoperation import rop, ResOperation from rpython.jit.metainterp.optimizeopt.info import AbstractInfo, INFO_NONNULL,\ INFO_UNKNOWN, INFO_NULL @@ -174,15 +177,13 @@ def div_bound(self, other): if self.has_upper and self.has_lower and \ other.has_upper and other.has_lower and \ - not other.contains(0): - try: - vals = (ovfcheck(self.upper / other.upper), - ovfcheck(self.upper / other.lower), - ovfcheck(self.lower / other.upper), - ovfcheck(self.lower / other.lower)) - return IntBound(min4(vals), max4(vals)) - except OverflowError: - return IntUnbounded() + not other.contains(0) and self.lower > (-sys.maxint-1): + vals = ( + llop.int_floordiv(lltype.Signed, self.upper, other.upper), + llop.int_floordiv(lltype.Signed, self.upper, other.lower), + llop.int_floordiv(lltype.Signed, self.lower, other.upper), + llop.int_floordiv(lltype.Signed, self.lower, other.lower)) + return IntBound(min4(vals), max4(vals)) else: return IntUnbounded() diff --git a/rpython/jit/metainterp/optimizeopt/test/test_intbound.py b/rpython/jit/metainterp/optimizeopt/test/test_intbound.py --- a/rpython/jit/metainterp/optimizeopt/test/test_intbound.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_intbound.py @@ -240,6 +240,8 @@ def test_div_bound(): + from rpython.rtyper.lltypesystem import lltype + from rpython.rtyper.lltypesystem.lloperation import llop for _, _, b1 in some_bounds(): for _, _, b2 in some_bounds(): b3 = b1.div_bound(b2) @@ -247,7 +249,8 @@ for n2 in nbr: if b1.contains(n1) and b2.contains(n2): if n2 != 0: - assert b3.contains(n1 / n2) + assert b3.contains( + llop.int_floordiv(lltype.Signed, n1, n2)) a=bound(2, 4).div_bound(bound(1, 2)) assert not a.contains(0) diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py @@ -5529,6 +5529,27 @@ """ self.optimize_loop(ops, expected) + def test_division_bound_bug(self): + ops = """ + [i4] + i1 = int_ge(i4, -50) + guard_true(i1) [] + i2 = int_le(i4, -40) + guard_true(i2) [] + # here, -50 <= i4 <= -40 + + i5 = int_floordiv(i4, 30) + # here, we know that that i5 == -1 (C-style handling of negatives!) + escape_n(i5) + jump(i4) + """ + expected = """ + [i4, i5] + escape_n(-1) + jump(i4, -1) + """ + self.optimize_loop(ops, expected) + def test_subsub_ovf(self): ops = """ [i0] diff --git a/rpython/rlib/runicode.py b/rpython/rlib/runicode.py --- a/rpython/rlib/runicode.py +++ b/rpython/rlib/runicode.py @@ -989,8 +989,6 @@ return result.build(), pos -# Specialize on the errorhandler when it's a constant -@specialize.arg_or_var(4) def str_decode_ascii(s, size, errors, final=False, errorhandler=None): if errorhandler is None: @@ -1020,8 +1018,6 @@ return result.build() -# Specialize on the errorhandler when it's a constant -@specialize.arg_or_var(3) def unicode_encode_ucs1_helper(p, size, errors, errorhandler=None, limit=256): if errorhandler is None: @@ -1064,12 +1060,10 @@ return result.build() -@specialize.arg_or_var(3) def unicode_encode_latin_1(p, size, errors, errorhandler=None): res = unicode_encode_ucs1_helper(p, size, errors, errorhandler, 256) return res -@specialize.arg_or_var(3) def unicode_encode_ascii(p, size, errors, errorhandler=None): res = unicode_encode_ucs1_helper(p, size, errors, errorhandler, 128) return res @@ -1194,8 +1188,6 @@ builder.append(res) return pos -# Specialize on the errorhandler when it's a constant -@specialize.arg_or_var(4) def str_decode_unicode_escape(s, size, errors, final=False, errorhandler=None, unicodedata_handler=None): diff --git a/rpython/translator/driver.py b/rpython/translator/driver.py --- a/rpython/translator/driver.py +++ b/rpython/translator/driver.py @@ -552,16 +552,16 @@ self.log.info('usession directory: %s' % (udir,)) return result - @staticmethod - def from_targetspec(targetspec_dic, config=None, args=None, + @classmethod + def from_targetspec(cls, targetspec_dic, config=None, args=None, empty_translator=None, disable=[], default_goal=None): if args is None: args = [] - driver = TranslationDriver(config=config, default_goal=default_goal, - disable=disable) + driver = cls(config=config, default_goal=default_goal, + disable=disable) target = targetspec_dic['target'] spec = target(driver, args) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit