Author: Armin Rigo <ar...@tunes.org>
Branch: py3.6
Changeset: r97268:08f03166561f
Date: 2019-08-26 17:06 +0200
http://bitbucket.org/pypy/pypy/changeset/08f03166561f/

Log:    merge heads

diff --git a/lib-python/3/test/list_tests.py b/lib-python/3/test/list_tests.py
--- a/lib-python/3/test/list_tests.py
+++ b/lib-python/3/test/list_tests.py
@@ -546,7 +546,7 @@
         u += "eggs"
         self.assertEqual(u, self.type2test("spameggs"))
 
-        self.assertRaises(TypeError, u.__iadd__, None)
+        self.assertRaises(TypeError, "u += None")  # PyPy change
 
     def test_imul(self):
         u = self.type2test([0, 1])
diff --git a/lib-python/3/test/test_asyncio/test_futures.py 
b/lib-python/3/test/test_asyncio/test_futures.py
--- a/lib-python/3/test/test_asyncio/test_futures.py
+++ b/lib-python/3/test/test_asyncio/test_futures.py
@@ -534,7 +534,7 @@
 @unittest.skipUnless(hasattr(futures, '_CFuture'),
                      'requires the C _asyncio module')
 class CFutureTests(BaseFutureTests, test_utils.TestCase):
-    cls = getattr(futures, '_CFuture')
+    cls = getattr(futures, '_CFuture', None)
 
 
 class PyFutureTests(BaseFutureTests, test_utils.TestCase):
diff --git a/lib_pypy/_ctypes/array.py b/lib_pypy/_ctypes/array.py
--- a/lib_pypy/_ctypes/array.py
+++ b/lib_pypy/_ctypes/array.py
@@ -108,27 +108,29 @@
         # array accepts very strange parameters as part of structure
         # or function argument...
         from ctypes import c_char, c_wchar
-        if issubclass(self._type_, c_char):
-            if isinstance(value, bytes):
-                if len(value) > self._length_:
-                    raise ValueError("Invalid length")
-                value = self(*value)
-            elif not isinstance(value, self):
-                raise TypeError("expected bytes, %s found"
-                                % (value.__class__.__name__,))
-        elif issubclass(self._type_, c_wchar):
-            if isinstance(value, str):
-                if len(value) > self._length_:
-                    raise ValueError("Invalid length")
-                value = self(*value)
-            elif not isinstance(value, self):
-                raise TypeError("expected unicode string, %s found"
-                                % (value.__class__.__name__,))
-        else:
-            if isinstance(value, tuple):
-                if len(value) > self._length_:
-                    raise RuntimeError("Invalid length")
-                value = self(*value)
+        if isinstance(value, self):
+            return value
+        if hasattr(self, '_type_'):
+            if issubclass(self._type_, c_char):
+                if isinstance(value, bytes):
+                    if len(value) > self._length_:
+                        raise ValueError("Invalid length")
+                    value = self(*value)
+                elif not isinstance(value, self):
+                    raise TypeError("expected bytes, %s found"
+                                    % (value.__class__.__name__,))
+            elif issubclass(self._type_, c_wchar):
+                if isinstance(value, str):
+                    if len(value) > self._length_:
+                        raise ValueError("Invalid length")
+                    value = self(*value)
+                elif not isinstance(value, self):
+                    raise TypeError("expected unicode string, %s found"
+                                    % (value.__class__.__name__,))
+        if isinstance(value, tuple):
+            if len(value) > self._length_:
+                raise RuntimeError("Invalid length")
+            value = self(*value)
         return _CDataMeta.from_param(self, value)
 
     def _build_ffiargtype(self):
diff --git a/lib_pypy/_ctypes/basics.py b/lib_pypy/_ctypes/basics.py
--- a/lib_pypy/_ctypes/basics.py
+++ b/lib_pypy/_ctypes/basics.py
@@ -45,6 +45,9 @@
         self.details = details
 
 class _CDataMeta(type):
+    def _is_abstract(self):
+        return getattr(self, '_type_', 'abstract') == 'abstract'
+
     def from_param(self, value):
         if isinstance(value, self):
             return value
@@ -95,6 +98,8 @@
         return self.from_address(dll.__pypy_dll__.getaddressindll(name))
 
     def from_buffer(self, obj, offset=0):
+        if self._is_abstract():
+            raise TypeError('abstract class')
         size = self._sizeofinstances()
         buf = memoryview(obj)
         if buf.nbytes < offset + size:
@@ -111,6 +116,8 @@
         return result
 
     def from_buffer_copy(self, obj, offset=0):
+        if self._is_abstract():
+            raise TypeError('abstract class')
         size = self._sizeofinstances()
         buf = memoryview(obj)
         if buf.nbytes < offset + size:
diff --git a/lib_pypy/_ctypes/pointer.py b/lib_pypy/_ctypes/pointer.py
--- a/lib_pypy/_ctypes/pointer.py
+++ b/lib_pypy/_ctypes/pointer.py
@@ -40,14 +40,17 @@
     def from_param(self, value):
         if value is None:
             return self(None)
-        # If we expect POINTER(<type>), but receive a <type> instance, accept
-        # it by calling byref(<type>).
-        if isinstance(value, self._type_):
-            return byref(value)
-        # Array instances are also pointers when the item types are the same.
-        if isinstance(value, (_Pointer, Array)):
-            if issubclass(type(value)._type_, self._type_):
-                return value
+        if isinstance(value, self):
+            return value
+        if hasattr(self, '_type_'):
+            # If we expect POINTER(<type>), but receive a <type> instance, 
accept
+            # it by calling byref(<type>).
+            if isinstance(value, self._type_):
+                return byref(value)
+            # Array instances are also pointers when the item types are the 
same.
+            if isinstance(value, (_Pointer, Array)):
+                if issubclass(type(value)._type_, self._type_):
+                    return value
         return _CDataMeta.from_param(self, value)
 
     def _sizeofinstances(self):
@@ -60,6 +63,8 @@
         return True
 
     def set_type(self, TP):
+        if self._is_abstract():
+            raise TypeError('abstract class')
         ffiarray = _rawffi.Array('P')
         def __init__(self, value=None):
             if not hasattr(self, '_buffer'):
@@ -179,6 +184,7 @@
         klass = type(_Pointer)("LP_%s" % cls,
                                (_Pointer,),
                                {})
+        klass._type_ = 'P'
         _pointer_type_cache[id(klass)] = klass
         return klass
     else:
diff --git a/lib_pypy/_ctypes/primitive.py b/lib_pypy/_ctypes/primitive.py
--- a/lib_pypy/_ctypes/primitive.py
+++ b/lib_pypy/_ctypes/primitive.py
@@ -158,6 +158,8 @@
                     break
             else:
                 raise AttributeError("cannot find _type_ attribute")
+        if tp == 'abstract':
+            tp = 'i'
         if (not isinstance(tp, str) or
             not len(tp) == 1 or
             tp not in SIMPLE_TYPE_CHARS):
@@ -341,7 +343,8 @@
     def from_param(self, value):
         if isinstance(value, self):
             return value
-
+        if self._type_ == 'abstract':
+            raise TypeError('abstract class')
         from_param_f = FROM_PARAM_BY_TYPE.get(self._type_)
         if from_param_f:
             res = from_param_f(self, value)
@@ -371,7 +374,7 @@
         return self._type_ in "sPzUZXO"
 
 class _SimpleCData(_CData, metaclass=SimpleType):
-    _type_ = 'i'
+    _type_ = 'abstract'
 
     def __init__(self, value=DEFAULT_VALUE):
         if not hasattr(self, '_buffer'):
diff --git a/lib_pypy/_ctypes/structure.py b/lib_pypy/_ctypes/structure.py
--- a/lib_pypy/_ctypes/structure.py
+++ b/lib_pypy/_ctypes/structure.py
@@ -119,6 +119,8 @@
         if self.is_bitfield:
             # bitfield member, use direct access
             return obj._buffer.__getattr__(self.name)
+        elif not isinstance(obj, _CData):
+            raise(TypeError, 'not a ctype instance') 
         else:
             fieldtype = self.ctype
             offset = self.num
@@ -142,6 +144,8 @@
             from ctypes import memmove
             dest = obj._buffer.fieldaddress(self.name)
             memmove(dest, arg, fieldtype._fficompositesize_)
