From c993315b188b08b6d78248522f6d0ed31d52f939 Mon Sep 17 00:00:00 2001 From: Tim Peters Date: Tue, 16 Oct 2001 20:18:24 +0000 Subject: SF bug [#468061] __str__ ignored in str subclass. 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 | 31 +++++++++++++++++++++++++++++++ Objects/object.c | 6 ------ Objects/stringobject.c | 23 +++++++++++++++++++++-- 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index a15e7a0..c9235c8 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -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__": diff --git a/Objects/object.c b/Objects/object.c index be8eb07..af0c0bb 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -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); diff --git a/Objects/stringobject.c b/Objects/stringobject.c index aea31ac..0a3155e 100644 --- a/Objects/stringobject.c +++ b/Objects/stringobject.c @@ -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 -- cgit v0.12