Add a format specifier %V to PyUnicode_FromFormat(), that works similar to %U,
but requires an additional char * that will be used if the unicode object is NULL. Use %V in descrobject.c and classobject.c.
This commit is contained in:
parent
3ef72bb0a9
commit
d7fb7644da
@ -227,7 +227,7 @@ method_repr(PyMethodObject *a)
|
|||||||
PyObject *func = a->im_func;
|
PyObject *func = a->im_func;
|
||||||
PyObject *klass = a->im_class;
|
PyObject *klass = a->im_class;
|
||||||
PyObject *funcname = NULL, *klassname = NULL, *result = NULL;
|
PyObject *funcname = NULL, *klassname = NULL, *result = NULL;
|
||||||
char *sfuncname = "?", *sklassname = "?";
|
char *defname = "?";
|
||||||
|
|
||||||
funcname = PyObject_GetAttrString(func, "__name__");
|
funcname = PyObject_GetAttrString(func, "__name__");
|
||||||
if (funcname == NULL) {
|
if (funcname == NULL) {
|
||||||
@ -239,8 +239,6 @@ method_repr(PyMethodObject *a)
|
|||||||
Py_DECREF(funcname);
|
Py_DECREF(funcname);
|
||||||
funcname = NULL;
|
funcname = NULL;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
sfuncname = PyUnicode_AsString(funcname);
|
|
||||||
if (klass == NULL)
|
if (klass == NULL)
|
||||||
klassname = NULL;
|
klassname = NULL;
|
||||||
else {
|
else {
|
||||||
@ -254,16 +252,16 @@ method_repr(PyMethodObject *a)
|
|||||||
Py_DECREF(klassname);
|
Py_DECREF(klassname);
|
||||||
klassname = NULL;
|
klassname = NULL;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
sklassname = PyUnicode_AsString(klassname);
|
|
||||||
}
|
}
|
||||||
if (self == NULL)
|
if (self == NULL)
|
||||||
result = PyUnicode_FromFormat("<unbound method %s.%s>",
|
result = PyUnicode_FromFormat("<unbound method %V.%V>",
|
||||||
sklassname, sfuncname);
|
klassname, defname,
|
||||||
|
funcname, defname);
|
||||||
else {
|
else {
|
||||||
/* XXX Shouldn't use repr()/%R here! */
|
/* XXX Shouldn't use repr()/%R here! */
|
||||||
result = PyUnicode_FromFormat("<bound method %s.%s of %R>",
|
result = PyUnicode_FromFormat("<bound method %V.%V of %R>",
|
||||||
sklassname, sfuncname, self);
|
klassname, defname,
|
||||||
|
funcname, defname, self);
|
||||||
}
|
}
|
||||||
Py_XDECREF(funcname);
|
Py_XDECREF(funcname);
|
||||||
Py_XDECREF(klassname);
|
Py_XDECREF(klassname);
|
||||||
|
@ -12,51 +12,50 @@ descr_dealloc(PyDescrObject *descr)
|
|||||||
PyObject_GC_Del(descr);
|
PyObject_GC_Del(descr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static PyObject *
|
||||||
descr_name(PyDescrObject *descr)
|
descr_name(PyDescrObject *descr)
|
||||||
{
|
{
|
||||||
if (descr->d_name != NULL && PyUnicode_Check(descr->d_name))
|
if (descr->d_name != NULL && PyUnicode_Check(descr->d_name))
|
||||||
return PyUnicode_AsString(descr->d_name);
|
return descr->d_name;
|
||||||
else if (descr->d_name != NULL && PyString_Check(descr->d_name))
|
return NULL;
|
||||||
/* XXX this should not happen */
|
|
||||||
return PyString_AS_STRING(descr->d_name);
|
|
||||||
else
|
|
||||||
return "?";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
descr_repr(PyDescrObject *descr, char *format)
|
descr_repr(PyDescrObject *descr, char *format)
|
||||||
{
|
{
|
||||||
return PyUnicode_FromFormat(format, descr_name(descr),
|
PyObject *name = NULL;
|
||||||
descr->d_type->tp_name);
|
if (descr->d_name != NULL && PyUnicode_Check(descr->d_name))
|
||||||
|
name = descr->d_name;
|
||||||
|
|
||||||
|
return PyUnicode_FromFormat(format, name, "?", descr->d_type->tp_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
method_repr(PyMethodDescrObject *descr)
|
method_repr(PyMethodDescrObject *descr)
|
||||||
{
|
{
|
||||||
return descr_repr((PyDescrObject *)descr,
|
return descr_repr((PyDescrObject *)descr,
|
||||||
"<method '%s' of '%s' objects>");
|
"<method '%V' of '%s' objects>");
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
member_repr(PyMemberDescrObject *descr)
|
member_repr(PyMemberDescrObject *descr)
|
||||||
{
|
{
|
||||||
return descr_repr((PyDescrObject *)descr,
|
return descr_repr((PyDescrObject *)descr,
|
||||||
"<member '%s' of '%s' objects>");
|
"<member '%V' of '%s' objects>");
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
getset_repr(PyGetSetDescrObject *descr)
|
getset_repr(PyGetSetDescrObject *descr)
|
||||||
{
|
{
|
||||||
return descr_repr((PyDescrObject *)descr,
|
return descr_repr((PyDescrObject *)descr,
|
||||||
"<attribute '%s' of '%s' objects>");
|
"<attribute '%V' of '%s' objects>");
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
wrapperdescr_repr(PyWrapperDescrObject *descr)
|
wrapperdescr_repr(PyWrapperDescrObject *descr)
|
||||||
{
|
{
|
||||||
return descr_repr((PyDescrObject *)descr,
|
return descr_repr((PyDescrObject *)descr,
|
||||||
"<slot wrapper '%s' of '%s' objects>");
|
"<slot wrapper '%V' of '%s' objects>");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -69,9 +68,9 @@ descr_check(PyDescrObject *descr, PyObject *obj, PyObject **pres)
|
|||||||
}
|
}
|
||||||
if (!PyObject_TypeCheck(obj, descr->d_type)) {
|
if (!PyObject_TypeCheck(obj, descr->d_type)) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"descriptor '%s' for '%s' objects "
|
"descriptor '%V' for '%s' objects "
|
||||||
"doesn't apply to '%s' object",
|
"doesn't apply to '%s' object",
|
||||||
descr_name((PyDescrObject *)descr),
|
descr_name((PyDescrObject *)descr), "?",
|
||||||
descr->d_type->tp_name,
|
descr->d_type->tp_name,
|
||||||
obj->ob_type->tp_name);
|
obj->ob_type->tp_name);
|
||||||
*pres = NULL;
|
*pres = NULL;
|
||||||
@ -90,27 +89,27 @@ classmethod_get(PyMethodDescrObject *descr, PyObject *obj, PyObject *type)
|
|||||||
else {
|
else {
|
||||||
/* Wot - no type?! */
|
/* Wot - no type?! */
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"descriptor '%s' for type '%s' "
|
"descriptor '%V' for type '%s' "
|
||||||
"needs either an object or a type",
|
"needs either an object or a type",
|
||||||
descr_name((PyDescrObject *)descr),
|
descr_name((PyDescrObject *)descr), "?",
|
||||||
descr->d_type->tp_name);
|
descr->d_type->tp_name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!PyType_Check(type)) {
|
if (!PyType_Check(type)) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"descriptor '%s' for type '%s' "
|
"descriptor '%V' for type '%s' "
|
||||||
"needs a type, not a '%s' as arg 2",
|
"needs a type, not a '%s' as arg 2",
|
||||||
descr_name((PyDescrObject *)descr),
|
descr_name((PyDescrObject *)descr), "?",
|
||||||
descr->d_type->tp_name,
|
descr->d_type->tp_name,
|
||||||
type->ob_type->tp_name);
|
type->ob_type->tp_name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!PyType_IsSubtype((PyTypeObject *)type, descr->d_type)) {
|
if (!PyType_IsSubtype((PyTypeObject *)type, descr->d_type)) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"descriptor '%s' for type '%s' "
|
"descriptor '%V' for type '%s' "
|
||||||
"doesn't apply to type '%s'",
|
"doesn't apply to type '%s'",
|
||||||
descr_name((PyDescrObject *)descr),
|
descr_name((PyDescrObject *)descr), "?",
|
||||||
descr->d_type->tp_name,
|
descr->d_type->tp_name,
|
||||||
((PyTypeObject *)type)->tp_name);
|
((PyTypeObject *)type)->tp_name);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -148,8 +147,8 @@ getset_get(PyGetSetDescrObject *descr, PyObject *obj, PyObject *type)
|
|||||||
if (descr->d_getset->get != NULL)
|
if (descr->d_getset->get != NULL)
|
||||||
return descr->d_getset->get(obj, descr->d_getset->closure);
|
return descr->d_getset->get(obj, descr->d_getset->closure);
|
||||||
PyErr_Format(PyExc_AttributeError,
|
PyErr_Format(PyExc_AttributeError,
|
||||||
"attribute '%.300s' of '%.100s' objects is not readable",
|
"attribute '%V' of '%.100s' objects is not readable",
|
||||||
descr_name((PyDescrObject *)descr),
|
descr_name((PyDescrObject *)descr), "?",
|
||||||
descr->d_type->tp_name);
|
descr->d_type->tp_name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -171,9 +170,9 @@ descr_setcheck(PyDescrObject *descr, PyObject *obj, PyObject *value,
|
|||||||
assert(obj != NULL);
|
assert(obj != NULL);
|
||||||
if (!PyObject_IsInstance(obj, (PyObject *)(descr->d_type))) {
|
if (!PyObject_IsInstance(obj, (PyObject *)(descr->d_type))) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"descriptor '%.200s' for '%.100s' objects "
|
"descriptor '%V' for '%.100s' objects "
|
||||||
"doesn't apply to '%.100s' object",
|
"doesn't apply to '%.100s' object",
|
||||||
descr_name(descr),
|
descr_name(descr), "?",
|
||||||
descr->d_type->tp_name,
|
descr->d_type->tp_name,
|
||||||
obj->ob_type->tp_name);
|
obj->ob_type->tp_name);
|
||||||
*pres = -1;
|
*pres = -1;
|
||||||
@ -203,8 +202,8 @@ getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value)
|
|||||||
return descr->d_getset->set(obj, value,
|
return descr->d_getset->set(obj, value,
|
||||||
descr->d_getset->closure);
|
descr->d_getset->closure);
|
||||||
PyErr_Format(PyExc_AttributeError,
|
PyErr_Format(PyExc_AttributeError,
|
||||||
"attribute '%.300s' of '%.100s' objects is not writable",
|
"attribute '%V' of '%.100s' objects is not writable",
|
||||||
descr_name((PyDescrObject *)descr),
|
descr_name((PyDescrObject *)descr), "?",
|
||||||
descr->d_type->tp_name);
|
descr->d_type->tp_name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -220,19 +219,19 @@ methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwds)
|
|||||||
argc = PyTuple_GET_SIZE(args);
|
argc = PyTuple_GET_SIZE(args);
|
||||||
if (argc < 1) {
|
if (argc < 1) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"descriptor '%.300s' of '%.100s' "
|
"descriptor '%V' of '%.100s' "
|
||||||
"object needs an argument",
|
"object needs an argument",
|
||||||
descr_name((PyDescrObject *)descr),
|
descr_name((PyDescrObject *)descr), "?",
|
||||||
descr->d_type->tp_name);
|
descr->d_type->tp_name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
self = PyTuple_GET_ITEM(args, 0);
|
self = PyTuple_GET_ITEM(args, 0);
|
||||||
if (!PyObject_IsInstance(self, (PyObject *)(descr->d_type))) {
|
if (!PyObject_IsInstance(self, (PyObject *)(descr->d_type))) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"descriptor '%.200s' "
|
"descriptor '%V' "
|
||||||
"requires a '%.100s' object "
|
"requires a '%.100s' object "
|
||||||
"but received a '%.100s'",
|
"but received a '%.100s'",
|
||||||
descr_name((PyDescrObject *)descr),
|
descr_name((PyDescrObject *)descr), "?",
|
||||||
descr->d_type->tp_name,
|
descr->d_type->tp_name,
|
||||||
self->ob_type->tp_name);
|
self->ob_type->tp_name);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -278,19 +277,19 @@ wrapperdescr_call(PyWrapperDescrObject *descr, PyObject *args, PyObject *kwds)
|
|||||||
argc = PyTuple_GET_SIZE(args);
|
argc = PyTuple_GET_SIZE(args);
|
||||||
if (argc < 1) {
|
if (argc < 1) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"descriptor '%.300s' of '%.100s' "
|
"descriptor '%V' of '%.100s' "
|
||||||
"object needs an argument",
|
"object needs an argument",
|
||||||
descr_name((PyDescrObject *)descr),
|
descr_name((PyDescrObject *)descr), "?",
|
||||||
descr->d_type->tp_name);
|
descr->d_type->tp_name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
self = PyTuple_GET_ITEM(args, 0);
|
self = PyTuple_GET_ITEM(args, 0);
|
||||||
if (!PyObject_IsInstance(self, (PyObject *)(descr->d_type))) {
|
if (!PyObject_IsInstance(self, (PyObject *)(descr->d_type))) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"descriptor '%.200s' "
|
"descriptor '%V' "
|
||||||
"requires a '%.100s' object "
|
"requires a '%.100s' object "
|
||||||
"but received a '%.100s'",
|
"but received a '%.100s'",
|
||||||
descr_name((PyDescrObject *)descr),
|
descr_name((PyDescrObject *)descr), "?",
|
||||||
descr->d_type->tp_name,
|
descr->d_type->tp_name,
|
||||||
self->ob_type->tp_name);
|
self->ob_type->tp_name);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -631,6 +631,18 @@ PyUnicode_FromFormatV(const char *format, va_list vargs)
|
|||||||
n += PyUnicode_GET_SIZE(obj);
|
n += PyUnicode_GET_SIZE(obj);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'V':
|
||||||
|
{
|
||||||
|
PyObject *obj = va_arg(count, PyObject *);
|
||||||
|
const char *str = va_arg(count, const char *);
|
||||||
|
assert(obj || str);
|
||||||
|
assert(!obj || PyUnicode_Check(obj));
|
||||||
|
if (obj)
|
||||||
|
n += PyUnicode_GET_SIZE(obj);
|
||||||
|
else
|
||||||
|
n += strlen(str);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'S':
|
case 'S':
|
||||||
{
|
{
|
||||||
PyObject *obj = va_arg(count, PyObject *);
|
PyObject *obj = va_arg(count, PyObject *);
|
||||||
@ -775,6 +787,19 @@ PyUnicode_FromFormatV(const char *format, va_list vargs)
|
|||||||
s += size;
|
s += size;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'V':
|
||||||
|
{
|
||||||
|
PyObject *obj = va_arg(vargs, PyObject *);
|
||||||
|
const char *str = va_arg(vargs, const char *);
|
||||||
|
if (obj) {
|
||||||
|
Py_ssize_t size = PyUnicode_GET_SIZE(obj);
|
||||||
|
Py_UNICODE_COPY(s, PyUnicode_AS_UNICODE(obj), size);
|
||||||
|
s += size;
|
||||||
|
} else {
|
||||||
|
appendstring(str);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'S':
|
case 'S':
|
||||||
case 'R':
|
case 'R':
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user