+        elif not isinstance(obj, _CData):
+            raise(TypeError, 'not a ctype instance') 
         else:
             obj._buffer.__setattr__(self.name, arg)
 
@@ -209,6 +213,9 @@
 
     __setattr__ = struct_setattr
 
+    def _is_abstract(self):
+        return False
+
     def from_address(self, address):
         instance = StructOrUnion.__new__(self)
         if isinstance(address, _rawffi.StructureInstance):
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -296,15 +296,17 @@
                     "expected %s, got %T object", expected, self)
 
     def int(self, space):
-        from pypy.objspace.std.intobject import _new_int
+        from pypy.objspace.std.intobject import W_AbstractIntObject
         w_impl = space.lookup(self, '__int__')
         if w_impl is None:
             self._typed_unwrap_error(space, "integer")
         w_result = space.get_and_call_function(w_impl, self)
 
         if space.is_w(space.type(w_result), space.w_int):
+            assert isinstance(w_result, W_AbstractIntObject)
             return w_result
         if space.isinstance_w(w_result, space.w_int):
+            assert isinstance(w_result, W_AbstractIntObject)
             tp = space.type(w_result).name
             space.warn(space.newtext(
                 "__int__ returned non-int (type %s).  "
@@ -816,7 +818,7 @@
             return self.w_None
         return w_obj
 
-    @signature(types.any(), types.bool(), returns=types.instance(W_Root))
+    @signature(types.any(), types.bool(), returns=types.any())
     def newbool(self, b):
         if b:
             return self.w_True
diff --git a/pypy/module/_codecs/interp_codecs.py 
b/pypy/module/_codecs/interp_codecs.py
--- a/pypy/module/_codecs/interp_codecs.py
+++ b/pypy/module/_codecs/interp_codecs.py
@@ -618,10 +618,10 @@
 # ____________________________________________________________
 # Helpers for unicode.encode() and bytes.decode()
 def lookup_text_codec(space, action, encoding):
-    codec_info = lookup_codec(space, encoding)
+    w_codec_info = lookup_codec(space, encoding)
     try:
         is_text_encoding = space.is_true(
-                space.getattr(codec_info, space.newtext('_is_text_encoding')))
+                space.getattr(w_codec_info, 
space.newtext('_is_text_encoding')))
     except OperationError as e:
         if e.match(space, space.w_AttributeError):
             is_text_encoding = True
@@ -630,8 +630,8 @@
     if not is_text_encoding:
         raise oefmt(space.w_LookupError,
                     "'%s' is not a text encoding; "
-                    "use %s to handle arbitrary codecs", encoding, action)
-    return codec_info
+                    "use codecs.%s() to handle arbitrary codecs", encoding, 
action)
+    return w_codec_info
 
 # ____________________________________________________________
 
diff --git a/pypy/module/_io/interp_bufferedio.py 
b/pypy/module/_io/interp_bufferedio.py
--- a/pypy/module/_io/interp_bufferedio.py
+++ b/pypy/module/_io/interp_bufferedio.py
@@ -319,7 +319,6 @@
         with self.lock:
             if self.writable:
                 self._writer_flush_unlocked(space)
-                self._writer_reset_buf()
 
             if whence == 1:
                 pos -= self._raw_offset()
@@ -371,6 +370,7 @@
 
     def _writer_flush_unlocked(self, space):
         if self.write_end == -1 or self.write_pos == self.write_end:
+            self._writer_reset_buf()
             return
         # First, rewind
         rewind = self._raw_offset() + (self.pos - self.write_pos)
diff --git a/pypy/module/_io/interp_iobase.py b/pypy/module/_io/interp_iobase.py
--- a/pypy/module/_io/interp_iobase.py
+++ b/pypy/module/_io/interp_iobase.py
@@ -266,24 +266,16 @@
 
     def readlines_w(self, space, w_hint=None):
         hint = convert_size(space, w_hint)
-
         if hint <= 0:
             return space.newlist(space.unpackiterable(self))
 
+        length = 0
         lines_w = []
-        length = 0
-        while True:
-            w_line = space.call_method(self, "readline")
-            line_length = space.len_w(w_line)
-            if line_length == 0: # done
-                break
-
+        for w_line in space.iteriterable(self):
             lines_w.append(w_line)
