diff options
-rw-r--r-- | CHANGES.txt | 4 | ||||
-rw-r--r-- | pysnmp/smi/indices.py | 73 |
2 files changed, 40 insertions, 37 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 2f9166e7..24ea285a 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,5 +1,5 @@ -Revision 4.4.7, released 2018-11-XX +Revision 4.4.7, released 2018-12-XX ----------------------------------- - Exposed ASN.1 `Null` type through `rfc1902` module for convenience. @@ -9,6 +9,8 @@ Revision 4.4.7, released 2018-11-XX are different even if just timeout/retries options differ - Fixed hlapi LCD configurator to include `contextName`. Prior to this fix sending SNMPv3 TRAP with non-default `contextName` would fail. +- Fixed possible duplicate key occurrence in the `OrderedDict` following + a race condition Revision 4.4.6, released 2018-09-13 ----------------------------------- diff --git a/pysnmp/smi/indices.py b/pysnmp/smi/indices.py index 00d95a63..7e15a8cd 100644 --- a/pysnmp/smi/indices.py +++ b/pysnmp/smi/indices.py @@ -10,36 +10,26 @@ from bisect import bisect class OrderedDict(dict): """Ordered dictionary used for indices""" - def __init__(self, **kwargs): + def __init__(self, *args, **kwargs): self.__keys = [] self.__dirty = True super(OrderedDict, self).__init__() + if args: + self.update(*args) if kwargs: - self.update(kwargs) + self.update(**kwargs) def __setitem__(self, key, value): - if key not in self: - self.__keys.append(key) super(OrderedDict, self).__setitem__(key, value) - self.__dirty = True - - def __repr__(self): - if self.__dirty: - self.__order() - return super(OrderedDict, self).__repr__() - - def __str__(self): - if self.__dirty: - self.__order() - return super(OrderedDict, self).__str__() + if key not in self.__keys: + self.__keys.append(key) + self.__dirty = True def __delitem__(self, key): - if super(OrderedDict, self).__contains__(key): - self.__keys.remove(key) super(OrderedDict, self).__delitem__(key) - self.__dirty = True - - __delattr__ = __delitem__ + if key in self.__keys: + self.__keys.remove(key) + self.__dirty = True def clear(self): super(OrderedDict, self).clear() @@ -61,30 +51,43 @@ class OrderedDict(dict): self.__order() return [(k, self[k]) for k in self.__keys] - def update(self, d): - [self.__setitem__(k, v) for k, v in d.items()] + def update(self, *args, **kwargs): + if args: + iterable = args[0] + if hasattr(iterable, 'keys'): + for k in iterable: + self[k] = iterable[k] + else: + for k, v in iterable: + self[k] = v + + if kwargs: + for k in kwargs: + self[k] = kwargs[k] def sortingFun(self, keys): keys.sort() def __order(self): self.sortingFun(self.__keys) - d = {} - for k in self.__keys: - d[len(k)] = 1 - l = list(d.keys()) - l.sort(reverse=True) - self.__keysLens = tuple(l) + self.__keysLens = sorted(set(len(k) for k in self.__keys), reverse=True) self.__dirty = False def nextKey(self, key): - keys = list(self.keys()) - if key in self: + if self.__dirty: + self.__order() + + keys = self.__keys + + if key in keys: nextIdx = keys.index(key) + 1 + else: nextIdx = bisect(keys, key) + if nextIdx < len(keys): return keys[nextIdx] + else: raise KeyError(key) @@ -97,24 +100,22 @@ class OrderedDict(dict): class OidOrderedDict(OrderedDict): """OID-ordered dictionary used for indices""" - def __init__(self, **kwargs): + def __init__(self, *args, **kwargs): self.__keysCache = {} - OrderedDict.__init__(self, **kwargs) + OrderedDict.__init__(self, *args, **kwargs) def __setitem__(self, key, value): + OrderedDict.__setitem__(self, key, value) if key not in self.__keysCache: if isinstance(key, tuple): self.__keysCache[key] = key else: self.__keysCache[key] = [int(x) for x in key.split('.') if x] - OrderedDict.__setitem__(self, key, value) def __delitem__(self, key): + OrderedDict.__delitem__(self, key) if key in self.__keysCache: del self.__keysCache[key] - OrderedDict.__delitem__(self, key) - - __delattr__ = __delitem__ def sortingFun(self, keys): keys.sort(key=lambda k, d=self.__keysCache: d[k]) |