[pypy-commit] pypy int_w-refactor: first step: change the meaning of space.int_w: now by default it also accepts objects which implements __int__, except floats. You can trigger the old behavior by passing allow_conversion=False
antocuni
noreply at buildbot.pypy.org
Tue Feb 25 18:06:00 CET 2014
Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: int_w-refactor
Changeset: r69429:7e1beef017c9
Date: 2014-02-25 10:49 +0100
http://bitbucket.org/pypy/pypy/changeset/7e1beef017c9/
Log: first step: change the meaning of space.int_w: now by default it
also accepts objects which implements __int__, except floats. You
can trigger the old behavior by passing allow_conversion=False
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -201,7 +201,15 @@
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_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):
@@ -220,8 +228,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
@@ -1348,8 +1355,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)
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_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/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
@@ -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/compile.py b/pypy/module/micronumpy/compile.py
--- a/pypy/module/micronumpy/compile.py
+++ b/pypy/module/micronumpy/compile.py
@@ -157,6 +157,7 @@
return w_obj.floatval
def int_w(self, w_obj):
+ XXX # fix this
if isinstance(w_obj, IntObject):
return w_obj.intval
elif isinstance(w_obj, FloatObject):
diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py
--- a/pypy/module/micronumpy/interp_boxes.py
+++ b/pypy/module/micronumpy/interp_boxes.py
@@ -366,6 +366,7 @@
class W_IntegerBox(W_NumberBox):
def int_w(self, space):
+ XXX # fix this
return space.int_w(self.descr_int(space))
class W_SignedIntegerBox(W_IntegerBox):
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,7 +45,7 @@
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):
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,6 +34,9 @@
def unwrap(self, space):
return self.floatval
+ def int_w(self, space, allow_conversion=True):
+ self._typed_unwrap_error(space, "integer")
+
def float_w(self, space):
return self.floatval
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
@@ -309,9 +309,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
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:
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:
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
More information about the pypy-commit
mailing list