Skip to content

Commit 3eff285

Browse files
author
tim.peters
committed
Teach PyString_FromFormat, PyErr_Format, and PyString_FromFormatV
about "%u", "%lu" and "%zu" formats. Since PyString_FromFormat and PyErr_Format have exactly the same rules (both inherited from PyString_FromFormatV), it would be good if someone with more LaTeX Fu changed one of them to just point to the other. Their docs were way out of synch before this patch, and I just did a mass copy+paste to repair that. Not a backport candidate (this is a new feature). git-svn-id: http://svn.python.org/projects/python/trunk@45992 6015fed2-1504-0410-9fe1-9d1591cc4771
1 parent bc8c179 commit 3eff285

5 files changed

Lines changed: 127 additions & 40 deletions

File tree

Doc/api/concrete.tex

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ \subsection{Boolean Objects \label{boolObjects}}
245245
\end{csimplemacrodesc}
246246

247247
\begin{cfuncdesc}{PyObject*}{PyBool_FromLong}{long v}
248-
Return a new reference to \constant{Py_True} or \constant{Py_False}
248+
Return a new reference to \constant{Py_True} or \constant{Py_False}
249249
depending on the truth value of \var{v}.
250250
\versionadded{2.3}
251251
\end{cfuncdesc}
@@ -618,12 +618,24 @@ \subsection{String Objects \label{stringObjects}}
618618
exactly to the format characters in the \var{format} string. The
619619
following format characters are allowed:
620620

621+
% This should be exactly the same as the table in PyErr_Format.
622+
% One should just refer to the other.
623+
624+
% The descriptions for %zd and %zu are wrong, but the truth is complicated
625+
% because not all compilers support the %z width modifier -- we fake it
626+
% when necessary via interpolating PY_FORMAT_SIZE_T.
627+
628+
% %u, %lu, %zu should have "new in Python 2.5" blurbs.
629+
621630
\begin{tableiii}{l|l|l}{member}{Format Characters}{Type}{Comment}
622631
\lineiii{\%\%}{\emph{n/a}}{The literal \% character.}
623632
\lineiii{\%c}{int}{A single character, represented as an C int.}
624633
\lineiii{\%d}{int}{Exactly equivalent to \code{printf("\%d")}.}
634+
\lineiii{\%u}{unsigned int}{Exactly equivalent to \code{printf("\%u")}.}
625635
\lineiii{\%ld}{long}{Exactly equivalent to \code{printf("\%ld")}.}
626-
\lineiii{\%zd}{long}{Exactly equivalent to \code{printf("\%zd")}.}
636+
\lineiii{\%lu}{unsigned long}{Exactly equivalent to \code{printf("\%lu")}.}
637+
\lineiii{\%zd}{Py_ssize_t}{Exactly equivalent to \code{printf("\%zd")}.}
638+
\lineiii{\%zu}{ssize_t}{Exactly equivalent to \code{printf("\%zu")}.}
627639
\lineiii{\%i}{int}{Exactly equivalent to \code{printf("\%i")}.}
628640
\lineiii{\%x}{int}{Exactly equivalent to \code{printf("\%x")}.}
629641
\lineiii{\%s}{char*}{A null-terminated C character array.}
@@ -632,6 +644,10 @@ \subsection{String Objects \label{stringObjects}}
632644
guaranteed to start with the literal \code{0x} regardless of
633645
what the platform's \code{printf} yields.}
634646
\end{tableiii}
647+
648+
An unrecognized format character causes all the rest of the format
649+
string to be copied as-is to the result string, and any extra
650+
arguments discarded.
635651
\end{cfuncdesc}
636652

637653
\begin{cfuncdesc}{PyObject*}{PyString_FromFormatV}{const char *format,
@@ -687,7 +703,7 @@ \subsection{String Objects \label{stringObjects}}
687703
\var{size})}. It must not be deallocated. If \var{string} is a
688704
Unicode object, this function computes the default encoding of
689705
\var{string} and operates on that. If \var{string} is not a string
690-
object at all, \cfunction{PyString_AsStringAndSize()} returns
706+
object at all, \cfunction{PyString_AsStringAndSize()} returns
691707
\code{-1} and raises \exception{TypeError}.
692708
\end{cfuncdesc}
693709

@@ -1494,7 +1510,7 @@ \subsubsection{Methods and Slot Functions \label{unicodeMethodsAndSlots}}
14941510
Return 1 if \var{substr} matches \var{str}[\var{start}:\var{end}] at
14951511
the given tail end (\var{direction} == -1 means to do a prefix
14961512
match, \var{direction} == 1 a suffix match), 0 otherwise.
1497-
Return \code{-1} if an error occurred.
1513+
Return \code{-1} if an error occurred.
14981514
\end{cfuncdesc}
14991515

15001516
\begin{cfuncdesc}{Py_ssize_t}{PyUnicode_Find}{PyObject *str,
@@ -3013,7 +3029,7 @@ \subsection{DateTime Objects \label{datetime-objects}}
30133029

30143030

30153031
\subsection{Set Objects \label{setObjects}}
3016-
\sectionauthor{Raymond D. Hettinger}{python@rcn.com}
3032+
\sectionauthor{Raymond D. Hettinger}{python@rcn.com}
30173033

30183034
\obindex{set}
30193035
\obindex{frozenset}
@@ -3022,8 +3038,8 @@ \subsection{Set Objects \label{setObjects}}
30223038
This section details the public API for \class{set} and \class{frozenset}
30233039
objects. Any functionality not listed below is best accessed using the
30243040
either the abstract object protocol (including
3025-
\cfunction{PyObject_CallMethod()}, \cfunction{PyObject_RichCompareBool()},
3026-
\cfunction{PyObject_Hash()}, \cfunction{PyObject_Repr()},
3041+
\cfunction{PyObject_CallMethod()}, \cfunction{PyObject_RichCompareBool()},
3042+
\cfunction{PyObject_Hash()}, \cfunction{PyObject_Repr()},
30273043
\cfunction{PyObject_IsTrue()}, \cfunction{PyObject_Print()}, and
30283044
\cfunction{PyObject_GetIter()})
30293045
or the abstract number protocol (including
@@ -3040,7 +3056,7 @@ \subsection{Set Objects \label{setObjects}}
30403056
block of memory for medium and large sized sets (much like list storage).
30413057
None of the fields of this structure should be considered public and
30423058
are subject to change. All access should be done through the
3043-
documented API rather than by manipulating the values in the structure.
3059+
documented API rather than by manipulating the values in the structure.
30443060

30453061
\end{ctypedesc}
30463062

@@ -3059,7 +3075,7 @@ \subsection{Set Objects \label{setObjects}}
30593075
Likewise, the constructor functions work with any iterable Python object.
30603076

30613077
\begin{cfuncdesc}{int}{PyAnySet_Check}{PyObject *p}
3062-
Return true if \var{p} is a \class{set} object, a \class{frozenset}
3078+
Return true if \var{p} is a \class{set} object, a \class{frozenset}
30633079
object, or an instance of a subtype.
30643080
\end{cfuncdesc}
30653081

@@ -3112,7 +3128,7 @@ \subsection{Set Objects \label{setObjects}}
31123128
function does not automatically convert unhashable sets into temporary
31133129
frozensets. Raise a \exception{TypeError} if the \var{key} is unhashable.
31143130
Raise \exception{PyExc_SystemError} if \var{anyset} is not a \class{set},
3115-
\class{frozenset}, or an instance of a subtype.
3131+
\class{frozenset}, or an instance of a subtype.
31163132
\end{cfuncdesc}
31173133

31183134
The following functions are available for instances of \class{set} or
@@ -3134,15 +3150,15 @@ \subsection{Set Objects \label{setObjects}}
31343150
unhashable. Unlike the Python \method{discard()} method, this function
31353151
does not automatically convert unhashable sets into temporary frozensets.
31363152
Raise \exception{PyExc_SystemError} if \var{set} is an not an instance
3137-
of \class{set} or its subtype.
3153+
of \class{set} or its subtype.
31383154
\end{cfuncdesc}
31393155

31403156
\begin{cfuncdesc}{PyObject*}{PySet_Pop}{PyObject *set}
31413157
Return a new reference to an arbitrary object in the \var{set},
31423158
and removes the object from the \var{set}. Return \NULL{} on
31433159
failure. Raise \exception{KeyError} if the set is empty.
31443160
Raise a \exception{SystemError} if \var{set} is an not an instance
3145-
of \class{set} or its subtype.
3161+
of \class{set} or its subtype.
31463162
\end{cfuncdesc}
31473163

31483164
\begin{cfuncdesc}{int}{PySet_Clear}{PyObject *set}

Doc/api/exceptions.tex

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -135,13 +135,32 @@ \chapter{Exception Handling \label{exceptionHandling}}
135135
codes, similar to \cfunction{printf()}. The \code{width.precision}
136136
before a format code is parsed, but the width part is ignored.
137137

138-
\begin{tableii}{c|l}{character}{Character}{Meaning}
139-
\lineii{c}{Character, as an \ctype{int} parameter}
140-
\lineii{d}{Number in decimal, as an \ctype{int} parameter}
141-
\lineii{x}{Number in hexadecimal, as an \ctype{int} parameter}
142-
\lineii{s}{A string, as a \ctype{char *} parameter}
143-
\lineii{p}{A hex pointer, as a \ctype{void *} parameter}
144-
\end{tableii}
138+
% This should be exactly the same as the table in PyString_FromFormat.
139+
% One should just refer to the other.
140+
141+
% The descriptions for %zd and %zu are wrong, but the truth is complicated
142+
% because not all compilers support the %z width modifier -- we fake it
143+
% when necessary via interpolating PY_FORMAT_SIZE_T.
144+
145+
% %u, %lu, %zu should have "new in Python 2.5" blurbs.
146+
147+
\begin{tableiii}{l|l|l}{member}{Format Characters}{Type}{Comment}
148+
\lineiii{\%\%}{\emph{n/a}}{The literal \% character.}
149+
\lineiii{\%c}{int}{A single character, represented as an C int.}
150+
\lineiii{\%d}{int}{Exactly equivalent to \code{printf("\%d")}.}
151+
\lineiii{\%u}{unsigned int}{Exactly equivalent to \code{printf("\%u")}.}
152+
\lineiii{\%ld}{long}{Exactly equivalent to \code{printf("\%ld")}.}
153+
\lineiii{\%lu}{unsigned long}{Exactly equivalent to \code{printf("\%lu")}.}
154+
\lineiii{\%zd}{Py_ssize_t}{Exactly equivalent to \code{printf("\%zd")}.}
155+
\lineiii{\%zu}{ssize_t}{Exactly equivalent to \code{printf("\%zu")}.}
156+
\lineiii{\%i}{int}{Exactly equivalent to \code{printf("\%i")}.}
157+
\lineiii{\%x}{int}{Exactly equivalent to \code{printf("\%x")}.}
158+
\lineiii{\%s}{char*}{A null-terminated C character array.}
159+
\lineiii{\%p}{void*}{The hex representation of a C pointer.
160+
Mostly equivalent to \code{printf("\%p")} except that it is
161+
guaranteed to start with the literal \code{0x} regardless of
162+
what the platform's \code{printf} yields.}
163+
\end{tableiii}
145164

146165
An unrecognized format character causes all the rest of the format
147166
string to be copied as-is to the result string, and any extra
@@ -275,8 +294,8 @@ \chapter{Exception Handling \label{exceptionHandling}}
275294
command line documentation. There is no C API for warning control.
276295
\end{cfuncdesc}
277296

278-
\begin{cfuncdesc}{int}{PyErr_WarnExplicit}{PyObject *category,
279-
const char *message, const char *filename, int lineno,
297+
\begin{cfuncdesc}{int}{PyErr_WarnExplicit}{PyObject *category,
298+
const char *message, const char *filename, int lineno,
280299
const char *module, PyObject *registry}
281300
Issue a warning message with explicit control over all warning
282301
attributes. This is a straightforward wrapper around the Python
@@ -402,5 +421,5 @@ \section{Deprecation of String Exceptions}
402421
\withsubitem{(built-in exception)}{\ttindex{BaseException}}
403422

404423
String exceptions are still supported in the interpreter to allow
405-
existing code to run unmodified, but this will also change in a future
424+
existing code to run unmodified, but this will also change in a future
406425
release.

Misc/NEWS

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ Core and builtins
7272
Extension Modules
7373
-----------------
7474

75-
- On Win32, os.listdir now supports arbitrarily-long Unicode path names
75+
- On Win32, os.listdir now supports arbitrarily-long Unicode path names
7676
(up to the system limit of 32K characters).
7777

7878
- Use Win32 API to implement os.{access,chdir,chmod,mkdir,remove,rename,rmdir,utime}.
@@ -200,6 +200,10 @@ Build
200200
C API
201201
-----
202202

203+
- ``PyString_FromFormat``, ``PyErr_Format``, and ``PyString_FromFormatV``
204+
now accept formats "%u" for unsigned ints, "%lu" for unsigned longs,
205+
and "%zu" for unsigned integers of type ``size_t``.
206+
203207
Tests
204208
-----
205209

Modules/_testcapimodule.c

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -486,8 +486,8 @@ test_u_code(PyObject *self)
486486
return Py_None;
487487
}
488488

489-
static
490-
PyObject *codec_incrementalencoder(PyObject *self, PyObject *args)
489+
static PyObject *
490+
codec_incrementalencoder(PyObject *self, PyObject *args)
491491
{
492492
const char *encoding, *errors = NULL;
493493
if (!PyArg_ParseTuple(args, "s|s:test_incrementalencoder",
@@ -496,8 +496,8 @@ PyObject *codec_incrementalencoder(PyObject *self, PyObject *args)
496496
return PyCodec_IncrementalEncoder(encoding, errors);
497497
}
498498

499-
static
500-
PyObject *codec_incrementaldecoder(PyObject *self, PyObject *args)
499+
static PyObject *
500+
codec_incrementaldecoder(PyObject *self, PyObject *args)
501501
{
502502
const char *encoding, *errors = NULL;
503503
if (!PyArg_ParseTuple(args, "s|s:test_incrementaldecoder",
@@ -660,6 +660,44 @@ test_thread_state(PyObject *self, PyObject *args)
660660
}
661661
#endif
662662

663+
/* Some tests of PyString_FromFormat(). This needs more tests.
664+
* PyString_FromFormat() also needs docs.
665+
*/
666+
static PyObject *
667+
test_string_from_format(PyObject *self, PyObject *args)
668+
{
669+
PyObject *result;
670+
char *msg;
671+
672+
#define CHECK_1_FORMAT(FORMAT, TYPE) \
673+
result = PyString_FromFormat(FORMAT, (TYPE)1); \
674+
if (result == NULL) \
675+
return NULL; \
676+
if (strcmp(PyString_AsString(result), "1")) { \
677+
msg = FORMAT " failed at 1"; \
678+
goto Fail; \
679+
} \
680+
Py_DECREF(result)
681+
682+
CHECK_1_FORMAT("%d", int);
683+
CHECK_1_FORMAT("%ld", long);
684+
/* The z width modifier was added in Python 2.5. */
685+
CHECK_1_FORMAT("%zd", Py_ssize_t);
686+
687+
/* The u type code was added in Python 2.5. */
688+
CHECK_1_FORMAT("%u", unsigned int);
689+
CHECK_1_FORMAT("%lu", unsigned long);
690+
CHECK_1_FORMAT("%zu", size_t);
691+
692+
Py_RETURN_NONE;
693+
694+
Fail:
695+
Py_XDECREF(result);
696+
return raiseTestError("test_string_from_format", msg);
697+
698+
#undef CHECK_1_FORMAT
699+
}
700+
663701
static PyMethodDef TestMethods[] = {
664702
{"raise_exception", raise_exception, METH_VARARGS},
665703
{"test_config", (PyCFunction)test_config, METH_NOARGS},
@@ -669,6 +707,7 @@ static PyMethodDef TestMethods[] = {
669707
{"test_long_numbits", (PyCFunction)test_long_numbits, METH_NOARGS},
670708
{"test_k_code", (PyCFunction)test_k_code, METH_NOARGS},
671709
{"test_null_strings", (PyCFunction)test_null_strings, METH_NOARGS},
710+
{"test_string_from_format", (PyCFunction)test_string_from_format, METH_NOARGS},
672711

673712
{"getargs_b", getargs_b, METH_VARARGS},
674713
{"getargs_B", getargs_B, METH_VARARGS},

Objects/stringobject.c

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -176,14 +176,11 @@ PyString_FromFormatV(const char *format, va_list vargs)
176176
while (*++f && *f != '%' && !isalpha(Py_CHARMASK(*f)))
177177
;
178178

179-
/* skip the 'l' in %ld, since it doesn't change the
180-
width. although only %d is supported (see
181-
"expand" section below), others can be easily
182-
added */
183-
if (*f == 'l' && *(f+1) == 'd')
184-
++f;
185-
/* likewise for %zd */
186-
if (*f == 'z' && *(f+1) == 'd')
179+
/* skip the 'l' or 'z' in {%ld, %zd, %lu, %zu} since
180+
* they don't affect the amount of space we reserve.
181+
*/
182+
if ((*f == 'l' || *f == 'z') &&
183+
(f[1] == 'd' || f[1] == 'u'))
187184
++f;
188185

189186
switch (*f) {
@@ -193,7 +190,7 @@ PyString_FromFormatV(const char *format, va_list vargs)
193190
case '%':
194191
n++;
195192
break;
196-
case 'd': case 'i': case 'x':
193+
case 'd': case 'u': case 'i': case 'x':
197194
(void) va_arg(count, int);
198195
/* 20 bytes is enough to hold a 64-bit
199196
integer. Decimal takes the most space.
@@ -255,14 +252,14 @@ PyString_FromFormatV(const char *format, va_list vargs)
255252
}
256253
while (*f && *f != '%' && !isalpha(Py_CHARMASK(*f)))
257254
f++;
258-
/* handle the long flag, but only for %ld. others
259-
can be added when necessary. */
260-
if (*f == 'l' && *(f+1) == 'd') {
255+
/* handle the long flag, but only for %ld and %lu.
256+
others can be added when necessary. */
257+
if (*f == 'l' && (f[1] == 'd' || f[1] == 'u')) {
261258
longflag = 1;
262259
++f;
263260
}
264261
/* handle the size_t flag. */
265-
if (*f == 'z' && *(f+1) == 'd') {
262+
if (*f == 'z' && (f[1] == 'd' || f[1] == 'u')) {
266263
size_tflag = 1;
267264
++f;
268265
}
@@ -281,6 +278,18 @@ PyString_FromFormatV(const char *format, va_list vargs)
281278
sprintf(s, "%d", va_arg(vargs, int));
282279
s += strlen(s);
283280
break;
281+
case 'u':
282+
if (longflag)
283+
sprintf(s, "%lu",
284+
va_arg(vargs, unsigned long));
285+
else if (size_tflag)
286+
sprintf(s, "%" PY_FORMAT_SIZE_T "u",
287+
va_arg(vargs, size_t));
288+
else
289+
sprintf(s, "%u",
290+
va_arg(vargs, unsigned int));
291+
s += strlen(s);
292+
break;
284293
case 'i':
285294
sprintf(s, "%i", va_arg(vargs, int));
286295
s += strlen(s);

0 commit comments

Comments
 (0)