@@ -186,19 +186,41 @@ def get_identifiers(self):
186
186
# The field name parser is implemented in _string.formatter_field_name_split
187
187
188
188
class Formatter :
189
+
190
+ class AutoNumber :
191
+ def __init__ (self ):
192
+ self .field_number = 0
193
+
194
+ def __next__ (self ):
195
+ if self .field_number is False :
196
+ raise ValueError ('cannot switch from manual field '
197
+ 'specification to automatic field '
198
+ 'numbering' )
199
+ self .field_number += 1
200
+ return self .field_number - 1
201
+
202
+ def set_manual (self ):
203
+ if self .field_number :
204
+ raise ValueError ('cannot switch from automatic '
205
+ 'field numbering to manual '
206
+ 'field specification' )
207
+ self .field_number = False
208
+
189
209
def format (self , format_string , / , * args , ** kwargs ):
190
210
return self .vformat (format_string , args , kwargs )
191
211
192
212
def vformat (self , format_string , args , kwargs ):
193
213
used_args = set ()
194
- result , _ = self ._vformat (format_string , args , kwargs , used_args , 2 )
214
+ result = self ._vformat (format_string , args , kwargs , used_args , 2 )
195
215
self .check_unused_args (used_args , args , kwargs )
196
216
return result
197
217
198
218
def _vformat (self , format_string , args , kwargs , used_args , recursion_depth ,
199
- auto_arg_index = 0 ):
219
+ auto_number = None ):
200
220
if recursion_depth < 0 :
201
221
raise ValueError ('Max string recursion exceeded' )
222
+ if not auto_number :
223
+ auto_number = Formatter .AutoNumber ()
202
224
result = []
203
225
for literal_text , field_name , format_spec , conversion in \
204
226
self .parse (format_string ):
@@ -212,22 +234,8 @@ def _vformat(self, format_string, args, kwargs, used_args, recursion_depth,
212
234
# this is some markup, find the object and do
213
235
# the formatting
214
236
215
- # handle arg indexing when empty field_names are given.
216
- if field_name == '' :
217
- if auto_arg_index is False :
218
- raise ValueError ('cannot switch from manual field '
219
- 'specification to automatic field '
220
- 'numbering' )
221
- field_name = str (auto_arg_index )
222
- auto_arg_index += 1
223
- elif field_name .isdigit ():
224
- if auto_arg_index :
225
- raise ValueError ('cannot switch from manual field '
226
- 'specification to automatic field '
227
- 'numbering' )
228
- # disable auto arg incrementing, if it gets
229
- # used later on, then an exception will be raised
230
- auto_arg_index = False
237
+ field_name = self .ensure_reference (field_name ,
238
+ auto_number )
231
239
232
240
# given the field_name, find the object it references
233
241
# and the argument it came from
@@ -238,15 +246,15 @@ def _vformat(self, format_string, args, kwargs, used_args, recursion_depth,
238
246
obj = self .convert_field (obj , conversion )
239
247
240
248
# expand the format spec, if needed
241
- format_spec , auto_arg_index = self ._vformat (
249
+ format_spec = self ._vformat (
242
250
format_spec , args , kwargs ,
243
251
used_args , recursion_depth - 1 ,
244
- auto_arg_index = auto_arg_index )
252
+ auto_number )
245
253
246
254
# format the object and append to the result
247
255
result .append (self .format_field (obj , format_spec ))
248
256
249
- return '' .join (result ), auto_arg_index
257
+ return '' .join (result )
250
258
251
259
252
260
def get_value (self , key , args , kwargs ):
@@ -288,6 +296,23 @@ def parse(self, format_string):
288
296
return _string .formatter_parser (format_string )
289
297
290
298
299
+ # given a field_name and auto_number, return a version
300
+ # starting with a name or index, taken from auto_number
301
+ # if necessary; calls auto_number.set_manual()
302
+ # if field_name already contains index
303
+ # field_name: the field being checked, e.g. "",
304
+ # ".name" or "[3]"
305
+ # auto_number numbering source
306
+ def ensure_reference (self , field_name , auto_number ):
307
+ first , _ = _string .formatter_field_name_split (field_name )
308
+ if first == '' :
309
+ first = str (next (auto_number ))
310
+ field_name = first + field_name
311
+ elif isinstance (first , int ):
312
+ auto_number .set_manual ()
313
+ return field_name
314
+
315
+
291
316
# given a field_name, find the object it references.
292
317
# field_name: the field being looked up, e.g. "0.name"
293
318
# or "lookup[3]"
0 commit comments