-
-            length += line_length
+            length += space.len_w(w_line)
             if length > hint:
                 break
-
         return space.newlist(lines_w)
 
     def writelines_w(self, space, w_lines):
diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py
--- a/pypy/module/_io/interp_textio.py
+++ b/pypy/module/_io/interp_textio.py
@@ -663,12 +663,15 @@
             # To prepare for tell(), we need to snapshot a point in the file
             # where the decoder's input buffer is empty.
             w_state = space.call_method(self.w_decoder, "getstate")
+            if (not space.isinstance_w(w_state, space.w_tuple)
+                    or space.len_w(w_state) != 2):
+                raise oefmt(space.w_TypeError, "illegal decoder state")
             # Given this, we know there was a valid snapshot point
             # len(dec_buffer) bytes ago with decoder state (b'', dec_flags).
             w_dec_buffer, w_dec_flags = space.unpackiterable(w_state, 2)
             if not space.isinstance_w(w_dec_buffer, space.w_bytes):
-                msg = "decoder getstate() should have returned a bytes " \
-                      "object not '%T'"
+                msg = ("illegal decoder state: the first value should be a "
+                    "bytes object not '%T'")
                 raise oefmt(space.w_TypeError, msg, w_dec_buffer)
             dec_buffer = space.bytes_w(w_dec_buffer)
             dec_flags = space.int_w(w_dec_flags)
diff --git a/pypy/module/_io/test/test_bufferedio.py 
b/pypy/module/_io/test/test_bufferedio.py
--- a/pypy/module/_io/test/test_bufferedio.py
+++ b/pypy/module/_io/test/test_bufferedio.py
@@ -513,6 +513,17 @@
         assert b.truncate() == 8
         assert b.tell() == 8
 
+    def test_truncate_after_write(self):
+        import _io
+        raw = _io.FileIO(self.tmpfile, 'rb+')
+        raw.write(b'\x00' * 50)
+        raw.seek(0)
+        b = _io.BufferedRandom(raw, 10)
+        b.write(b'\x00' * 11)
+        b.read(1)
+        b.truncate()
+        assert b.tell() == 12
+
     def test_write_non_blocking(self):
         import _io, io
         class MockNonBlockWriterIO(io.RawIOBase):
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
@@ -87,10 +87,12 @@
         self.register_finalizer(space)
 
     @unwrap_spec(sizehint=int, flags=int)
-    def descr__new__(space, w_subtype, sizehint=0, flags=0):
-        if sizehint < 0:     # 'sizehint' is otherwise ignored
+    def descr__new__(space, w_subtype, sizehint=-1, flags=0):
+        if sizehint == -1:
+            sizehint = FD_SETSIZE - 1
+        elif sizehint <= 0:     # 'sizehint' is otherwise ignored
             raise oefmt(space.w_ValueError,
-                        "sizehint must be greater than zero, got %d", sizehint)
+                        "sizehint must be positive or -1")
         epfd = epoll_create1(flags | EPOLL_CLOEXEC)
         if epfd < 0:
             raise exception_from_saved_errno(space, space.w_IOError)
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
@@ -9,7 +9,7 @@
 import sys
 
 from rpython.rlib import jit
-from rpython.rlib.objectmodel import instantiate
+from rpython.rlib.objectmodel import instantiate, enforceargs
 from rpython.rlib.rarithmetic import (
     LONG_BIT, intmask, is_valid_int, ovfcheck, r_longlong, r_uint,
     string_to_int)
@@ -851,80 +851,49 @@
             sys.maxint == 2147483647)
 
 
-def _string_to_int_or_long(space, w_inttype, w_source, string, base=10):
+def _string_to_int_or_long(space, w_source, string, base=10):
     try:
-        value = string_to_int(string, base, allow_underscores=True, 
no_implicit_octal=True)
+        value = string_to_int(
+            string, base, allow_underscores=True, no_implicit_octal=True)
+        return wrapint(space, value)
     except ParseStringError as e:
         raise wrap_parsestringerror(space, e, w_source)
     except ParseStringOverflowError as e:
-        return _retry_to_w_long(space, e.parser, w_inttype, w_source)
+        return _retry_to_w_long(space, e.parser, w_source)
 
-    if space.is_w(w_inttype, space.w_int):
-        w_result = wrapint(space, value)
-    else:
-        w_result = space.allocate_instance(W_IntObject, w_inttype)
-        W_IntObject.__init__(w_result, value)
-    return w_result
 
-
-def _retry_to_w_long(space, parser, w_inttype, w_source):
+def _retry_to_w_long(space, parser, w_source):
     from pypy.objspace.std.longobject import newbigint
     parser.rewind()
     try:
         bigint = rbigint._from_numberstring_parser(parser)
     except ParseStringError as e:
         raise wrap_parsestringerror(space, e, w_source)
-    return newbigint(space, w_inttype, bigint)
+    return newbigint(space, space.w_int, bigint)
 
 
 def _new_int(space, w_inttype, w_x, w_base=None):
-    from pypy.objspace.std.longobject import (
-        W_AbstractLongObject, W_LongObject, newlong, newbigint)
-    if space.config.objspace.std.withsmalllong:
-        from pypy.objspace.std.smalllongobject import W_SmallLongObject
+    w_value = w_x     # 'x' is the keyword argument name in CPython
+    if w_inttype is space.w_int:
+        return _new_baseint(space, w_x, w_base)
     else:
-        W_SmallLongObject = None
+        w_tmp = _new_baseint(space, w_x, w_base)
+        return _as_subint(space, w_inttype, w_tmp)
 
-    w_longval = None
-    w_value = w_x     # 'x' is the keyword argument name in CPython
-    value = 0
+def _new_baseint(space, w_value, w_base=None):
     if w_base is None:
-        #import pdb; pdb.set_trace()
-        # check for easy cases
-        if type(w_value) is W_IntObject:
-            if space.is_w(w_inttype, space.w_int):
-                return w_value
-            value = w_value.intval
-            w_obj = space.allocate_instance(W_IntObject, w_inttype)
-            W_IntObject.__init__(w_obj, value)
-            return w_obj
-        elif type(w_value) is W_LongObject:
-            if space.is_w(w_inttype, space.w_int):
-                return w_value
-            return newbigint(space, w_inttype, w_value.num)
-        elif W_SmallLongObject and type(w_value) is W_SmallLongObject:
-            if space.is_w(w_inttype, space.w_int):
-                return w_value
-            return newbigint(space, w_inttype, space.bigint_w(w_value))
+        if space.is_w(space.type(w_value), space.w_int):
+            assert isinstance(w_value, W_AbstractIntObject)
+            return w_value
         elif space.lookup(w_value, '__int__') is not None:
             w_intvalue = space.int(w_value)
-            if isinstance(w_intvalue, W_IntObject):
-                if type(w_intvalue) is not W_IntObject:
-                    w_intvalue = wrapint(space, w_intvalue.intval)
-                return _new_int(space, w_inttype, w_intvalue)
-            elif isinstance(w_intvalue, W_AbstractLongObject):
-                if type(w_intvalue) is not W_LongObject:
-                    w_intvalue = newlong(space, w_intvalue.asbigint())
-                return _new_int(space, w_inttype, w_intvalue)
-            else:
-                # shouldn't happen
-                raise oefmt(space.w_RuntimeError,
-                    "internal error in int.__new__()")
+            return _ensure_baseint(space, w_intvalue)
         elif space.lookup(w_value, '__trunc__') is not None:
             w_obj = space.trunc(w_value)
-            if not space.is_w(space.type(w_obj), space.w_int):
+            if not space.isinstance_w(w_obj, space.w_int):
                 w_obj = space.int(w_obj)
-            return _from_intlike(space, w_inttype, w_obj)
+            assert isinstance(w_obj, W_AbstractIntObject)
+            return _ensure_baseint(space, w_obj)
         elif space.isinstance_w(w_value, space.w_unicode):
             from pypy.objspace.std.unicodeobject import unicode_to_decimal_w
             try:
@@ -933,10 +902,10 @@
                 raise oefmt(space.w_ValueError,
                             'invalid literal for int() with base 10: %R',
                             w_value)
-            return _string_to_int_or_long(space, w_inttype, w_value, b)
+            return _string_to_int_or_long(space, w_value, b)
         elif (space.isinstance_w(w_value, space.w_bytearray) or
               space.isinstance_w(w_value, space.w_bytes)):
-            return _string_to_int_or_long(space, w_inttype, w_value,
+            return _string_to_int_or_long(space, w_value,
                                           space.charbuf_w(w_value))
         else:
             # If object supports the buffer interface
@@ -949,7 +918,7 @@
                             "int() argument must be a string, a bytes-like "
                             "object or a number, not '%T'", w_value)
             else:
-                return _string_to_int_or_long(space, w_inttype, w_value, buf)
+                return _string_to_int_or_long(space, w_value, buf)
     else:
         try:
             base = space.getindex_w(w_base, None)
@@ -973,14 +942,40 @@
             raise oefmt(space.w_TypeError,
                         "int() can't convert non-string with explicit base")
 
-        return _string_to_int_or_long(space, w_inttype, w_value, s, base)
+        return _string_to_int_or_long(space, w_value, s, base)
 
+@enforceargs(None, None, W_AbstractIntObject, typecheck=False)
+def _as_subint(space, w_inttype, w_value):
+    from pypy.objspace.std.longobject import W_LongObject, newbigint
+    if space.config.objspace.std.withsmalllong:
+        from pypy.objspace.std.smalllongobject import W_SmallLongObject
+    else:
+        W_SmallLongObject = None
+    if type(w_value) is W_IntObject:
+        w_obj = space.allocate_instance(W_IntObject, w_inttype)
+        W_IntObject.__init__(w_obj, w_value.intval)
+        return w_obj
+    elif type(w_value) is W_LongObject:
+        return newbigint(space, w_inttype, w_value.num)
+    elif W_SmallLongObject and type(w_value) is W_SmallLongObject:
+        return newbigint(space, w_inttype, space.bigint_w(w_value))
 
