]> granicus.if.org Git - python/commitdiff
SF bug [#468061] __str__ ignored in str subclass.
authorTim Peters <tim.peters@gmail.com>
Tue, 16 Oct 2001 20:18:24 +0000 (20:18 +0000)
committerTim Peters <tim.peters@gmail.com>
Tue, 16 Oct 2001 20:18:24 +0000 (20:18 +0000)
object.c, PyObject_Str:  Don't try to optimize anything except exact
string objects here; in particular, let str subclasses go thru tp_str,
same as non-str objects.  This allows overrides of tp_str to take
effect.

stringobject.c:
+ string_print (str's tp_print):  If the argument isn't an exact string
  object, get one from PyObject_Str.

+ string_str (str's tp_str):  Make a genuine-string copy of the object if
  it's of a proper str subclass type.  str() applied to a str subclass
  that doesn't override __str__ ends up here.

test_descr.py:  New str_of_str_subclass() test.

Lib/test/test_descr.py
Objects/object.c
Objects/stringobject.c

index a15e7a0760724c2918f424453aed1502b049d55d..c9235c8b0e5aa65eee9285cf77795c2a03cbc8d9 100644 (file)
@@ -2298,6 +2298,36 @@ def buffer_inherit():
     except TypeError:
         pass
 
+def str_of_str_subclass():
+    import binascii
+    import cStringIO
+
+    if verbose:
+        print "Testing __str__ defined in subclass of str ..."
+
+    class octetstring(str):
+        def __str__(self):
+            return binascii.b2a_hex(self)
+        def __repr__(self):
+            return self + " repr"
+
+    o = octetstring('A')
+    vereq(type(o), octetstring)
+    vereq(type(str(o)), str)
+    vereq(type(repr(o)), str)
+    vereq(ord(o), 0x41)
+    vereq(str(o), '41')
+    vereq(repr(o), 'A repr')
+    vereq(o.__str__(), '41')
+    vereq(o.__repr__(), 'A repr')
+
+    capture = cStringIO.StringIO()
+    # Calling str() or not exercises different internal paths.
+    print >> capture, o
+    print >> capture, str(o)
+    vereq(capture.getvalue(), '41\n41\n')
+    capture.close()
+
 def test_main():
     class_docstrings()
     lists()
@@ -2346,6 +2376,7 @@ def test_main():
     binopoverride()
     subclasspropagation()
     buffer_inherit()
+    str_of_str_subclass()
     if verbose: print "All OK"
 
 if __name__ == "__main__":
index be8eb07d46194f4734450f837c3f222a39fa863b..af0c0bbed053aee2f2bd9fc2ff44b1145a2b7e7d 100644 (file)
@@ -261,12 +261,6 @@ PyObject_Str(PyObject *v)
                Py_INCREF(v);
                return v;
        }
-       if (PyString_Check(v)) {
-               /* For a string subtype that's not a string, return a true
-                  string with the same string data. */
-               PyStringObject *s = (PyStringObject *)v;
-               return PyString_FromStringAndSize(s->ob_sval, s->ob_size);
-       }
        if (v->ob_type->tp_str == NULL)
                return PyObject_Repr(v);
 
index aea31aca6b1a0f6d59b4781b9abe5feda7a0487d..0a3155e2975d954744d974b35bbf02e5111bc47d 100644 (file)
@@ -566,7 +566,18 @@ string_print(PyStringObject *op, FILE *fp, int flags)
        int i;
        char c;
        int quote;
+
        /* XXX Ought to check for interrupts when writing long strings */
+       if (! PyString_CheckExact(op)) {
+               int ret;
+               /* A str subclass may have its own __str__ method. */
+               op = (PyStringObject *) PyObject_Str((PyObject *)op);
+               if (op == NULL)
+                       return -1;
+               ret = string_print(op, fp, flags);
+               Py_DECREF(op);
+               return ret;
+       }
        if (flags & Py_PRINT_RAW) {
                fwrite(op->ob_sval, 1, (int) op->ob_size, fp);
                return 0;
@@ -651,8 +662,16 @@ string_repr(register PyStringObject *op)
 static PyObject *
 string_str(PyObject *s)
 {
-       Py_INCREF(s);
-       return s;
+       assert(PyString_Check(s));
+       if (PyString_CheckExact(s)) {
+               Py_INCREF(s);
+               return s;
+       }
+       else {
+               /* Subtype -- return genuine string with the same value. */
+               PyStringObject *t = (PyStringObject *) s;
+               return PyString_FromStringAndSize(t->ob_sval, t->ob_size);
+       }
 }
 
 static int