Commits

Brian Kearns  committed a5313cb

intobject try int/trunc methods before str/unicode/buffer

  • Participants
  • Parent commits caa5f3b

Comments (0)

Files changed (2)

File pypy/objspace/std/inttype.py

         if type(w_value) is W_IntObject:
             value = w_value.intval
             ok = True
+        elif space.lookup(w_value, '__int__') is not None or \
+                space.lookup(w_value, '__trunc__') is not None:
+            # otherwise, use the __int__() or the __trunc__() methods
+            w_obj = w_value
+            if space.lookup(w_obj, '__int__') is None:
+                w_obj = space.trunc(w_obj)
+            w_obj = space.int(w_obj)
+            # 'int(x)' should return what x.__int__() returned, which should
+            # be an int or long or a subclass thereof.
+            if space.is_w(w_inttype, space.w_int):
+                return w_obj
+            # int_w is effectively what we want in this case,
+            # we cannot construct a subclass of int instance with an
+            # an overflowing long
+            try:
+                value = space.int_w(w_obj)
+            except OperationError, e:
+                if not e.match(space, space.w_TypeError):
+                    raise
+            else:
+                ok = True
         elif space.isinstance_w(w_value, space.w_str):
             value, w_longval = string_to_int_or_long(space, space.str_w(w_value))
             ok = True
                 ok = True
 
         if not ok:
-            # otherwise, use the __int__() or the __trunc__() methods
-            w_obj = w_value
-            if space.lookup(w_obj, '__int__') is None:
-                if space.lookup(w_obj, '__trunc__') is not None:
-                    w_obj = space.trunc(w_obj)
-                else:
-                    raise operationerrfmt(space.w_TypeError,
-                        "int() argument must be a string or a number, not '%T'",
-                        w_obj)
-            w_obj = space.int(w_obj)
-            # 'int(x)' should return what x.__int__() returned, which should
-            # be an int or long or a subclass thereof.
-            if space.is_w(w_inttype, space.w_int):
-                return w_obj
-            # int_w is effectively what we want in this case,
-            # we cannot construct a subclass of int instance with an
-            # an overflowing long
-            try:
-                value = space.int_w(w_obj)
-            except OperationError, e:
-                if e.match(space, space.w_TypeError):
-                    raise OperationError(space.w_ValueError,
-                        space.wrap("value can't be converted to int"))
-                raise e
+            raise operationerrfmt(space.w_TypeError,
+                "int() argument must be a string or a number, not '%T'",
+                w_value)
     else:
         base = space.int_w(w_base)
 

File pypy/objspace/std/test/test_intobject.py

                 return Integral()
         assert int(TruncReturnsNonInt()) == 42
 
+    def test_int_before_string(self):
+        class Integral(str):
+            def __int__(self):
+                return 42
+        assert int(Integral('abc')) == 42
+
     def test_getnewargs(self):
         assert  0 .__getnewargs__() == (0,)
 
         # __eq__ & the others.
         assert 1 .__cmp__
         assert int .__cmp__
-    
+
     def test_bit_length(self):
         for val, bits in [
             (0, 0),