diff options
author | Eric Smith <eric@trueblade.com> | 2007-08-25 02:26:07 (GMT) |
---|---|---|
committer | Eric Smith <eric@trueblade.com> | 2007-08-25 02:26:07 (GMT) |
commit | 8c6632636807c35bee40210ed8483c1eca82664f (patch) | |
tree | 50f386d98ce14116eaf9d83085b82ff11bdb3e69 /Python | |
parent | e4dc32488446240942123cf4e9e7296ad97e20bf (diff) | |
download | cpython-8c6632636807c35bee40210ed8483c1eca82664f.zip cpython-8c6632636807c35bee40210ed8483c1eca82664f.tar.gz cpython-8c6632636807c35bee40210ed8483c1eca82664f.tar.bz2 |
Implementation of PEP 3101, Advanced String Formatting.
Known issues:
The string.Formatter class, as discussed in the PEP, is incomplete.
Error handling needs to conform to the PEP.
Need to fix this warning that I introduced in Python/formatter_unicode.c:
Objects/stringlib/unicodedefs.h:26: warning: `STRINGLIB_CMP' defined but not used
Need to make sure sign formatting is correct, more tests needed.
Need to remove '()' sign formatting, left over from an earlier version of the PEP.
Diffstat (limited to 'Python')
-rw-r--r-- | Python/Python-ast.c | 4 | ||||
-rw-r--r-- | Python/bltinmodule.c | 56 | ||||
-rw-r--r-- | Python/formatter_unicode.c | 13 | ||||
-rw-r--r-- | Python/sysmodule.c | 50 |
4 files changed, 121 insertions, 2 deletions
diff --git a/Python/Python-ast.c b/Python/Python-ast.c index 605a152..4c6f42c 100644 --- a/Python/Python-ast.c +++ b/Python/Python-ast.c @@ -2,7 +2,7 @@ /* - __version__ 56266. + __version__ . This module must be committed separately after each AST grammar change; The __version__ number is set to the revision number of the commit @@ -3179,7 +3179,7 @@ init_ast(void) if (PyDict_SetItemString(d, "AST", (PyObject*)AST_type) < 0) return; if (PyModule_AddIntConstant(m, "PyCF_ONLY_AST", PyCF_ONLY_AST) < 0) return; - if (PyModule_AddStringConstant(m, "__version__", "56266") < 0) + if (PyModule_AddStringConstant(m, "__version__", "") < 0) return; if (PyDict_SetItemString(d, "mod", (PyObject*)mod_type) < 0) return; if (PyDict_SetItemString(d, "Module", (PyObject*)Module_type) < 0) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index d087e9c..17f5b59 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -275,6 +275,61 @@ for which the predicate (a Boolean function) returns true.\n\ If the predicate is None, 'lambda x: bool(x)' is assumed.\n\ (This is identical to itertools.ifilter().)"); +static PyObject * +builtin_format(PyObject *self, PyObject *args) +{ + static PyObject * format_str = NULL; + PyObject *value; + PyObject *spec; + PyObject *meth; + PyObject *result; + + /* 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; + } + + if (!PyArg_ParseTuple(args, "OO:format", &value, &spec)) + return NULL; + + /* Make sure the type is initialized. float gets initialized late */ + if (Py_Type(value)->tp_dict == NULL) + if (PyType_Ready(Py_Type(value)) < 0) + return NULL; + + /* Find the (unbound!) __format__ method (a borrowed reference) */ + meth = _PyType_Lookup(Py_Type(value), format_str); + if (meth == NULL) { + PyErr_Format(PyExc_TypeError, + "Type %.100s doesn't define __format__", + Py_Type(value)->tp_name); + return NULL; + } + + /* And call it, binding it to the value */ + result = PyObject_CallFunctionObjArgs(meth, value, spec, NULL); + +#if 0 + /* XXX this is segfaulting, not sure why. find out later! */ + if (!PyUnicode_Check(result)) { + PyErr_SetString(PyExc_TypeError, + "__format__ method did not return string"); + Py_DECREF(result); + return NULL; + } +#endif + + return result; +} + + +PyDoc_STRVAR(format_doc, +"format(value, format_spec) -> string\n\ +\n\ +Returns value.__format__(format_spec)."); static PyObject * builtin_chr8(PyObject *self, PyObject *args) @@ -1676,6 +1731,7 @@ static PyMethodDef builtin_methods[] = { {"eval", builtin_eval, METH_VARARGS, eval_doc}, {"exec", builtin_exec, METH_VARARGS, exec_doc}, {"filter", builtin_filter, METH_VARARGS, filter_doc}, + {"format", builtin_format, METH_VARARGS, format_doc}, {"getattr", builtin_getattr, METH_VARARGS, getattr_doc}, {"globals", (PyCFunction)builtin_globals, METH_NOARGS, globals_doc}, {"hasattr", builtin_hasattr, METH_VARARGS, hasattr_doc}, diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c new file mode 100644 index 0000000..114fe30 --- /dev/null +++ b/Python/formatter_unicode.c @@ -0,0 +1,13 @@ +/* implements the unicode (as opposed to string) version of the + built-in formatters for string, int, float. that is, the versions + of int.__float__, etc., that take and return unicode objects */ + +#include "Python.h" +#include "formatter_unicode.h" + +#include "../Objects/stringlib/unicodedefs.h" + +#define FORMAT_STRING unicode_unicode__format__ +#define FORMAT_LONG unicode_long__format__ +#define FORMAT_FLOAT unicode_float__format__ +#include "../Objects/stringlib/formatter.h" diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 6ccd3e9..10a7427 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -660,6 +660,54 @@ sys_current_frames(PyObject *self, PyObject *noargs) return _PyThread_CurrentFrames(); } +/* sys_formatter_iterator is used to implement + string.Formatter.vformat. it parses a string and returns tuples + describing the parsed elements. see unicodeobject.c's + _unicodeformatter_iterator for details */ +static PyObject * +sys_formatter_iterator(PyObject *self, PyObject *args) +{ + /* in 2.6, check type and dispatch to unicode or string + accordingly */ + PyObject *str; + + if (!PyArg_ParseTuple(args, "O:_formatter_iterator", &str)) + return NULL; + + if (!PyUnicode_Check(str)) { + PyErr_SetString(PyExc_TypeError, + "_formatter_iterator expects unicode object"); + return NULL; + } + + return _unicodeformatter_iterator(str); +} + +/* sys_formatter_lookup is used to implement string.Formatter.vformat. + it takes an PEP 3101 "field name", args, and kwargs, and returns a + tuple (index, name, object). see unicodeobject.c's + _unicodeformatter_lookup for details */ +static PyObject * +sys_formatter_lookup(PyObject *self, PyObject *args) +{ + PyObject *field_name; + PyObject *arg_args; + PyObject *kwargs; + + if (!PyArg_ParseTuple(args, "OOO:_formatter_lookup", &field_name, + &arg_args, &kwargs)) + return NULL; + + if (!PyUnicode_Check(field_name)) { + PyErr_SetString(PyExc_TypeError, + "_formatter_lookup expects unicode object"); + return NULL; + } + + return _unicodeformatter_lookup(field_name, arg_args, kwargs); +} + + PyDoc_STRVAR(call_tracing_doc, "call_tracing(func, args) -> object\n\ \n\ @@ -724,6 +772,8 @@ static PyMethodDef sys_methods[] = { callstats_doc}, {"_current_frames", sys_current_frames, METH_NOARGS, current_frames_doc}, + {"_formatter_parser", sys_formatter_iterator, METH_VARARGS}, + {"_formatter_lookup", sys_formatter_lookup, METH_VARARGS}, {"displayhook", sys_displayhook, METH_O, displayhook_doc}, {"exc_info", sys_exc_info, METH_NOARGS, exc_info_doc}, {"excepthook", sys_excepthook, METH_VARARGS, excepthook_doc}, |