Change the %s format specifier for str objects so that it returns a
unicode instance if the argument is not an instance of basestring and calling __str__ on the argument returns a unicode instance.
This commit is contained in:
parent
ba7d95e215
commit
cf52c07843
|
@ -371,6 +371,7 @@ PyAPI_FUNC(PyObject *) _PyType_Lookup(PyTypeObject *, PyObject *);
|
|||
PyAPI_FUNC(int) PyObject_Print(PyObject *, FILE *, int);
|
||||
PyAPI_FUNC(void) _PyObject_Dump(PyObject *);
|
||||
PyAPI_FUNC(PyObject *) PyObject_Repr(PyObject *);
|
||||
PyAPI_FUNC(PyObject *) _PyObject_Str(PyObject *);
|
||||
PyAPI_FUNC(PyObject *) PyObject_Str(PyObject *);
|
||||
#ifdef Py_USING_UNICODE
|
||||
PyAPI_FUNC(PyObject *) PyObject_Unicode(PyObject *);
|
||||
|
|
|
@ -388,6 +388,10 @@ class UnicodeTest(
|
|||
self.assertEqual('%i %*.*s' % (10, 5,3,u'abc',), u'10 abc')
|
||||
self.assertEqual('%i%s %*.*s' % (10, 3, 5, 3, u'abc',), u'103 abc')
|
||||
self.assertEqual('%c' % u'a', u'a')
|
||||
class Wrapper:
|
||||
def __str__(self):
|
||||
return u'\u1234'
|
||||
self.assertEqual('%s' % Wrapper(), u'\u1234')
|
||||
|
||||
def test_constructor(self):
|
||||
# unicode(obj) tests (this maps to PyObject_Unicode() at C level)
|
||||
|
|
|
@ -118,6 +118,10 @@ Core and builtins
|
|||
positions. It once again reports a syntax error if a future
|
||||
statement occurs after anything other than a doc string.
|
||||
|
||||
- Change the %s format specifier for str objects so that it returns a
|
||||
unicode instance if the argument is not an instance of basestring and
|
||||
calling __str__ on the argument returns a unicode instance.
|
||||
|
||||
Extension Modules
|
||||
-----------------
|
||||
|
||||
|
|
|
@ -331,22 +331,48 @@ PyObject_Repr(PyObject *v)
|
|||
}
|
||||
|
||||
PyObject *
|
||||
PyObject_Str(PyObject *v)
|
||||
_PyObject_Str(PyObject *v)
|
||||
{
|
||||
PyObject *res;
|
||||
|
||||
int type_ok;
|
||||
if (v == NULL)
|
||||
return PyString_FromString("<NULL>");
|
||||
if (PyString_CheckExact(v)) {
|
||||
Py_INCREF(v);
|
||||
return v;
|
||||
}
|
||||
#ifdef Py_USING_UNICODE
|
||||
if (PyUnicode_CheckExact(v)) {
|
||||
Py_INCREF(v);
|
||||
return v;
|
||||
}
|
||||
#endif
|
||||
if (v->ob_type->tp_str == NULL)
|
||||
return PyObject_Repr(v);
|
||||
|
||||
res = (*v->ob_type->tp_str)(v);
|
||||
if (res == NULL)
|
||||
return NULL;
|
||||
type_ok = PyString_Check(res);
|
||||
#ifdef Py_USING_UNICODE
|
||||
type_ok = type_ok || PyUnicode_Check(res);
|
||||
#endif
|
||||
if (!type_ok) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"__str__ returned non-string (type %.200s)",
|
||||
res->ob_type->tp_name);
|
||||
Py_DECREF(res);
|
||||
return NULL;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
PyObject_Str(PyObject *v)
|
||||
{
|
||||
PyObject *res = _PyObject_Str(v);
|
||||
if (res == NULL)
|
||||
return NULL;
|
||||
#ifdef Py_USING_UNICODE
|
||||
if (PyUnicode_Check(res)) {
|
||||
PyObject* str;
|
||||
|
@ -358,13 +384,7 @@ PyObject_Str(PyObject *v)
|
|||
return NULL;
|
||||
}
|
||||
#endif
|
||||
if (!PyString_Check(res)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"__str__ returned non-string (type %.200s)",
|
||||
res->ob_type->tp_name);
|
||||
Py_DECREF(res);
|
||||
return NULL;
|
||||
}
|
||||
assert(PyString_Check(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -3853,7 +3853,6 @@ formatchar(char *buf, size_t buflen, PyObject *v)
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...)
|
||||
|
||||
FORMATBUFLEN is the length of the buffer in which the floats, ints, &
|
||||
|
@ -4079,7 +4078,9 @@ PyString_Format(PyObject *format, PyObject *args)
|
|||
break;
|
||||
case 's':
|
||||
#ifdef Py_USING_UNICODE
|
||||
if (PyUnicode_Check(v)) {
|
||||
temp = _PyObject_Str(v);
|
||||
if (temp != NULL && PyUnicode_Check(temp)) {
|
||||
Py_DECREF(temp);
|
||||
fmt = fmt_start;
|
||||
argidx = argidx_start;
|
||||
goto unicode;
|
||||
|
@ -4087,16 +4088,11 @@ PyString_Format(PyObject *format, PyObject *args)
|
|||
#endif
|
||||
/* Fall through */
|
||||
case 'r':
|
||||
if (c == 's')
|
||||
temp = PyObject_Str(v);
|
||||
else
|
||||
if (c == 'r')
|
||||
temp = PyObject_Repr(v);
|
||||
if (temp == NULL)
|
||||
goto error;
|
||||
if (!PyString_Check(temp)) {
|
||||
/* XXX Note: this should never happen,
|
||||
since PyObject_Repr() and
|
||||
PyObject_Str() assure this */
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"%s argument has non-string str()");
|
||||
Py_DECREF(temp);
|
||||
|
|
Loading…
Reference in New Issue