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.
This commit is contained in:
Tim Peters 2001-10-16 20:18:24 +00:00
parent dfefc06fe0
commit c993315b18
3 changed files with 52 additions and 8 deletions

View 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__":

View 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);

View 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