File: attribute.py

package info (click to toggle)
python-bx 0.13.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 5,000 kB
  • sloc: python: 17,136; ansic: 2,326; makefile: 24; sh: 8
file content (152 lines) | stat: -rw-r--r-- 4,055 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
"""
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 f"_{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)
        if "r" in permission:

            def fget(self):
                value = default
                try:
                    value = getattr(self, attrname)
                except AttributeError:
                    setattr(self, attrname, default)
                return value

        else:
            fget = None

        if "w" in permission:

            def fset(self, value):
                setattr(self, attrname, value)

        else:
            fset = None

        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)

        else:
            fdel = None
        return property(fget=fget, fset=fset, fdel=fdel, doc=propname)

    for attrname, default in kwds.items():
        classdict[attrname] = _property(attrname, default)