fixes issue with wrong-chars in string items of CallingMap by its representation, additionally don't calculate values implicitly (may be unexpected for some constellations resp. too slow in DEBUG)

pull/2171/head
sebres 2018-06-29 18:33:24 +02:00
parent 2f5059ebfb
commit 79350e916e
3 changed files with 36 additions and 10 deletions

View File

@ -83,6 +83,8 @@ class CallingMap(MutableMapping, object):
The dictionary data which can be accessed to obtain items uncalled The dictionary data which can be accessed to obtain items uncalled
""" """
CM_REPR_ITEMS = ()
# immutable=True saves content between actions, without interim copying (save original on demand, recoverable via reset) # immutable=True saves content between actions, without interim copying (save original on demand, recoverable via reset)
__slots__ = ('data', 'storage', 'immutable', '__org_data') __slots__ = ('data', 'storage', 'immutable', '__org_data')
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -98,14 +100,29 @@ class CallingMap(MutableMapping, object):
pass pass
self.immutable = immutable self.immutable = immutable
def __repr__(self): def _asrepr(self, calculated=False):
return "%s(%r)" % (self.__class__.__name__, self._asdict()) # be sure it is suitable as string, so use str as checker:
return "%s(%r)" % (self.__class__.__name__, self._asdict(calculated, str))
def _asdict(self): __repr__ = _asrepr
def _asdict(self, calculated=False, checker=None):
d = dict(self.data, **self.storage)
if not calculated:
return dict((n,v) for n,v in d.iteritems() \
if not callable(v) or n in self.CM_REPR_ITEMS)
for n,v in d.items():
if callable(v):
try: try:
return dict(self) # calculate:
except: v = self.__getitem__(n)
return dict(self.data, **self.storage) # convert if needed:
if checker: checker(v)
# store calculated:
d[n] = v
except: # can't calculate - just ignore it
pass
return d
def getRawItem(self, key): def getRawItem(self, key):
try: try:

View File

@ -290,6 +290,8 @@ class Actions(JailThread, Mapping):
class ActionInfo(CallingMap): class ActionInfo(CallingMap):
CM_REPR_ITEMS = ("fid", "raw-ticket")
AI_DICT = { AI_DICT = {
"ip": lambda self: self.__ticket.getIP(), "ip": lambda self: self.__ticket.getIP(),
"family": lambda self: self['ip'].familyStr, "family": lambda self: self['ip'].familyStr,
@ -307,7 +309,9 @@ class Actions(JailThread, Mapping):
"ipmatches": lambda self: "\n".join(self._mi4ip(True).getMatches()), "ipmatches": lambda self: "\n".join(self._mi4ip(True).getMatches()),
"ipjailmatches": lambda self: "\n".join(self._mi4ip().getMatches()), "ipjailmatches": lambda self: "\n".join(self._mi4ip().getMatches()),
"ipfailures": lambda self: self._mi4ip(True).getAttempt(), "ipfailures": lambda self: self._mi4ip(True).getAttempt(),
"ipjailfailures": lambda self: self._mi4ip().getAttempt() "ipjailfailures": lambda self: self._mi4ip().getAttempt(),
# raw ticket info:
"raw-ticket": lambda self: repr(self.__ticket)
} }
__slots__ = CallingMap.__slots__ + ('__ticket', '__jail', '__mi4ip') __slots__ = CallingMap.__slots__ + ('__ticket', '__jail', '__mi4ip')

View File

@ -567,13 +567,18 @@ class CommandActionTest(LogCaptureTestCase):
'b': lambda self: self['a'] + 6, 'b': lambda self: self['a'] + 6,
'c': '' 'c': ''
}) })
s = repr(m) s = repr(m); # only stored values (no calculated)
self.assertNotIn("'a': ", s)
self.assertNotIn("'b': ", s)
self.assertIn("'c': ''", s)
s = m._asrepr(True) # all values (including calculated)
self.assertIn("'a': 5", s) self.assertIn("'a': 5", s)
self.assertIn("'b': 11", s) self.assertIn("'b': 11", s)
self.assertIn("'c': ''", s) self.assertIn("'c': ''", s)
m['c'] = lambda self: self['xxx'] + 7; # unresolvable m['c'] = lambda self: self['xxx'] + 7; # unresolvable
s = repr(m) s = m._asrepr(True)
self.assertIn("'a': 5", s) self.assertIn("'a': 5", s)
self.assertIn("'b': 11", s) self.assertIn("'b': 11", s)
self.assertIn("'c': ", s) # presents as callable self.assertIn("'c': ", s) # presents as callable