Author: Maciej Fijalkowski <fij...@gmail.com> Branch: Changeset: r69554:3da10e6aef02 Date: 2014-02-28 17:44 +0200 http://bitbucket.org/pypy/pypy/changeset/3da10e6aef02/
Log: merge diff --git a/lib-python/2.7/ctypes/test/test_numbers.py b/lib-python/2.7/ctypes/test/test_numbers.py --- a/lib-python/2.7/ctypes/test/test_numbers.py +++ b/lib-python/2.7/ctypes/test/test_numbers.py @@ -105,7 +105,6 @@ self.assertEqual(ArgType, type(parm)) - @xfail def test_floats(self): # c_float and c_double can be created from # Python int, long and float diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -92,7 +92,7 @@ i = 2 * HUGEVAL_BYTES addrstring = [' '] * i while True: - n = space.int_w(space.and_(w_id, w_0x0F)) + n = space.int_w(space.and_(w_id, w_0x0F), allow_conversion=False) n += ord('0') if n > ord('9'): n += (ord('a') - ord('9') - 1) @@ -201,16 +201,38 @@ def unicode_w(self, space): self._typed_unwrap_error(space, "unicode") - def int_w(self, space): + def int_w(self, space, allow_conversion=True): + # note that W_IntObject.int_w has a fast path and W_FloatObject.int_w + # raises w_TypeError + w_obj = self + if allow_conversion: + w_obj = space.int(self) + return w_obj._int_w(space) + + def _int_w(self, space): self._typed_unwrap_error(space, "integer") - def float_w(self, space): + def float_w(self, space, allow_conversion=True): + w_obj = self + if allow_conversion: + w_obj = space.float(self) + return w_obj._float_w(space) + + def _float_w(self, space): self._typed_unwrap_error(space, "float") def uint_w(self, space): self._typed_unwrap_error(space, "integer") - def bigint_w(self, space): + def bigint_w(self, space, allow_conversion=True): + # note that W_IntObject and W_LongObject have fast paths, + # W_FloatObject.rbigint_w raises w_TypeError raises + w_obj = self + if allow_conversion: + w_obj = space.long(self) + return w_obj._bigint_w(space) + + def _bigint_w(self, space): self._typed_unwrap_error(space, "integer") def _typed_unwrap_error(self, space, expected): @@ -220,8 +242,7 @@ def int(self, space): w_impl = space.lookup(self, '__int__') if w_impl is None: - raise oefmt(space.w_TypeError, - "unsupported operand type for int(): '%T'", self) + self._typed_unwrap_error(space, "integer") w_result = space.get_and_call_function(w_impl, self) if (space.isinstance_w(w_result, space.w_int) or @@ -1210,7 +1231,7 @@ assert isinstance(w_index_or_slice, W_SliceObject) start, stop, step = w_index_or_slice.indices3(self, seqlength) else: - start = self.int_w(w_index_or_slice) + start = self.int_w(w_index_or_slice, allow_conversion=False) if start < 0: start += seqlength if not (0 <= start < seqlength): @@ -1231,7 +1252,7 @@ start, stop, step, length = w_index_or_slice.indices4(self, seqlength) else: - start = self.int_w(w_index_or_slice) + start = self.int_w(w_index_or_slice, allow_conversion=False) if start < 0: start += seqlength if not (0 <= start < seqlength): @@ -1255,7 +1276,10 @@ raise oefmt(self.w_TypeError, "%s must be an integer, not %T", objdescr, w_obj) try: - index = self.int_w(w_index) + # allow_conversion=False it's not really necessary because the + # return type of __index__ is already checked by space.index(), + # but there is no reason to allow conversions anyway + index = self.int_w(w_index, allow_conversion=False) except OperationError, err: if not err.match(self, self.w_OverflowError): raise @@ -1272,16 +1296,16 @@ else: return index - def r_longlong_w(self, w_obj): - bigint = self.bigint_w(w_obj) + def r_longlong_w(self, w_obj, allow_conversion=True): + bigint = self.bigint_w(w_obj, allow_conversion) try: return bigint.tolonglong() except OverflowError: raise OperationError(self.w_OverflowError, self.wrap('integer too large')) - def r_ulonglong_w(self, w_obj): - bigint = self.bigint_w(w_obj) + def r_ulonglong_w(self, w_obj, allow_conversion=True): + bigint = self.bigint_w(w_obj, allow_conversion) try: return bigint.toulonglong() except OverflowError: @@ -1348,8 +1372,19 @@ 'argument must be a string without NUL characters')) return rstring.assert_str0(result) - def int_w(self, w_obj): - return w_obj.int_w(self) + def int_w(self, w_obj, allow_conversion=True): + """ + Unwrap an app-level int object into an interpret-level int. + + If allow_conversion==True, w_obj might be of any type which implements + __int__, *except* floats which are explicitly rejected. This is the + same logic as CPython's PyArg_ParseTuple. If you want to also allow + floats, you can call space.int_w(space.int(w_obj)). + + If allow_conversion=False, w_obj needs to be an app-level int or a + subclass. + """ + return w_obj.int_w(self, allow_conversion) def int(self, w_obj): return w_obj.int(self) @@ -1357,11 +1392,19 @@ def uint_w(self, w_obj): return w_obj.uint_w(self) - def bigint_w(self, w_obj): - return w_obj.bigint_w(self) + def bigint_w(self, w_obj, allow_conversion=True): + """ + Like int_w, but return a rlib.rbigint object and call __long__ if + allow_conversion is True. + """ + return w_obj.bigint_w(self, allow_conversion) - def float_w(self, w_obj): - return w_obj.float_w(self) + def float_w(self, w_obj, allow_conversion=True): + """ + Like int_w, but return an interp-level float and call __float__ if + allow_conversion is True. + """ + return w_obj.float_w(self, allow_conversion) def realstr_w(self, w_obj): # Like str_w, but only works if w_obj is really of type 'str'. @@ -1399,20 +1442,10 @@ return w_obj.ord(self) # This is all interface for gateway.py. - def gateway_int_w(self, w_obj): - if self.isinstance_w(w_obj, self.w_float): - raise OperationError(self.w_TypeError, - self.wrap("integer argument expected, got float")) - return self.int_w(self.int(w_obj)) - - def gateway_float_w(self, w_obj): - return self.float_w(self.float(w_obj)) - - def gateway_r_longlong_w(self, w_obj): - if self.isinstance_w(w_obj, self.w_float): - raise OperationError(self.w_TypeError, - self.wrap("integer argument expected, got float")) - return self.r_longlong_w(self.int(w_obj)) + gateway_int_w = int_w + gateway_float_w = float_w + gateway_r_longlong_w = r_longlong_w + gateway_r_ulonglong_w = r_ulonglong_w def gateway_r_uint_w(self, w_obj): if self.isinstance_w(w_obj, self.w_float): @@ -1420,12 +1453,6 @@ self.wrap("integer argument expected, got float")) return self.uint_w(self.int(w_obj)) - def gateway_r_ulonglong_w(self, w_obj): - if self.isinstance_w(w_obj, self.w_float): - raise OperationError(self.w_TypeError, - self.wrap("integer argument expected, got float")) - return self.r_ulonglong_w(self.int(w_obj)) - def gateway_nonnegint_w(self, w_obj): # Like space.gateway_int_w(), but raises an app-level ValueError if # the integer is negative. Here for gateway.py. @@ -1447,7 +1474,7 @@ def c_uint_w(self, w_obj): # Like space.gateway_uint_w(), but raises an app-level OverflowError if # the integer does not fit in 32 bits. Here for gateway.py. - value = self.gateway_r_uint_w(w_obj) + value = self.uint_w(w_obj) if value > UINT_MAX_32_BITS: raise OperationError(self.w_OverflowError, self.wrap("expected an unsigned 32-bit integer")) @@ -1457,7 +1484,7 @@ # Like space.gateway_int_w(), but raises an app-level ValueError if # the integer is negative or does not fit in 32 bits. Here # for gateway.py. - value = self.gateway_int_w(w_obj) + value = self.int_w(w_obj) if value < 0: raise OperationError(self.w_ValueError, self.wrap("expected a non-negative integer")) @@ -1466,22 +1493,22 @@ self.wrap("expected a 32-bit integer")) return value - def truncatedint_w(self, w_obj): + def truncatedint_w(self, w_obj, allow_conversion=True): # Like space.gateway_int_w(), but return the integer truncated # instead of raising OverflowError. For obscure cases only. try: - return self.int_w(w_obj) + return self.int_w(w_obj, allow_conversion) except OperationError, e: if not e.match(self, self.w_OverflowError): raise from rpython.rlib.rarithmetic import intmask return intmask(self.bigint_w(w_obj).uintmask()) - def truncatedlonglong_w(self, w_obj): + def truncatedlonglong_w(self, w_obj, allow_conversion=True): # Like space.gateway_r_longlong_w(), but return the integer truncated # instead of raising OverflowError. try: - return self.r_longlong_w(w_obj) + return self.r_longlong_w(w_obj, allow_conversion) except OperationError, e: if not e.match(self, self.w_OverflowError): raise diff --git a/pypy/interpreter/main.py b/pypy/interpreter/main.py --- a/pypy/interpreter/main.py +++ b/pypy/interpreter/main.py @@ -134,7 +134,7 @@ exitcode = 0 else: try: - exitcode = space.int_w(w_exitcode) + exitcode = space.int_w(w_exitcode, allow_conversion=False) except OperationError: # not an integer: print it to stderr msg = space.str_w(space.str(w_exitcode)) 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 @@ -106,7 +106,7 @@ def len(self, x): return len(x) - def int_w(self, x): + def int_w(self, x, allow_conversion=True): return x def eq_w(self, x, y): diff --git a/pypy/interpreter/test/test_gateway.py b/pypy/interpreter/test/test_gateway.py --- a/pypy/interpreter/test/test_gateway.py +++ b/pypy/interpreter/test/test_gateway.py @@ -457,6 +457,8 @@ space.mul(space.wrap(sys.maxint), space.wrap(-7))) def test_interp2app_unwrap_spec_typechecks(self): + from rpython.rlib.rarithmetic import r_longlong + space = self.space w = space.wrap def g3_id(space, x): @@ -491,6 +493,12 @@ raises(gateway.OperationError,space.call_function,w_app_g3_f,w(None)) raises(gateway.OperationError,space.call_function,w_app_g3_f,w("foo")) + app_g3_r = gateway.interp2app_temp(g3_id, + unwrap_spec=[gateway.ObjSpace, + r_longlong]) + w_app_g3_r = space.wrap(app_g3_r) + raises(gateway.OperationError,space.call_function,w_app_g3_r,w(1.0)) + def test_interp2app_unwrap_spec_unicode(self): space = self.space w = space.wrap diff --git a/pypy/interpreter/test/test_objspace.py b/pypy/interpreter/test/test_objspace.py --- a/pypy/interpreter/test/test_objspace.py +++ b/pypy/interpreter/test/test_objspace.py @@ -167,6 +167,40 @@ self.space.setattr(w_oldstyle, self.space.wrap("__call__"), w_func) assert is_callable(w_oldstyle) + def test_int_w(self): + space = self.space + w_x = space.wrap(42) + assert space.int_w(w_x) == 42 + assert space.int_w(w_x, allow_conversion=False) == 42 + # + w_x = space.wrap(44.0) + space.raises_w(space.w_TypeError, space.int_w, w_x) + space.raises_w(space.w_TypeError, space.int_w, w_x, allow_conversion=False) + # + w_instance = self.space.appexec([], """(): + class MyInt(object): + def __int__(self): + return 43 + return MyInt() + """) + assert space.int_w(w_instance) == 43 + space.raises_w(space.w_TypeError, space.int_w, w_instance, allow_conversion=False) + # + w_instance = self.space.appexec([], """(): + class MyInt(object): + def __int__(self): + return 43 + + class AnotherInt(object): + def __int__(self): + return MyInt() + + return AnotherInt() + """) + space.raises_w(space.w_TypeError, space.int_w, w_instance) + space.raises_w(space.w_TypeError, space.int_w, w_instance, allow_conversion=False) + + def test_interp_w(self): w = self.space.wrap w_bltinfunction = self.space.builtin.get('len') diff --git a/pypy/module/__builtin__/test/test_buffer.py b/pypy/module/__builtin__/test/test_buffer.py --- a/pypy/module/__builtin__/test/test_buffer.py +++ b/pypy/module/__builtin__/test/test_buffer.py @@ -170,6 +170,19 @@ for step in indices[1:]: assert b[start:stop:step] == s[start:stop:step] + def test_getitem_only_ints(self): + class MyInt(object): + def __init__(self, x): + self.x = x + + def __int__(self): + return self.x + + buf = buffer('hello world') + raises(TypeError, "buf[MyInt(0)]") + raises(TypeError, "buf[MyInt(0):MyInt(5)]") + + class AppTestMemoryView: def test_basic(self): v = memoryview("abc") 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 @@ -131,13 +131,13 @@ if space.is_w(space.type(w_ob), space.w_int): # shortcut return space.int_w(w_ob) try: - bigint = space.bigint_w(w_ob) + bigint = space.bigint_w(w_ob, allow_conversion=False) except OperationError, e: if not e.match(space, space.w_TypeError): raise if _is_a_float(space, w_ob): raise - bigint = space.bigint_w(space.int(w_ob)) + bigint = space.bigint_w(space.int(w_ob), allow_conversion=False) try: return bigint.tolonglong() except OverflowError: @@ -148,13 +148,13 @@ if space.is_w(space.type(w_ob), space.w_int): # shortcut return space.int_w(w_ob) try: - bigint = space.bigint_w(w_ob) + bigint = space.bigint_w(w_ob, allow_conversion=False) except OperationError, e: if not e.match(space, space.w_TypeError): raise if _is_a_float(space, w_ob): raise - bigint = space.bigint_w(space.int(w_ob)) + bigint = space.bigint_w(space.int(w_ob), allow_conversion=False) try: return bigint.toint() except OverflowError: @@ -171,13 +171,13 @@ raise OperationError(space.w_OverflowError, space.wrap(neg_msg)) return r_ulonglong(value) try: - bigint = space.bigint_w(w_ob) + bigint = space.bigint_w(w_ob, allow_conversion=False) except OperationError, e: if not e.match(space, space.w_TypeError): raise if strict and _is_a_float(space, w_ob): raise - bigint = space.bigint_w(space.int(w_ob)) + bigint = space.bigint_w(space.int(w_ob), allow_conversion=False) if strict: try: return bigint.toulonglong() @@ -196,13 +196,13 @@ raise OperationError(space.w_OverflowError, space.wrap(neg_msg)) return r_uint(value) try: - bigint = space.bigint_w(w_ob) + bigint = space.bigint_w(w_ob, allow_conversion=False) except OperationError, e: if not e.match(space, space.w_TypeError): raise if strict and _is_a_float(space, w_ob): raise - bigint = space.bigint_w(space.int(w_ob)) + bigint = space.bigint_w(space.int(w_ob), allow_conversion=False) if strict: try: return bigint.touint() 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 @@ -1418,8 +1418,10 @@ p = newp(BStructPtr, [12]) assert p.a1 == 12 e = py.test.raises(TypeError, newp, BStructPtr, [None]) - assert ("an integer is required" in str(e.value) or - "unsupported operand type for int(): 'NoneType'" in str(e.value)) #PyPy + msg = str(e.value) + assert ("an integer is required" in msg or # CPython + "unsupported operand type for int(): 'NoneType'" in msg or # old PyPys + "expected integer, got NoneType object" in msg) # newer PyPys py.test.raises(TypeError, 'p.a1 = "def"') if sys.version_info < (3,): BEnum2 = new_enum_type(unicode("foo"), (unicode('abc'),), (5,), BInt) diff --git a/pypy/module/_rawffi/alt/test/test_funcptr.py b/pypy/module/_rawffi/alt/test/test_funcptr.py --- a/pypy/module/_rawffi/alt/test/test_funcptr.py +++ b/pypy/module/_rawffi/alt/test/test_funcptr.py @@ -185,6 +185,10 @@ set_val_to_ptr(ptr2, 123) assert get_dummy() == 123 set_val_to_ptr(ptr2, 0) + # + class OldStyle: + pass + raises(TypeError, "set_val_to_ptr(OldStyle(), 0)") def test_convert_strings_to_char_p(self): """ diff --git a/pypy/module/_rawffi/alt/type_converter.py b/pypy/module/_rawffi/alt/type_converter.py --- a/pypy/module/_rawffi/alt/type_converter.py +++ b/pypy/module/_rawffi/alt/type_converter.py @@ -25,7 +25,7 @@ assert libffi.IS_32_BIT self._longlong(w_ffitype, w_obj) elif w_ffitype.is_signed(): - intval = space.truncatedint_w(w_obj) + intval = space.truncatedint_w(w_obj, allow_conversion=False) self.handle_signed(w_ffitype, w_obj, intval) elif self.maybe_handle_char_or_unichar_p(w_ffitype, w_obj): # the object was already handled from within @@ -33,16 +33,16 @@ pass elif w_ffitype.is_pointer(): w_obj = self.convert_pointer_arg_maybe(w_obj, w_ffitype) - intval = space.truncatedint_w(w_obj) + intval = space.truncatedint_w(w_obj, allow_conversion=False) self.handle_pointer(w_ffitype, w_obj, intval) elif w_ffitype.is_unsigned(): - uintval = r_uint(space.truncatedint_w(w_obj)) + uintval = r_uint(space.truncatedint_w(w_obj, allow_conversion=False)) self.handle_unsigned(w_ffitype, w_obj, uintval) elif w_ffitype.is_char(): - intval = space.int_w(space.ord(w_obj)) + intval = space.int_w(space.ord(w_obj), allow_conversion=False) self.handle_char(w_ffitype, w_obj, intval) elif w_ffitype.is_unichar(): - intval = space.int_w(space.ord(w_obj)) + intval = space.int_w(space.ord(w_obj), allow_conversion=False) self.handle_unichar(w_ffitype, w_obj, intval) elif w_ffitype.is_double(): self._float(w_ffitype, w_obj) @@ -60,20 +60,20 @@ def _longlong(self, w_ffitype, w_obj): # a separate function, which can be seen by the jit or not, # depending on whether longlongs are supported - longlongval = self.space.truncatedlonglong_w(w_obj) + longlongval = self.space.truncatedlonglong_w(w_obj, allow_conversion=False) self.handle_longlong(w_ffitype, w_obj, longlongval) def _float(self, w_ffitype, w_obj): # a separate function, which can be seen by the jit or not, # depending on whether floats are supported - floatval = self.space.float_w(w_obj) + floatval = self.space.float_w(w_obj, allow_conversion=False) self.handle_float(w_ffitype, w_obj, floatval) def _singlefloat(self, w_ffitype, w_obj): # a separate function, which can be seen by the jit or not, # depending on whether singlefloats are supported from rpython.rlib.rarithmetic import r_singlefloat - floatval = self.space.float_w(w_obj) + floatval = self.space.float_w(w_obj, allow_conversion=False) singlefloatval = r_singlefloat(floatval) self.handle_singlefloat(w_ffitype, w_obj, singlefloatval) diff --git a/pypy/module/array/test/test_array.py b/pypy/module/array/test/test_array.py --- a/pypy/module/array/test/test_array.py +++ b/pypy/module/array/test/test_array.py @@ -1034,6 +1034,18 @@ assert len(b) == 13 assert str(b[12]) == "-0.0" + def test_getitem_only_ints(self): + class MyInt(object): + def __init__(self, x): + self.x = x + + def __int__(self): + return self.x + + a = self.array('i', [1, 2, 3, 4, 5, 6]) + raises(TypeError, "a[MyInt(0)]") + raises(TypeError, "a[MyInt(0):MyInt(5)]") + class AppTestArrayBuiltinShortcut(AppTestArray): spaceconfig = AppTestArray.spaceconfig.copy() diff --git a/pypy/module/cppyy/test/test_zjit.py b/pypy/module/cppyy/test/test_zjit.py --- a/pypy/module/cppyy/test/test_zjit.py +++ b/pypy/module/cppyy/test/test_zjit.py @@ -120,7 +120,7 @@ return FakeInt(int(obj)) assert 0 - def float_w(self, w_obj): + def float_w(self, w_obj, allow_conversion=True): assert isinstance(w_obj, FakeFloat) return w_obj.val @@ -141,7 +141,7 @@ def is_w(self, w_one, w_two): return w_one is w_two - def int_w(self, w_obj): + def int_w(self, w_obj, allow_conversion=True): assert isinstance(w_obj, FakeInt) return w_obj.val diff --git a/pypy/module/micronumpy/boxes.py b/pypy/module/micronumpy/boxes.py --- a/pypy/module/micronumpy/boxes.py +++ b/pypy/module/micronumpy/boxes.py @@ -375,7 +375,7 @@ pass class W_IntegerBox(W_NumberBox): - def int_w(self, space): + def _int_w(self, space): return space.int_w(self.descr_int(space)) class W_SignedIntegerBox(W_IntegerBox): diff --git a/pypy/module/micronumpy/compile.py b/pypy/module/micronumpy/compile.py --- a/pypy/module/micronumpy/compile.py +++ b/pypy/module/micronumpy/compile.py @@ -151,11 +151,11 @@ assert isinstance(w_obj, boxes.W_GenericBox) return self.float(w_obj.descr_float(self)) - def float_w(self, w_obj): + def float_w(self, w_obj, allow_conversion=True): assert isinstance(w_obj, FloatObject) return w_obj.floatval - def int_w(self, w_obj): + def int_w(self, w_obj, allow_conversion=True): if isinstance(w_obj, IntObject): return w_obj.intval elif isinstance(w_obj, FloatObject): diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py --- a/pypy/module/posix/interp_posix.py +++ b/pypy/module/posix/interp_posix.py @@ -868,8 +868,8 @@ args_w = space.fixedview(w_tuple) if len(args_w) != 2: raise OperationError(space.w_TypeError, space.wrap(msg)) - actime = space.float_w(args_w[0]) - modtime = space.float_w(args_w[1]) + actime = space.float_w(args_w[0], allow_conversion=False) + modtime = space.float_w(args_w[1], allow_conversion=False) dispatch_filename(rposix.utime, 2)(space, w_path, (actime, modtime)) except OSError, e: raise wrap_oserror2(space, e, w_path) diff --git a/pypy/module/struct/test/test_struct.py b/pypy/module/struct/test/test_struct.py --- a/pypy/module/struct/test/test_struct.py +++ b/pypy/module/struct/test/test_struct.py @@ -20,7 +20,6 @@ """) cls.w_native_is_bigendian = cls.space.wrap(native_is_bigendian) - def test_error(self): """ struct.error should be an exception class. @@ -384,6 +383,19 @@ assert self.struct.unpack("ii", b) == (62, 12) raises(self.struct.error, self.struct.unpack, "i", b) + def test___float__(self): + class MyFloat(object): + def __init__(self, x): + self.x = x + def __float__(self): + return self.x + + obj = MyFloat(42.3) + data = self.struct.pack('d', obj) + obj2, = self.struct.unpack('d', data) + assert type(obj2) is float + assert obj2 == 42.3 + class AppTestStructBuffer(object): spaceconfig = dict(usemodules=['struct', '__pypy__']) diff --git a/pypy/objspace/fake/objspace.py b/pypy/objspace/fake/objspace.py --- a/pypy/objspace/fake/objspace.py +++ b/pypy/objspace/fake/objspace.py @@ -45,13 +45,13 @@ def unicode_w(self, space): return NonConstant(u"foobar") - def int_w(self, space): + def int_w(self, space, allow_conversion=True): return NonConstant(-42) def uint_w(self, space): return r_uint(NonConstant(42)) - def bigint_w(self, space): + def bigint_w(self, space, allow_conversion=True): from rpython.rlib.rbigint import rbigint return rbigint.fromint(NonConstant(42)) @@ -117,7 +117,7 @@ def _freeze_(self): return True - def float_w(self, w_obj): + def float_w(self, w_obj, allow_conversion=True): is_root(w_obj) return NonConstant(42.5) diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py --- a/pypy/objspace/std/floatobject.py +++ b/pypy/objspace/std/floatobject.py @@ -34,7 +34,16 @@ def unwrap(self, space): return self.floatval - def float_w(self, space): + def int_w(self, space, allow_conversion=True): + self._typed_unwrap_error(space, "integer") + + def bigint_w(self, space, allow_conversion=True): + self._typed_unwrap_error(space, "integer") + + def float_w(self, space, allow_conversion=True): + return self.floatval + + def _float_w(self, space): return self.floatval def int(self, space): diff --git a/pypy/objspace/std/intobject.py b/pypy/objspace/std/intobject.py --- a/pypy/objspace/std/intobject.py +++ b/pypy/objspace/std/intobject.py @@ -42,7 +42,8 @@ return False if self.user_overridden_class or w_other.user_overridden_class: return self is w_other - return space.int_w(self) == space.int_w(w_other) + return (space.int_w(self, allow_conversion=False) == + space.int_w(w_other, allow_conversion=False)) def immutable_unique_id(self, space): if self.user_overridden_class: @@ -309,9 +310,13 @@ """representation for debugging purposes""" return "%s(%d)" % (self.__class__.__name__, self.intval) - def int_w(self, space): + def int_w(self, space, allow_conversion=True): return int(self.intval) - unwrap = int_w + + def _int_w(self, space): + return int(self.intval) + + unwrap = _int_w def uint_w(self, space): intval = self.intval @@ -320,12 +325,18 @@ "cannot convert negative integer to unsigned") return r_uint(intval) - def bigint_w(self, space): + def bigint_w(self, space, allow_conversion=True): return rbigint.fromint(self.intval) - def float_w(self, space): + def _bigint_w(self, space): + return rbigint.fromint(self.intval) + + def float_w(self, space, allow_conversion=True): return float(self.intval) + # note that we do NOT implement _float_w, because __float__ cannot return + # an int + def int(self, space): if type(self) is W_IntObject: return self @@ -665,7 +676,7 @@ # int_w is effectively what we want in this case, # we cannot construct a subclass of int instance with an # an overflowing long - value = space.int_w(w_obj) + value = space.int_w(w_obj, allow_conversion=False) elif space.isinstance_w(w_value, space.w_str): value, w_longval = _string_to_int_or_long(space, w_value, space.str_w(w_value)) diff --git a/pypy/objspace/std/longobject.py b/pypy/objspace/std/longobject.py --- a/pypy/objspace/std/longobject.py +++ b/pypy/objspace/std/longobject.py @@ -244,7 +244,7 @@ def fromrarith_int(i): return W_LongObject(rbigint.fromrarith_int(i)) - def int_w(self, space): + def _int_w(self, space): try: return self.num.toint() except OverflowError: @@ -261,10 +261,16 @@ raise oefmt(space.w_OverflowError, "long int too large to convert to unsigned int") - def bigint_w(self, space): + def bigint_w(self, space, allow_conversion=True): return self.num - def float_w(self, space): + def _bigint_w(self, space): + return self.num + + def float_w(self, space, allow_conversion=True): + return self.tofloat(space) + + def _float_w(self, space): return self.tofloat(space) def int(self, space): diff --git a/pypy/objspace/std/smalllongobject.py b/pypy/objspace/std/smalllongobject.py --- a/pypy/objspace/std/smalllongobject.py +++ b/pypy/objspace/std/smalllongobject.py @@ -44,7 +44,7 @@ def __repr__(self): return '<W_SmallLongObject(%d)>' % self.longlong - def int_w(self, space): + def _int_w(self, space): a = self.longlong b = intmask(a) if b == a: @@ -63,10 +63,13 @@ raise oefmt(space.w_OverflowError, "long int too large to convert to unsigned int") - def bigint_w(self, space): + def bigint_w(self, space, allow_conversion=True): return self.asbigint() - def float_w(self, space): + def _bigint_w(self, space): + return self.asbigint() + + def _float_w(self, space): return float(self.longlong) def int(self, space): diff --git a/pypy/objspace/std/test/test_dictmultiobject.py b/pypy/objspace/std/test/test_dictmultiobject.py --- a/pypy/objspace/std/test/test_dictmultiobject.py +++ b/pypy/objspace/std/test/test_dictmultiobject.py @@ -1046,7 +1046,7 @@ assert isinstance(string, str) return string - def int_w(self, integer): + def int_w(self, integer, allow_conversion=True): assert isinstance(integer, int) return integer diff --git a/pypy/objspace/std/test/test_intobject.py b/pypy/objspace/std/test/test_intobject.py --- a/pypy/objspace/std/test/test_intobject.py +++ b/pypy/objspace/std/test/test_intobject.py @@ -553,6 +553,15 @@ assert 3 .__coerce__(4) == (3, 4) assert 3 .__coerce__(4L) == NotImplemented + def test_fake_int_as_base(self): + class MyInt(object): + def __init__(self, x): + self.x = x + def __int__(self): + return self.x + + base = MyInt(24) + assert int('10', base) == 24 class AppTestIntShortcut(AppTestInt): spaceconfig = {"objspace.std.intshortcut": True} diff --git a/pypy/objspace/std/test/test_listobject.py b/pypy/objspace/std/test/test_listobject.py --- a/pypy/objspace/std/test/test_listobject.py +++ b/pypy/objspace/std/test/test_listobject.py @@ -842,6 +842,26 @@ except TypeError: pass + def test_mul___index__(self): + class MyInt(object): + def __init__(self, x): + self.x = x + + def __int__(self): + return self.x + + class MyIndex(object): + def __init__(self, x): + self.x = x + + def __index__(self): + return self.x + + assert [0] * MyIndex(3) == [0, 0, 0] + raises(TypeError, "[0]*MyInt(3)") + raises(TypeError, "[0]*MyIndex(MyInt(3))") + + def test_index(self): c = range(10) assert c.index(0) == 0 diff --git a/pypy/objspace/std/test/test_stringformat.py b/pypy/objspace/std/test/test_stringformat.py --- a/pypy/objspace/std/test/test_stringformat.py +++ b/pypy/objspace/std/test/test_stringformat.py @@ -186,6 +186,22 @@ def test_broken_unicode(self): raises(UnicodeDecodeError, 'Názov: %s'.__mod__, u'Jerry') + def test___int__(self): + class MyInt(object): + def __init__(self, x): + self.x = x + def __int__(self): + return self.x + # + x = MyInt(65) + assert '%c' % x == 'A' + + +class Foo(object): + def __cmp__(self, other): + return MyInt(0) + + class AppTestWidthPrec: def test_width(self): a = 'a' diff --git a/pypy/objspace/test/test_descroperation.py b/pypy/objspace/test/test_descroperation.py --- a/pypy/objspace/test/test_descroperation.py +++ b/pypy/objspace/test/test_descroperation.py @@ -721,8 +721,19 @@ return CannotConvertToBool() x = X() raises(MyError, "'foo' in x") - - + + def test___cmp___fake_int(self): + class MyInt(object): + def __init__(self, x): + self.x = x + def __int__(self): + return self.x + class X(object): + def __cmp__(self, other): + return MyInt(0) + + assert X() == 'hello' + class AppTestWithBuiltinShortcut(AppTest_Descroperation): spaceconfig = {'objspace.std.builtinshortcut': True} _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit