Author: Ronan Lamy <[email protected]>
Branch: py3.5
Changeset: r88975:877aef4785e1
Date: 2016-12-08 15:01 +0000
http://bitbucket.org/pypy/pypy/changeset/877aef4785e1/

Log:    CPython issue #25766: .__bytes__() now works in str subclasses

diff --git a/pypy/objspace/std/bytesobject.py b/pypy/objspace/std/bytesobject.py
--- a/pypy/objspace/std/bytesobject.py
+++ b/pypy/objspace/std/bytesobject.py
@@ -700,28 +700,34 @@
     return chr(value)
 
 def newbytesdata_w(space, w_source, encoding, errors):
+    # None value
+    if w_source is None:
+        if encoding is not None or errors is not None:
+            raise oefmt(space.w_TypeError,
+                "encoding or errors without sequence argument")
+        else:
+            return b""
     # Unicode with encoding
-    if w_source is not None and space.isinstance_w(w_source, space.w_unicode):
-        if encoding is None:
+    if encoding is not None:
+        if not space.isinstance_w(w_source, space.w_unicode):
             raise oefmt(space.w_TypeError,
-                        "string argument without an encoding")
+                "encoding without string argument (got '%T' instead)",
+                w_source)
         from pypy.objspace.std.unicodeobject import encode_object
         w_source = encode_object(space, w_source, encoding, errors)
         # and continue with the encoded string
-    elif encoding is not None or errors is not None:
-        if w_source is None:
+    elif errors is not None:
+        if not space.isinstance_w(w_source, space.w_unicode):
             raise oefmt(space.w_TypeError,
-                        "encoding or errors without string argument")
-        raise oefmt(space.w_TypeError,
-               "encoding or errors without string argument (got '%T' instead)",
-               w_source)
-    # None value
-    if w_source is None:
-        return b""
+                "errors without string argument (got '%T' instead)",
+                w_source)
+        else:
+            raise oefmt(space.w_TypeError,
+                "string argument without an encoding")
     # Fast-path for bytes
     if space.isinstance_w(w_source, space.w_str):
         return space.bytes_w(w_source)
-    # Some other object with a __bytes__ special method
+    # Some other object with a __bytes__ special method (could be str subclass)
     w_bytes_method = space.lookup(w_source, "__bytes__")
     if w_bytes_method is not None:
         w_bytes = space.get_and_call_function(w_bytes_method, w_source)
@@ -729,6 +735,9 @@
             raise oefmt(space.w_TypeError,
                         "__bytes__ returned non-bytes (type '%T')", w_bytes)
         return space.bytes_w(w_bytes)
+    if space.isinstance_w(w_source, space.w_unicode):
+        raise oefmt(space.w_TypeError, "string argument without an encoding")
+
     # Is it an integer?
     # Note that we're calling space.getindex_w() instead of space.int_w().
     try:
diff --git a/pypy/objspace/std/test/test_bytesobject.py 
b/pypy/objspace/std/test/test_bytesobject.py
--- a/pypy/objspace/std/test/test_bytesobject.py
+++ b/pypy/objspace/std/test/test_bytesobject.py
@@ -832,6 +832,11 @@
                 return 3
         assert bytes(WithIndex()) == b'a'
 
+        class Str(str):
+            def __bytes__(self):
+                return b'a'
+        assert bytes(Str('abc')) == b'a'
+
     def test_getnewargs(self):
         assert  b"foo".__getnewargs__() == (b"foo",)
 
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to