| 113 | |
| 114 | |
| 115 | class ObservableDict(UserDict): |
| 116 | def __init__(self, dict: Optional[Mapping[_KT, _VT]] = None, **kwargs: _VT) -> None: |
| 117 | super().__init__(**kwargs) |
| 118 | self._observers = [] |
| 119 | |
| 120 | if dict: |
| 121 | self.update(dict) |
| 122 | |
| 123 | def subscribe(self, observer): |
| 124 | self._observers.append(observer) |
| 125 | |
| 126 | def unsubscribe(self, observer): |
| 127 | if observer in self._observers: |
| 128 | self._observers.remove(observer) |
| 129 | |
| 130 | def set(self, another_dict): |
| 131 | old_values = dict(self) |
| 132 | |
| 133 | obsolete_keys = {key for key in self.keys() if key not in another_dict} |
| 134 | for key in obsolete_keys: |
| 135 | super().__delitem__(key) |
| 136 | |
| 137 | for key, value in another_dict.items(): |
| 138 | super().__setitem__(key, value) |
| 139 | |
| 140 | if self._observers: |
| 141 | for obsolete_key in obsolete_keys: |
| 142 | old_value = old_values[obsolete_key] |
| 143 | for observer in self._observers: |
| 144 | observer(obsolete_key, old_value, None) |
| 145 | |
| 146 | for key, value in self.items(): |
| 147 | old_value = old_values.get(key) |
| 148 | if old_value != value: |
| 149 | for observer in self._observers: |
| 150 | observer(key, old_value, value) |
| 151 | |
| 152 | def __setitem__(self, key: _KT, item: _VT) -> None: |
| 153 | old_value = self.get(key) |
| 154 | |
| 155 | super().__setitem__(key, item) |
| 156 | |
| 157 | if item == old_value: |
| 158 | return |
| 159 | |
| 160 | self._notify_observers(key, old_value, item) |
| 161 | |
| 162 | def __delitem__(self, key: _KT) -> None: |
| 163 | old_value = self.get(key) |
| 164 | |
| 165 | super().__delitem__(key) |
| 166 | |
| 167 | if old_value is None: |
| 168 | return |
| 169 | |
| 170 | self._notify_observers(key, old_value, None) |
| 171 | |
| 172 | def _notify_observers(self, key, old_value, new_value): |
no outgoing calls