From 2af397120c412f0d86fa7bb8d086a6752df92e83 Mon Sep 17 00:00:00 2001 From: helmutm Date: Thu, 23 Nov 2006 09:14:49 +0000 Subject: [PATCH] new (third and hopefully last) implementation of the basic MultiKeyDict class git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@1518 fd906abe-77d9-0310-91a1-e0d9ade77398 --- index/README.txt | 3 +-- index/multikey.py | 58 +++++++++++++++++------------------------------ 2 files changed, 22 insertions(+), 39 deletions(-) diff --git a/index/README.txt b/index/README.txt index 146ab73..fbc0cc4 100644 --- a/index/README.txt +++ b/index/README.txt @@ -42,7 +42,7 @@ The more on the left a matching key part is the higher is its priority: >>> registry[('index.html', 'task', 'bugfixes', 'Custom')] 'Global index.html for Custom skin' -Index entries that are present in the stored dictionaries must always match: +Index entries that are present in the stored dictionary must always match: >>> registry[('edit.html', 'topic', 'zope3', 'Custom')] = 'very special edit.html' @@ -62,4 +62,3 @@ Index entries that are present in the stored dictionaries must always match: >>> registry[('edit.html', 'task', 'bugfixes', 'Custom')] 'edit.html for Custom skin' - diff --git a/index/multikey.py b/index/multikey.py index a882251..284c834 100644 --- a/index/multikey.py +++ b/index/multikey.py @@ -24,23 +24,24 @@ $Id$ _not_found = object() -class MultiKeyDict(dict): +class MultiKeyDict(object): - def __init__(self, keylen=None, **kw): - super(MultiKeyDict, self).__init__(**kw) - self.submapping = {} + def __init__(self, keylen=None): self.keylen = keylen + self.mapping = {} def __setitem__(self, key, value): assert type(key) is tuple + assert len(key) > 0 if self.keylen is None: self.keylen = len(key) assert len(key) == self.keylen - k0 = key[0] - if len(key) > 1: - sub = self.submapping.setdefault(k0, MultiKeyDict(self.keylen-1)) - sub[key[1:]] = value - super(MultiKeyDict, self).__setitem__(k0, value) + mapping = self.mapping + for n, k in enumerate(key): + if n == self.keylen - 1: + mapping[k] = value + else: + mapping = mapping.setdefault(k, {}) def __getitem__(self, key): r = self.get(key, _not_found) @@ -51,33 +52,16 @@ class MultiKeyDict(dict): def get(self, key, default=None): assert type(key) is tuple assert len(key) == self.keylen - k0 = key[0] - rsub = _not_found - r0 = super(MultiKeyDict, self).get(k0, _not_found) - if r0 is _not_found: - r0 = self.getFallback(k0) - if r0 is _not_found: - return default - if len(key) > 1: - sub = self.submapping.get(k0, _not_found) - if sub is _not_found: - sub = self.getSubmappingFallback(key) - if sub is _not_found: - rsub = _not_found - else: - rsub = sub.get(key[1:], _not_found) - if rsub is _not_found: - return default - result = rsub is _not_found and r0 or rsub - return result is _not_found and default or result + mapping = self.mapping + for n, k in enumerate(key): + entry = mapping.get(k, _not_found) + if entry == _not_found: + entry = self._fallback(mapping, k) + if entry == _not_found: + return default + mapping = entry + return entry - def getFallback(self, key): - return super(MultiKeyDict, self).get(None, _not_found) - - def getSubmappingFallback(self, key): - return self.submapping.get(None, _not_found) - - def __repr__(self): - return ('' - % (super(MultiKeyDict, self).__repr__(), `self.submapping`)) + def _fallback(self, mapping, key): + return mapping.get(None, _not_found)