| 1 | # (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) |
|---|
| 2 | # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php |
|---|
| 3 | |
|---|
| 4 | class ClassInitMeta(type): |
|---|
| 5 | |
|---|
| 6 | def __new__(meta, class_name, bases, new_attrs): |
|---|
| 7 | cls = type.__new__(meta, class_name, bases, new_attrs) |
|---|
| 8 | if (new_attrs.has_key('__classinit__') |
|---|
| 9 | and not isinstance(cls.__classinit__, staticmethod)): |
|---|
| 10 | setattr(cls, '__classinit__', |
|---|
| 11 | staticmethod(cls.__classinit__.im_func)) |
|---|
| 12 | if hasattr(cls, '__classinit__'): |
|---|
| 13 | cls.__classinit__(cls, new_attrs) |
|---|
| 14 | return cls |
|---|
| 15 | |
|---|
| 16 | def build_properties(cls, new_attrs): |
|---|
| 17 | """ |
|---|
| 18 | Given a class and a new set of attributes (as passed in by |
|---|
| 19 | __classinit__), create or modify properties based on functions |
|---|
| 20 | with special names ending in __get, __set, and __del. |
|---|
| 21 | """ |
|---|
| 22 | for name, value in new_attrs.items(): |
|---|
| 23 | if (name.endswith('__get') or name.endswith('__set') |
|---|
| 24 | or name.endswith('__del')): |
|---|
| 25 | base = name[:-5] |
|---|
| 26 | if hasattr(cls, base): |
|---|
| 27 | old_prop = getattr(cls, base) |
|---|
| 28 | if not isinstance(old_prop, property): |
|---|
| 29 | raise ValueError( |
|---|
| 30 | "Attribute %s is a %s, not a property; function %s is named like a property" |
|---|
| 31 | % (base, type(old_prop), name)) |
|---|
| 32 | attrs = {'fget': old_prop.fget, |
|---|
| 33 | 'fset': old_prop.fset, |
|---|
| 34 | 'fdel': old_prop.fdel, |
|---|
| 35 | 'doc': old_prop.__doc__} |
|---|
| 36 | else: |
|---|
| 37 | attrs = {} |
|---|
| 38 | attrs['f' + name[-3:]] = value |
|---|
| 39 | if name.endswith('__get') and value.__doc__: |
|---|
| 40 | attrs['doc'] = value.__doc__ |
|---|
| 41 | new_prop = property(**attrs) |
|---|
| 42 | setattr(cls, base, new_prop) |
|---|