Fixes for shared 2.6 code that implements PEP 3101, advanced string

formatting.

Includes:
 - Modifying tests for basic types to use __format__ methods, instead
   of builtin "format".
 - Adding PyObject_Format.
 - General str/unicode cleanup discovered when backporting to 2.6.
 - Removing datetimemodule.c's time_format, since it was identical
   to date_format.

The files in Objects/stringlib that implement PEP 3101 (stringdefs.h,
unicodedefs.h, formatter.h, string_format.h) are identical in trunk
and py3k.  Any changes from here on should be made to trunk, and
changes will propogate to py3k).
This commit is contained in:
Eric Smith 2008-02-17 19:48:00 +00:00
parent 18c66898b0
commit 8fd3eba050
10 changed files with 330 additions and 256 deletions

View file

@ -6,6 +6,11 @@
*/
/* Defines for Python 2.6 compatability */
#if PY_VERSION_HEX < 0x03000000
#define PyLong_FromSsize_t _PyLong_FromSsize_t
#endif
/* Defines for more efficiently reallocating the string buffer */
#define INITIAL_SIZE_INCREMENT 100
#define SIZE_MULTIPLIER 2
@ -470,66 +475,6 @@ get_field_object(SubString *input, PyObject *args, PyObject *kwargs)
field object and field specification string generated by
get_field_and_spec, and renders the field into the output string.
format() does the actual calling of the objects __format__ method.
*/
/* returns fieldobj.__format__(format_spec) */
static PyObject *
format(PyObject *fieldobj, SubString *format_spec)
{
static PyObject *format_str = NULL;
PyObject *meth;
PyObject *spec = NULL;
PyObject *result = NULL;
/* Initialize cached value */
if (format_str == NULL) {
/* Initialize static variable needed by _PyType_Lookup */
format_str = PyUnicode_FromString("__format__");
if (format_str == NULL)
return NULL;
}
/* Make sure the type is initialized. float gets initialized late */
if (Py_TYPE(fieldobj)->tp_dict == NULL)
if (PyType_Ready(Py_TYPE(fieldobj)) < 0)
return NULL;
/* we need to create an object out of the pointers we have */
spec = SubString_new_object_or_empty(format_spec);
if (spec == NULL)
goto done;
/* Find the (unbound!) __format__ method (a borrowed reference) */
meth = _PyType_Lookup(Py_TYPE(fieldobj), format_str);
if (meth == NULL) {
PyErr_Format(PyExc_TypeError,
"Type %.100s doesn't define __format__",
Py_TYPE(fieldobj)->tp_name);
goto done;
}
/* And call it, binding it to the value */
result = PyObject_CallFunctionObjArgs(meth, fieldobj, spec, NULL);
if (result == NULL)
goto done;
if (!STRINGLIB_CHECK(result)) {
PyErr_SetString(PyExc_TypeError,
"__format__ method did not return "
STRINGLIB_TYPE_NAME);
Py_DECREF(result);
result = NULL;
goto done;
}
done:
Py_XDECREF(spec);
return result;
}
/*
render_field calls fieldobj.__format__(format_spec) method, and
appends to the output.
*/
@ -537,14 +482,21 @@ static int
render_field(PyObject *fieldobj, SubString *format_spec, OutputString *output)
{
int ok = 0;
PyObject *result = format(fieldobj, format_spec);
PyObject *result = NULL;
/* we need to create an object out of the pointers we have */
PyObject *format_spec_object = SubString_new_object_or_empty(format_spec);
if (format_spec_object == NULL)
goto done;
result = PyObject_Format(fieldobj, format_spec_object);
if (result == NULL)
goto done;
ok = output_data(output,
STRINGLIB_STR(result), STRINGLIB_LEN(result));
done:
Py_DECREF(format_spec_object);
Py_XDECREF(result);
return ok;
}
@ -770,7 +722,7 @@ do_conversion(PyObject *obj, STRINGLIB_CHAR conversion)
case 'r':
return PyObject_Repr(obj);
case 's':
return PyObject_Str(obj);
return STRINGLIB_TOSTR(obj);
default:
PyErr_Format(PyExc_ValueError,
"Unknown converion specifier %c",
@ -845,7 +797,7 @@ output_markup(SubString *field_name, SubString *format_spec,
}
/*
do_markup is the top-level loop for the format() function. It
do_markup is the top-level loop for the format() method. It
searches through the format string for escapes to markup codes, and
calls other functions to move non-markup text to the output,
and to perform the markup to the output.
@ -958,7 +910,7 @@ do_string_format(PyObject *self, PyObject *args, PyObject *kwargs)
typedef struct {
PyObject_HEAD
PyUnicodeObject *str;
STRINGLIB_OBJECT *str;
MarkupIterator it_markup;
} formatteriterobject;
@ -984,7 +936,7 @@ formatteriter_next(formatteriterobject *it)
SubString literal;
SubString field_name;
SubString format_spec;
Py_UNICODE conversion;
STRINGLIB_CHAR conversion;
int format_spec_needs_expanding;
int result = MarkupIterator_next(&it->it_markup, &literal, &field_name,
&format_spec, &conversion,
@ -1028,7 +980,7 @@ formatteriter_next(formatteriterobject *it)
Py_INCREF(conversion_str);
}
else
conversion_str = PyUnicode_FromUnicode(&conversion, 1);
conversion_str = STRINGLIB_NEW(&conversion, 1);
if (conversion_str == NULL)
goto done;
@ -1047,7 +999,7 @@ static PyMethodDef formatteriter_methods[] = {
{NULL, NULL} /* sentinel */
};
PyTypeObject PyFormatterIter_Type = {
static PyTypeObject PyFormatterIter_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"formatteriterator", /* tp_name */
sizeof(formatteriterobject), /* tp_basicsize */
@ -1085,7 +1037,7 @@ PyTypeObject PyFormatterIter_Type = {
describing the parsed elements. It's a wrapper around
stringlib/string_format.h's MarkupIterator */
static PyObject *
formatter_parser(PyUnicodeObject *self)
formatter_parser(STRINGLIB_OBJECT *self)
{
formatteriterobject *it;
@ -1099,8 +1051,8 @@ formatter_parser(PyUnicodeObject *self)
/* initialize the contained MarkupIterator */
MarkupIterator_init(&it->it_markup,
PyUnicode_AS_UNICODE(self),
PyUnicode_GET_SIZE(self));
STRINGLIB_STR(self),
STRINGLIB_LEN(self));
return (PyObject *)it;
}
@ -1118,7 +1070,7 @@ formatter_parser(PyUnicodeObject *self)
typedef struct {
PyObject_HEAD
PyUnicodeObject *str;
STRINGLIB_OBJECT *str;
FieldNameIterator it_field;
} fieldnameiterobject;
@ -1220,7 +1172,7 @@ static PyTypeObject PyFieldNameIter_Type = {
field_name_split. The iterator it returns is a
FieldNameIterator */
static PyObject *
formatter_field_name_split(PyUnicodeObject *self)
formatter_field_name_split(STRINGLIB_OBJECT *self)
{
SubString first;
Py_ssize_t first_idx;