scripts: Added punescape repetition + nesting
Maybe a bit overkill, but I needed more flexibility around adding
arbitrary whitespace.
New modifiers:
%s A space
%{ Start a substring
%}s End and format a subtring
%aaa[mod] Repeat this mod aaa times
With this, it's easy to add arbitrary spaces:
"%8s" -> " "
Or equivalently:
"%8{ %}s" -> " "
Which allows arbitrary repitition of any substring:
"%4{hi!%}s" -> "hi!hi!hi!hi!"
This substring modifier includes its own format string, which allows for
some really nice padding normally impossible in printf:
"%{%(a)d/%(b)d%}8s" % {a:1,b:2} -> " 1/2"
"%{%(a)d/%(b)d%}8s" % {a:12,b:34} -> " 12/34"
This commit is contained in:
+48
-28
@@ -474,27 +474,17 @@ def si2(x):
|
|||||||
# attrs can override __getitem__ for lazy attr generation
|
# attrs can override __getitem__ for lazy attr generation
|
||||||
def punescape(s, attrs=None):
|
def punescape(s, attrs=None):
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'%[%n]'
|
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||||
'|' '%x..'
|
'[%ns]'
|
||||||
'|' '%u....'
|
'|' 'x..'
|
||||||
'|' '%U........'
|
'|' 'u....'
|
||||||
'|' '%\((?P<field>[^)]*)\)'
|
'|' 'U........'
|
||||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
'|' '\((?P<field>[^)]*)\)'
|
||||||
def unescape(m):
|
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])'
|
||||||
if m.group()[1] == '%': return '%'
|
'|' '\{(?P<substring>(?:[^%]|%[^}])*)%\}'
|
||||||
elif m.group()[1] == 'n': return '\n'
|
'(?P<subformat>[+\- #0-9\.]*[siIdboxXfFeEgG])' ')')
|
||||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
|
||||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
def format(f, v):
|
||||||
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
|
||||||
elif m.group()[1] == '(':
|
|
||||||
if attrs is not None:
|
|
||||||
try:
|
|
||||||
v = attrs[m.group('field')]
|
|
||||||
except KeyError:
|
|
||||||
return m.group()
|
|
||||||
else:
|
|
||||||
return m.group()
|
|
||||||
f = m.group('format')
|
|
||||||
if f[-1] in 'dboxX':
|
if f[-1] in 'dboxX':
|
||||||
if isinstance(v, str):
|
if isinstance(v, str):
|
||||||
v = dat(v, 0)
|
v = dat(v, 0)
|
||||||
@@ -514,19 +504,49 @@ def punescape(s, attrs=None):
|
|||||||
v = str(v)
|
v = str(v)
|
||||||
# note we need Python's new format syntax for binary
|
# note we need Python's new format syntax for binary
|
||||||
return ('{:%s}' % f).format(v)
|
return ('{:%s}' % f).format(v)
|
||||||
else: assert False
|
|
||||||
|
def unescape(m):
|
||||||
|
if m.group('pun')[0] == '%': s = '%'
|
||||||
|
elif m.group('pun')[0] == 'n': s = '\n'
|
||||||
|
elif m.group('pun')[0] == 's': s = ' '
|
||||||
|
elif m.group('pun')[0] == 'x': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == 'u': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == 'U': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == '(':
|
||||||
|
if attrs is not None:
|
||||||
|
try:
|
||||||
|
v = attrs[m.group('field')]
|
||||||
|
except KeyError:
|
||||||
|
return m.group()
|
||||||
|
else:
|
||||||
|
return m.group()
|
||||||
|
s = format(m.group('format'), v)
|
||||||
|
elif m.group('pun')[0] == '{':
|
||||||
|
v = punescape(m.group('substring'), attrs)
|
||||||
|
s = format(m.group('subformat'), v)
|
||||||
|
else:
|
||||||
|
return m.group()
|
||||||
|
|
||||||
|
if m.group('rep'):
|
||||||
|
s = int(m.group('rep'), 10) * s
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
return re.sub(pattern, unescape, s)
|
return re.sub(pattern, unescape, s)
|
||||||
|
|
||||||
# split %-escaped strings into chars
|
# split %-escaped strings into chars
|
||||||
def psplit(s):
|
def psplit(s):
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'%[%n]'
|
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||||
'|' '%x..'
|
'[%ns]'
|
||||||
'|' '%u....'
|
'|' 'x..'
|
||||||
'|' '%U........'
|
'|' 'u....'
|
||||||
'|' '%\((?P<field>[^)]*)\)'
|
'|' 'U........'
|
||||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
'|' '\((?P<field>[^)]*)\)'
|
||||||
|
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])'
|
||||||
|
'|' '\{(?P<substring>(?:[^%]|%[^}])*)%\}'
|
||||||
|
'(?P<subformat>[+\- #0-9\.]*[siIdboxXfFeEgG])' ')')
|
||||||
|
|
||||||
return [m.group() for m in re.finditer(pattern.pattern + '|.', s)]
|
return [m.group() for m in re.finditer(pattern.pattern + '|.', s)]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+38
-22
@@ -336,27 +336,17 @@ def si2(x):
|
|||||||
# attrs can override __getitem__ for lazy attr generation
|
# attrs can override __getitem__ for lazy attr generation
|
||||||
def punescape(s, attrs=None):
|
def punescape(s, attrs=None):
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'%[%n]'
|
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||||
'|' '%x..'
|
'[%ns]'
|
||||||
'|' '%u....'
|
'|' 'x..'
|
||||||
'|' '%U........'
|
'|' 'u....'
|
||||||
'|' '%\((?P<field>[^)]*)\)'
|
'|' 'U........'
|
||||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
'|' '\((?P<field>[^)]*)\)'
|
||||||
def unescape(m):
|
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])'
|
||||||
if m.group()[1] == '%': return '%'
|
'|' '\{(?P<substring>(?:[^%]|%[^}])*)%\}'
|
||||||
elif m.group()[1] == 'n': return '\n'
|
'(?P<subformat>[+\- #0-9\.]*[siIdboxXfFeEgG])' ')')
|
||||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
|
||||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
def format(f, v):
|
||||||
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
|
||||||
elif m.group()[1] == '(':
|
|
||||||
if attrs is not None:
|
|
||||||
try:
|
|
||||||
v = attrs[m.group('field')]
|
|
||||||
except KeyError:
|
|
||||||
return m.group()
|
|
||||||
else:
|
|
||||||
return m.group()
|
|
||||||
f = m.group('format')
|
|
||||||
if f[-1] in 'dboxX':
|
if f[-1] in 'dboxX':
|
||||||
if isinstance(v, str):
|
if isinstance(v, str):
|
||||||
v = dat(v, 0)
|
v = dat(v, 0)
|
||||||
@@ -376,7 +366,33 @@ def punescape(s, attrs=None):
|
|||||||
v = str(v)
|
v = str(v)
|
||||||
# note we need Python's new format syntax for binary
|
# note we need Python's new format syntax for binary
|
||||||
return ('{:%s}' % f).format(v)
|
return ('{:%s}' % f).format(v)
|
||||||
else: assert False
|
|
||||||
|
def unescape(m):
|
||||||
|
if m.group('pun')[0] == '%': s = '%'
|
||||||
|
elif m.group('pun')[0] == 'n': s = '\n'
|
||||||
|
elif m.group('pun')[0] == 's': s = ' '
|
||||||
|
elif m.group('pun')[0] == 'x': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == 'u': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == 'U': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == '(':
|
||||||
|
if attrs is not None:
|
||||||
|
try:
|
||||||
|
v = attrs[m.group('field')]
|
||||||
|
except KeyError:
|
||||||
|
return m.group()
|
||||||
|
else:
|
||||||
|
return m.group()
|
||||||
|
s = format(m.group('format'), v)
|
||||||
|
elif m.group('pun')[0] == '{':
|
||||||
|
v = punescape(m.group('substring'), attrs)
|
||||||
|
s = format(m.group('subformat'), v)
|
||||||
|
else:
|
||||||
|
return m.group()
|
||||||
|
|
||||||
|
if m.group('rep'):
|
||||||
|
s = int(m.group('rep'), 10) * s
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
return re.sub(pattern, unescape, s)
|
return re.sub(pattern, unescape, s)
|
||||||
|
|
||||||
|
|||||||
+45
-22
@@ -1712,27 +1712,17 @@ def si2(x):
|
|||||||
# attrs can override __getitem__ for lazy attr generation
|
# attrs can override __getitem__ for lazy attr generation
|
||||||
def punescape(s, attrs=None):
|
def punescape(s, attrs=None):
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'%[%n]'
|
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||||
'|' '%x..'
|
'[%ns]'
|
||||||
'|' '%u....'
|
'|' 'x..'
|
||||||
'|' '%U........'
|
'|' 'u....'
|
||||||
'|' '%\((?P<field>[^)]*)\)'
|
'|' 'U........'
|
||||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
'|' '\((?P<field>[^)]*)\)'
|
||||||
def unescape(m):
|
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])'
|
||||||
if m.group()[1] == '%': return '%'
|
'|' '\{(?P<substring>(?:[^%]|%[^}])*)%\}'
|
||||||
elif m.group()[1] == 'n': return '\n'
|
'(?P<subformat>[+\- #0-9\.]*[siIdboxXfFeEgG])' ')')
|
||||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
|
||||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
def format(f, v):
|
||||||
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
|
||||||
elif m.group()[1] == '(':
|
|
||||||
if attrs is not None:
|
|
||||||
try:
|
|
||||||
v = attrs[m.group('field')]
|
|
||||||
except KeyError:
|
|
||||||
return m.group()
|
|
||||||
else:
|
|
||||||
return m.group()
|
|
||||||
f = m.group('format')
|
|
||||||
if f[-1] in 'dboxX':
|
if f[-1] in 'dboxX':
|
||||||
if isinstance(v, str):
|
if isinstance(v, str):
|
||||||
v = dat(v, 0)
|
v = dat(v, 0)
|
||||||
@@ -1752,7 +1742,33 @@ def punescape(s, attrs=None):
|
|||||||
v = str(v)
|
v = str(v)
|
||||||
# note we need Python's new format syntax for binary
|
# note we need Python's new format syntax for binary
|
||||||
return ('{:%s}' % f).format(v)
|
return ('{:%s}' % f).format(v)
|
||||||
else: assert False
|
|
||||||
|
def unescape(m):
|
||||||
|
if m.group('pun')[0] == '%': s = '%'
|
||||||
|
elif m.group('pun')[0] == 'n': s = '\n'
|
||||||
|
elif m.group('pun')[0] == 's': s = ' '
|
||||||
|
elif m.group('pun')[0] == 'x': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == 'u': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == 'U': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == '(':
|
||||||
|
if attrs is not None:
|
||||||
|
try:
|
||||||
|
v = attrs[m.group('field')]
|
||||||
|
except KeyError:
|
||||||
|
return m.group()
|
||||||
|
else:
|
||||||
|
return m.group()
|
||||||
|
s = format(m.group('format'), v)
|
||||||
|
elif m.group('pun')[0] == '{':
|
||||||
|
v = punescape(m.group('substring'), attrs)
|
||||||
|
s = format(m.group('subformat'), v)
|
||||||
|
else:
|
||||||
|
return m.group()
|
||||||
|
|
||||||
|
if m.group('rep'):
|
||||||
|
s = int(m.group('rep'), 10) * s
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
return re.sub(pattern, unescape, s)
|
return re.sub(pattern, unescape, s)
|
||||||
|
|
||||||
@@ -1769,6 +1785,7 @@ def punescape_help():
|
|||||||
print('mods:')
|
print('mods:')
|
||||||
print(' %-21s %s' % ('%%', 'A literal % character'))
|
print(' %-21s %s' % ('%%', 'A literal % character'))
|
||||||
print(' %-21s %s' % ('%n', 'A newline'))
|
print(' %-21s %s' % ('%n', 'A newline'))
|
||||||
|
print(' %-21s %s' % ('%s', 'A space'))
|
||||||
print(' %-21s %s' % (
|
print(' %-21s %s' % (
|
||||||
'%xaa', 'A character with the hex value aa'))
|
'%xaa', 'A character with the hex value aa'))
|
||||||
print(' %-21s %s' % (
|
print(' %-21s %s' % (
|
||||||
@@ -1785,6 +1802,12 @@ def punescape_help():
|
|||||||
'%(field)[dboxX]', 'An existing field formatted as an integer'))
|
'%(field)[dboxX]', 'An existing field formatted as an integer'))
|
||||||
print(' %-21s %s' % (
|
print(' %-21s %s' % (
|
||||||
'%(field)[fFeEgG]', 'An existing field formatted as a float'))
|
'%(field)[fFeEgG]', 'An existing field formatted as a float'))
|
||||||
|
print(' %-21s %s' % (
|
||||||
|
'%{', 'Start a substring'))
|
||||||
|
print(' %-21s %s' % (
|
||||||
|
'%}s', 'End and format a subtring'))
|
||||||
|
print(' %-21s %s' % (
|
||||||
|
'%aaa[mod]', 'Repeat this mod aaa times'))
|
||||||
|
|
||||||
|
|
||||||
# open with '-' for stdin/stdout
|
# open with '-' for stdin/stdout
|
||||||
|
|||||||
+48
-28
@@ -4207,27 +4207,17 @@ def si2(x):
|
|||||||
# attrs can override __getitem__ for lazy attr generation
|
# attrs can override __getitem__ for lazy attr generation
|
||||||
def punescape(s, attrs=None):
|
def punescape(s, attrs=None):
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'%[%n]'
|
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||||
'|' '%x..'
|
'[%ns]'
|
||||||
'|' '%u....'
|
'|' 'x..'
|
||||||
'|' '%U........'
|
'|' 'u....'
|
||||||
'|' '%\((?P<field>[^)]*)\)'
|
'|' 'U........'
|
||||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
'|' '\((?P<field>[^)]*)\)'
|
||||||
def unescape(m):
|
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])'
|
||||||
if m.group()[1] == '%': return '%'
|
'|' '\{(?P<substring>(?:[^%]|%[^}])*)%\}'
|
||||||
elif m.group()[1] == 'n': return '\n'
|
'(?P<subformat>[+\- #0-9\.]*[siIdboxXfFeEgG])' ')')
|
||||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
|
||||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
def format(f, v):
|
||||||
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
|
||||||
elif m.group()[1] == '(':
|
|
||||||
if attrs is not None:
|
|
||||||
try:
|
|
||||||
v = attrs[m.group('field')]
|
|
||||||
except KeyError:
|
|
||||||
return m.group()
|
|
||||||
else:
|
|
||||||
return m.group()
|
|
||||||
f = m.group('format')
|
|
||||||
if f[-1] in 'dboxX':
|
if f[-1] in 'dboxX':
|
||||||
if isinstance(v, str):
|
if isinstance(v, str):
|
||||||
v = dat(v, 0)
|
v = dat(v, 0)
|
||||||
@@ -4247,19 +4237,49 @@ def punescape(s, attrs=None):
|
|||||||
v = str(v)
|
v = str(v)
|
||||||
# note we need Python's new format syntax for binary
|
# note we need Python's new format syntax for binary
|
||||||
return ('{:%s}' % f).format(v)
|
return ('{:%s}' % f).format(v)
|
||||||
else: assert False
|
|
||||||
|
def unescape(m):
|
||||||
|
if m.group('pun')[0] == '%': s = '%'
|
||||||
|
elif m.group('pun')[0] == 'n': s = '\n'
|
||||||
|
elif m.group('pun')[0] == 's': s = ' '
|
||||||
|
elif m.group('pun')[0] == 'x': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == 'u': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == 'U': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == '(':
|
||||||
|
if attrs is not None:
|
||||||
|
try:
|
||||||
|
v = attrs[m.group('field')]
|
||||||
|
except KeyError:
|
||||||
|
return m.group()
|
||||||
|
else:
|
||||||
|
return m.group()
|
||||||
|
s = format(m.group('format'), v)
|
||||||
|
elif m.group('pun')[0] == '{':
|
||||||
|
v = punescape(m.group('substring'), attrs)
|
||||||
|
s = format(m.group('subformat'), v)
|
||||||
|
else:
|
||||||
|
return m.group()
|
||||||
|
|
||||||
|
if m.group('rep'):
|
||||||
|
s = int(m.group('rep'), 10) * s
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
return re.sub(pattern, unescape, s)
|
return re.sub(pattern, unescape, s)
|
||||||
|
|
||||||
# split %-escaped strings into chars
|
# split %-escaped strings into chars
|
||||||
def psplit(s):
|
def psplit(s):
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'%[%n]'
|
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||||
'|' '%x..'
|
'[%ns]'
|
||||||
'|' '%u....'
|
'|' 'x..'
|
||||||
'|' '%U........'
|
'|' 'u....'
|
||||||
'|' '%\((?P<field>[^)]*)\)'
|
'|' 'U........'
|
||||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
'|' '\((?P<field>[^)]*)\)'
|
||||||
|
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])'
|
||||||
|
'|' '\{(?P<substring>(?:[^%]|%[^}])*)%\}'
|
||||||
|
'(?P<subformat>[+\- #0-9\.]*[siIdboxXfFeEgG])' ')')
|
||||||
|
|
||||||
return [m.group() for m in re.finditer(pattern.pattern + '|.', s)]
|
return [m.group() for m in re.finditer(pattern.pattern + '|.', s)]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+38
-22
@@ -4096,27 +4096,17 @@ def si2(x):
|
|||||||
# attrs can override __getitem__ for lazy attr generation
|
# attrs can override __getitem__ for lazy attr generation
|
||||||
def punescape(s, attrs=None):
|
def punescape(s, attrs=None):
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'%[%n]'
|
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||||
'|' '%x..'
|
'[%ns]'
|
||||||
'|' '%u....'
|
'|' 'x..'
|
||||||
'|' '%U........'
|
'|' 'u....'
|
||||||
'|' '%\((?P<field>[^)]*)\)'
|
'|' 'U........'
|
||||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
'|' '\((?P<field>[^)]*)\)'
|
||||||
def unescape(m):
|
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])'
|
||||||
if m.group()[1] == '%': return '%'
|
'|' '\{(?P<substring>(?:[^%]|%[^}])*)%\}'
|
||||||
elif m.group()[1] == 'n': return '\n'
|
'(?P<subformat>[+\- #0-9\.]*[siIdboxXfFeEgG])' ')')
|
||||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
|
||||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
def format(f, v):
|
||||||
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
|
||||||
elif m.group()[1] == '(':
|
|
||||||
if attrs is not None:
|
|
||||||
try:
|
|
||||||
v = attrs[m.group('field')]
|
|
||||||
except KeyError:
|
|
||||||
return m.group()
|
|
||||||
else:
|
|
||||||
return m.group()
|
|
||||||
f = m.group('format')
|
|
||||||
if f[-1] in 'dboxX':
|
if f[-1] in 'dboxX':
|
||||||
if isinstance(v, str):
|
if isinstance(v, str):
|
||||||
v = dat(v, 0)
|
v = dat(v, 0)
|
||||||
@@ -4136,7 +4126,33 @@ def punescape(s, attrs=None):
|
|||||||
v = str(v)
|
v = str(v)
|
||||||
# note we need Python's new format syntax for binary
|
# note we need Python's new format syntax for binary
|
||||||
return ('{:%s}' % f).format(v)
|
return ('{:%s}' % f).format(v)
|
||||||
else: assert False
|
|
||||||
|
def unescape(m):
|
||||||
|
if m.group('pun')[0] == '%': s = '%'
|
||||||
|
elif m.group('pun')[0] == 'n': s = '\n'
|
||||||
|
elif m.group('pun')[0] == 's': s = ' '
|
||||||
|
elif m.group('pun')[0] == 'x': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == 'u': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == 'U': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == '(':
|
||||||
|
if attrs is not None:
|
||||||
|
try:
|
||||||
|
v = attrs[m.group('field')]
|
||||||
|
except KeyError:
|
||||||
|
return m.group()
|
||||||
|
else:
|
||||||
|
return m.group()
|
||||||
|
s = format(m.group('format'), v)
|
||||||
|
elif m.group('pun')[0] == '{':
|
||||||
|
v = punescape(m.group('substring'), attrs)
|
||||||
|
s = format(m.group('subformat'), v)
|
||||||
|
else:
|
||||||
|
return m.group()
|
||||||
|
|
||||||
|
if m.group('rep'):
|
||||||
|
s = int(m.group('rep'), 10) * s
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
return re.sub(pattern, unescape, s)
|
return re.sub(pattern, unescape, s)
|
||||||
|
|
||||||
|
|||||||
+48
-28
@@ -482,27 +482,17 @@ def si2(x):
|
|||||||
# attrs can override __getitem__ for lazy attr generation
|
# attrs can override __getitem__ for lazy attr generation
|
||||||
def punescape(s, attrs=None):
|
def punescape(s, attrs=None):
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'%[%n]'
|
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||||
'|' '%x..'
|
'[%ns]'
|
||||||
'|' '%u....'
|
'|' 'x..'
|
||||||
'|' '%U........'
|
'|' 'u....'
|
||||||
'|' '%\((?P<field>[^)]*)\)'
|
'|' 'U........'
|
||||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
'|' '\((?P<field>[^)]*)\)'
|
||||||
def unescape(m):
|
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])'
|
||||||
if m.group()[1] == '%': return '%'
|
'|' '\{(?P<substring>(?:[^%]|%[^}])*)%\}'
|
||||||
elif m.group()[1] == 'n': return '\n'
|
'(?P<subformat>[+\- #0-9\.]*[siIdboxXfFeEgG])' ')')
|
||||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
|
||||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
def format(f, v):
|
||||||
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
|
||||||
elif m.group()[1] == '(':
|
|
||||||
if attrs is not None:
|
|
||||||
try:
|
|
||||||
v = attrs[m.group('field')]
|
|
||||||
except KeyError:
|
|
||||||
return m.group()
|
|
||||||
else:
|
|
||||||
return m.group()
|
|
||||||
f = m.group('format')
|
|
||||||
if f[-1] in 'dboxX':
|
if f[-1] in 'dboxX':
|
||||||
if isinstance(v, str):
|
if isinstance(v, str):
|
||||||
v = dat(v, 0)
|
v = dat(v, 0)
|
||||||
@@ -522,19 +512,49 @@ def punescape(s, attrs=None):
|
|||||||
v = str(v)
|
v = str(v)
|
||||||
# note we need Python's new format syntax for binary
|
# note we need Python's new format syntax for binary
|
||||||
return ('{:%s}' % f).format(v)
|
return ('{:%s}' % f).format(v)
|
||||||
else: assert False
|
|
||||||
|
def unescape(m):
|
||||||
|
if m.group('pun')[0] == '%': s = '%'
|
||||||
|
elif m.group('pun')[0] == 'n': s = '\n'
|
||||||
|
elif m.group('pun')[0] == 's': s = ' '
|
||||||
|
elif m.group('pun')[0] == 'x': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == 'u': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == 'U': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == '(':
|
||||||
|
if attrs is not None:
|
||||||
|
try:
|
||||||
|
v = attrs[m.group('field')]
|
||||||
|
except KeyError:
|
||||||
|
return m.group()
|
||||||
|
else:
|
||||||
|
return m.group()
|
||||||
|
s = format(m.group('format'), v)
|
||||||
|
elif m.group('pun')[0] == '{':
|
||||||
|
v = punescape(m.group('substring'), attrs)
|
||||||
|
s = format(m.group('subformat'), v)
|
||||||
|
else:
|
||||||
|
return m.group()
|
||||||
|
|
||||||
|
if m.group('rep'):
|
||||||
|
s = int(m.group('rep'), 10) * s
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
return re.sub(pattern, unescape, s)
|
return re.sub(pattern, unescape, s)
|
||||||
|
|
||||||
# split %-escaped strings into chars
|
# split %-escaped strings into chars
|
||||||
def psplit(s):
|
def psplit(s):
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'%[%n]'
|
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||||
'|' '%x..'
|
'[%ns]'
|
||||||
'|' '%u....'
|
'|' 'x..'
|
||||||
'|' '%U........'
|
'|' 'u....'
|
||||||
'|' '%\((?P<field>[^)]*)\)'
|
'|' 'U........'
|
||||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
'|' '\((?P<field>[^)]*)\)'
|
||||||
|
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])'
|
||||||
|
'|' '\{(?P<substring>(?:[^%]|%[^}])*)%\}'
|
||||||
|
'(?P<subformat>[+\- #0-9\.]*[siIdboxXfFeEgG])' ')')
|
||||||
|
|
||||||
return [m.group() for m in re.finditer(pattern.pattern + '|.', s)]
|
return [m.group() for m in re.finditer(pattern.pattern + '|.', s)]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+48
-28
@@ -640,27 +640,17 @@ class CsvAttr:
|
|||||||
# attrs can override __getitem__ for lazy attr generation
|
# attrs can override __getitem__ for lazy attr generation
|
||||||
def punescape(s, attrs=None):
|
def punescape(s, attrs=None):
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'%[%n]'
|
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||||
'|' '%x..'
|
'[%ns]'
|
||||||
'|' '%u....'
|
'|' 'x..'
|
||||||
'|' '%U........'
|
'|' 'u....'
|
||||||
'|' '%\((?P<field>[^)]*)\)'
|
'|' 'U........'
|
||||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
'|' '\((?P<field>[^)]*)\)'
|
||||||
def unescape(m):
|
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])'
|
||||||
if m.group()[1] == '%': return '%'
|
'|' '\{(?P<substring>(?:[^%]|%[^}])*)%\}'
|
||||||
elif m.group()[1] == 'n': return '\n'
|
'(?P<subformat>[+\- #0-9\.]*[siIdboxXfFeEgG])' ')')
|
||||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
|
||||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
def format(f, v):
|
||||||
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
|
||||||
elif m.group()[1] == '(':
|
|
||||||
if attrs is not None:
|
|
||||||
try:
|
|
||||||
v = attrs[m.group('field')]
|
|
||||||
except KeyError:
|
|
||||||
return m.group()
|
|
||||||
else:
|
|
||||||
return m.group()
|
|
||||||
f = m.group('format')
|
|
||||||
if f[-1] in 'dboxX':
|
if f[-1] in 'dboxX':
|
||||||
if isinstance(v, str):
|
if isinstance(v, str):
|
||||||
v = dat(v, 0)
|
v = dat(v, 0)
|
||||||
@@ -680,19 +670,49 @@ def punescape(s, attrs=None):
|
|||||||
v = str(v)
|
v = str(v)
|
||||||
# note we need Python's new format syntax for binary
|
# note we need Python's new format syntax for binary
|
||||||
return ('{:%s}' % f).format(v)
|
return ('{:%s}' % f).format(v)
|
||||||
else: assert False
|
|
||||||
|
def unescape(m):
|
||||||
|
if m.group('pun')[0] == '%': s = '%'
|
||||||
|
elif m.group('pun')[0] == 'n': s = '\n'
|
||||||
|
elif m.group('pun')[0] == 's': s = ' '
|
||||||
|
elif m.group('pun')[0] == 'x': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == 'u': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == 'U': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == '(':
|
||||||
|
if attrs is not None:
|
||||||
|
try:
|
||||||
|
v = attrs[m.group('field')]
|
||||||
|
except KeyError:
|
||||||
|
return m.group()
|
||||||
|
else:
|
||||||
|
return m.group()
|
||||||
|
s = format(m.group('format'), v)
|
||||||
|
elif m.group('pun')[0] == '{':
|
||||||
|
v = punescape(m.group('substring'), attrs)
|
||||||
|
s = format(m.group('subformat'), v)
|
||||||
|
else:
|
||||||
|
return m.group()
|
||||||
|
|
||||||
|
if m.group('rep'):
|
||||||
|
s = int(m.group('rep'), 10) * s
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
return re.sub(pattern, unescape, s)
|
return re.sub(pattern, unescape, s)
|
||||||
|
|
||||||
# split %-escaped strings into chars
|
# split %-escaped strings into chars
|
||||||
def psplit(s):
|
def psplit(s):
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'%[%n]'
|
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||||
'|' '%x..'
|
'[%ns]'
|
||||||
'|' '%u....'
|
'|' 'x..'
|
||||||
'|' '%U........'
|
'|' 'u....'
|
||||||
'|' '%\((?P<field>[^)]*)\)'
|
'|' 'U........'
|
||||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
'|' '\((?P<field>[^)]*)\)'
|
||||||
|
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])'
|
||||||
|
'|' '\{(?P<substring>(?:[^%]|%[^}])*)%\}'
|
||||||
|
'(?P<subformat>[+\- #0-9\.]*[siIdboxXfFeEgG])' ')')
|
||||||
|
|
||||||
return [m.group() for m in re.finditer(pattern.pattern + '|.', s)]
|
return [m.group() for m in re.finditer(pattern.pattern + '|.', s)]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+38
-22
@@ -524,27 +524,17 @@ class CsvAttr:
|
|||||||
# attrs can override __getitem__ for lazy attr generation
|
# attrs can override __getitem__ for lazy attr generation
|
||||||
def punescape(s, attrs=None):
|
def punescape(s, attrs=None):
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'%[%n]'
|
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||||
'|' '%x..'
|
'[%ns]'
|
||||||
'|' '%u....'
|
'|' 'x..'
|
||||||
'|' '%U........'
|
'|' 'u....'
|
||||||
'|' '%\((?P<field>[^)]*)\)'
|
'|' 'U........'
|
||||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
'|' '\((?P<field>[^)]*)\)'
|
||||||
def unescape(m):
|
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])'
|
||||||
if m.group()[1] == '%': return '%'
|
'|' '\{(?P<substring>(?:[^%]|%[^}])*)%\}'
|
||||||
elif m.group()[1] == 'n': return '\n'
|
'(?P<subformat>[+\- #0-9\.]*[siIdboxXfFeEgG])' ')')
|
||||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
|
||||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
def format(f, v):
|
||||||
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
|
||||||
elif m.group()[1] == '(':
|
|
||||||
if attrs is not None:
|
|
||||||
try:
|
|
||||||
v = attrs[m.group('field')]
|
|
||||||
except KeyError:
|
|
||||||
return m.group()
|
|
||||||
else:
|
|
||||||
return m.group()
|
|
||||||
f = m.group('format')
|
|
||||||
if f[-1] in 'dboxX':
|
if f[-1] in 'dboxX':
|
||||||
if isinstance(v, str):
|
if isinstance(v, str):
|
||||||
v = dat(v, 0)
|
v = dat(v, 0)
|
||||||
@@ -564,7 +554,33 @@ def punescape(s, attrs=None):
|
|||||||
v = str(v)
|
v = str(v)
|
||||||
# note we need Python's new format syntax for binary
|
# note we need Python's new format syntax for binary
|
||||||
return ('{:%s}' % f).format(v)
|
return ('{:%s}' % f).format(v)
|
||||||
else: assert False
|
|
||||||
|
def unescape(m):
|
||||||
|
if m.group('pun')[0] == '%': s = '%'
|
||||||
|
elif m.group('pun')[0] == 'n': s = '\n'
|
||||||
|
elif m.group('pun')[0] == 's': s = ' '
|
||||||
|
elif m.group('pun')[0] == 'x': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == 'u': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == 'U': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == '(':
|
||||||
|
if attrs is not None:
|
||||||
|
try:
|
||||||
|
v = attrs[m.group('field')]
|
||||||
|
except KeyError:
|
||||||
|
return m.group()
|
||||||
|
else:
|
||||||
|
return m.group()
|
||||||
|
s = format(m.group('format'), v)
|
||||||
|
elif m.group('pun')[0] == '{':
|
||||||
|
v = punescape(m.group('substring'), attrs)
|
||||||
|
s = format(m.group('subformat'), v)
|
||||||
|
else:
|
||||||
|
return m.group()
|
||||||
|
|
||||||
|
if m.group('rep'):
|
||||||
|
s = int(m.group('rep'), 10) * s
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
return re.sub(pattern, unescape, s)
|
return re.sub(pattern, unescape, s)
|
||||||
|
|
||||||
|
|||||||
+48
-28
@@ -561,27 +561,17 @@ def si2(x):
|
|||||||
# attrs can override __getitem__ for lazy attr generation
|
# attrs can override __getitem__ for lazy attr generation
|
||||||
def punescape(s, attrs=None):
|
def punescape(s, attrs=None):
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'%[%n]'
|
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||||
'|' '%x..'
|
'[%ns]'
|
||||||
'|' '%u....'
|
'|' 'x..'
|
||||||
'|' '%U........'
|
'|' 'u....'
|
||||||
'|' '%\((?P<field>[^)]*)\)'
|
'|' 'U........'
|
||||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
'|' '\((?P<field>[^)]*)\)'
|
||||||
def unescape(m):
|
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])'
|
||||||
if m.group()[1] == '%': return '%'
|
'|' '\{(?P<substring>(?:[^%]|%[^}])*)%\}'
|
||||||
elif m.group()[1] == 'n': return '\n'
|
'(?P<subformat>[+\- #0-9\.]*[siIdboxXfFeEgG])' ')')
|
||||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
|
||||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
def format(f, v):
|
||||||
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
|
||||||
elif m.group()[1] == '(':
|
|
||||||
if attrs is not None:
|
|
||||||
try:
|
|
||||||
v = attrs[m.group('field')]
|
|
||||||
except KeyError:
|
|
||||||
return m.group()
|
|
||||||
else:
|
|
||||||
return m.group()
|
|
||||||
f = m.group('format')
|
|
||||||
if f[-1] in 'dboxX':
|
if f[-1] in 'dboxX':
|
||||||
if isinstance(v, str):
|
if isinstance(v, str):
|
||||||
v = dat(v, 0)
|
v = dat(v, 0)
|
||||||
@@ -601,19 +591,49 @@ def punescape(s, attrs=None):
|
|||||||
v = str(v)
|
v = str(v)
|
||||||
# note we need Python's new format syntax for binary
|
# note we need Python's new format syntax for binary
|
||||||
return ('{:%s}' % f).format(v)
|
return ('{:%s}' % f).format(v)
|
||||||
else: assert False
|
|
||||||
|
def unescape(m):
|
||||||
|
if m.group('pun')[0] == '%': s = '%'
|
||||||
|
elif m.group('pun')[0] == 'n': s = '\n'
|
||||||
|
elif m.group('pun')[0] == 's': s = ' '
|
||||||
|
elif m.group('pun')[0] == 'x': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == 'u': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == 'U': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == '(':
|
||||||
|
if attrs is not None:
|
||||||
|
try:
|
||||||
|
v = attrs[m.group('field')]
|
||||||
|
except KeyError:
|
||||||
|
return m.group()
|
||||||
|
else:
|
||||||
|
return m.group()
|
||||||
|
s = format(m.group('format'), v)
|
||||||
|
elif m.group('pun')[0] == '{':
|
||||||
|
v = punescape(m.group('substring'), attrs)
|
||||||
|
s = format(m.group('subformat'), v)
|
||||||
|
else:
|
||||||
|
return m.group()
|
||||||
|
|
||||||
|
if m.group('rep'):
|
||||||
|
s = int(m.group('rep'), 10) * s
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
return re.sub(pattern, unescape, s)
|
return re.sub(pattern, unescape, s)
|
||||||
|
|
||||||
# split %-escaped strings into chars
|
# split %-escaped strings into chars
|
||||||
def psplit(s):
|
def psplit(s):
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'%[%n]'
|
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||||
'|' '%x..'
|
'[%ns]'
|
||||||
'|' '%u....'
|
'|' 'x..'
|
||||||
'|' '%U........'
|
'|' 'u....'
|
||||||
'|' '%\((?P<field>[^)]*)\)'
|
'|' 'U........'
|
||||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
'|' '\((?P<field>[^)]*)\)'
|
||||||
|
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])'
|
||||||
|
'|' '\{(?P<substring>(?:[^%]|%[^}])*)%\}'
|
||||||
|
'(?P<subformat>[+\- #0-9\.]*[siIdboxXfFeEgG])' ')')
|
||||||
|
|
||||||
return [m.group() for m in re.finditer(pattern.pattern + '|.', s)]
|
return [m.group() for m in re.finditer(pattern.pattern + '|.', s)]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+38
-22
@@ -422,27 +422,17 @@ def si2(x):
|
|||||||
# attrs can override __getitem__ for lazy attr generation
|
# attrs can override __getitem__ for lazy attr generation
|
||||||
def punescape(s, attrs=None):
|
def punescape(s, attrs=None):
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'%[%n]'
|
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||||
'|' '%x..'
|
'[%ns]'
|
||||||
'|' '%u....'
|
'|' 'x..'
|
||||||
'|' '%U........'
|
'|' 'u....'
|
||||||
'|' '%\((?P<field>[^)]*)\)'
|
'|' 'U........'
|
||||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
'|' '\((?P<field>[^)]*)\)'
|
||||||
def unescape(m):
|
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])'
|
||||||
if m.group()[1] == '%': return '%'
|
'|' '\{(?P<substring>(?:[^%]|%[^}])*)%\}'
|
||||||
elif m.group()[1] == 'n': return '\n'
|
'(?P<subformat>[+\- #0-9\.]*[siIdboxXfFeEgG])' ')')
|
||||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
|
||||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
def format(f, v):
|
||||||
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
|
||||||
elif m.group()[1] == '(':
|
|
||||||
if attrs is not None:
|
|
||||||
try:
|
|
||||||
v = attrs[m.group('field')]
|
|
||||||
except KeyError:
|
|
||||||
return m.group()
|
|
||||||
else:
|
|
||||||
return m.group()
|
|
||||||
f = m.group('format')
|
|
||||||
if f[-1] in 'dboxX':
|
if f[-1] in 'dboxX':
|
||||||
if isinstance(v, str):
|
if isinstance(v, str):
|
||||||
v = dat(v, 0)
|
v = dat(v, 0)
|
||||||
@@ -462,7 +452,33 @@ def punescape(s, attrs=None):
|
|||||||
v = str(v)
|
v = str(v)
|
||||||
# note we need Python's new format syntax for binary
|
# note we need Python's new format syntax for binary
|
||||||
return ('{:%s}' % f).format(v)
|
return ('{:%s}' % f).format(v)
|
||||||
else: assert False
|
|
||||||
|
def unescape(m):
|
||||||
|
if m.group('pun')[0] == '%': s = '%'
|
||||||
|
elif m.group('pun')[0] == 'n': s = '\n'
|
||||||
|
elif m.group('pun')[0] == 's': s = ' '
|
||||||
|
elif m.group('pun')[0] == 'x': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == 'u': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == 'U': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == '(':
|
||||||
|
if attrs is not None:
|
||||||
|
try:
|
||||||
|
v = attrs[m.group('field')]
|
||||||
|
except KeyError:
|
||||||
|
return m.group()
|
||||||
|
else:
|
||||||
|
return m.group()
|
||||||
|
s = format(m.group('format'), v)
|
||||||
|
elif m.group('pun')[0] == '{':
|
||||||
|
v = punescape(m.group('substring'), attrs)
|
||||||
|
s = format(m.group('subformat'), v)
|
||||||
|
else:
|
||||||
|
return m.group()
|
||||||
|
|
||||||
|
if m.group('rep'):
|
||||||
|
s = int(m.group('rep'), 10) * s
|
||||||
|
|
||||||
|
return s
|
||||||
|
|
||||||
return re.sub(pattern, unescape, s)
|
return re.sub(pattern, unescape, s)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user