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:
+59
-39
@@ -474,19 +474,45 @@ 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>[^)]*)\)'
|
||||||
|
'(?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)
|
||||||
|
v = int(v)
|
||||||
|
elif f[-1] in 'iIfFeEgG':
|
||||||
|
if isinstance(v, str):
|
||||||
|
v = dat(v, 0)
|
||||||
|
v = float(v)
|
||||||
|
if f[-1] in 'iI':
|
||||||
|
v = (si if 'i' in f[-1] else si2)(v)
|
||||||
|
f = f.replace('i', 's').replace('I', 's')
|
||||||
|
if '+' in f and not v.startswith('-'):
|
||||||
|
v = '+'+v
|
||||||
|
f = f.replace('+', '').replace('-', '')
|
||||||
|
else:
|
||||||
|
f = ('<' if '-' in f else '>') + f.replace('-', '')
|
||||||
|
v = str(v)
|
||||||
|
# note we need Python's new format syntax for binary
|
||||||
|
return ('{:%s}' % f).format(v)
|
||||||
|
|
||||||
def unescape(m):
|
def unescape(m):
|
||||||
if m.group()[1] == '%': return '%'
|
if m.group('pun')[0] == '%': s = '%'
|
||||||
elif m.group()[1] == 'n': return '\n'
|
elif m.group('pun')[0] == 'n': s = '\n'
|
||||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 's': s = ' '
|
||||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 'x': s = chr(int(m.group('pun')[1:], 16))
|
||||||
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 'u': s = chr(int(m.group('pun')[1:], 16))
|
||||||
elif m.group()[1] == '(':
|
elif m.group('pun')[0] == 'U': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == '(':
|
||||||
if attrs is not None:
|
if attrs is not None:
|
||||||
try:
|
try:
|
||||||
v = attrs[m.group('field')]
|
v = attrs[m.group('field')]
|
||||||
@@ -494,39 +520,33 @@ def punescape(s, attrs=None):
|
|||||||
return m.group()
|
return m.group()
|
||||||
else:
|
else:
|
||||||
return m.group()
|
return m.group()
|
||||||
f = m.group('format')
|
s = format(m.group('format'), v)
|
||||||
if f[-1] in 'dboxX':
|
elif m.group('pun')[0] == '{':
|
||||||
if isinstance(v, str):
|
v = punescape(m.group('substring'), attrs)
|
||||||
v = dat(v, 0)
|
s = format(m.group('subformat'), v)
|
||||||
v = int(v)
|
else:
|
||||||
elif f[-1] in 'iIfFeEgG':
|
return m.group()
|
||||||
if isinstance(v, str):
|
|
||||||
v = dat(v, 0)
|
if m.group('rep'):
|
||||||
v = float(v)
|
s = int(m.group('rep'), 10) * s
|
||||||
if f[-1] in 'iI':
|
|
||||||
v = (si if 'i' in f[-1] else si2)(v)
|
return s
|
||||||
f = f.replace('i', 's').replace('I', 's')
|
|
||||||
if '+' in f and not v.startswith('-'):
|
|
||||||
v = '+'+v
|
|
||||||
f = f.replace('+', '').replace('-', '')
|
|
||||||
else:
|
|
||||||
f = ('<' if '-' in f else '>') + f.replace('-', '')
|
|
||||||
v = str(v)
|
|
||||||
# note we need Python's new format syntax for binary
|
|
||||||
return ('{:%s}' % f).format(v)
|
|
||||||
else: assert False
|
|
||||||
|
|
||||||
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)]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+49
-33
@@ -336,19 +336,45 @@ 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>[^)]*)\)'
|
||||||
|
'(?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)
|
||||||
|
v = int(v)
|
||||||
|
elif f[-1] in 'iIfFeEgG':
|
||||||
|
if isinstance(v, str):
|
||||||
|
v = dat(v, 0)
|
||||||
|
v = float(v)
|
||||||
|
if f[-1] in 'iI':
|
||||||
|
v = (si if 'i' in f[-1] else si2)(v)
|
||||||
|
f = f.replace('i', 's').replace('I', 's')
|
||||||
|
if '+' in f and not v.startswith('-'):
|
||||||
|
v = '+'+v
|
||||||
|
f = f.replace('+', '').replace('-', '')
|
||||||
|
else:
|
||||||
|
f = ('<' if '-' in f else '>') + f.replace('-', '')
|
||||||
|
v = str(v)
|
||||||
|
# note we need Python's new format syntax for binary
|
||||||
|
return ('{:%s}' % f).format(v)
|
||||||
|
|
||||||
def unescape(m):
|
def unescape(m):
|
||||||
if m.group()[1] == '%': return '%'
|
if m.group('pun')[0] == '%': s = '%'
|
||||||
elif m.group()[1] == 'n': return '\n'
|
elif m.group('pun')[0] == 'n': s = '\n'
|
||||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 's': s = ' '
|
||||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 'x': s = chr(int(m.group('pun')[1:], 16))
|
||||||
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 'u': s = chr(int(m.group('pun')[1:], 16))
|
||||||
elif m.group()[1] == '(':
|
elif m.group('pun')[0] == 'U': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == '(':
|
||||||
if attrs is not None:
|
if attrs is not None:
|
||||||
try:
|
try:
|
||||||
v = attrs[m.group('field')]
|
v = attrs[m.group('field')]
|
||||||
@@ -356,27 +382,17 @@ def punescape(s, attrs=None):
|
|||||||
return m.group()
|
return m.group()
|
||||||
else:
|
else:
|
||||||
return m.group()
|
return m.group()
|
||||||
f = m.group('format')
|
s = format(m.group('format'), v)
|
||||||
if f[-1] in 'dboxX':
|
elif m.group('pun')[0] == '{':
|
||||||
if isinstance(v, str):
|
v = punescape(m.group('substring'), attrs)
|
||||||
v = dat(v, 0)
|
s = format(m.group('subformat'), v)
|
||||||
v = int(v)
|
else:
|
||||||
elif f[-1] in 'iIfFeEgG':
|
return m.group()
|
||||||
if isinstance(v, str):
|
|
||||||
v = dat(v, 0)
|
if m.group('rep'):
|
||||||
v = float(v)
|
s = int(m.group('rep'), 10) * s
|
||||||
if f[-1] in 'iI':
|
|
||||||
v = (si if 'i' in f[-1] else si2)(v)
|
return s
|
||||||
f = f.replace('i', 's').replace('I', 's')
|
|
||||||
if '+' in f and not v.startswith('-'):
|
|
||||||
v = '+'+v
|
|
||||||
f = f.replace('+', '').replace('-', '')
|
|
||||||
else:
|
|
||||||
f = ('<' if '-' in f else '>') + f.replace('-', '')
|
|
||||||
v = str(v)
|
|
||||||
# note we need Python's new format syntax for binary
|
|
||||||
return ('{:%s}' % f).format(v)
|
|
||||||
else: assert False
|
|
||||||
|
|
||||||
return re.sub(pattern, unescape, s)
|
return re.sub(pattern, unescape, s)
|
||||||
|
|
||||||
|
|||||||
+56
-33
@@ -1712,19 +1712,45 @@ 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>[^)]*)\)'
|
||||||
|
'(?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)
|
||||||
|
v = int(v)
|
||||||
|
elif f[-1] in 'iIfFeEgG':
|
||||||
|
if isinstance(v, str):
|
||||||
|
v = dat(v, 0)
|
||||||
|
v = float(v)
|
||||||
|
if f[-1] in 'iI':
|
||||||
|
v = (si if 'i' in f[-1] else si2)(v)
|
||||||
|
f = f.replace('i', 's').replace('I', 's')
|
||||||
|
if '+' in f and not v.startswith('-'):
|
||||||
|
v = '+'+v
|
||||||
|
f = f.replace('+', '').replace('-', '')
|
||||||
|
else:
|
||||||
|
f = ('<' if '-' in f else '>') + f.replace('-', '')
|
||||||
|
v = str(v)
|
||||||
|
# note we need Python's new format syntax for binary
|
||||||
|
return ('{:%s}' % f).format(v)
|
||||||
|
|
||||||
def unescape(m):
|
def unescape(m):
|
||||||
if m.group()[1] == '%': return '%'
|
if m.group('pun')[0] == '%': s = '%'
|
||||||
elif m.group()[1] == 'n': return '\n'
|
elif m.group('pun')[0] == 'n': s = '\n'
|
||||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 's': s = ' '
|
||||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 'x': s = chr(int(m.group('pun')[1:], 16))
|
||||||
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 'u': s = chr(int(m.group('pun')[1:], 16))
|
||||||
elif m.group()[1] == '(':
|
elif m.group('pun')[0] == 'U': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == '(':
|
||||||
if attrs is not None:
|
if attrs is not None:
|
||||||
try:
|
try:
|
||||||
v = attrs[m.group('field')]
|
v = attrs[m.group('field')]
|
||||||
@@ -1732,27 +1758,17 @@ def punescape(s, attrs=None):
|
|||||||
return m.group()
|
return m.group()
|
||||||
else:
|
else:
|
||||||
return m.group()
|
return m.group()
|
||||||
f = m.group('format')
|
s = format(m.group('format'), v)
|
||||||
if f[-1] in 'dboxX':
|
elif m.group('pun')[0] == '{':
|
||||||
if isinstance(v, str):
|
v = punescape(m.group('substring'), attrs)
|
||||||
v = dat(v, 0)
|
s = format(m.group('subformat'), v)
|
||||||
v = int(v)
|
else:
|
||||||
elif f[-1] in 'iIfFeEgG':
|
return m.group()
|
||||||
if isinstance(v, str):
|
|
||||||
v = dat(v, 0)
|
if m.group('rep'):
|
||||||
v = float(v)
|
s = int(m.group('rep'), 10) * s
|
||||||
if f[-1] in 'iI':
|
|
||||||
v = (si if 'i' in f[-1] else si2)(v)
|
return s
|
||||||
f = f.replace('i', 's').replace('I', 's')
|
|
||||||
if '+' in f and not v.startswith('-'):
|
|
||||||
v = '+'+v
|
|
||||||
f = f.replace('+', '').replace('-', '')
|
|
||||||
else:
|
|
||||||
f = ('<' if '-' in f else '>') + f.replace('-', '')
|
|
||||||
v = str(v)
|
|
||||||
# note we need Python's new format syntax for binary
|
|
||||||
return ('{:%s}' % f).format(v)
|
|
||||||
else: assert False
|
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
+59
-39
@@ -4207,19 +4207,45 @@ 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>[^)]*)\)'
|
||||||
|
'(?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)
|
||||||
|
v = int(v)
|
||||||
|
elif f[-1] in 'iIfFeEgG':
|
||||||
|
if isinstance(v, str):
|
||||||
|
v = dat(v, 0)
|
||||||
|
v = float(v)
|
||||||
|
if f[-1] in 'iI':
|
||||||
|
v = (si if 'i' in f[-1] else si2)(v)
|
||||||
|
f = f.replace('i', 's').replace('I', 's')
|
||||||
|
if '+' in f and not v.startswith('-'):
|
||||||
|
v = '+'+v
|
||||||
|
f = f.replace('+', '').replace('-', '')
|
||||||
|
else:
|
||||||
|
f = ('<' if '-' in f else '>') + f.replace('-', '')
|
||||||
|
v = str(v)
|
||||||
|
# note we need Python's new format syntax for binary
|
||||||
|
return ('{:%s}' % f).format(v)
|
||||||
|
|
||||||
def unescape(m):
|
def unescape(m):
|
||||||
if m.group()[1] == '%': return '%'
|
if m.group('pun')[0] == '%': s = '%'
|
||||||
elif m.group()[1] == 'n': return '\n'
|
elif m.group('pun')[0] == 'n': s = '\n'
|
||||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 's': s = ' '
|
||||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 'x': s = chr(int(m.group('pun')[1:], 16))
|
||||||
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 'u': s = chr(int(m.group('pun')[1:], 16))
|
||||||
elif m.group()[1] == '(':
|
elif m.group('pun')[0] == 'U': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == '(':
|
||||||
if attrs is not None:
|
if attrs is not None:
|
||||||
try:
|
try:
|
||||||
v = attrs[m.group('field')]
|
v = attrs[m.group('field')]
|
||||||
@@ -4227,39 +4253,33 @@ def punescape(s, attrs=None):
|
|||||||
return m.group()
|
return m.group()
|
||||||
else:
|
else:
|
||||||
return m.group()
|
return m.group()
|
||||||
f = m.group('format')
|
s = format(m.group('format'), v)
|
||||||
if f[-1] in 'dboxX':
|
elif m.group('pun')[0] == '{':
|
||||||
if isinstance(v, str):
|
v = punescape(m.group('substring'), attrs)
|
||||||
v = dat(v, 0)
|
s = format(m.group('subformat'), v)
|
||||||
v = int(v)
|
else:
|
||||||
elif f[-1] in 'iIfFeEgG':
|
return m.group()
|
||||||
if isinstance(v, str):
|
|
||||||
v = dat(v, 0)
|
if m.group('rep'):
|
||||||
v = float(v)
|
s = int(m.group('rep'), 10) * s
|
||||||
if f[-1] in 'iI':
|
|
||||||
v = (si if 'i' in f[-1] else si2)(v)
|
return s
|
||||||
f = f.replace('i', 's').replace('I', 's')
|
|
||||||
if '+' in f and not v.startswith('-'):
|
|
||||||
v = '+'+v
|
|
||||||
f = f.replace('+', '').replace('-', '')
|
|
||||||
else:
|
|
||||||
f = ('<' if '-' in f else '>') + f.replace('-', '')
|
|
||||||
v = str(v)
|
|
||||||
# note we need Python's new format syntax for binary
|
|
||||||
return ('{:%s}' % f).format(v)
|
|
||||||
else: assert False
|
|
||||||
|
|
||||||
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)]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+49
-33
@@ -4096,19 +4096,45 @@ 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>[^)]*)\)'
|
||||||
|
'(?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)
|
||||||
|
v = int(v)
|
||||||
|
elif f[-1] in 'iIfFeEgG':
|
||||||
|
if isinstance(v, str):
|
||||||
|
v = dat(v, 0)
|
||||||
|
v = float(v)
|
||||||
|
if f[-1] in 'iI':
|
||||||
|
v = (si if 'i' in f[-1] else si2)(v)
|
||||||
|
f = f.replace('i', 's').replace('I', 's')
|
||||||
|
if '+' in f and not v.startswith('-'):
|
||||||
|
v = '+'+v
|
||||||
|
f = f.replace('+', '').replace('-', '')
|
||||||
|
else:
|
||||||
|
f = ('<' if '-' in f else '>') + f.replace('-', '')
|
||||||
|
v = str(v)
|
||||||
|
# note we need Python's new format syntax for binary
|
||||||
|
return ('{:%s}' % f).format(v)
|
||||||
|
|
||||||
def unescape(m):
|
def unescape(m):
|
||||||
if m.group()[1] == '%': return '%'
|
if m.group('pun')[0] == '%': s = '%'
|
||||||
elif m.group()[1] == 'n': return '\n'
|
elif m.group('pun')[0] == 'n': s = '\n'
|
||||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 's': s = ' '
|
||||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 'x': s = chr(int(m.group('pun')[1:], 16))
|
||||||
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 'u': s = chr(int(m.group('pun')[1:], 16))
|
||||||
elif m.group()[1] == '(':
|
elif m.group('pun')[0] == 'U': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == '(':
|
||||||
if attrs is not None:
|
if attrs is not None:
|
||||||
try:
|
try:
|
||||||
v = attrs[m.group('field')]
|
v = attrs[m.group('field')]
|
||||||
@@ -4116,27 +4142,17 @@ def punescape(s, attrs=None):
|
|||||||
return m.group()
|
return m.group()
|
||||||
else:
|
else:
|
||||||
return m.group()
|
return m.group()
|
||||||
f = m.group('format')
|
s = format(m.group('format'), v)
|
||||||
if f[-1] in 'dboxX':
|
elif m.group('pun')[0] == '{':
|
||||||
if isinstance(v, str):
|
v = punescape(m.group('substring'), attrs)
|
||||||
v = dat(v, 0)
|
s = format(m.group('subformat'), v)
|
||||||
v = int(v)
|
else:
|
||||||
elif f[-1] in 'iIfFeEgG':
|
return m.group()
|
||||||
if isinstance(v, str):
|
|
||||||
v = dat(v, 0)
|
if m.group('rep'):
|
||||||
v = float(v)
|
s = int(m.group('rep'), 10) * s
|
||||||
if f[-1] in 'iI':
|
|
||||||
v = (si if 'i' in f[-1] else si2)(v)
|
return s
|
||||||
f = f.replace('i', 's').replace('I', 's')
|
|
||||||
if '+' in f and not v.startswith('-'):
|
|
||||||
v = '+'+v
|
|
||||||
f = f.replace('+', '').replace('-', '')
|
|
||||||
else:
|
|
||||||
f = ('<' if '-' in f else '>') + f.replace('-', '')
|
|
||||||
v = str(v)
|
|
||||||
# note we need Python's new format syntax for binary
|
|
||||||
return ('{:%s}' % f).format(v)
|
|
||||||
else: assert False
|
|
||||||
|
|
||||||
return re.sub(pattern, unescape, s)
|
return re.sub(pattern, unescape, s)
|
||||||
|
|
||||||
|
|||||||
+59
-39
@@ -482,19 +482,45 @@ 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>[^)]*)\)'
|
||||||
|
'(?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)
|
||||||
|
v = int(v)
|
||||||
|
elif f[-1] in 'iIfFeEgG':
|
||||||
|
if isinstance(v, str):
|
||||||
|
v = dat(v, 0)
|
||||||
|
v = float(v)
|
||||||
|
if f[-1] in 'iI':
|
||||||
|
v = (si if 'i' in f[-1] else si2)(v)
|
||||||
|
f = f.replace('i', 's').replace('I', 's')
|
||||||
|
if '+' in f and not v.startswith('-'):
|
||||||
|
v = '+'+v
|
||||||
|
f = f.replace('+', '').replace('-', '')
|
||||||
|
else:
|
||||||
|
f = ('<' if '-' in f else '>') + f.replace('-', '')
|
||||||
|
v = str(v)
|
||||||
|
# note we need Python's new format syntax for binary
|
||||||
|
return ('{:%s}' % f).format(v)
|
||||||
|
|
||||||
def unescape(m):
|
def unescape(m):
|
||||||
if m.group()[1] == '%': return '%'
|
if m.group('pun')[0] == '%': s = '%'
|
||||||
elif m.group()[1] == 'n': return '\n'
|
elif m.group('pun')[0] == 'n': s = '\n'
|
||||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 's': s = ' '
|
||||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 'x': s = chr(int(m.group('pun')[1:], 16))
|
||||||
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 'u': s = chr(int(m.group('pun')[1:], 16))
|
||||||
elif m.group()[1] == '(':
|
elif m.group('pun')[0] == 'U': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == '(':
|
||||||
if attrs is not None:
|
if attrs is not None:
|
||||||
try:
|
try:
|
||||||
v = attrs[m.group('field')]
|
v = attrs[m.group('field')]
|
||||||
@@ -502,39 +528,33 @@ def punescape(s, attrs=None):
|
|||||||
return m.group()
|
return m.group()
|
||||||
else:
|
else:
|
||||||
return m.group()
|
return m.group()
|
||||||
f = m.group('format')
|
s = format(m.group('format'), v)
|
||||||
if f[-1] in 'dboxX':
|
elif m.group('pun')[0] == '{':
|
||||||
if isinstance(v, str):
|
v = punescape(m.group('substring'), attrs)
|
||||||
v = dat(v, 0)
|
s = format(m.group('subformat'), v)
|
||||||
v = int(v)
|
else:
|
||||||
elif f[-1] in 'iIfFeEgG':
|
return m.group()
|
||||||
if isinstance(v, str):
|
|
||||||
v = dat(v, 0)
|
if m.group('rep'):
|
||||||
v = float(v)
|
s = int(m.group('rep'), 10) * s
|
||||||
if f[-1] in 'iI':
|
|
||||||
v = (si if 'i' in f[-1] else si2)(v)
|
return s
|
||||||
f = f.replace('i', 's').replace('I', 's')
|
|
||||||
if '+' in f and not v.startswith('-'):
|
|
||||||
v = '+'+v
|
|
||||||
f = f.replace('+', '').replace('-', '')
|
|
||||||
else:
|
|
||||||
f = ('<' if '-' in f else '>') + f.replace('-', '')
|
|
||||||
v = str(v)
|
|
||||||
# note we need Python's new format syntax for binary
|
|
||||||
return ('{:%s}' % f).format(v)
|
|
||||||
else: assert False
|
|
||||||
|
|
||||||
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)]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+59
-39
@@ -640,19 +640,45 @@ 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>[^)]*)\)'
|
||||||
|
'(?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)
|
||||||
|
v = int(v)
|
||||||
|
elif f[-1] in 'iIfFeEgG':
|
||||||
|
if isinstance(v, str):
|
||||||
|
v = dat(v, 0)
|
||||||
|
v = float(v)
|
||||||
|
if f[-1] in 'iI':
|
||||||
|
v = (si if 'i' in f[-1] else si2)(v)
|
||||||
|
f = f.replace('i', 's').replace('I', 's')
|
||||||
|
if '+' in f and not v.startswith('-'):
|
||||||
|
v = '+'+v
|
||||||
|
f = f.replace('+', '').replace('-', '')
|
||||||
|
else:
|
||||||
|
f = ('<' if '-' in f else '>') + f.replace('-', '')
|
||||||
|
v = str(v)
|
||||||
|
# note we need Python's new format syntax for binary
|
||||||
|
return ('{:%s}' % f).format(v)
|
||||||
|
|
||||||
def unescape(m):
|
def unescape(m):
|
||||||
if m.group()[1] == '%': return '%'
|
if m.group('pun')[0] == '%': s = '%'
|
||||||
elif m.group()[1] == 'n': return '\n'
|
elif m.group('pun')[0] == 'n': s = '\n'
|
||||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 's': s = ' '
|
||||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 'x': s = chr(int(m.group('pun')[1:], 16))
|
||||||
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 'u': s = chr(int(m.group('pun')[1:], 16))
|
||||||
elif m.group()[1] == '(':
|
elif m.group('pun')[0] == 'U': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == '(':
|
||||||
if attrs is not None:
|
if attrs is not None:
|
||||||
try:
|
try:
|
||||||
v = attrs[m.group('field')]
|
v = attrs[m.group('field')]
|
||||||
@@ -660,39 +686,33 @@ def punescape(s, attrs=None):
|
|||||||
return m.group()
|
return m.group()
|
||||||
else:
|
else:
|
||||||
return m.group()
|
return m.group()
|
||||||
f = m.group('format')
|
s = format(m.group('format'), v)
|
||||||
if f[-1] in 'dboxX':
|
elif m.group('pun')[0] == '{':
|
||||||
if isinstance(v, str):
|
v = punescape(m.group('substring'), attrs)
|
||||||
v = dat(v, 0)
|
s = format(m.group('subformat'), v)
|
||||||
v = int(v)
|
else:
|
||||||
elif f[-1] in 'iIfFeEgG':
|
return m.group()
|
||||||
if isinstance(v, str):
|
|
||||||
v = dat(v, 0)
|
if m.group('rep'):
|
||||||
v = float(v)
|
s = int(m.group('rep'), 10) * s
|
||||||
if f[-1] in 'iI':
|
|
||||||
v = (si if 'i' in f[-1] else si2)(v)
|
return s
|
||||||
f = f.replace('i', 's').replace('I', 's')
|
|
||||||
if '+' in f and not v.startswith('-'):
|
|
||||||
v = '+'+v
|
|
||||||
f = f.replace('+', '').replace('-', '')
|
|
||||||
else:
|
|
||||||
f = ('<' if '-' in f else '>') + f.replace('-', '')
|
|
||||||
v = str(v)
|
|
||||||
# note we need Python's new format syntax for binary
|
|
||||||
return ('{:%s}' % f).format(v)
|
|
||||||
else: assert False
|
|
||||||
|
|
||||||
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)]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+49
-33
@@ -524,19 +524,45 @@ 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>[^)]*)\)'
|
||||||
|
'(?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)
|
||||||
|
v = int(v)
|
||||||
|
elif f[-1] in 'iIfFeEgG':
|
||||||
|
if isinstance(v, str):
|
||||||
|
v = dat(v, 0)
|
||||||
|
v = float(v)
|
||||||
|
if f[-1] in 'iI':
|
||||||
|
v = (si if 'i' in f[-1] else si2)(v)
|
||||||
|
f = f.replace('i', 's').replace('I', 's')
|
||||||
|
if '+' in f and not v.startswith('-'):
|
||||||
|
v = '+'+v
|
||||||
|
f = f.replace('+', '').replace('-', '')
|
||||||
|
else:
|
||||||
|
f = ('<' if '-' in f else '>') + f.replace('-', '')
|
||||||
|
v = str(v)
|
||||||
|
# note we need Python's new format syntax for binary
|
||||||
|
return ('{:%s}' % f).format(v)
|
||||||
|
|
||||||
def unescape(m):
|
def unescape(m):
|
||||||
if m.group()[1] == '%': return '%'
|
if m.group('pun')[0] == '%': s = '%'
|
||||||
elif m.group()[1] == 'n': return '\n'
|
elif m.group('pun')[0] == 'n': s = '\n'
|
||||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 's': s = ' '
|
||||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 'x': s = chr(int(m.group('pun')[1:], 16))
|
||||||
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 'u': s = chr(int(m.group('pun')[1:], 16))
|
||||||
elif m.group()[1] == '(':
|
elif m.group('pun')[0] == 'U': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == '(':
|
||||||
if attrs is not None:
|
if attrs is not None:
|
||||||
try:
|
try:
|
||||||
v = attrs[m.group('field')]
|
v = attrs[m.group('field')]
|
||||||
@@ -544,27 +570,17 @@ def punescape(s, attrs=None):
|
|||||||
return m.group()
|
return m.group()
|
||||||
else:
|
else:
|
||||||
return m.group()
|
return m.group()
|
||||||
f = m.group('format')
|
s = format(m.group('format'), v)
|
||||||
if f[-1] in 'dboxX':
|
elif m.group('pun')[0] == '{':
|
||||||
if isinstance(v, str):
|
v = punescape(m.group('substring'), attrs)
|
||||||
v = dat(v, 0)
|
s = format(m.group('subformat'), v)
|
||||||
v = int(v)
|
else:
|
||||||
elif f[-1] in 'iIfFeEgG':
|
return m.group()
|
||||||
if isinstance(v, str):
|
|
||||||
v = dat(v, 0)
|
if m.group('rep'):
|
||||||
v = float(v)
|
s = int(m.group('rep'), 10) * s
|
||||||
if f[-1] in 'iI':
|
|
||||||
v = (si if 'i' in f[-1] else si2)(v)
|
return s
|
||||||
f = f.replace('i', 's').replace('I', 's')
|
|
||||||
if '+' in f and not v.startswith('-'):
|
|
||||||
v = '+'+v
|
|
||||||
f = f.replace('+', '').replace('-', '')
|
|
||||||
else:
|
|
||||||
f = ('<' if '-' in f else '>') + f.replace('-', '')
|
|
||||||
v = str(v)
|
|
||||||
# note we need Python's new format syntax for binary
|
|
||||||
return ('{:%s}' % f).format(v)
|
|
||||||
else: assert False
|
|
||||||
|
|
||||||
return re.sub(pattern, unescape, s)
|
return re.sub(pattern, unescape, s)
|
||||||
|
|
||||||
|
|||||||
+59
-39
@@ -561,19 +561,45 @@ 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>[^)]*)\)'
|
||||||
|
'(?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)
|
||||||
|
v = int(v)
|
||||||
|
elif f[-1] in 'iIfFeEgG':
|
||||||
|
if isinstance(v, str):
|
||||||
|
v = dat(v, 0)
|
||||||
|
v = float(v)
|
||||||
|
if f[-1] in 'iI':
|
||||||
|
v = (si if 'i' in f[-1] else si2)(v)
|
||||||
|
f = f.replace('i', 's').replace('I', 's')
|
||||||
|
if '+' in f and not v.startswith('-'):
|
||||||
|
v = '+'+v
|
||||||
|
f = f.replace('+', '').replace('-', '')
|
||||||
|
else:
|
||||||
|
f = ('<' if '-' in f else '>') + f.replace('-', '')
|
||||||
|
v = str(v)
|
||||||
|
# note we need Python's new format syntax for binary
|
||||||
|
return ('{:%s}' % f).format(v)
|
||||||
|
|
||||||
def unescape(m):
|
def unescape(m):
|
||||||
if m.group()[1] == '%': return '%'
|
if m.group('pun')[0] == '%': s = '%'
|
||||||
elif m.group()[1] == 'n': return '\n'
|
elif m.group('pun')[0] == 'n': s = '\n'
|
||||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 's': s = ' '
|
||||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 'x': s = chr(int(m.group('pun')[1:], 16))
|
||||||
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 'u': s = chr(int(m.group('pun')[1:], 16))
|
||||||
elif m.group()[1] == '(':
|
elif m.group('pun')[0] == 'U': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == '(':
|
||||||
if attrs is not None:
|
if attrs is not None:
|
||||||
try:
|
try:
|
||||||
v = attrs[m.group('field')]
|
v = attrs[m.group('field')]
|
||||||
@@ -581,39 +607,33 @@ def punescape(s, attrs=None):
|
|||||||
return m.group()
|
return m.group()
|
||||||
else:
|
else:
|
||||||
return m.group()
|
return m.group()
|
||||||
f = m.group('format')
|
s = format(m.group('format'), v)
|
||||||
if f[-1] in 'dboxX':
|
elif m.group('pun')[0] == '{':
|
||||||
if isinstance(v, str):
|
v = punescape(m.group('substring'), attrs)
|
||||||
v = dat(v, 0)
|
s = format(m.group('subformat'), v)
|
||||||
v = int(v)
|
else:
|
||||||
elif f[-1] in 'iIfFeEgG':
|
return m.group()
|
||||||
if isinstance(v, str):
|
|
||||||
v = dat(v, 0)
|
if m.group('rep'):
|
||||||
v = float(v)
|
s = int(m.group('rep'), 10) * s
|
||||||
if f[-1] in 'iI':
|
|
||||||
v = (si if 'i' in f[-1] else si2)(v)
|
return s
|
||||||
f = f.replace('i', 's').replace('I', 's')
|
|
||||||
if '+' in f and not v.startswith('-'):
|
|
||||||
v = '+'+v
|
|
||||||
f = f.replace('+', '').replace('-', '')
|
|
||||||
else:
|
|
||||||
f = ('<' if '-' in f else '>') + f.replace('-', '')
|
|
||||||
v = str(v)
|
|
||||||
# note we need Python's new format syntax for binary
|
|
||||||
return ('{:%s}' % f).format(v)
|
|
||||||
else: assert False
|
|
||||||
|
|
||||||
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)]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+49
-33
@@ -422,19 +422,45 @@ 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>[^)]*)\)'
|
||||||
|
'(?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)
|
||||||
|
v = int(v)
|
||||||
|
elif f[-1] in 'iIfFeEgG':
|
||||||
|
if isinstance(v, str):
|
||||||
|
v = dat(v, 0)
|
||||||
|
v = float(v)
|
||||||
|
if f[-1] in 'iI':
|
||||||
|
v = (si if 'i' in f[-1] else si2)(v)
|
||||||
|
f = f.replace('i', 's').replace('I', 's')
|
||||||
|
if '+' in f and not v.startswith('-'):
|
||||||
|
v = '+'+v
|
||||||
|
f = f.replace('+', '').replace('-', '')
|
||||||
|
else:
|
||||||
|
f = ('<' if '-' in f else '>') + f.replace('-', '')
|
||||||
|
v = str(v)
|
||||||
|
# note we need Python's new format syntax for binary
|
||||||
|
return ('{:%s}' % f).format(v)
|
||||||
|
|
||||||
def unescape(m):
|
def unescape(m):
|
||||||
if m.group()[1] == '%': return '%'
|
if m.group('pun')[0] == '%': s = '%'
|
||||||
elif m.group()[1] == 'n': return '\n'
|
elif m.group('pun')[0] == 'n': s = '\n'
|
||||||
elif m.group()[1] == 'x': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 's': s = ' '
|
||||||
elif m.group()[1] == 'u': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 'x': s = chr(int(m.group('pun')[1:], 16))
|
||||||
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
elif m.group('pun')[0] == 'u': s = chr(int(m.group('pun')[1:], 16))
|
||||||
elif m.group()[1] == '(':
|
elif m.group('pun')[0] == 'U': s = chr(int(m.group('pun')[1:], 16))
|
||||||
|
elif m.group('pun')[0] == '(':
|
||||||
if attrs is not None:
|
if attrs is not None:
|
||||||
try:
|
try:
|
||||||
v = attrs[m.group('field')]
|
v = attrs[m.group('field')]
|
||||||
@@ -442,27 +468,17 @@ def punescape(s, attrs=None):
|
|||||||
return m.group()
|
return m.group()
|
||||||
else:
|
else:
|
||||||
return m.group()
|
return m.group()
|
||||||
f = m.group('format')
|
s = format(m.group('format'), v)
|
||||||
if f[-1] in 'dboxX':
|
elif m.group('pun')[0] == '{':
|
||||||
if isinstance(v, str):
|
v = punescape(m.group('substring'), attrs)
|
||||||
v = dat(v, 0)
|
s = format(m.group('subformat'), v)
|
||||||
v = int(v)
|
else:
|
||||||
elif f[-1] in 'iIfFeEgG':
|
return m.group()
|
||||||
if isinstance(v, str):
|
|
||||||
v = dat(v, 0)
|
if m.group('rep'):
|
||||||
v = float(v)
|
s = int(m.group('rep'), 10) * s
|
||||||
if f[-1] in 'iI':
|
|
||||||
v = (si if 'i' in f[-1] else si2)(v)
|
return s
|
||||||
f = f.replace('i', 's').replace('I', 's')
|
|
||||||
if '+' in f and not v.startswith('-'):
|
|
||||||
v = '+'+v
|
|
||||||
f = f.replace('+', '').replace('-', '')
|
|
||||||
else:
|
|
||||||
f = ('<' if '-' in f else '>') + f.replace('-', '')
|
|
||||||
v = str(v)
|
|
||||||
# note we need Python's new format syntax for binary
|
|
||||||
return ('{:%s}' % f).format(v)
|
|
||||||
else: assert False
|
|
||||||
|
|
||||||
return re.sub(pattern, unescape, s)
|
return re.sub(pattern, unescape, s)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user