1 | """
|
---|
2 | Provides functions for creating simple properties.
|
---|
3 |
|
---|
4 | If, inside a class definition, you write:
|
---|
5 |
|
---|
6 | attribute(foo=1, bar=2)
|
---|
7 |
|
---|
8 | simple properties named 'foo' and 'bar' are created for this class.
|
---|
9 | Also, private instance variables '__foo' and '__bar' will be added
|
---|
10 | to instances of this class.
|
---|
11 |
|
---|
12 | USEAGE:
|
---|
13 |
|
---|
14 | # assumes attribute.py is on path
|
---|
15 | from attribute import *
|
---|
16 |
|
---|
17 | class MyClass(object):
|
---|
18 | readable(foo=1, bar=2) # or, attribute('r', foo=1, bar=2)
|
---|
19 | writable(fro=3, boz=4) # or, attribute('w', fro=3, boz=4)
|
---|
20 | attribute(baz=5)
|
---|
21 |
|
---|
22 | This is equivalent to the following:
|
---|
23 |
|
---|
24 | class MyClass(object):
|
---|
25 | def __init__(self):
|
---|
26 | self.__foo = 1
|
---|
27 | self.__bar = 2
|
---|
28 | self.__fro = 3
|
---|
29 | self.__boz = 4
|
---|
30 | self.__baz = 5
|
---|
31 |
|
---|
32 | def get_foo(self):
|
---|
33 | return self.__foo
|
---|
34 | def get_bar(self):
|
---|
35 | return self.__bar
|
---|
36 | def set_fro(self, value):
|
---|
37 | self.__fro = value
|
---|
38 | def set_boz(self, value):
|
---|
39 | self.__boz = value
|
---|
40 | def get_baz(self):
|
---|
41 | return self.__baz
|
---|
42 | def set_baz(self, value):
|
---|
43 | self.__baz = value
|
---|
44 | def del_baz(self):
|
---|
45 | del self.__baz
|
---|
46 |
|
---|
47 | foo = property(fget=get_foo, doc="foo")
|
---|
48 | bar = property(fget=get_bar, doc="bar")
|
---|
49 | fro = property(fset=set_fro, doc="fro")
|
---|
50 | boz = property(fset=set_boz, doc="boz")
|
---|
51 | baz = property(fget=get_baz, fset=set_baz, fdel=del_baz, doc="baz")
|
---|
52 | """
|
---|
53 |
|
---|
54 | __all__ = ['attribute', 'readable', 'writable']
|
---|
55 | __version__ = '3.0'
|
---|
56 | __author__ = 'Sean Ross'
|
---|
57 | __credits__ = ['Guido van Rossum', 'Garth Kidd']
|
---|
58 | __created__ = '10/21/02'
|
---|
59 |
|
---|
60 | import sys
|
---|
61 |
|
---|
62 | def mangle(classname, attrname):
|
---|
63 | """mangles name according to python name-mangling
|
---|
64 | conventions for private variables"""
|
---|
65 | return "_%s__%s" % (classname, attrname)
|
---|
66 |
|
---|
67 | def class_space(classlevel=3):
|
---|
68 | "returns the calling class' name and dictionary"
|
---|
69 | frame = sys._getframe(classlevel)
|
---|
70 | classname = frame.f_code.co_name
|
---|
71 | classdict = frame.f_locals
|
---|
72 | return classname, classdict
|
---|
73 |
|
---|
74 | # convenience function
|
---|
75 | def readable(**kwds):
|
---|
76 | "returns one read-only property for each (key,value) pair in kwds"
|
---|
77 | return _attribute(permission='r', **kwds)
|
---|
78 |
|
---|
79 | # convenience function
|
---|
80 | def writable(**kwds):
|
---|
81 | "returns one write-only property for each (key,value) pair in kwds"
|
---|
82 | return _attribute(permission='w', **kwds)
|
---|
83 |
|
---|
84 | # needed because of the way class_space is resolved in _attribute
|
---|
85 | def attribute(permission='rwd', **kwds):
|
---|
86 | """returns one property for each (key,value) pair in kwds;
|
---|
87 | each property provides the specified level of access(permission):
|
---|
88 | 'r': readable, 'w':writable, 'd':deletable
|
---|
89 | """
|
---|
90 | return _attribute(permission, **kwds)
|
---|
91 |
|
---|
92 | # based on code by Guido van Rossum, comp.lang.python 2001-07-31
|
---|
93 | def _attribute(permission='rwd', **kwds):
|
---|
94 | """returns one property for each (key,value) pair in kwds;
|
---|
95 | each property provides the specified level of access(permission):
|
---|
96 | 'r': readable, 'w':writable, 'd':deletable
|
---|
97 | """
|
---|
98 | classname, classdict = class_space()
|
---|
99 | def _property(attrname, default):
|
---|
100 | propname, attrname = attrname, mangle(classname, attrname)
|
---|
101 | fget, fset, fdel, doc = None, None, None, propname
|
---|
102 | if 'r' in permission:
|
---|
103 | def fget(self):
|
---|
104 | value = default
|
---|
105 | try: value = getattr(self, attrname)
|
---|
106 | except AttributeError: setattr(self, attrname, default)
|
---|
107 | return value
|
---|
108 | if 'w' in permission:
|
---|
109 | def fset(self, value):
|
---|
110 | setattr(self, attrname, value)
|
---|
111 | if 'd' in permission:
|
---|
112 | def fdel(self):
|
---|
113 | try: delattr(self, attrname)
|
---|
114 | except AttributeError: pass
|
---|
115 | # calling fget can restore this attribute, so remove property
|
---|
116 | delattr(self.__class__, propname)
|
---|
117 | return property(fget=fget, fset=fset, fdel=fdel, doc=doc)
|
---|
118 |
|
---|
119 | for attrname, default in kwds.items():
|
---|
120 | classdict[attrname] = _property(attrname, default)
|
---|
121 |
|
---|