From: Raymond Hettinger Date: Wed, 26 Nov 2003 08:21:35 +0000 (+0000) Subject: Add optional fillchar argument to ljust(), rjust(), and center() string methods. X-Git-Tag: v2.4a1~1203 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4f8f9765766a126ebfff3c81655454821f1ad532;p=thirdparty%2FPython%2Fcpython.git Add optional fillchar argument to ljust(), rjust(), and center() string methods. --- diff --git a/Doc/lib/libstdtypes.tex b/Doc/lib/libstdtypes.tex index 4eb45958597e..9281dac8a3c4 100644 --- a/Doc/lib/libstdtypes.tex +++ b/Doc/lib/libstdtypes.tex @@ -546,9 +546,9 @@ objects support: Return a copy of the string with only its first character capitalized. \end{methoddesc} -\begin{methoddesc}[string]{center}{width} +\begin{methoddesc}[string]{center}{width\optional{, fillchar}} Return centered in a string of length \var{width}. Padding is done -using spaces. +using the specified \var{fillchar} (default is a space). \end{methoddesc} \begin{methoddesc}[string]{count}{sub\optional{, start\optional{, end}}} @@ -645,9 +645,10 @@ sequence \var{seq}. The separator between elements is the string providing this method. \end{methoddesc} -\begin{methoddesc}[string]{ljust}{width} +\begin{methoddesc}[string]{ljust}{width\optional{, fillchar}} Return the string left justified in a string of length \var{width}. -Padding is done using spaces. The original string is returned if +Padding is done using the specified \var{fillchar} (default is a +space). The original string is returned if \var{width} is less than \code{len(\var{s})}. \end{methoddesc} @@ -683,9 +684,10 @@ Like \method{rfind()} but raises \exception{ValueError} when the substring \var{sub} is not found. \end{methoddesc} -\begin{methoddesc}[string]{rjust}{width} +\begin{methoddesc}[string]{rjust}{width\optional{, fillchar}} Return the string right justified in a string of length \var{width}. -Padding is done using spaces. The original string is returned if +Padding is done using the specified \var{fillchar} (default is a space). +The original string is returned if \var{width} is less than \code{len(\var{s})}. \end{methoddesc} diff --git a/Lib/UserString.py b/Lib/UserString.py index 730cdba9e305..f28e54c44102 100755 --- a/Lib/UserString.py +++ b/Lib/UserString.py @@ -60,7 +60,8 @@ class UserString: # the following methods are defined in alphabetical order: def capitalize(self): return self.__class__(self.data.capitalize()) - def center(self, width): return self.__class__(self.data.center(width)) + def center(self, width, *args): + return self.__class__(self.data.center(width, *args)) def count(self, sub, start=0, end=sys.maxint): return self.data.count(sub, start, end) def decode(self, encoding=None, errors=None): # XXX improve this? @@ -97,7 +98,8 @@ class UserString: def istitle(self): return self.data.istitle() def isupper(self): return self.data.isupper() def join(self, seq): return self.data.join(seq) - def ljust(self, width): return self.__class__(self.data.ljust(width)) + def ljust(self, width, *args): + return self.__class__(self.data.ljust(width, *args)) def lower(self): return self.__class__(self.data.lower()) def lstrip(self, chars=None): return self.__class__(self.data.lstrip(chars)) def replace(self, old, new, maxsplit=-1): @@ -106,7 +108,8 @@ class UserString: return self.data.rfind(sub, start, end) def rindex(self, sub, start=0, end=sys.maxint): return self.data.rindex(sub, start, end) - def rjust(self, width): return self.__class__(self.data.rjust(width)) + def rjust(self, width, *args): + return self.__class__(self.data.rjust(width, *args)) def rstrip(self, chars=None): return self.__class__(self.data.rstrip(chars)) def split(self, sep=None, maxsplit=-1): return self.data.split(sep, maxsplit) diff --git a/Lib/string.py b/Lib/string.py index 5b5ddc3bb558..0a77f461ffda 100644 --- a/Lib/string.py +++ b/Lib/string.py @@ -237,37 +237,37 @@ def atol(s, base=10): # Left-justify a string -def ljust(s, width): - """ljust(s, width) -> string +def ljust(s, width, *args): + """ljust(s, width[, fillchar]) -> string Return a left-justified version of s, in a field of the specified width, padded with spaces as needed. The string is - never truncated. + never truncated. If specified the fillchar is used instead of spaces. """ - return s.ljust(width) + return s.ljust(width, *args) # Right-justify a string -def rjust(s, width): - """rjust(s, width) -> string +def rjust(s, width, *args): + """rjust(s, width[, fillchar]) -> string Return a right-justified version of s, in a field of the specified width, padded with spaces as needed. The string is - never truncated. + never truncated. If specified the fillchar is used instead of spaces. """ - return s.rjust(width) + return s.rjust(width, *args) # Center a string -def center(s, width): - """center(s, width) -> string +def center(s, width, *args): + """center(s, width[, fillchar]) -> string Return a center version of s, in a field of the specified width. padded with spaces as needed. The string is never - truncated. + truncated. If specified the fillchar is used instead of spaces. """ - return s.center(width) + return s.center(width, *args) # Zero-fill a number, e.g., (12, 3) --> '012' and (-3, 3) --> '-03' # Decadent feature: the argument may be a string or a number diff --git a/Lib/test/string_tests.py b/Lib/test/string_tests.py index af171d08ab3f..236c577607cd 100644 --- a/Lib/test/string_tests.py +++ b/Lib/test/string_tests.py @@ -227,7 +227,7 @@ class CommonTest(unittest.TestCase): self.checkequal('abc ', 'abc', 'ljust', 6) self.checkequal('abc', 'abc', 'ljust', 3) self.checkequal('abc', 'abc', 'ljust', 2) - + self.checkequal('abc*******', 'abc', 'ljust', 10, '*') self.checkraises(TypeError, 'abc', 'ljust') def test_rjust(self): @@ -235,7 +235,7 @@ class CommonTest(unittest.TestCase): self.checkequal(' abc', 'abc', 'rjust', 6) self.checkequal('abc', 'abc', 'rjust', 3) self.checkequal('abc', 'abc', 'rjust', 2) - + self.checkequal('*******abc', 'abc', 'rjust', 10, '*') self.checkraises(TypeError, 'abc', 'rjust') def test_center(self): @@ -243,7 +243,7 @@ class CommonTest(unittest.TestCase): self.checkequal(' abc ', 'abc', 'center', 6) self.checkequal('abc', 'abc', 'center', 3) self.checkequal('abc', 'abc', 'center', 2) - + self.checkequal('***abc****', 'abc', 'center', 10, '*') self.checkraises(TypeError, 'abc', 'center') def test_swapcase(self): diff --git a/Misc/NEWS b/Misc/NEWS index a3f3a18969ff..c9b7baa1c69c 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,10 @@ What's New in Python 2.4 alpha 1? Core and builtins ----------------- +- For str and unicode objects, the ljust(), center(), and rjust() + methods now accept an optional argument specifying a fill + character other than a space. + - When method objects have an attribute that can be satisfied either by the function object or by the method object, the function object's attribute usually wins. Christian Tismer pointed out that diff --git a/Objects/stringobject.c b/Objects/stringobject.c index 0a2244067102..739cc3edded2 100644 --- a/Objects/stringobject.c +++ b/Objects/stringobject.c @@ -2617,16 +2617,18 @@ pad(PyStringObject *self, int left, int right, char fill) } PyDoc_STRVAR(ljust__doc__, -"S.ljust(width) -> string\n" +"S.ljust(width[, fillchar]) -> string\n" "\n" "Return S left justified in a string of length width. Padding is\n" -"done using spaces."); +"done using the specified fill character (default is a space)."); static PyObject * string_ljust(PyStringObject *self, PyObject *args) { int width; - if (!PyArg_ParseTuple(args, "i:ljust", &width)) + char fillchar = ' '; + + if (!PyArg_ParseTuple(args, "i|c:ljust", &width, &fillchar)) return NULL; if (PyString_GET_SIZE(self) >= width && PyString_CheckExact(self)) { @@ -2634,21 +2636,23 @@ string_ljust(PyStringObject *self, PyObject *args) return (PyObject*) self; } - return pad(self, 0, width - PyString_GET_SIZE(self), ' '); + return pad(self, 0, width - PyString_GET_SIZE(self), fillchar); } PyDoc_STRVAR(rjust__doc__, -"S.rjust(width) -> string\n" +"S.rjust(width[, fillchar]) -> string\n" "\n" "Return S right justified in a string of length width. Padding is\n" -"done using spaces."); +"done using the specified fill character (default is a space)"); static PyObject * string_rjust(PyStringObject *self, PyObject *args) { int width; - if (!PyArg_ParseTuple(args, "i:rjust", &width)) + char fillchar = ' '; + + if (!PyArg_ParseTuple(args, "i|c:rjust", &width, &fillchar)) return NULL; if (PyString_GET_SIZE(self) >= width && PyString_CheckExact(self)) { @@ -2656,23 +2660,24 @@ string_rjust(PyStringObject *self, PyObject *args) return (PyObject*) self; } - return pad(self, width - PyString_GET_SIZE(self), 0, ' '); + return pad(self, width - PyString_GET_SIZE(self), 0, fillchar); } PyDoc_STRVAR(center__doc__, -"S.center(width) -> string\n" +"S.center(width[, fillchar]) -> string\n" "\n" -"Return S centered in a string of length width. Padding is done\n" -"using spaces."); +"Return S centered in a string of length width. Padding is\n" +"done using the specified fill character (default is a space)"); static PyObject * string_center(PyStringObject *self, PyObject *args) { int marg, left; int width; + char fillchar = ' '; - if (!PyArg_ParseTuple(args, "i:center", &width)) + if (!PyArg_ParseTuple(args, "i|c:center", &width, &fillchar)) return NULL; if (PyString_GET_SIZE(self) >= width && PyString_CheckExact(self)) { @@ -2683,7 +2688,7 @@ string_center(PyStringObject *self, PyObject *args) marg = width - PyString_GET_SIZE(self); left = marg / 2 + (marg & width & 1); - return pad(self, left, marg - left, ' '); + return pad(self, left, marg - left, fillchar); } PyDoc_STRVAR(zfill__doc__, diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c index e4fe53169567..c950f8b1691c 100644 --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -4404,19 +4404,47 @@ onError: } #endif +/* Argument converter. Coerces to a single unicode character */ + +static int +convert_uc(PyObject *obj, void *addr) +{ + Py_UNICODE *fillcharloc = (Py_UNICODE *)addr; + PyObject *uniobj; + Py_UNICODE *unistr; + + uniobj = PyUnicode_FromObject(obj); + if (uniobj == NULL) { + PyErr_SetString(PyExc_TypeError, + "The fill character cannot be converted to Unicode"); + return 0; + } + if (PyUnicode_GET_SIZE(uniobj) != 1) { + PyErr_SetString(PyExc_TypeError, + "The fill character must be exactly one character long"); + Py_DECREF(uniobj); + return 0; + } + unistr = PyUnicode_AS_UNICODE(uniobj); + *fillcharloc = unistr[0]; + Py_DECREF(uniobj); + return 1; +} + PyDoc_STRVAR(center__doc__, -"S.center(width) -> unicode\n\ +"S.center(width[, fillchar]) -> unicode\n\ \n\ -Return S centered in a Unicode string of length width. Padding is done\n\ -using spaces."); +Return S centered in a Unicode string of length width. Padding is\n\ +done using the specified fill character (default is a space)"); static PyObject * unicode_center(PyUnicodeObject *self, PyObject *args) { int marg, left; int width; + Py_UNICODE fillchar = ' '; - if (!PyArg_ParseTuple(args, "i:center", &width)) + if (!PyArg_ParseTuple(args, "i|O&:center", &width, convert_uc, &fillchar)) return NULL; if (self->length >= width && PyUnicode_CheckExact(self)) { @@ -4427,7 +4455,7 @@ unicode_center(PyUnicodeObject *self, PyObject *args) marg = width - self->length; left = marg / 2 + (marg & width & 1); - return (PyObject*) pad(self, left, marg - left, ' '); + return (PyObject*) pad(self, left, marg - left, fillchar); } #if 0 @@ -5170,16 +5198,18 @@ unicode_length(PyUnicodeObject *self) } PyDoc_STRVAR(ljust__doc__, -"S.ljust(width) -> unicode\n\ +"S.ljust(width[, fillchar]) -> unicode\n\ \n\ Return S left justified in a Unicode string of length width. Padding is\n\ -done using spaces."); +done using the specified fill character (default is a space)."); static PyObject * unicode_ljust(PyUnicodeObject *self, PyObject *args) { int width; - if (!PyArg_ParseTuple(args, "i:ljust", &width)) + Py_UNICODE fillchar = ' '; + + if (!PyArg_ParseTuple(args, "i|O&:ljust", &width, convert_uc, &fillchar)) return NULL; if (self->length >= width && PyUnicode_CheckExact(self)) { @@ -5187,7 +5217,7 @@ unicode_ljust(PyUnicodeObject *self, PyObject *args) return (PyObject*) self; } - return (PyObject*) pad(self, 0, width - self->length, ' '); + return (PyObject*) pad(self, 0, width - self->length, fillchar); } PyDoc_STRVAR(lower__doc__, @@ -5552,16 +5582,18 @@ unicode_rindex(PyUnicodeObject *self, PyObject *args) } PyDoc_STRVAR(rjust__doc__, -"S.rjust(width) -> unicode\n\ +"S.rjust(width[, fillchar]) -> unicode\n\ \n\ Return S right justified in a Unicode string of length width. Padding is\n\ -done using spaces."); +done using the specified fill character (default is a space)."); static PyObject * unicode_rjust(PyUnicodeObject *self, PyObject *args) { int width; - if (!PyArg_ParseTuple(args, "i:rjust", &width)) + Py_UNICODE fillchar = ' '; + + if (!PyArg_ParseTuple(args, "i|O&:rjust", &width, convert_uc, &fillchar)) return NULL; if (self->length >= width && PyUnicode_CheckExact(self)) { @@ -5569,7 +5601,7 @@ unicode_rjust(PyUnicodeObject *self, PyObject *args) return (PyObject*) self; } - return (PyObject*) pad(self, width - self->length, 0, ' '); + return (PyObject*) pad(self, width - self->length, 0, fillchar); } static PyObject*