""" Provides functions for creating simple properties. If, inside a class definition, you write: attribute(foo=1, bar=2) simple properties named 'foo' and 'bar' are created for this class. Also, private instance variables '__foo' and '__bar' will be added to instances of this class. USEAGE: # assumes attribute.py is on path from attribute import * class MyClass(object): readable(foo=1, bar=2) # or, attribute('r', foo=1, bar=2) writable(fro=3, boz=4) # or, attribute('w', fro=3, boz=4) attribute(baz=5) This is equivalent to the following: class MyClass(object): def __init__(self): self.__foo = 1 self.__bar = 2 self.__fro = 3 self.__boz = 4 self.__baz = 5 def get_foo(self): return self.__foo def get_bar(self): return self.__bar def set_fro(self, value): self.__fro = value def set_boz(self, value): self.__boz = value def get_baz(self): return self.__baz def set_baz(self, value): self.__baz = value def del_baz(self): del self.__baz foo = property(fget=get_foo, doc="foo") bar = property(fget=get_bar, doc="bar") fro = property(fset=set_fro, doc="fro") boz = property(fset=set_boz, doc="boz") baz = property(fget=get_baz, fset=set_baz, fdel=del_baz, doc="baz") """ __all__ = ['attribute', 'readable', 'writable'] __version__ = '3.0' __author__ = 'Sean Ross' __credits__ = ['Guido van Rossum', 'Garth Kidd'] __created__ = '10/21/02' import sys def mangle(classname, attrname): """mangles name according to python name-mangling conventions for private variables""" return "_%s__%s" % (classname, attrname) def class_space(classlevel=3): "returns the calling class' name and dictionary" frame = sys._getframe(classlevel) classname = frame.f_code.co_name classdict = frame.f_locals return classname, classdict # convenience function def readable(**kwds): "returns one read-only property for each (key,value) pair in kwds" return _attribute(permission='r', **kwds) # convenience function def writable(**kwds): "returns one write-only property for each (key,value) pair in kwds" return _attribute(permission='w', **kwds) # needed because of the way class_space is resolved in _attribute def attribute(permission='rwd', **kwds): """returns one property for each (key,value) pair in kwds; each property provides the specified level of access(permission): 'r': readable, 'w':writable, 'd':deletable """ return _attribute(permission, **kwds) # based on code by Guido van Rossum, comp.lang.python 2001-07-31 def _attribute(permission='rwd', **kwds): """returns one property for each (key,value) pair in kwds; each property provides the specified level of access(permission): 'r': readable, 'w':writable, 'd':deletable """ classname, classdict = class_space() def _property(attrname, default): propname, attrname = attrname, mangle(classname, attrname) fget, fset, fdel, doc = None, None, None, propname if 'r' in permission: def fget(self): value = default try: value = getattr(self, attrname) except AttributeError: setattr(self, attrname, default) return value if 'w' in permission: def fset(self, value): setattr(self, attrname, value) if 'd' in permission: def fdel(self): try: delattr(self, attrname) except AttributeError: pass # calling fget can restore this attribute, so remove property delattr(self.__class__, propname) return property(fget=fget, fset=fset, fdel=fdel, doc=doc) for attrname, default in kwds.items(): classdict[attrname] = _property(attrname, default)