@@ -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
0 commit comments