Skip to content

Commit eb6076d

Browse files
author
eric.smith
committed
Simplified tuple returned by string._formatter_parser to only have
4 elements. No need for old is_markup element, the same information is indicated by literal_string being None. Factored string.Formatter class to make subclasses easier to write. git-svn-id: http://svn.python.org/projects/python/branches/py3k@57615 6015fed2-1504-0410-9fe1-9d1591cc4771
1 parent 38fa109 commit eb6076d

2 files changed

Lines changed: 59 additions & 32 deletions

File tree

Lib/string.py

Lines changed: 58 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -208,49 +208,83 @@ def format(self, format_string, *args, **kwargs):
208208
return self.vformat(format_string, args, kwargs)
209209

210210
def vformat(self, format_string, args, kwargs):
211-
used_args = set()
211+
used_args = self.get_empty_used_args()
212212
result = []
213-
for (is_markup, literal, field_name, format_spec, conversion) in \
214-
format_string._formatter_parser():
215-
if is_markup:
216-
# given the field_name, find the object it references
217-
218-
# split it into the first part, and and iterator that
219-
# looks over the rest
220-
first, rest = field_name._formatter_field_name_split()
221-
222-
used_args.add(first)
223-
obj = self.get_value(first, args, kwargs)
213+
for literal_text, field_name, format_spec, conversion in \
214+
self.parse(format_string):
215+
if literal_text is None:
216+
# this is some markup, find the object and do
217+
# the formatting
224218

225-
# loop through the rest of the field_name, doing
226-
# getattr or getitem as needed
227-
for is_attr, i in rest:
228-
if is_attr:
229-
obj = getattr(obj, i)
230-
else:
231-
obj = obj[i]
219+
# given the field_name, find the object it references
220+
obj = self.get_field(field_name, args, kwargs, used_args)
232221

233222
# do any conversion on the resulting object
234-
if conversion == 'r':
235-
obj = repr(obj)
236-
elif conversion == 's':
237-
obj = str(obj)
223+
obj = self.convert_field(obj, conversion)
238224

239225
# format the object and append to the result
240226
result.append(self.format_field(obj, format_spec))
241227
else:
242-
result.append(literal)
228+
# this is literal text, use it directly
229+
result.append(literal_text)
243230
self.check_unused_args(used_args, args, kwargs)
244231
return ''.join(result)
245232

233+
234+
def get_empty_used_args(self):
235+
return set()
236+
237+
246238
def get_value(self, key, args, kwargs):
247239
if isinstance(key, int):
248240
return args[key]
249241
else:
250242
return kwargs[key]
251243

244+
252245
def check_unused_args(self, used_args, args, kwargs):
253246
pass
254247

248+
255249
def format_field(self, value, format_spec):
256250
return format(value, format_spec)
251+
252+
253+
def convert_field(self, value, conversion):
254+
# do any conversion on the resulting object
255+
if conversion == 'r':
256+
return repr(value)
257+
elif conversion == 's':
258+
return str(value)
259+
else:
260+
assert conversion is None
261+
return value
262+
263+
264+
# returns an iterable that contains tuples of the form:
265+
# (literal_text, field_name, format_spec, conversion)
266+
def parse(self, format_string):
267+
return format_string._formatter_parser()
268+
269+
270+
# given a field_name, find the object it references.
271+
# field_name: the field being looked up, e.g. "0.name"
272+
# or "lookup[3]"
273+
# used_args: a set of which args have been used
274+
# args, kwargs: as passed in to vformat
275+
# also, mark it as used in 'used_args'
276+
def get_field(self, field_name, args, kwargs, used_args):
277+
first, rest = field_name._formatter_field_name_split()
278+
279+
used_args.add(first)
280+
obj = self.get_value(first, args, kwargs)
281+
282+
# loop through the rest of the field_name, doing
283+
# getattr or getitem as needed
284+
for is_attr, i in rest:
285+
if is_attr:
286+
obj = getattr(obj, i)
287+
else:
288+
obj = obj[i]
289+
290+
return obj

Objects/stringlib/string_format.h

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -979,17 +979,12 @@ formatteriter_next(formatteriterobject *it)
979979
/* if 0, error has already been set, if 1, iterator is empty */
980980
return NULL;
981981
else {
982-
PyObject *is_markup_bool = NULL;
983982
PyObject *literal_str = NULL;
984983
PyObject *field_name_str = NULL;
985984
PyObject *format_spec_str = NULL;
986985
PyObject *conversion_str = NULL;
987986
PyObject *tuple = NULL;
988987

989-
is_markup_bool = PyBool_FromLong(is_markup);
990-
if (!is_markup_bool)
991-
return NULL;
992-
993988
if (is_markup) {
994989
/* field_name, format_spec, and conversion are returned */
995990
literal_str = Py_None;
@@ -1030,11 +1025,9 @@ formatteriter_next(formatteriterobject *it)
10301025
Py_INCREF(format_spec_str);
10311026
Py_INCREF(conversion_str);
10321027
}
1033-
tuple = PyTuple_Pack(5, is_markup_bool, literal_str,
1034-
field_name_str, format_spec_str,
1028+
tuple = PyTuple_Pack(4, literal_str, field_name_str, format_spec_str,
10351029
conversion_str);
10361030
error:
1037-
Py_XDECREF(is_markup_bool);
10381031
Py_XDECREF(literal_str);
10391032
Py_XDECREF(field_name_str);
10401033
Py_XDECREF(format_spec_str);

0 commit comments

Comments
 (0)