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
|
||||
def punescape(s, attrs=None):
|
||||
pattern = re.compile(
|
||||
'%[%n]'
|
||||
'|' '%x..'
|
||||
'|' '%u....'
|
||||
'|' '%U........'
|
||||
'|' '%\((?P<field>[^)]*)\)'
|
||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
||||
def unescape(m):
|
||||
if m.group()[1] == '%': return '%'
|
||||
elif m.group()[1] == 'n': return '\n'
|
||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
||||
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')
|
||||
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||
'[%ns]'
|
||||
'|' 'x..'
|
||||
'|' 'u....'
|
||||
'|' 'U........'
|
||||
'|' '\((?P<field>[^)]*)\)'
|
||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])'
|
||||
'|' '\{(?P<substring>(?:[^%]|%[^}])*)%\}'
|
||||
'(?P<subformat>[+\- #0-9\.]*[siIdboxXfFeEgG])' ')')
|
||||
|
||||
def format(f, v):
|
||||
if f[-1] in 'dboxX':
|
||||
if isinstance(v, str):
|
||||
v = dat(v, 0)
|
||||
@@ -514,19 +504,49 @@ def punescape(s, attrs=None):
|
||||
v = str(v)
|
||||
# note we need Python's new format syntax for binary
|
||||
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)
|
||||
|
||||
# split %-escaped strings into chars
|
||||
def psplit(s):
|
||||
pattern = re.compile(
|
||||
'%[%n]'
|
||||
'|' '%x..'
|
||||
'|' '%u....'
|
||||
'|' '%U........'
|
||||
'|' '%\((?P<field>[^)]*)\)'
|
||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
||||
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||
'[%ns]'
|
||||
'|' 'x..'
|
||||
'|' 'u....'
|
||||
'|' 'U........'
|
||||
'|' '\((?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)]
|
||||
|
||||
|
||||
|
||||
+38
-22
@@ -336,27 +336,17 @@ def si2(x):
|
||||
# attrs can override __getitem__ for lazy attr generation
|
||||
def punescape(s, attrs=None):
|
||||
pattern = re.compile(
|
||||
'%[%n]'
|
||||
'|' '%x..'
|
||||
'|' '%u....'
|
||||
'|' '%U........'
|
||||
'|' '%\((?P<field>[^)]*)\)'
|
||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
||||
def unescape(m):
|
||||
if m.group()[1] == '%': return '%'
|
||||
elif m.group()[1] == 'n': return '\n'
|
||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
||||
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')
|
||||
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||
'[%ns]'
|
||||
'|' 'x..'
|
||||
'|' 'u....'
|
||||
'|' 'U........'
|
||||
'|' '\((?P<field>[^)]*)\)'
|
||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])'
|
||||
'|' '\{(?P<substring>(?:[^%]|%[^}])*)%\}'
|
||||
'(?P<subformat>[+\- #0-9\.]*[siIdboxXfFeEgG])' ')')
|
||||
|
||||
def format(f, v):
|
||||
if f[-1] in 'dboxX':
|
||||
if isinstance(v, str):
|
||||
v = dat(v, 0)
|
||||
@@ -376,7 +366,33 @@ def punescape(s, attrs=None):
|
||||
v = str(v)
|
||||
# note we need Python's new format syntax for binary
|
||||
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)
|
||||
|
||||
|
||||
+45
-22
@@ -1712,27 +1712,17 @@ def si2(x):
|
||||
# attrs can override __getitem__ for lazy attr generation
|
||||
def punescape(s, attrs=None):
|
||||
pattern = re.compile(
|
||||
'%[%n]'
|
||||
'|' '%x..'
|
||||
'|' '%u....'
|
||||
'|' '%U........'
|
||||
'|' '%\((?P<field>[^)]*)\)'
|
||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
||||
def unescape(m):
|
||||
if m.group()[1] == '%': return '%'
|
||||
elif m.group()[1] == 'n': return '\n'
|
||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
||||
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')
|
||||
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||
'[%ns]'
|
||||
'|' 'x..'
|
||||
'|' 'u....'
|
||||
'|' 'U........'
|
||||
'|' '\((?P<field>[^)]*)\)'
|
||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])'
|
||||
'|' '\{(?P<substring>(?:[^%]|%[^}])*)%\}'
|
||||
'(?P<subformat>[+\- #0-9\.]*[siIdboxXfFeEgG])' ')')
|
||||
|
||||
def format(f, v):
|
||||
if f[-1] in 'dboxX':
|
||||
if isinstance(v, str):
|
||||
v = dat(v, 0)
|
||||
@@ -1752,7 +1742,33 @@ def punescape(s, attrs=None):
|
||||
v = str(v)
|
||||
# note we need Python's new format syntax for binary
|
||||
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)
|
||||
|
||||
@@ -1769,6 +1785,7 @@ def punescape_help():
|
||||
print('mods:')
|
||||
print(' %-21s %s' % ('%%', 'A literal % character'))
|
||||
print(' %-21s %s' % ('%n', 'A newline'))
|
||||
print(' %-21s %s' % ('%s', 'A space'))
|
||||
print(' %-21s %s' % (
|
||||
'%xaa', 'A character with the hex value aa'))
|
||||
print(' %-21s %s' % (
|
||||
@@ -1785,6 +1802,12 @@ def punescape_help():
|
||||
'%(field)[dboxX]', 'An existing field formatted as an integer'))
|
||||
print(' %-21s %s' % (
|
||||
'%(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
|
||||
|
||||
+48
-28
@@ -4207,27 +4207,17 @@ def si2(x):
|
||||
# attrs can override __getitem__ for lazy attr generation
|
||||
def punescape(s, attrs=None):
|
||||
pattern = re.compile(
|
||||
'%[%n]'
|
||||
'|' '%x..'
|
||||
'|' '%u....'
|
||||
'|' '%U........'
|
||||
'|' '%\((?P<field>[^)]*)\)'
|
||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
||||
def unescape(m):
|
||||
if m.group()[1] == '%': return '%'
|
||||
elif m.group()[1] == 'n': return '\n'
|
||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
||||
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')
|
||||
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||
'[%ns]'
|
||||
'|' 'x..'
|
||||
'|' 'u....'
|
||||
'|' 'U........'
|
||||
'|' '\((?P<field>[^)]*)\)'
|
||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])'
|
||||
'|' '\{(?P<substring>(?:[^%]|%[^}])*)%\}'
|
||||
'(?P<subformat>[+\- #0-9\.]*[siIdboxXfFeEgG])' ')')
|
||||
|
||||
def format(f, v):
|
||||
if f[-1] in 'dboxX':
|
||||
if isinstance(v, str):
|
||||
v = dat(v, 0)
|
||||
@@ -4247,19 +4237,49 @@ def punescape(s, attrs=None):
|
||||
v = str(v)
|
||||
# note we need Python's new format syntax for binary
|
||||
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)
|
||||
|
||||
# split %-escaped strings into chars
|
||||
def psplit(s):
|
||||
pattern = re.compile(
|
||||
'%[%n]'
|
||||
'|' '%x..'
|
||||
'|' '%u....'
|
||||
'|' '%U........'
|
||||
'|' '%\((?P<field>[^)]*)\)'
|
||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
||||
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||
'[%ns]'
|
||||
'|' 'x..'
|
||||
'|' 'u....'
|
||||
'|' 'U........'
|
||||
'|' '\((?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)]
|
||||
|
||||
|
||||
|
||||
+38
-22
@@ -4096,27 +4096,17 @@ def si2(x):
|
||||
# attrs can override __getitem__ for lazy attr generation
|
||||
def punescape(s, attrs=None):
|
||||
pattern = re.compile(
|
||||
'%[%n]'
|
||||
'|' '%x..'
|
||||
'|' '%u....'
|
||||
'|' '%U........'
|
||||
'|' '%\((?P<field>[^)]*)\)'
|
||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
||||
def unescape(m):
|
||||
if m.group()[1] == '%': return '%'
|
||||
elif m.group()[1] == 'n': return '\n'
|
||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
||||
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')
|
||||
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||
'[%ns]'
|
||||
'|' 'x..'
|
||||
'|' 'u....'
|
||||
'|' 'U........'
|
||||
'|' '\((?P<field>[^)]*)\)'
|
||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])'
|
||||
'|' '\{(?P<substring>(?:[^%]|%[^}])*)%\}'
|
||||
'(?P<subformat>[+\- #0-9\.]*[siIdboxXfFeEgG])' ')')
|
||||
|
||||
def format(f, v):
|
||||
if f[-1] in 'dboxX':
|
||||
if isinstance(v, str):
|
||||
v = dat(v, 0)
|
||||
@@ -4136,7 +4126,33 @@ def punescape(s, attrs=None):
|
||||
v = str(v)
|
||||
# note we need Python's new format syntax for binary
|
||||
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)
|
||||
|
||||
|
||||
+48
-28
@@ -482,27 +482,17 @@ def si2(x):
|
||||
# attrs can override __getitem__ for lazy attr generation
|
||||
def punescape(s, attrs=None):
|
||||
pattern = re.compile(
|
||||
'%[%n]'
|
||||
'|' '%x..'
|
||||
'|' '%u....'
|
||||
'|' '%U........'
|
||||
'|' '%\((?P<field>[^)]*)\)'
|
||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
||||
def unescape(m):
|
||||
if m.group()[1] == '%': return '%'
|
||||
elif m.group()[1] == 'n': return '\n'
|
||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
||||
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')
|
||||
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||
'[%ns]'
|
||||
'|' 'x..'
|
||||
'|' 'u....'
|
||||
'|' 'U........'
|
||||
'|' '\((?P<field>[^)]*)\)'
|
||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])'
|
||||
'|' '\{(?P<substring>(?:[^%]|%[^}])*)%\}'
|
||||
'(?P<subformat>[+\- #0-9\.]*[siIdboxXfFeEgG])' ')')
|
||||
|
||||
def format(f, v):
|
||||
if f[-1] in 'dboxX':
|
||||
if isinstance(v, str):
|
||||
v = dat(v, 0)
|
||||
@@ -522,19 +512,49 @@ def punescape(s, attrs=None):
|
||||
v = str(v)
|
||||
# note we need Python's new format syntax for binary
|
||||
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)
|
||||
|
||||
# split %-escaped strings into chars
|
||||
def psplit(s):
|
||||
pattern = re.compile(
|
||||
'%[%n]'
|
||||
'|' '%x..'
|
||||
'|' '%u....'
|
||||
'|' '%U........'
|
||||
'|' '%\((?P<field>[^)]*)\)'
|
||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
||||
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||
'[%ns]'
|
||||
'|' 'x..'
|
||||
'|' 'u....'
|
||||
'|' 'U........'
|
||||
'|' '\((?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)]
|
||||
|
||||
|
||||
|
||||
+48
-28
@@ -640,27 +640,17 @@ class CsvAttr:
|
||||
# attrs can override __getitem__ for lazy attr generation
|
||||
def punescape(s, attrs=None):
|
||||
pattern = re.compile(
|
||||
'%[%n]'
|
||||
'|' '%x..'
|
||||
'|' '%u....'
|
||||
'|' '%U........'
|
||||
'|' '%\((?P<field>[^)]*)\)'
|
||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
||||
def unescape(m):
|
||||
if m.group()[1] == '%': return '%'
|
||||
elif m.group()[1] == 'n': return '\n'
|
||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
||||
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')
|
||||
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||
'[%ns]'
|
||||
'|' 'x..'
|
||||
'|' 'u....'
|
||||
'|' 'U........'
|
||||
'|' '\((?P<field>[^)]*)\)'
|
||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])'
|
||||
'|' '\{(?P<substring>(?:[^%]|%[^}])*)%\}'
|
||||
'(?P<subformat>[+\- #0-9\.]*[siIdboxXfFeEgG])' ')')
|
||||
|
||||
def format(f, v):
|
||||
if f[-1] in 'dboxX':
|
||||
if isinstance(v, str):
|
||||
v = dat(v, 0)
|
||||
@@ -680,19 +670,49 @@ def punescape(s, attrs=None):
|
||||
v = str(v)
|
||||
# note we need Python's new format syntax for binary
|
||||
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)
|
||||
|
||||
# split %-escaped strings into chars
|
||||
def psplit(s):
|
||||
pattern = re.compile(
|
||||
'%[%n]'
|
||||
'|' '%x..'
|
||||
'|' '%u....'
|
||||
'|' '%U........'
|
||||
'|' '%\((?P<field>[^)]*)\)'
|
||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
||||
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||
'[%ns]'
|
||||
'|' 'x..'
|
||||
'|' 'u....'
|
||||
'|' 'U........'
|
||||
'|' '\((?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)]
|
||||
|
||||
|
||||
|
||||
+38
-22
@@ -524,27 +524,17 @@ class CsvAttr:
|
||||
# attrs can override __getitem__ for lazy attr generation
|
||||
def punescape(s, attrs=None):
|
||||
pattern = re.compile(
|
||||
'%[%n]'
|
||||
'|' '%x..'
|
||||
'|' '%u....'
|
||||
'|' '%U........'
|
||||
'|' '%\((?P<field>[^)]*)\)'
|
||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
||||
def unescape(m):
|
||||
if m.group()[1] == '%': return '%'
|
||||
elif m.group()[1] == 'n': return '\n'
|
||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
||||
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')
|
||||
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||
'[%ns]'
|
||||
'|' 'x..'
|
||||
'|' 'u....'
|
||||
'|' 'U........'
|
||||
'|' '\((?P<field>[^)]*)\)'
|
||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])'
|
||||
'|' '\{(?P<substring>(?:[^%]|%[^}])*)%\}'
|
||||
'(?P<subformat>[+\- #0-9\.]*[siIdboxXfFeEgG])' ')')
|
||||
|
||||
def format(f, v):
|
||||
if f[-1] in 'dboxX':
|
||||
if isinstance(v, str):
|
||||
v = dat(v, 0)
|
||||
@@ -564,7 +554,33 @@ def punescape(s, attrs=None):
|
||||
v = str(v)
|
||||
# note we need Python's new format syntax for binary
|
||||
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)
|
||||
|
||||
|
||||
+48
-28
@@ -561,27 +561,17 @@ def si2(x):
|
||||
# attrs can override __getitem__ for lazy attr generation
|
||||
def punescape(s, attrs=None):
|
||||
pattern = re.compile(
|
||||
'%[%n]'
|
||||
'|' '%x..'
|
||||
'|' '%u....'
|
||||
'|' '%U........'
|
||||
'|' '%\((?P<field>[^)]*)\)'
|
||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
||||
def unescape(m):
|
||||
if m.group()[1] == '%': return '%'
|
||||
elif m.group()[1] == 'n': return '\n'
|
||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
||||
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')
|
||||
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||
'[%ns]'
|
||||
'|' 'x..'
|
||||
'|' 'u....'
|
||||
'|' 'U........'
|
||||
'|' '\((?P<field>[^)]*)\)'
|
||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])'
|
||||
'|' '\{(?P<substring>(?:[^%]|%[^}])*)%\}'
|
||||
'(?P<subformat>[+\- #0-9\.]*[siIdboxXfFeEgG])' ')')
|
||||
|
||||
def format(f, v):
|
||||
if f[-1] in 'dboxX':
|
||||
if isinstance(v, str):
|
||||
v = dat(v, 0)
|
||||
@@ -601,19 +591,49 @@ def punescape(s, attrs=None):
|
||||
v = str(v)
|
||||
# note we need Python's new format syntax for binary
|
||||
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)
|
||||
|
||||
# split %-escaped strings into chars
|
||||
def psplit(s):
|
||||
pattern = re.compile(
|
||||
'%[%n]'
|
||||
'|' '%x..'
|
||||
'|' '%u....'
|
||||
'|' '%U........'
|
||||
'|' '%\((?P<field>[^)]*)\)'
|
||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
||||
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||
'[%ns]'
|
||||
'|' 'x..'
|
||||
'|' 'u....'
|
||||
'|' 'U........'
|
||||
'|' '\((?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)]
|
||||
|
||||
|
||||
|
||||
+38
-22
@@ -422,27 +422,17 @@ def si2(x):
|
||||
# attrs can override __getitem__ for lazy attr generation
|
||||
def punescape(s, attrs=None):
|
||||
pattern = re.compile(
|
||||
'%[%n]'
|
||||
'|' '%x..'
|
||||
'|' '%u....'
|
||||
'|' '%U........'
|
||||
'|' '%\((?P<field>[^)]*)\)'
|
||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])')
|
||||
def unescape(m):
|
||||
if m.group()[1] == '%': return '%'
|
||||
elif m.group()[1] == 'n': return '\n'
|
||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
||||
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')
|
||||
'%' '(?P<rep>[0-9]*)' '(?P<pun>'
|
||||
'[%ns]'
|
||||
'|' 'x..'
|
||||
'|' 'u....'
|
||||
'|' 'U........'
|
||||
'|' '\((?P<field>[^)]*)\)'
|
||||
'(?P<format>[+\- #0-9\.]*[siIdboxXfFeEgG])'
|
||||
'|' '\{(?P<substring>(?:[^%]|%[^}])*)%\}'
|
||||
'(?P<subformat>[+\- #0-9\.]*[siIdboxXfFeEgG])' ')')
|
||||
|
||||
def format(f, v):
|
||||
if f[-1] in 'dboxX':
|
||||
if isinstance(v, str):
|
||||
v = dat(v, 0)
|
||||
@@ -462,7 +452,33 @@ def punescape(s, attrs=None):
|
||||
v = str(v)
|
||||
# note we need Python's new format syntax for binary
|
||||
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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user