mirror of
https://github.com/python/cpython.git
synced 2026-01-03 22:12:27 +00:00
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:
parent
18c66898b0
commit
8fd3eba050
10 changed files with 330 additions and 256 deletions
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue