aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Objects/stringlib/string_format.h
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/stringlib/string_format.h')
-rw-r--r--Objects/stringlib/string_format.h61
1 files changed, 42 insertions, 19 deletions
diff --git a/Objects/stringlib/string_format.h b/Objects/stringlib/string_format.h
index 965e1ad0ef3..c46bdc2656e 100644
--- a/Objects/stringlib/string_format.h
+++ b/Objects/stringlib/string_format.h
@@ -496,15 +496,28 @@ get_field_object(SubString *input, PyObject *args, PyObject *kwargs,
PyObject *key = SubString_new_object(&first);
if (key == NULL)
goto error;
- if ((kwargs == NULL) || (obj = PyDict_GetItem(kwargs, key)) == NULL) {
+
+ /* Use PyObject_GetItem instead of PyDict_GetItem because this
+ code is no longer just used with kwargs. It might be passed
+ a non-dict when called through format_map. */
+ if ((kwargs == NULL) || (obj = PyObject_GetItem(kwargs, key)) == NULL) {
PyErr_SetObject(PyExc_KeyError, key);
Py_DECREF(key);
goto error;
}
Py_DECREF(key);
- Py_INCREF(obj);
}
else {
+ /* If args is NULL, we have a format string with a positional field
+ with only kwargs to retrieve it from. This can only happen when
+ used with format_map(), where positional arguments are not
+ allowed. */
+ if (args == NULL) {
+ PyErr_SetString(PyExc_ValueError, "Format string contains "
+ "positional fields");
+ goto error;
+ }
+
/* look up in args */
obj = PySequence_GetItem(args, index);
if (obj == NULL)
@@ -570,24 +583,15 @@ render_field(PyObject *fieldobj, SubString *format_spec, OutputString *output)
/* If we know the type exactly, skip the lookup of __format__ and just
call the formatter directly. */
-#if STRINGLIB_IS_UNICODE
if (PyUnicode_CheckExact(fieldobj))
formatter = _PyUnicode_FormatAdvanced;
- /* Unfortunately, there's a problem with checking for int, long,
- and float here. If we're being included as unicode, their
- formatters expect string format_spec args. For now, just skip
- this optimization for unicode. This could be fixed, but it's a
- hassle. */
-#else
- if (PyString_CheckExact(fieldobj))
- formatter = _PyBytes_FormatAdvanced;
- else if (PyInt_CheckExact(fieldobj))
- formatter =_PyInt_FormatAdvanced;
else if (PyLong_CheckExact(fieldobj))
formatter =_PyLong_FormatAdvanced;
else if (PyFloat_CheckExact(fieldobj))
formatter = _PyFloat_FormatAdvanced;
-#endif
+
+ /* XXX: for 2.6, convert format_spec to the appropriate type
+ (unicode, str) */
if (formatter) {
/* we know exactly which formatter will be called when __format__ is
@@ -610,7 +614,7 @@ render_field(PyObject *fieldobj, SubString *format_spec, OutputString *output)
#if PY_VERSION_HEX >= 0x03000000
assert(PyUnicode_Check(result));
#else
- assert(PyString_Check(result) || PyUnicode_Check(result));
+ assert(PyBytes_Check(result) || PyUnicode_Check(result));
/* Convert result to our type. We could be str, and result could
be unicode */
@@ -849,6 +853,10 @@ do_conversion(PyObject *obj, STRINGLIB_CHAR conversion)
return PyObject_Repr(obj);
case 's':
return STRINGLIB_TOSTR(obj);
+#if PY_VERSION_HEX >= 0x03000000
+ case 'a':
+ return STRINGLIB_TOASCII(obj);
+#endif
default:
if (conversion > 32 && conversion < 127) {
/* It's the ASCII subrange; casting to char is safe
@@ -1041,6 +1049,11 @@ do_string_format(PyObject *self, PyObject *args, PyObject *kwargs)
return build_string(&input, args, kwargs, recursion_depth, &auto_number);
}
+static PyObject *
+do_string_format_map(PyObject *self, PyObject *obj)
+{
+ return do_string_format(self, NULL, obj);
+}
/************************************************************************/
@@ -1154,7 +1167,7 @@ static PyTypeObject PyFormatterIter_Type = {
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
- 0, /* tp_compare */
+ 0, /* tp_reserved */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
@@ -1182,10 +1195,15 @@ static PyTypeObject PyFormatterIter_Type = {
describing the parsed elements. It's a wrapper around
stringlib/string_format.h's MarkupIterator */
static PyObject *
-formatter_parser(STRINGLIB_OBJECT *self)
+formatter_parser(PyObject *ignored, STRINGLIB_OBJECT *self)
{
formatteriterobject *it;
+ if (!PyUnicode_Check(self)) {
+ PyErr_Format(PyExc_TypeError, "expected str, got %s", Py_TYPE(self)->tp_name);
+ return NULL;
+ }
+
it = PyObject_New(formatteriterobject, &PyFormatterIter_Type);
if (it == NULL)
return NULL;
@@ -1287,7 +1305,7 @@ static PyTypeObject PyFieldNameIter_Type = {
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
- 0, /* tp_compare */
+ 0, /* tp_reserved */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
@@ -1317,7 +1335,7 @@ static PyTypeObject PyFieldNameIter_Type = {
field_name_split. The iterator it returns is a
FieldNameIterator */
static PyObject *
-formatter_field_name_split(STRINGLIB_OBJECT *self)
+formatter_field_name_split(PyObject *ignored, STRINGLIB_OBJECT *self)
{
SubString first;
Py_ssize_t first_idx;
@@ -1326,6 +1344,11 @@ formatter_field_name_split(STRINGLIB_OBJECT *self)
PyObject *first_obj = NULL;
PyObject *result = NULL;
+ if (!PyUnicode_Check(self)) {
+ PyErr_Format(PyExc_TypeError, "expected str, got %s", Py_TYPE(self)->tp_name);
+ return NULL;
+ }
+
it = PyObject_New(fieldnameiterobject, &PyFieldNameIter_Type);
if (it == NULL)
return NULL;