Movatterモバイル変換


[0]ホーム

URL:


Skip to content
Search Gists
Sign in Sign up

Instantly share code, notes, and snippets.

@vsajip
CreatedOctober 3, 2009 22:25
    • Star(0)You must be signed in to star a gist
    • Fork(0)You must be signed in to fork a gist

    Select an option

    Save vsajip/200936 to your computer and use it in GitHub Desktop.
    #
    # Copyright (C) 2009 Vinay Sajip.
    # Licensed under the PSF licence.
    # Exploratory code to convert %-format strings to {}-format.
    #
    importre
    PATTERN=re.compile(r'''
    % # specifier start
    (\((?P<key>[^)]+)\))? # optional mapping key
    (?P<flags>[#+0 -]*) # conversion flags
    (?P<min_width>(\*|([1-9][0-9]*)))? # minimum width
    (\.(?P<precision>(\*|([1-9][0-9]*))))? # precision
    (?P<len_modifier>[hlL])? # length modifier
    (?P<conversion>[diouxXeEfFgGcrs%]) # conversion
    ''',re.VERBOSE)
    classPercentConversion:
    '''Represents a single conversion group.'''
    def__init__(self,converter,match):
    '''
    Initialize using the regex match information.
    The converter is passed because we need to keep track of the
    positional argument index, so that we can support minimum width
    and precision values of '*'.
    '''
    self.source=match.group(0)
    d=match.groupdict()
    self.span=match.span()
    s=d['key']
    ifsisNone:
    self.key=converter.next_index()
    else:
    self.key=s
    s=d['min_width']
    ifs=='*':
    #TODO {} representation is hard-wired, could generalise this
    #if needed.
    self.min_width='{%s}'%converter.next_index()
    else:
    self.min_width=s
    s=d['precision']
    ifs=='*':
    self.precision='{%s}'%converter.next_index()
    else:
    self.precision=s
    #len_modifier not used
    #self.len_modifier = d['len_modifier']
    self.flags=d['flags']
    self.conversion=d['conversion']
    defas_brace(self):
    '''Return representation of this conversion group for {}-formatting.'''
    #TODO: '#', ' ' flags not handled
    conversion=self.conversion
    ifconversion=='%':
    result='%'
    else:
    key=self.key
    flags=self.flags
    ifself.min_widthisNone:
    align=''
    elif'-'inflags:
    align=''# could use '<', but as it's the default...
    elif'0'inflagsandconversionin'diouxX':
    align='='
    else:
    align='>'
    sign=''
    if'+'inflags:
    sign='+'
    elif' 'inflags:
    sign=' '
    alt=''
    fill=''
    if'0'inflagsand'-'notinflagsandconversionnotin'crs':
    fill='0'
    if'#'inflagsandconversionin'diuxX':# exclude 'o'
    alt='#'
    transform=''
    ifconversionin'iu':
    conversion='d'
    #%s is interpreted as calling str() on the operand, so
    #we specify !s in the {}-format. If we don't do this, then
    #we can't convert the case where %s is used to print e.g. integers
    #or floats.
    elifconversionin'rs':
    transform='!'+conversion
    conversion=''
    prefix='%s%s'% (key,transform)
    suffix='%s%s%s%s'% (fill,align,sign,alt)
    ifself.min_width:
    suffix+=self.min_width
    ifself.precision:
    suffix+='.'+self.precision
    suffix+=conversion
    result=prefix
    ifsuffix:
    result+=':'+suffix
    result='{%s}'%result
    returnresult
    classPercentToBraceConverter:
    '''Utility class to convert a %-format string to a {}-format string.'''
    def__init__(self,percent_format):
    self.initial=percent_format
    self.argindex=0
    defnext_index(self):
    '''Get the next argument index.'''
    result='%d'%self.argindex
    self.argindex+=1
    returnresult
    defconvert(self):
    '''Perform the conversion, and return its result.'''
    s=self.initial.replace('{','{{').replace('}','}}')
    result= [cforcins]# convert to mutable form
    matches= [mforminPATTERN.finditer(s)]
    conversions= []
    ifmatches:
    forminmatches:
    conversions.append(PercentConversion(self,m))
    #Go backwards so that span values remain valid as we go
    forconvinreversed(conversions):
    s,e=conv.span
    result[s:e]=conv.as_brace()
    return''.join(result),conversions
    defmain():
    '''Quick-n-dirty test harness for PercentToBraceConverter.'''
    importsys
    fromrandomimportchoice
    ifsys.version_info[0]==3:
    get_str=input
    else:
    get_str=raw_input
    classDummy:
    def__str__(self):
    return"I'm a dummy at %#x"%id(self)
    INSTANCE_VALUE=Dummy()
    INTEGER_VALUE=0x1234
    NEGATIVE_VALUE=-0x5678
    FLOAT_VALUE=3.14159265358979323846
    LARGE_FLOAT_VALUE=31415926535323846e108
    NEGATIVE_FLOAT_VALUE=-2.71828182845904523536
    LARGE_NEGATIVE_FLOAT_VALUE=-271828182845904523536e108
    INT_VALUES= (INTEGER_VALUE,NEGATIVE_VALUE)
    FLOAT_VALUES= (FLOAT_VALUE,NEGATIVE_FLOAT_VALUE,LARGE_FLOAT_VALUE,LARGE_NEGATIVE_FLOAT_VALUE)
    STRING_VALUE='abcd'
    STRING_VALUES= (INTEGER_VALUE,NEGATIVE_VALUE,FLOAT_VALUE,LARGE_FLOAT_VALUE,NEGATIVE_FLOAT_VALUE,LARGE_NEGATIVE_FLOAT_VALUE,STRING_VALUE,INSTANCE_VALUE)
    VALUE_MAP= {
    'd' :INT_VALUES,
    'i' :INT_VALUES,
    'o' :INT_VALUES,
    'u' :INT_VALUES,
    'x' :INT_VALUES,
    'X' :INT_VALUES,
    'e' :FLOAT_VALUES,
    'E' :FLOAT_VALUES,
    'f' :FLOAT_VALUES,
    'F' :FLOAT_VALUES,
    'g' :FLOAT_VALUES,
    'G' :FLOAT_VALUES,
    'c' : (INTEGER_VALUE,),
    'r' :STRING_VALUES,
    's' :STRING_VALUES,
    }
    whileTrue:
    s=get_str("Enter a %-format string:")
    ifnots:
    break
    f,conversions=PercentToBraceConverter(s).convert()
    print('%s -> %s'% (s,f))
    ifconversions:
    values= []
    forcinconversions:
    vals=VALUE_MAP.get(c.conversion,None)
    ifvals:
    values.append(choice(vals))
    values=tuple(values)
    print("%-20s: %s"% ('Example raw values',', '.join([repr(v)forvinvalues])))
    print("%-20s: %s"% ('Output using %',s%values))
    print("%-20s: %s"% ('Output using {}',f.format(*values)))
    if__name__=="__main__":
    main()
    Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

    [8]ページ先頭

    ©2009-2025 Movatter.jp