added jeep module, a general purpose class for objects acting like a list, a dictionary and a normal object with attributes

git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@1606 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2007-03-02 18:58:44 +00:00
parent b380b0fcd7
commit bc83147047
3 changed files with 160 additions and 0 deletions

70
util/jeep.py Normal file
View file

@ -0,0 +1,70 @@
#
# Copyright (c) 2007 Helmut Merz helmutm@cy55.de
#
# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
A general purpose (thus 'Jeep') class that provides most of the interfaces
of sequences and dictionaries and in addition allows attribute access to
the dictionary entries.
$Id$
"""
_notfound = object()
class Jeep(object):
_attributes = ('_sequence',)
def __init__(self, init=None):
self._sequence = []
if init is not None:
for attr, value in init:
setattr(self, attr, value)
def __iter__(self):
for key in self._sequence:
yield key
def __setattr__(self, attr, value):
if not attr in self._attributes:
if getattr(self, attr, _notfound) is _notfound:
self._sequence.append(attr)
object.__setattr__(self, attr, value)
def __getitem__(self, key):
if type(key) is int:
return getattr(self, self._sequence[key])
value = getattr(self, key, _notfound)
if value is _notfound:
raise KeyError(key)
return value
def __setitem__(self, key, value):
setattr(self, key, value)
def keys(self):
return list(self)
def values(self):
return [self[k] for k in self]
def items(self):
return [(k, self[k]) for k in self]
def get(self, key, default=None):
return getattr(self, key, default)

89
util/jeep.txt Normal file
View file

@ -0,0 +1,89 @@
==============================
Jeep - a General Purpose Class
==============================
$Id$
>>> from cybertools.util.jeep import Jeep
>>> jeep = Jeep()
>>> jeep.first = 'first value'
>>> jeep.second = 'second value'
>>> jeep.first
'first value'
In addition to the usual access via dot notation all attributes can be
accessed via dictionary notation:
The third type of interface provided by Jeep objects is the sequence or
iterator interface. Converting a jeep object to a list iterates over the
keys:
>>> list(jeep)
['first', 'second']
Direct index access to certain entries gives the corresponding value,
not the key:
>>> jeep[1]
'second value'
Changing Jeep Objects
---------------------
Assignment by dictionary or attribute access appends the newly assigned
attribute:
>>> jeep['third'] = 'third value'
>>> jeep.third
'third value'
>>> list(jeep)
['first', 'second', 'third']
Assigning a new value to an already existing attribute does not change the
order but only changes the attribute's value
>>> jeep.second = 'new second value'
>>> list(jeep)
['first', 'second', 'third']
>>> jeep[1]
'new second value'
More Dictionary Methods
-----------------------
>>> jeep.keys()
['first', 'second', 'third']
>>> jeep.values()
['first value', 'new second value', 'third value']
>>> jeep.items()
[('first', 'first value'), ('second', 'new second value'), ('third', 'third value')]
>>> jeep.get('second')
'new second value'
>>> jeep.get('fourth', 'default')
'default'
>>> jeep.get('fourth') is None
True
>>> jeep['fourth']
Traceback (most recent call last):
...
KeyError: 'fourth'
>>> dict(jeep)
{'second': 'new second value', 'third': 'third value', 'first': 'first value'}
Constructors
------------
>>> jeep2 = Jeep((('f', '1st'), ('s', '2nd'), ('t', '3rd')))
>>> list(jeep2)
['f', 's', 't']

View file

@ -21,6 +21,7 @@ def test_suite():
doctest.DocFileSuite('adapter.txt', optionflags=flags),
doctest.DocFileSuite('defer.txt', optionflags=flags),
doctest.DocFileSuite('property.txt', optionflags=flags),
doctest.DocFileSuite('jeep.txt', optionflags=flags),
))
if __name__ == '__main__':