-def _from_intlike(space, w_inttype, w_intlike):
-    if space.is_w(w_inttype, space.w_int):
-        return w_intlike
-    from pypy.objspace.std.longobject import newbigint
-    return newbigint(space, w_inttype, space.bigint_w(w_intlike))
+@enforceargs(None, W_AbstractIntObject, typecheck=False)
+def _ensure_baseint(space, w_intvalue):
+    from pypy.objspace.std.longobject import (
+        W_LongObject, W_AbstractLongObject, newlong)
+    if isinstance(w_intvalue, W_IntObject):
+        if type(w_intvalue) is not W_IntObject:
+            w_intvalue = wrapint(space, w_intvalue.intval)
+        return w_intvalue
+    elif isinstance(w_intvalue, W_AbstractLongObject):
+        if type(w_intvalue) is not W_LongObject:
+            w_intvalue = newlong(space, w_intvalue.asbigint())
+        return w_intvalue
+    else:
+        # shouldn't happen
+        raise oefmt(space.w_RuntimeError,
+            "internal error in int.__new__()")
 
 
 W_AbstractIntObject.typedef = TypeDef("int",
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
@@ -533,6 +533,19 @@
             assert n == 1
             assert type(n) is int
 
+    def test_trunc_returns_int_subclass_2(self):
+        class BadInt:
+            def __int__(self):
+                return True
+
+        class TruncReturnsBadInt:
+            def __trunc__(self):
+                return BadInt()
+        bad_int = TruncReturnsBadInt()
+        n = int(bad_int)
+        assert n == 1
+        assert type(n) is int
+
     def test_int_before_string(self):
         class Integral(str):
             def __int__(self):
diff --git a/pypy/objspace/std/test/test_typeobject.py 
b/pypy/objspace/std/test/test_typeobject.py
--- a/pypy/objspace/std/test/test_typeobject.py
+++ b/pypy/objspace/std/test/test_typeobject.py
@@ -71,6 +71,22 @@
         raises(AttributeError, getattr, type, "__abstractmethods__")
         raises(TypeError, "int.__abstractmethods__ = ('abc', )")
 
+    def test_is_abstract_flag(self):
+        # IS_ABSTRACT flag should always be in sync with
+        # cls.__dict__['__abstractmethods__']
+        FLAG_IS_ABSTRACT = 1 << 20
+
+        class Base:
+            pass
+        Base.__abstractmethods__ = {'x'}
+        assert Base.__flags__ & FLAG_IS_ABSTRACT
+
+        class Derived(Base):
+            pass
+        assert not (Derived.__flags__ & FLAG_IS_ABSTRACT)
+        Derived.__abstractmethods__ = {'x'}
+        assert Derived.__flags__ & FLAG_IS_ABSTRACT
+
     def test_attribute_error(self):
         class X(object):
             __module__ = 'test'
diff --git a/pypy/objspace/std/test/test_unicodeobject.py 
b/pypy/objspace/std/test/test_unicodeobject.py
--- a/pypy/objspace/std/test/test_unicodeobject.py
+++ b/pypy/objspace/std/test/test_unicodeobject.py
@@ -780,6 +780,11 @@
         raises(UnicodeError, b"\xc2".decode, "utf-8")
         assert b'\xe1\x80'.decode('utf-8', 'replace') == "\ufffd"
 
+    def test_invalid_lookup(self):
+
+        raises(LookupError, u"abcd".encode, "hex")
+        raises(LookupError, b"abcd".decode, "hex")
+
     def test_repr_printable(self):
         # PEP 3138: __repr__ respects printable characters.
         x = '\u027d'
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -816,7 +816,7 @@
             return space.call_function(newfunc, w_winner, w_name, w_bases, 
w_dict)
         w_typetype = w_winner
 
-    name = space.text_w(w_name) 
+    name = space.text_w(w_name)
     if '\x00' in name:
         raise oefmt(space.w_ValueError, "type name must not contain null 
characters")
     pos = surrogate_in_utf8(name)
@@ -1339,7 +1339,6 @@
         if not isinstance(w_base, W_TypeObject):
             continue
         w_self.flag_cpytype |= w_base.flag_cpytype
-        w_self.flag_abstract |= w_base.flag_abstract
         if w_self.flag_map_or_seq == '?':
             w_self.flag_map_or_seq = w_base.flag_map_or_seq
 
diff --git a/pypy/objspace/std/unicodeobject.py 
b/pypy/objspace/std/unicodeobject.py
--- a/pypy/objspace/std/unicodeobject.py
+++ b/pypy/objspace/std/unicodeobject.py
@@ -1241,7 +1241,7 @@
     return encoding, errors
 
 def encode_object(space, w_obj, encoding, errors):
-    from pypy.module._codecs.interp_codecs import encode
+    from pypy.module._codecs.interp_codecs import _call_codec, 
lookup_text_codec
     if errors is None or errors == 'strict':
         # fast paths
         utf8 = space.utf8_w(w_obj)
@@ -1263,7 +1263,11 @@
                     a.pos, a.pos + 1)
                 assert False, "always raises"
             return space.newbytes(utf8)
-    w_retval = encode(space, w_obj, encoding, errors)
+    if encoding is None:
+        encoding = space.sys.defaultencoding
+    w_codec_info = lookup_text_codec(space, 'encode', encoding)
+    w_encfunc = space.getitem(w_codec_info, space.newint(0))
+    w_retval = _call_codec(space, w_encfunc, w_obj, "encoding", encoding, 
errors)
     if not space.isinstance_w(w_retval, space.w_bytes):
         raise oefmt(space.w_TypeError,
                     "'%s' encoder returned '%T' instead of 'bytes'; "
@@ -1274,6 +1278,7 @@
 
 
 def decode_object(space, w_obj, encoding, errors=None):
+    from pypy.module._codecs.interp_codecs import _call_codec, 
lookup_text_codec
     if errors == 'strict' or errors is None:
         # fast paths
         if encoding == 'ascii':
@@ -1284,8 +1289,11 @@
             s = space.charbuf_w(w_obj)
             lgt = unicodehelper.check_utf8_or_raise(space, s)
             return space.newutf8(s, lgt)
-    from pypy.module._codecs.interp_codecs import decode
-    w_retval = decode(space, w_obj, encoding, errors)
+    if encoding is None:
+        encoding = space.sys.defaultencoding
+    w_codec_info = lookup_text_codec(space, 'decode', encoding)
+    w_encfunc = space.getitem(w_codec_info, space.newint(1))
+    w_retval = _call_codec(space, w_encfunc, w_obj, "decoding", encoding, 
errors)
     if not isinstance(w_retval, W_UnicodeObject):
         raise oefmt(space.w_TypeError,
                     "'%s' decoder returned '%T' instead of 'str'; "
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to