class itemproperty(object):
def __init__(self, fget=None, fset=None, fdel=None, doc=None):
if doc is None and fget is not None and hasattr(fget, "__doc__"):
doc = fget.__doc__
self._get = fget
self._set = fset
self._del = fdel
self.__doc__ = doc
def __get__(self, instance, owner):
if instance is None:
return self
else:
return bounditemproperty(self, instance)
def __set__(self, instance, value):
raise AttributeError("can't set attribute")
def __delete__(self, instance):
raise AttributeError("can't delete attribute")
def getter(self, fget):
return itemproperty(fget, self._set, self._del, self.__doc__)
def setter(self, fset):
return itemproperty(self._get, fset, self._del, self.__doc__)
def deleter(self, fdel):
return itemproperty(self._get, self._set, fdel, self.__doc__)
class bounditemproperty(object):
def __init__(self, item_property, instance):
self.__item_property = item_property
self.__instance = instance
def __getitem__(self, key):
fget = self.__item_property._get
if fget is None:
raise AttributeError("unreadable attribute item")
return fget(self.__instance, key)
def __setitem__(self, key, value):
fset = self.__item_property._set
if fset is None:
raise AttributeError("can't set attribute item")
fset(self.__instance, key, value)
def __delitem__(self, key):
fdel = self.__item_property._del
if fdel is None:
raise AttributeError("can't delete attribute item")
fdel(self.__instance, key)
if __name__ == "__main__":
class Element(object):
def __init__(self, tag, value=None):
self.tag = tag
self.value = value
self.children = {}
@itemproperty
def xpath(self, path):
"""Get or set the value at a relative path."""
path = path.split('/')
element = self
for tag in path:
if tag in element.children:
element = element.children[tag]
else:
raise KeyError('path does not exist')
return element.value
@xpath.setter
def xpath(self, path, value):
path = path.split('/')
element = self
for tag in path:
element = element.children.setdefault(tag, Element(tag))
element.value = value
@xpath.deleter
def xpath(self, path):
path = path.split('/')
element = self
for tag in path[:-1]:
if tag in element.children:
element = element.children[tag]
else:
raise KeyError('path does not exist')
tag = path[-1]
if tag in element.children:
del element.children[tag]
else:
raise KeyError('path does not exist')
tree = Element('root')
tree.xpath['unladen/swallow'] = 'african'
assert tree.xpath['unladen/swallow'] == 'african'
assert tree.children['unladen'].xpath['swallow'] == 'african'
assert tree.children['unladen'].children['swallow'].value == 'african'
tree.xpath['unladen/swallow'] = 'european'
assert tree.xpath['unladen/swallow'] == 'european'
assert len(tree.children) == 1
assert len(tree.children['unladen'].children) == 1
tree.xpath['unladen/swallow/airspeed'] = 42
assert tree.xpath['unladen/swallow'] == 'european'
assert tree.xpath['unladen/swallow/airspeed'] == 42
del tree.xpath['unladen/swallow']
assert 'swallow' not in tree.children['unladen'].children
try:
tree.xpath['unladen/swallow/airspeed']
except KeyError:
pass
else:
assert False
Diff to Previous Revision
--- revision 1 2011-05-18 21:21:28
+++ revision 2 2012-05-09 23:24:55
@@ -1,5 +1,5 @@
class itemproperty(object):
-
+
def __init__(self, fget=None, fset=None, fdel=None, doc=None):
if doc is None and fget is not None and hasattr(fget, "__doc__"):
doc = fget.__doc__
@@ -7,31 +7,31 @@
self._set = fset
self._del = fdel
self.__doc__ = doc
-
+
def __get__(self, instance, owner):
if instance is None:
return self
else:
return bounditemproperty(self, instance)
-
+
def __set__(self, instance, value):
- raise AttributeError, "can't set attribute"
-
+ raise AttributeError("can't set attribute")
+
def __delete__(self, instance):
- raise AttributeError, "can't delete attribute"
-
+ raise AttributeError("can't delete attribute")
+
def getter(self, fget):
return itemproperty(fget, self._set, self._del, self.__doc__)
def setter(self, fset):
return itemproperty(self._get, fset, self._del, self.__doc__)
-
+
def deleter(self, fdel):
return itemproperty(self._get, self._set, fdel, self.__doc__)
class bounditemproperty(object):
-
+
def __init__(self, item_property, instance):
self.__item_property = item_property
self.__instance = instance
@@ -39,31 +39,31 @@
def __getitem__(self, key):
fget = self.__item_property._get
if fget is None:
- raise AttributeError, "unreadable attribute item"
+ raise AttributeError("unreadable attribute item")
return fget(self.__instance, key)
-
+
def __setitem__(self, key, value):
fset = self.__item_property._set
if fset is None:
- raise AttributeError, "can't set attribute item"
+ raise AttributeError("can't set attribute item")
fset(self.__instance, key, value)
-
+
def __delitem__(self, key):
fdel = self.__item_property._del
if fdel is None:
- raise AttributeError, "can't delete attribute item"
+ raise AttributeError("can't delete attribute item")
fdel(self.__instance, key)
if __name__ == "__main__":
-
+
class Element(object):
-
+
def __init__(self, tag, value=None):
self.tag = tag
self.value = value
self.children = {}
-
+
@itemproperty
def xpath(self, path):
"""Get or set the value at a relative path."""
@@ -104,16 +104,16 @@
assert tree.xpath['unladen/swallow'] == 'african'
assert tree.children['unladen'].xpath['swallow'] == 'african'
assert tree.children['unladen'].children['swallow'].value == 'african'
-
+
tree.xpath['unladen/swallow'] = 'european'
assert tree.xpath['unladen/swallow'] == 'european'
assert len(tree.children) == 1
assert len(tree.children['unladen'].children) == 1
-
+
tree.xpath['unladen/swallow/airspeed'] = 42
assert tree.xpath['unladen/swallow'] == 'european'
assert tree.xpath['unladen/swallow/airspeed'] == 42
-
+
del tree.xpath['unladen/swallow']
assert 'swallow' not in tree.children['unladen'].children
try: