scripts: Tweaked punescape to expect dict-like attrs
This simplifies attrs a bit, and scripts can always override __getitem__ if they want to provide lazy attr generation. The original intention of accepting functions was to make lazy attr generation easier, but while tinkering around with the idea I realized the actual attr mapping/generation would be complicated enough that you'd probably want a full class anyways. All of our scripts are only using dict attrs anyways. And lazy attr generation is probably a premature optimization for the same reason everyone's ok with Python's slices being O(n).
This commit is contained in:
+9
-9
@@ -375,13 +375,9 @@ class Attr:
|
|||||||
return len(self.keyed)
|
return len(self.keyed)
|
||||||
|
|
||||||
# parse %-escaped strings
|
# parse %-escaped strings
|
||||||
|
#
|
||||||
|
# attrs can override __getitem__ for lazy attr generation
|
||||||
def punescape(s, attrs=None):
|
def punescape(s, attrs=None):
|
||||||
if attrs is None:
|
|
||||||
attrs = {}
|
|
||||||
if isinstance(attrs, dict):
|
|
||||||
attrs_ = attrs
|
|
||||||
attrs = lambda k: attrs_[k]
|
|
||||||
|
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'%[%n]'
|
'%[%n]'
|
||||||
'|' '%x..'
|
'|' '%x..'
|
||||||
@@ -396,9 +392,12 @@ def punescape(s, attrs=None):
|
|||||||
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] == 'U': return chr(int(m.group()[2:], 16))
|
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
||||||
elif m.group()[1] == '(':
|
elif m.group()[1] == '(':
|
||||||
try:
|
if attrs is not None:
|
||||||
v = attrs(m.group('field'))
|
try:
|
||||||
except KeyError:
|
v = attrs[m.group('field')]
|
||||||
|
except KeyError:
|
||||||
|
return m.group()
|
||||||
|
else:
|
||||||
return m.group()
|
return m.group()
|
||||||
f = m.group('format')
|
f = m.group('format')
|
||||||
if f[-1] in 'dboxX':
|
if f[-1] in 'dboxX':
|
||||||
@@ -415,6 +414,7 @@ def punescape(s, attrs=None):
|
|||||||
# 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
|
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
|
||||||
|
|||||||
@@ -267,13 +267,9 @@ class Attr:
|
|||||||
return len(self.keyed)
|
return len(self.keyed)
|
||||||
|
|
||||||
# parse %-escaped strings
|
# parse %-escaped strings
|
||||||
|
#
|
||||||
|
# attrs can override __getitem__ for lazy attr generation
|
||||||
def punescape(s, attrs=None):
|
def punescape(s, attrs=None):
|
||||||
if attrs is None:
|
|
||||||
attrs = {}
|
|
||||||
if isinstance(attrs, dict):
|
|
||||||
attrs_ = attrs
|
|
||||||
attrs = lambda k: attrs_[k]
|
|
||||||
|
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'%[%n]'
|
'%[%n]'
|
||||||
'|' '%x..'
|
'|' '%x..'
|
||||||
@@ -288,9 +284,12 @@ def punescape(s, attrs=None):
|
|||||||
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] == 'U': return chr(int(m.group()[2:], 16))
|
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
||||||
elif m.group()[1] == '(':
|
elif m.group()[1] == '(':
|
||||||
try:
|
if attrs is not None:
|
||||||
v = attrs(m.group('field'))
|
try:
|
||||||
except KeyError:
|
v = attrs[m.group('field')]
|
||||||
|
except KeyError:
|
||||||
|
return m.group()
|
||||||
|
else:
|
||||||
return m.group()
|
return m.group()
|
||||||
f = m.group('format')
|
f = m.group('format')
|
||||||
if f[-1] in 'dboxX':
|
if f[-1] in 'dboxX':
|
||||||
@@ -307,6 +306,7 @@ def punescape(s, attrs=None):
|
|||||||
# 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
|
else: assert False
|
||||||
|
|
||||||
return re.sub(pattern, unescape, s)
|
return re.sub(pattern, unescape, s)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+9
-9
@@ -1268,13 +1268,9 @@ class RExpr:
|
|||||||
|
|
||||||
|
|
||||||
# parse %-escaped strings
|
# parse %-escaped strings
|
||||||
|
#
|
||||||
|
# attrs can override __getitem__ for lazy attr generation
|
||||||
def punescape(s, attrs=None):
|
def punescape(s, attrs=None):
|
||||||
if attrs is None:
|
|
||||||
attrs = {}
|
|
||||||
if isinstance(attrs, dict):
|
|
||||||
attrs_ = attrs
|
|
||||||
attrs = lambda k: attrs_[k]
|
|
||||||
|
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'%[%n]'
|
'%[%n]'
|
||||||
'|' '%x..'
|
'|' '%x..'
|
||||||
@@ -1289,9 +1285,12 @@ def punescape(s, attrs=None):
|
|||||||
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] == 'U': return chr(int(m.group()[2:], 16))
|
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
||||||
elif m.group()[1] == '(':
|
elif m.group()[1] == '(':
|
||||||
try:
|
if attrs is not None:
|
||||||
v = attrs(m.group('field'))
|
try:
|
||||||
except KeyError:
|
v = attrs[m.group('field')]
|
||||||
|
except KeyError:
|
||||||
|
return m.group()
|
||||||
|
else:
|
||||||
return m.group()
|
return m.group()
|
||||||
f = m.group('format')
|
f = m.group('format')
|
||||||
if f[-1] in 'dboxX':
|
if f[-1] in 'dboxX':
|
||||||
@@ -1308,6 +1307,7 @@ def punescape(s, attrs=None):
|
|||||||
# 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
|
else: assert False
|
||||||
|
|
||||||
return re.sub(pattern, unescape, s)
|
return re.sub(pattern, unescape, s)
|
||||||
|
|
||||||
def punescape_help():
|
def punescape_help():
|
||||||
|
|||||||
+9
-9
@@ -3898,13 +3898,9 @@ class Attr:
|
|||||||
return len(self.keyed)
|
return len(self.keyed)
|
||||||
|
|
||||||
# parse %-escaped strings
|
# parse %-escaped strings
|
||||||
|
#
|
||||||
|
# attrs can override __getitem__ for lazy attr generation
|
||||||
def punescape(s, attrs=None):
|
def punescape(s, attrs=None):
|
||||||
if attrs is None:
|
|
||||||
attrs = {}
|
|
||||||
if isinstance(attrs, dict):
|
|
||||||
attrs_ = attrs
|
|
||||||
attrs = lambda k: attrs_[k]
|
|
||||||
|
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'%[%n]'
|
'%[%n]'
|
||||||
'|' '%x..'
|
'|' '%x..'
|
||||||
@@ -3919,9 +3915,12 @@ def punescape(s, attrs=None):
|
|||||||
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] == 'U': return chr(int(m.group()[2:], 16))
|
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
||||||
elif m.group()[1] == '(':
|
elif m.group()[1] == '(':
|
||||||
try:
|
if attrs is not None:
|
||||||
v = attrs(m.group('field'))
|
try:
|
||||||
except KeyError:
|
v = attrs[m.group('field')]
|
||||||
|
except KeyError:
|
||||||
|
return m.group()
|
||||||
|
else:
|
||||||
return m.group()
|
return m.group()
|
||||||
f = m.group('format')
|
f = m.group('format')
|
||||||
if f[-1] in 'dboxX':
|
if f[-1] in 'dboxX':
|
||||||
@@ -3938,6 +3937,7 @@ def punescape(s, attrs=None):
|
|||||||
# 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
|
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
|
||||||
|
|||||||
@@ -3808,13 +3808,9 @@ class Attr:
|
|||||||
return len(self.keyed)
|
return len(self.keyed)
|
||||||
|
|
||||||
# parse %-escaped strings
|
# parse %-escaped strings
|
||||||
|
#
|
||||||
|
# attrs can override __getitem__ for lazy attr generation
|
||||||
def punescape(s, attrs=None):
|
def punescape(s, attrs=None):
|
||||||
if attrs is None:
|
|
||||||
attrs = {}
|
|
||||||
if isinstance(attrs, dict):
|
|
||||||
attrs_ = attrs
|
|
||||||
attrs = lambda k: attrs_[k]
|
|
||||||
|
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'%[%n]'
|
'%[%n]'
|
||||||
'|' '%x..'
|
'|' '%x..'
|
||||||
@@ -3829,9 +3825,12 @@ def punescape(s, attrs=None):
|
|||||||
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] == 'U': return chr(int(m.group()[2:], 16))
|
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
||||||
elif m.group()[1] == '(':
|
elif m.group()[1] == '(':
|
||||||
try:
|
if attrs is not None:
|
||||||
v = attrs(m.group('field'))
|
try:
|
||||||
except KeyError:
|
v = attrs[m.group('field')]
|
||||||
|
except KeyError:
|
||||||
|
return m.group()
|
||||||
|
else:
|
||||||
return m.group()
|
return m.group()
|
||||||
f = m.group('format')
|
f = m.group('format')
|
||||||
if f[-1] in 'dboxX':
|
if f[-1] in 'dboxX':
|
||||||
@@ -3848,6 +3847,7 @@ def punescape(s, attrs=None):
|
|||||||
# 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
|
else: assert False
|
||||||
|
|
||||||
return re.sub(pattern, unescape, s)
|
return re.sub(pattern, unescape, s)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+9
-9
@@ -552,13 +552,9 @@ class Attr:
|
|||||||
return len(self.keyed)
|
return len(self.keyed)
|
||||||
|
|
||||||
# parse %-escaped strings
|
# parse %-escaped strings
|
||||||
|
#
|
||||||
|
# attrs can override __getitem__ for lazy attr generation
|
||||||
def punescape(s, attrs=None):
|
def punescape(s, attrs=None):
|
||||||
if attrs is None:
|
|
||||||
attrs = {}
|
|
||||||
if isinstance(attrs, dict):
|
|
||||||
attrs_ = attrs
|
|
||||||
attrs = lambda k: attrs_[k]
|
|
||||||
|
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'%[%n]'
|
'%[%n]'
|
||||||
'|' '%x..'
|
'|' '%x..'
|
||||||
@@ -573,9 +569,12 @@ def punescape(s, attrs=None):
|
|||||||
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] == 'U': return chr(int(m.group()[2:], 16))
|
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
||||||
elif m.group()[1] == '(':
|
elif m.group()[1] == '(':
|
||||||
try:
|
if attrs is not None:
|
||||||
v = attrs(m.group('field'))
|
try:
|
||||||
except KeyError:
|
v = attrs[m.group('field')]
|
||||||
|
except KeyError:
|
||||||
|
return m.group()
|
||||||
|
else:
|
||||||
return m.group()
|
return m.group()
|
||||||
f = m.group('format')
|
f = m.group('format')
|
||||||
if f[-1] in 'dboxX':
|
if f[-1] in 'dboxX':
|
||||||
@@ -592,6 +591,7 @@ def punescape(s, attrs=None):
|
|||||||
# 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
|
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
|
||||||
|
|||||||
+9
-9
@@ -459,13 +459,9 @@ class Attr:
|
|||||||
return len(self.keyed)
|
return len(self.keyed)
|
||||||
|
|
||||||
# parse %-escaped strings
|
# parse %-escaped strings
|
||||||
|
#
|
||||||
|
# attrs can override __getitem__ for lazy attr generation
|
||||||
def punescape(s, attrs=None):
|
def punescape(s, attrs=None):
|
||||||
if attrs is None:
|
|
||||||
attrs = {}
|
|
||||||
if isinstance(attrs, dict):
|
|
||||||
attrs_ = attrs
|
|
||||||
attrs = lambda k: attrs_[k]
|
|
||||||
|
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'%[%n]'
|
'%[%n]'
|
||||||
'|' '%x..'
|
'|' '%x..'
|
||||||
@@ -480,9 +476,12 @@ def punescape(s, attrs=None):
|
|||||||
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] == 'U': return chr(int(m.group()[2:], 16))
|
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
||||||
elif m.group()[1] == '(':
|
elif m.group()[1] == '(':
|
||||||
try:
|
if attrs is not None:
|
||||||
v = attrs(m.group('field'))
|
try:
|
||||||
except KeyError:
|
v = attrs[m.group('field')]
|
||||||
|
except KeyError:
|
||||||
|
return m.group()
|
||||||
|
else:
|
||||||
return m.group()
|
return m.group()
|
||||||
f = m.group('format')
|
f = m.group('format')
|
||||||
if f[-1] in 'dboxX':
|
if f[-1] in 'dboxX':
|
||||||
@@ -499,6 +498,7 @@ def punescape(s, attrs=None):
|
|||||||
# 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
|
else: assert False
|
||||||
|
|
||||||
return re.sub(pattern, unescape, s)
|
return re.sub(pattern, unescape, s)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+9
-10
@@ -397,14 +397,9 @@ class Attr:
|
|||||||
return len(self.keyed)
|
return len(self.keyed)
|
||||||
|
|
||||||
# parse %-escaped strings
|
# parse %-escaped strings
|
||||||
|
#
|
||||||
|
# attrs can override __getitem__ for lazy attr generation
|
||||||
def punescape(s, attrs=None):
|
def punescape(s, attrs=None):
|
||||||
# TODO punescape should just take something that provides __getitem__
|
|
||||||
if attrs is None:
|
|
||||||
attrs = {}
|
|
||||||
if isinstance(attrs, dict):
|
|
||||||
attrs_ = attrs
|
|
||||||
attrs = lambda k: attrs_[k]
|
|
||||||
|
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'%[%n]'
|
'%[%n]'
|
||||||
'|' '%x..'
|
'|' '%x..'
|
||||||
@@ -419,9 +414,12 @@ def punescape(s, attrs=None):
|
|||||||
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] == 'U': return chr(int(m.group()[2:], 16))
|
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
||||||
elif m.group()[1] == '(':
|
elif m.group()[1] == '(':
|
||||||
try:
|
if attrs is not None:
|
||||||
v = attrs(m.group('field'))
|
try:
|
||||||
except KeyError:
|
v = attrs[m.group('field')]
|
||||||
|
except KeyError:
|
||||||
|
return m.group()
|
||||||
|
else:
|
||||||
return m.group()
|
return m.group()
|
||||||
f = m.group('format')
|
f = m.group('format')
|
||||||
if f[-1] in 'dboxX':
|
if f[-1] in 'dboxX':
|
||||||
@@ -438,6 +436,7 @@ def punescape(s, attrs=None):
|
|||||||
# 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
|
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
|
||||||
|
|||||||
+9
-9
@@ -444,13 +444,9 @@ class Attr:
|
|||||||
return len(self.keyed)
|
return len(self.keyed)
|
||||||
|
|
||||||
# parse %-escaped strings
|
# parse %-escaped strings
|
||||||
|
#
|
||||||
|
# attrs can override __getitem__ for lazy attr generation
|
||||||
def punescape(s, attrs=None):
|
def punescape(s, attrs=None):
|
||||||
if attrs is None:
|
|
||||||
attrs = {}
|
|
||||||
if isinstance(attrs, dict):
|
|
||||||
attrs_ = attrs
|
|
||||||
attrs = lambda k: attrs_[k]
|
|
||||||
|
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'%[%n]'
|
'%[%n]'
|
||||||
'|' '%x..'
|
'|' '%x..'
|
||||||
@@ -465,9 +461,12 @@ def punescape(s, attrs=None):
|
|||||||
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] == 'U': return chr(int(m.group()[2:], 16))
|
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
||||||
elif m.group()[1] == '(':
|
elif m.group()[1] == '(':
|
||||||
try:
|
if attrs is not None:
|
||||||
v = attrs(m.group('field'))
|
try:
|
||||||
except KeyError:
|
v = attrs[m.group('field')]
|
||||||
|
except KeyError:
|
||||||
|
return m.group()
|
||||||
|
else:
|
||||||
return m.group()
|
return m.group()
|
||||||
f = m.group('format')
|
f = m.group('format')
|
||||||
if f[-1] in 'dboxX':
|
if f[-1] in 'dboxX':
|
||||||
@@ -484,6 +483,7 @@ def punescape(s, attrs=None):
|
|||||||
# 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
|
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
|
||||||
|
|||||||
@@ -335,13 +335,9 @@ class Attr:
|
|||||||
return len(self.keyed)
|
return len(self.keyed)
|
||||||
|
|
||||||
# parse %-escaped strings
|
# parse %-escaped strings
|
||||||
|
#
|
||||||
|
# attrs can override __getitem__ for lazy attr generation
|
||||||
def punescape(s, attrs=None):
|
def punescape(s, attrs=None):
|
||||||
if attrs is None:
|
|
||||||
attrs = {}
|
|
||||||
if isinstance(attrs, dict):
|
|
||||||
attrs_ = attrs
|
|
||||||
attrs = lambda k: attrs_[k]
|
|
||||||
|
|
||||||
pattern = re.compile(
|
pattern = re.compile(
|
||||||
'%[%n]'
|
'%[%n]'
|
||||||
'|' '%x..'
|
'|' '%x..'
|
||||||
@@ -356,9 +352,12 @@ def punescape(s, attrs=None):
|
|||||||
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] == 'U': return chr(int(m.group()[2:], 16))
|
elif m.group()[1] == 'U': return chr(int(m.group()[2:], 16))
|
||||||
elif m.group()[1] == '(':
|
elif m.group()[1] == '(':
|
||||||
try:
|
if attrs is not None:
|
||||||
v = attrs(m.group('field'))
|
try:
|
||||||
except KeyError:
|
v = attrs[m.group('field')]
|
||||||
|
except KeyError:
|
||||||
|
return m.group()
|
||||||
|
else:
|
||||||
return m.group()
|
return m.group()
|
||||||
f = m.group('format')
|
f = m.group('format')
|
||||||
if f[-1] in 'dboxX':
|
if f[-1] in 'dboxX':
|
||||||
@@ -375,6 +374,7 @@ def punescape(s, attrs=None):
|
|||||||
# 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
|
else: assert False
|
||||||
|
|
||||||
return re.sub(pattern, unescape, s)
|
return re.sub(pattern, unescape, s)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user