@@ -527,3 +527,115 @@ def replace(s, old, new, maxsplit=-1):
527527 letters = lowercase + uppercase
528528except ImportError :
529529 pass # Use the original versions
530+
531+ ########################################################################
532+ # the Formatter class
533+ # see PEP 3101 for details and purpose of this class
534+
535+ # The hard parts are reused from the C implementation. They're
536+ # exposed here via the sys module. sys was chosen because it's always
537+ # available and doesn't have to be dynamically loaded.
538+
539+ # The overall parser is implemented in str._formatter_parser.
540+ # The field name parser is implemented in str._formatter_field_name_split
541+
542+ class Formatter (object ):
543+ def format (self , format_string , * args , ** kwargs ):
544+ return self .vformat (format_string , args , kwargs )
545+
546+ def vformat (self , format_string , args , kwargs ):
547+ used_args = set ()
548+ result = self ._vformat (format_string , args , kwargs , used_args , 2 )
549+ self .check_unused_args (used_args , args , kwargs )
550+ return result
551+
552+ def _vformat (self , format_string , args , kwargs , used_args , recursion_depth ):
553+ if recursion_depth < 0 :
554+ raise ValueError ('Max string recursion exceeded' )
555+ result = []
556+ for literal_text , field_name , format_spec , conversion in \
557+ self .parse (format_string ):
558+
559+ # output the literal text
560+ if literal_text :
561+ result .append (literal_text )
562+
563+ # if there's a field, output it
564+ if field_name is not None :
565+ # this is some markup, find the object and do
566+ # the formatting
567+
568+ # given the field_name, find the object it references
569+ # and the argument it came from
570+ obj , arg_used = self .get_field (field_name , args , kwargs )
571+ used_args .add (arg_used )
572+
573+ # do any conversion on the resulting object
574+ obj = self .convert_field (obj , conversion )
575+
576+ # expand the format spec, if needed
577+ format_spec = self ._vformat (format_spec , args , kwargs ,
578+ used_args , recursion_depth - 1 )
579+
580+ # format the object and append to the result
581+ result .append (self .format_field (obj , format_spec ))
582+
583+ return '' .join (result )
584+
585+
586+ def get_value (self , key , args , kwargs ):
587+ if isinstance (key , (int , long )):
588+ return args [key ]
589+ else :
590+ return kwargs [key ]
591+
592+
593+ def check_unused_args (self , used_args , args , kwargs ):
594+ pass
595+
596+
597+ def format_field (self , value , format_spec ):
598+ return format (value , format_spec )
599+
600+
601+ def convert_field (self , value , conversion ):
602+ # do any conversion on the resulting object
603+ if conversion == 'r' :
604+ return repr (value )
605+ elif conversion == 's' :
606+ return str (value )
607+ elif conversion is None :
608+ return value
609+ raise ValueError ("Unknown converion specifier {0!s}" .format (conversion ))
610+
611+
612+ # returns an iterable that contains tuples of the form:
613+ # (literal_text, field_name, format_spec, conversion)
614+ # literal_text can be zero length
615+ # field_name can be None, in which case there's no
616+ # object to format and output
617+ # if field_name is not None, it is looked up, formatted
618+ # with format_spec and conversion and then used
619+ def parse (self , format_string ):
620+ return format_string ._formatter_parser ()
621+
622+
623+ # given a field_name, find the object it references.
624+ # field_name: the field being looked up, e.g. "0.name"
625+ # or "lookup[3]"
626+ # used_args: a set of which args have been used
627+ # args, kwargs: as passed in to vformat
628+ def get_field (self , field_name , args , kwargs ):
629+ first , rest = field_name ._formatter_field_name_split ()
630+
631+ obj = self .get_value (first , args , kwargs )
632+
633+ # loop through the rest of the field_name, doing
634+ # getattr or getitem as needed
635+ for is_attr , i in rest :
636+ if is_attr :
637+ obj = getattr (obj , i )
638+ else :
639+ obj = obj [i ]
640+
641+ return obj , first
0 commit comments