[pypy-commit] pypy py3.5: PyUnicode_FromObject only works on instances of str

rlamy pypy.commits at gmail.com
Tue Nov 14 14:51:55 EST 2017


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: py3.5
Changeset: r93019:a3c86e99e3e4
Date: 2017-11-14 19:51 +0000
http://bitbucket.org/pypy/pypy/changeset/a3c86e99e3e4/

Log:	PyUnicode_FromObject only works on instances of str

diff --git a/pypy/module/cpyext/test/test_unicodeobject.py b/pypy/module/cpyext/test/test_unicodeobject.py
--- a/pypy/module/cpyext/test/test_unicodeobject.py
+++ b/pypy/module/cpyext/test/test_unicodeobject.py
@@ -319,6 +319,20 @@
         assert module.unsafe_len(u'aАbБcСdД') == 8
         assert module.unsafe_len(u"café\U0001F4A9") == 5
 
+    def test_FromObject(self):
+        module = self.import_extension('foo', [
+            ("from_object", "METH_O",
+             """
+                return PyUnicode_FromObject(args);
+             """)])
+        class my_str(str): pass
+        assert module.from_object('abc') == 'abc'
+        res = module.from_object(my_str('abc'))
+        assert type(res) is str
+        assert res == 'abc'
+        raises(TypeError, module.from_object, b'abc')
+        raises(TypeError, module.from_object, 42)
+
 
 class TestUnicode(BaseApiTest):
     def test_unicodeobject(self, space):
@@ -500,6 +514,12 @@
             assert ret == Py_CLEANUP_SUPPORTED
             assert space.isinstance_w(from_ref(space, result[0]), space.w_bytes)
             assert PyUnicode_FSDecoder(space, None, result) == 1
+        # Input is invalid
+        w_input = space.newint(42)
+        with lltype.scoped_alloc(PyObjectP.TO, 1) as result:
+            with pytest.raises(OperationError):
+                PyUnicode_FSConverter(space, w_input, result)
+
 
     def test_IS(self, space):
         for char in [0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x1c, 0x1d, 0x1e, 0x1f,
diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py
--- a/pypy/module/cpyext/unicodeobject.py
+++ b/pypy/module/cpyext/unicodeobject.py
@@ -505,12 +505,19 @@
 
 @cpython_api([PyObject], PyObject)
 def PyUnicode_FromObject(space, w_obj):
-    """Shortcut for PyUnicode_FromEncodedObject(obj, NULL, "strict") which is used
-    throughout the interpreter whenever coercion to Unicode is needed."""
+    """Copy an instance of a Unicode subtype to a new true Unicode object if
+    necessary. If obj is already a true Unicode object (not a subtype), return
+    the reference with incremented refcount.
+
+    Objects other than Unicode or its subtypes will cause a TypeError.
+    """
     if space.is_w(space.type(w_obj), space.w_unicode):
         return w_obj
+    elif space.isinstance_w(w_obj, space.w_unicode):
+        return space.call_function(space.w_unicode, w_obj)
     else:
-        return space.call_function(space.w_unicode, w_obj)
+        raise oefmt(space.w_TypeError,
+                    "Can't convert '%T' object to str implicitly", w_obj)
 
 @cpython_api([PyObject, CONST_STRING, CONST_STRING], PyObject)
 def PyUnicode_FromEncodedObject(space, w_obj, encoding, errors):


More information about the pypy-commit mailing list