[Python-checkins] r45992 - in python/trunk: Doc/api/concrete.tex Doc/api/exceptions.tex Misc/NEWS Modules/_testcapimodule.c Objects/stringobject.c

tim.peters python-checkins at python.org
Sun May 14 01:28:21 CEST 2006


Author: tim.peters
Date: Sun May 14 01:28:20 2006
New Revision: 45992

Modified:
   python/trunk/Doc/api/concrete.tex
   python/trunk/Doc/api/exceptions.tex
   python/trunk/Misc/NEWS
   python/trunk/Modules/_testcapimodule.c
   python/trunk/Objects/stringobject.c
Log:
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).


Modified: python/trunk/Doc/api/concrete.tex
==============================================================================
--- python/trunk/Doc/api/concrete.tex	(original)
+++ python/trunk/Doc/api/concrete.tex	Sun May 14 01:28:20 2006
@@ -245,7 +245,7 @@
 \end{csimplemacrodesc}
 
 \begin{cfuncdesc}{PyObject*}{PyBool_FromLong}{long v}
-  Return a new reference to \constant{Py_True} or \constant{Py_False} 
+  Return a new reference to \constant{Py_True} or \constant{Py_False}
   depending on the truth value of \var{v}.
 \versionadded{2.3}
 \end{cfuncdesc}
@@ -618,12 +618,24 @@
   exactly to the format characters in the \var{format} string.  The
   following format characters are allowed:
 
+  % This should be exactly the same as the table in PyErr_Format.
+  % One should just refer to the other.
+
+  % The descriptions for %zd and %zu are wrong, but the truth is complicated
+  % because not all compilers support the %z width modifier -- we fake it
+  % when necessary via interpolating PY_FORMAT_SIZE_T.
+
+  % %u, %lu, %zu should have "new in Python 2.5" blurbs.
+
   \begin{tableiii}{l|l|l}{member}{Format Characters}{Type}{Comment}
     \lineiii{\%\%}{\emph{n/a}}{The literal \% character.}
     \lineiii{\%c}{int}{A single character, represented as an C int.}
     \lineiii{\%d}{int}{Exactly equivalent to \code{printf("\%d")}.}
+    \lineiii{\%u}{unsigned int}{Exactly equivalent to \code{printf("\%u")}.}
     \lineiii{\%ld}{long}{Exactly equivalent to \code{printf("\%ld")}.}
-    \lineiii{\%zd}{long}{Exactly equivalent to \code{printf("\%zd")}.}
+    \lineiii{\%lu}{unsigned long}{Exactly equivalent to \code{printf("\%lu")}.}
+    \lineiii{\%zd}{Py_ssize_t}{Exactly equivalent to \code{printf("\%zd")}.}
+    \lineiii{\%zu}{ssize_t}{Exactly equivalent to \code{printf("\%zu")}.}
     \lineiii{\%i}{int}{Exactly equivalent to \code{printf("\%i")}.}
     \lineiii{\%x}{int}{Exactly equivalent to \code{printf("\%x")}.}
     \lineiii{\%s}{char*}{A null-terminated C character array.}
@@ -632,6 +644,10 @@
 	guaranteed to start with the literal \code{0x} regardless of
 	what the platform's \code{printf} yields.}
   \end{tableiii}
+
+  An unrecognized format character causes all the rest of the format
+  string to be copied as-is to the result string, and any extra
+  arguments discarded.
 \end{cfuncdesc}
 
 \begin{cfuncdesc}{PyObject*}{PyString_FromFormatV}{const char *format,
@@ -687,7 +703,7 @@
   \var{size})}.  It must not be deallocated.  If \var{string} is a
   Unicode object, this function computes the default encoding of
   \var{string} and operates on that.  If \var{string} is not a string
-  object at all, \cfunction{PyString_AsStringAndSize()} returns 
+  object at all, \cfunction{PyString_AsStringAndSize()} returns
   \code{-1} and raises \exception{TypeError}.
 \end{cfuncdesc}
 
@@ -1494,7 +1510,7 @@
   Return 1 if \var{substr} matches \var{str}[\var{start}:\var{end}] at
   the given tail end (\var{direction} == -1 means to do a prefix
   match, \var{direction} == 1 a suffix match), 0 otherwise.
-  Return \code{-1} if an error occurred.                         
+  Return \code{-1} if an error occurred.
 \end{cfuncdesc}
 
 \begin{cfuncdesc}{Py_ssize_t}{PyUnicode_Find}{PyObject *str,
@@ -3013,7 +3029,7 @@
 
 
 \subsection{Set Objects \label{setObjects}}
-\sectionauthor{Raymond D. Hettinger}{python at rcn.com}                     
+\sectionauthor{Raymond D. Hettinger}{python at rcn.com}
 
 \obindex{set}
 \obindex{frozenset}
@@ -3022,8 +3038,8 @@
 This section details the public API for \class{set} and \class{frozenset}
 objects.  Any functionality not listed below is best accessed using the
 either the abstract object protocol (including
-\cfunction{PyObject_CallMethod()}, \cfunction{PyObject_RichCompareBool()}, 
-\cfunction{PyObject_Hash()}, \cfunction{PyObject_Repr()}, 
+\cfunction{PyObject_CallMethod()}, \cfunction{PyObject_RichCompareBool()},
+\cfunction{PyObject_Hash()}, \cfunction{PyObject_Repr()},
 \cfunction{PyObject_IsTrue()}, \cfunction{PyObject_Print()}, and
 \cfunction{PyObject_GetIter()})
 or the abstract number protocol (including
@@ -3040,7 +3056,7 @@
   block of memory for medium and large sized sets (much like list storage).
   None of the fields of this structure should be considered public and
   are subject to change.  All access should be done through the
-  documented API rather than by manipulating the values in the structure. 
+  documented API rather than by manipulating the values in the structure.
 
 \end{ctypedesc}
 
@@ -3059,7 +3075,7 @@
 Likewise, the constructor functions work with any iterable Python object.
 
 \begin{cfuncdesc}{int}{PyAnySet_Check}{PyObject *p}
-  Return true if \var{p} is a \class{set} object, a \class{frozenset} 
+  Return true if \var{p} is a \class{set} object, a \class{frozenset}
   object, or an instance of a subtype.
 \end{cfuncdesc}
 
@@ -3112,7 +3128,7 @@
   function does not automatically convert unhashable sets into temporary
   frozensets.  Raise a \exception{TypeError} if the \var{key} is unhashable.
   Raise \exception{PyExc_SystemError} if \var{anyset} is not a \class{set},
-  \class{frozenset}, or an instance of a subtype.                         
+  \class{frozenset}, or an instance of a subtype.
 \end{cfuncdesc}
 
 The following functions are available for instances of \class{set} or
@@ -3134,7 +3150,7 @@
   unhashable.  Unlike the Python \method{discard()} method, this function
   does not automatically convert unhashable sets into temporary frozensets.
   Raise \exception{PyExc_SystemError} if \var{set} is an not an instance
-  of \class{set} or its subtype.                         
+  of \class{set} or its subtype.
 \end{cfuncdesc}
 
 \begin{cfuncdesc}{PyObject*}{PySet_Pop}{PyObject *set}
@@ -3142,7 +3158,7 @@
   and removes the object from the \var{set}.  Return \NULL{} on
   failure.  Raise \exception{KeyError} if the set is empty.
   Raise a \exception{SystemError} if \var{set} is an not an instance
-  of \class{set} or its subtype.                        
+  of \class{set} or its subtype.
 \end{cfuncdesc}
 
 \begin{cfuncdesc}{int}{PySet_Clear}{PyObject *set}

Modified: python/trunk/Doc/api/exceptions.tex
==============================================================================
--- python/trunk/Doc/api/exceptions.tex	(original)
+++ python/trunk/Doc/api/exceptions.tex	Sun May 14 01:28:20 2006
@@ -135,13 +135,32 @@
   codes, similar to \cfunction{printf()}. The \code{width.precision}
   before a format code is parsed, but the width part is ignored.
 
-  \begin{tableii}{c|l}{character}{Character}{Meaning}
-    \lineii{c}{Character, as an \ctype{int} parameter}
-    \lineii{d}{Number in decimal, as an \ctype{int} parameter}
-    \lineii{x}{Number in hexadecimal, as an \ctype{int} parameter}
-    \lineii{s}{A string, as a \ctype{char *} parameter}
-    \lineii{p}{A hex pointer, as a \ctype{void *} parameter}
-  \end{tableii}
+  % This should be exactly the same as the table in PyString_FromFormat.
+  % One should just refer to the other.
+
+  % The descriptions for %zd and %zu are wrong, but the truth is complicated
+  % because not all compilers support the %z width modifier -- we fake it
+  % when necessary via interpolating PY_FORMAT_SIZE_T.
+
+  % %u, %lu, %zu should have "new in Python 2.5" blurbs.
+
+  \begin{tableiii}{l|l|l}{member}{Format Characters}{Type}{Comment}
+    \lineiii{\%\%}{\emph{n/a}}{The literal \% character.}
+    \lineiii{\%c}{int}{A single character, represented as an C int.}
+    \lineiii{\%d}{int}{Exactly equivalent to \code{printf("\%d")}.}
+    \lineiii{\%u}{unsigned int}{Exactly equivalent to \code{printf("\%u")}.}
+    \lineiii{\%ld}{long}{Exactly equivalent to \code{printf("\%ld")}.}
+    \lineiii{\%lu}{unsigned long}{Exactly equivalent to \code{printf("\%lu")}.}
+    \lineiii{\%zd}{Py_ssize_t}{Exactly equivalent to \code{printf("\%zd")}.}
+    \lineiii{\%zu}{ssize_t}{Exactly equivalent to \code{printf("\%zu")}.}
+    \lineiii{\%i}{int}{Exactly equivalent to \code{printf("\%i")}.}
+    \lineiii{\%x}{int}{Exactly equivalent to \code{printf("\%x")}.}
+    \lineiii{\%s}{char*}{A null-terminated C character array.}
+    \lineiii{\%p}{void*}{The hex representation of a C pointer.
+	Mostly equivalent to \code{printf("\%p")} except that it is
+	guaranteed to start with the literal \code{0x} regardless of
+	what the platform's \code{printf} yields.}
+  \end{tableiii}
 
   An unrecognized format character causes all the rest of the format
   string to be copied as-is to the result string, and any extra
@@ -275,8 +294,8 @@
   command line documentation.  There is no C API for warning control.
 \end{cfuncdesc}
 
-\begin{cfuncdesc}{int}{PyErr_WarnExplicit}{PyObject *category, 
-                const char *message, const char *filename, int lineno, 
+\begin{cfuncdesc}{int}{PyErr_WarnExplicit}{PyObject *category,
+                const char *message, const char *filename, int lineno,
                 const char *module, PyObject *registry}
   Issue a warning message with explicit control over all warning
   attributes.  This is a straightforward wrapper around the Python
@@ -402,5 +421,5 @@
 \withsubitem{(built-in exception)}{\ttindex{BaseException}}
 
 String exceptions are still supported in the interpreter to allow
-existing code to run unmodified, but this will also change in a future 
+existing code to run unmodified, but this will also change in a future
 release.

Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS	(original)
+++ python/trunk/Misc/NEWS	Sun May 14 01:28:20 2006
@@ -72,7 +72,7 @@
 Extension Modules
 -----------------
 
-- On Win32, os.listdir now supports arbitrarily-long Unicode path names 
+- On Win32, os.listdir now supports arbitrarily-long Unicode path names
   (up to the system limit of 32K characters).
 
 - Use Win32 API to implement os.{access,chdir,chmod,mkdir,remove,rename,rmdir,utime}.
@@ -200,6 +200,10 @@
 C API
 -----
 
+- ``PyString_FromFormat``, ``PyErr_Format``, and ``PyString_FromFormatV``
+  now accept formats "%u" for unsigned ints, "%lu" for unsigned longs,
+  and "%zu" for unsigned integers of type ``size_t``.
+
 Tests
 -----
 

Modified: python/trunk/Modules/_testcapimodule.c
==============================================================================
--- python/trunk/Modules/_testcapimodule.c	(original)
+++ python/trunk/Modules/_testcapimodule.c	Sun May 14 01:28:20 2006
@@ -486,8 +486,8 @@
 	return Py_None;
 }
 
-static
-PyObject *codec_incrementalencoder(PyObject *self, PyObject *args)
+static PyObject *
+codec_incrementalencoder(PyObject *self, PyObject *args)
 {
 	const char *encoding, *errors = NULL;
 	if (!PyArg_ParseTuple(args, "s|s:test_incrementalencoder",
@@ -496,8 +496,8 @@
 	return PyCodec_IncrementalEncoder(encoding, errors);
 }
 
-static
-PyObject *codec_incrementaldecoder(PyObject *self, PyObject *args)
+static PyObject *
+codec_incrementaldecoder(PyObject *self, PyObject *args)
 {
 	const char *encoding, *errors = NULL;
 	if (!PyArg_ParseTuple(args, "s|s:test_incrementaldecoder",
@@ -660,6 +660,44 @@
 }
 #endif
 
+/* Some tests of PyString_FromFormat().  This needs more tests.
+ * PyString_FromFormat() also needs docs.
+ */
+static PyObject *
+test_string_from_format(PyObject *self, PyObject *args)
+{
+	PyObject *result;
+	char *msg;
+
+#define CHECK_1_FORMAT(FORMAT, TYPE) 			\
+	result = PyString_FromFormat(FORMAT, (TYPE)1);	\
+	if (result == NULL)				\
+		return NULL;				\
+	if (strcmp(PyString_AsString(result), "1")) {	\
+		msg = FORMAT " failed at 1";		\
+		goto Fail;				\
+	}						\
+	Py_DECREF(result)
+
+	CHECK_1_FORMAT("%d", int);
+	CHECK_1_FORMAT("%ld", long);
+	/* The z width modifier was added in Python 2.5. */
+	CHECK_1_FORMAT("%zd", Py_ssize_t);
+
+	/* The u type code was added in Python 2.5. */
+	CHECK_1_FORMAT("%u", unsigned int);
+	CHECK_1_FORMAT("%lu", unsigned long);
+	CHECK_1_FORMAT("%zu", size_t);
+
+	Py_RETURN_NONE;
+
+ Fail:
+ 	Py_XDECREF(result);
+	return raiseTestError("test_string_from_format", msg);
+
+#undef CHECK_1_FORMAT
+}
+
 static PyMethodDef TestMethods[] = {
 	{"raise_exception",	raise_exception,		 METH_VARARGS},
 	{"test_config",		(PyCFunction)test_config,	 METH_NOARGS},
@@ -669,6 +707,7 @@
 	{"test_long_numbits",	(PyCFunction)test_long_numbits,	 METH_NOARGS},
 	{"test_k_code",		(PyCFunction)test_k_code,	 METH_NOARGS},
 	{"test_null_strings",	(PyCFunction)test_null_strings,	 METH_NOARGS},
+	{"test_string_from_format", (PyCFunction)test_string_from_format, METH_NOARGS},
 
 	{"getargs_b",		getargs_b,			 METH_VARARGS},
 	{"getargs_B",		getargs_B,			 METH_VARARGS},

Modified: python/trunk/Objects/stringobject.c
==============================================================================
--- python/trunk/Objects/stringobject.c	(original)
+++ python/trunk/Objects/stringobject.c	Sun May 14 01:28:20 2006
@@ -176,14 +176,11 @@
 			while (*++f && *f != '%' && !isalpha(Py_CHARMASK(*f)))
 				;
 
-			/* skip the 'l' in %ld, since it doesn't change the
-			   width.  although only %d is supported (see
-			   "expand" section below), others can be easily
-			   added */
-			if (*f == 'l' && *(f+1) == 'd')
-				++f;
-			/* likewise for %zd */
-			if (*f == 'z' && *(f+1) == 'd')
+			/* skip the 'l' or 'z' in {%ld, %zd, %lu, %zu} since
+			 * they don't affect the amount of space we reserve.
+			 */
+			if ((*f == 'l' || *f == 'z') &&
+					(f[1] == 'd' || f[1] == 'u'))
 				++f;
 
 			switch (*f) {
@@ -193,7 +190,7 @@
 			case '%':
 				n++;
 				break;
-			case 'd': case 'i': case 'x':
+			case 'd': case 'u': case 'i': case 'x':
 				(void) va_arg(count, int);
 				/* 20 bytes is enough to hold a 64-bit
 				   integer.  Decimal takes the most space.
@@ -255,14 +252,14 @@
 			}
 			while (*f && *f != '%' && !isalpha(Py_CHARMASK(*f)))
 				f++;
-			/* handle the long flag, but only for %ld.  others
-			   can be added when necessary. */
-			if (*f == 'l' && *(f+1) == 'd') {
+			/* handle the long flag, but only for %ld and %lu.
+			   others can be added when necessary. */
+			if (*f == 'l' && (f[1] == 'd' || f[1] == 'u')) {
 				longflag = 1;
 				++f;
 			}
 			/* handle the size_t flag. */
-			if (*f == 'z' && *(f+1) == 'd') {
+			if (*f == 'z' && (f[1] == 'd' || f[1] == 'u')) {
 				size_tflag = 1;
 				++f;
 			}
@@ -281,6 +278,18 @@
 					sprintf(s, "%d", va_arg(vargs, int));
 				s += strlen(s);
 				break;
+			case 'u':
+				if (longflag)
+					sprintf(s, "%lu",
+						va_arg(vargs, unsigned long));
+				else if (size_tflag)
+					sprintf(s, "%" PY_FORMAT_SIZE_T "u",
+					        va_arg(vargs, size_t));
+				else
+					sprintf(s, "%u",
+						va_arg(vargs, unsigned int));
+				s += strlen(s);
+				break;
 			case 'i':
 				sprintf(s, "%i", va_arg(vargs, int));
 				s += strlen(s);


More information about the Python-checkins mailing list