diff --git a/util/jeep.py b/util/jeep.py index a2a9601..b5e5de0 100644 --- a/util/jeep.py +++ b/util/jeep.py @@ -30,11 +30,14 @@ class Jeep(object): _attributes = ('_sequence',) - def __init__(self, init=None): + def __init__(self, seq=[]): self._sequence = [] - if init is not None: - for attr, value in init: - setattr(self, attr, value) + for item in seq: + attr, value = item + setattr(self, attr, value) + + def __len__(self): + return len(self._sequence) def __iter__(self): for key in self._sequence: @@ -46,8 +49,12 @@ class Jeep(object): self._sequence.append(attr) object.__setattr__(self, attr, value) + def __delattr__(self, attr): + del self._sequence[self.index(attr)] + object.__delattr__(self, attr) + def __getitem__(self, key): - if type(key) is int: + if type(key) in (int, long): return getattr(self, self._sequence[key]) value = getattr(self, key, _notfound) if value is _notfound: @@ -57,6 +64,12 @@ class Jeep(object): def __setitem__(self, key, value): setattr(self, key, value) + def __delitem__(self, key): + delattr(self, key) + + def __contains__(self, key): + return getattr(self, key, _notfound) is not _notfound + def keys(self): return list(self) @@ -68,3 +81,31 @@ class Jeep(object): def get(self, key, default=None): return getattr(self, key, default) + + def index(self, key): + return self._sequence.index(key) + + def append(self, obj): + key = getattr(obj, '__name__', _notfound) + if key is _notfound: + raise AttributeError("No '__name__' attribute present") + if key in self: + raise ValueError("Object already present") + self[key] = obj + + def insert(self, idx, obj): + key = getattr(obj, '__name__', _notfound) + if key is _notfound: + raise AttributeError("No '__name__' attribute present") + if key in self: + raise ValueError("Object already present") + self._sequence.insert(idx, key) + object.__setattr__(self, key, obj) + + def pop(self, key=-1): + value = self[key] + if type(key) in (int, long): + key = self._sequence[key] + delattr(self, key) + return value + diff --git a/util/jeep.txt b/util/jeep.txt index 46095e5..1159b1f 100644 --- a/util/jeep.txt +++ b/util/jeep.txt @@ -65,13 +65,10 @@ More Dictionary Methods >>> jeep.get('second') 'new second value' - >>> jeep.get('fourth', 'default') 'default' - >>> jeep.get('fourth') is None True - >>> jeep['fourth'] Traceback (most recent call last): ... @@ -80,6 +77,60 @@ More Dictionary Methods >>> dict(jeep) {'second': 'new second value', 'third': 'third value', 'first': 'first value'} +More Methods and Operators +-------------------------- + + >>> 'third' in jeep + True + + >>> jeep.pop() + 'third value' + >>> len(jeep) + 2 + + >>> 'third' in jeep + False + + >>> jeep.index('second') + 1 + >>> jeep.index('third') + Traceback (most recent call last): + ... + ValueError: ...not in list + +Sequence Additions with Named Objects +------------------------------------- + +Objects that have a ``__name__`` attribute can be appended +to a Jeep object as the dictionary key can be obtained from these attribute. + + >>> class Term(object): + ... def __init__(self, token, title=None, value=None): + ... self.__name__ = self.token = token + ... self.title = title or token + ... self.value = value or title or token + + >>> t1 = Term('term1', 'title 1') + >>> jeep.append(t1) + >>> list(jeep) + ['first', 'second', 'term1'] + >>> jeep.term1.title + 'title 1' + + >>> jeep.insert(1, Term('term2', 'title 2')) + >>> list(jeep) + ['first', 'term2', 'second', 'term1'] + >>> jeep[1].title + 'title 2' + +Inserting or appending an object with a name that's already present raises +an exception: + + >>> jeep.append(t1) + Traceback (most recent call last): + ... + ValueError: ...already present + Constructors ------------