def __setitem__(self, key, value): ret = value if (key in ('encap', 'metrics')) and isinstance(value, dict): # transactionals attach as is if type(value) in (Encap, Metrics): with self._direct_state: return Transactional.__setitem__(self, key, value) # check, if it exists already ret = Transactional.__getitem__(self, key) # it doesn't # (plain dict can be safely discarded) if (type(ret) == dict) or not ret: # bake transactionals in place if key == 'encap': ret = Encap(parent=self) elif key == 'metrics': ret = Metrics(parent=self) # attach transactional to the route with self._direct_state: Transactional.__setitem__(self, key, ret) # begin() works only if the transactional is attached if any(value.values()): if self._mode in ('implicit', 'explicit'): ret._begin(tid=self.current_tx.uid) [ ret.__setitem__(k, v) for k, v in value.items() if v is not None ] # corresponding transactional exists else: # set fields for k in ret: ret[k] = value.get(k, None) return elif key == 'multipath': cur = Transactional.__getitem__(self, key) if isinstance(cur, NextHopSet): # load entries vs = NextHopSet(value) for key in vs - cur: cur.add(key) for key in cur - vs: cur.remove(key) else: # drop any result of `update()` Transactional.__setitem__(self, key, NextHopSet(value)) return elif key == 'encap_type' and not isinstance(value, int): ret = encap_type.get(value, value) elif key == 'type' and not isinstance(value, int): ret = rt_type.get(value, value) elif key == 'proto' and not isinstance(value, int): ret = rt_proto.get(value, value) elif key == 'dst' and \ isinstance(value, basestring) and \ value in ('0.0.0.0/0', '::/0'): ret = 'default' Transactional.__setitem__(self, key, ret)
def __setitem__(self, key, value): ret = value if (key in ('encap', 'metrics')) and isinstance(value, dict): # transactionals attach as is if type(value) in (Encap, Metrics): with self._direct_state: return Transactional.__setitem__(self, key, value) # check, if it exists already ret = Transactional.__getitem__(self, key) # it doesn't # (plain dict can be safely discarded) if (type(ret) == dict) or not ret: # bake transactionals in place if key == 'encap': ret = Encap(parent=self) elif key == 'metrics': ret = Metrics(parent=self) # attach transactional to the route with self._direct_state: Transactional.__setitem__(self, key, ret) # begin() works only if the transactional is attached if any(value.values()): if self._mode in ('implicit', 'explicit'): ret._begin(tid=self.current_tx.uid) [ret.__setitem__(k, v) for k, v in value.items() if v is not None] # corresponding transactional exists else: # set fields for k in ret: ret[k] = value.get(k, None) return elif key == 'multipath': cur = Transactional.__getitem__(self, key) if isinstance(cur, NextHopSet): # load entries vs = NextHopSet(value) for key in vs - cur: cur.add(key) for key in cur - vs: cur.remove(key) else: # drop any result of `update()` Transactional.__setitem__(self, key, NextHopSet(value)) return elif key == 'encap_type' and not isinstance(value, int): ret = encap_type.get(value, value) elif key == 'type' and not isinstance(value, int): ret = rt_type.get(value, value) elif key == 'proto' and not isinstance(value, int): ret = rt_proto.get(value, value) elif key == 'dst' and \ isinstance(value, basestring) and \ value in ('0.0.0.0/0', '::/0'): ret = 'default' Transactional.__setitem__(self, key, ret)