diff options
Diffstat (limited to 'sharedstate.git/sharedstate/shareddict.py')
-rw-r--r-- | sharedstate.git/sharedstate/shareddict.py | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/sharedstate.git/sharedstate/shareddict.py b/sharedstate.git/sharedstate/shareddict.py new file mode 100644 index 0000000..1a51a12 --- /dev/null +++ b/sharedstate.git/sharedstate/shareddict.py @@ -0,0 +1,107 @@ +# shareddict.py, classes to aid activities in sharing a state +# Reinier Heeres, reinier@heeres.eu +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +# Change log: +# 2007-06-21: rwh, first version + +import logging +_logger = logging.getLogger('sharinghelper') + +from sharedobject import SharedObject + +class SharedDict(SharedObject): + """Shared dictionary object, generates key-based difference objects""" + + def __init__(self, name, helper, opt={}): + SharedObject.__init__(self, name, helper, opt=opt) + self._value = {} + + def __getitem__(self, key): +# _logger.debug('SharedDict.__getitem__(%s)', key) + return self.get_key(key) + + def __setitem__(self, key, val): +# _logger.debug('SharedDict.__setitem__(%s, %s)', key, val) + return self.set_key(key, val) + + def __delitem__(self, key): + self.delete_key(key) + + def get_key(self, key, val): + return self._value[key] + + def set_key(self, key, val): + if key in self._value: + d = {'change': {key: val}} + else: + d = {'add': {key: val}} + self._value[key] = val + self.changed(d, True) + + def delete_key(self, key): + if key in self._value: + del self._value[key] + d = {'remove': key} + self.changed(d, True) + + def _compatible_diffs(self, diffa, diffb): + for key in diffa: + if key in diffb: + return False + return True + + def diff(self, cur, old): + ret = {'remove': [], 'add': {}, 'change': {}} + if old is None: + return ret + + for key in set(old.keys()).difference(cur.keys()): + ret['remove'].append(key) + + for key in set(cur.keys()).difference(old.keys()): + ret['add'][key] = cur[key] + + for key in set(cur.keys()).intersection(old.keys()): + if cur[key] is not old[key]: + ret['change'][key] = cur[key] + + return ret + + def _apply_diff_to(self, obj, diffobj): + """Apply a diff and return an object that describes the inverse diff""" + + if diffobj is None: + return (None, None) + + ret = {'add':{}, 'remove':[], 'change':{}} + + if 'remove' in diffobj: + for key in diffobj['remove']: + ret['add'][key] = obj[key] + del self._value[key] + + if 'add' in diffobj: + for key, val in diffobj['add'].iteritems(): + ret['remove'].append(key) + obj[key] = val + + if 'change' in diffobj: + for key, val in diffobj['change'].iteritems(): + ret[key] = self._value[key] + obj[key] = val + + return (obj, ret) |