| # (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) |
| # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php |
| |
| class ClassInitMeta(type): |
| |
| def __new__(meta, class_name, bases, new_attrs): |
| cls = type.__new__(meta, class_name, bases, new_attrs) |
| if (new_attrs.has_key('__classinit__') |
| and not isinstance(cls.__classinit__, staticmethod)): |
| setattr(cls, '__classinit__', |
| staticmethod(cls.__classinit__.im_func)) |
| if hasattr(cls, '__classinit__'): |
| cls.__classinit__(cls, new_attrs) |
| return cls |
| |
| def build_properties(cls, new_attrs): |
| """ |
| Given a class and a new set of attributes (as passed in by |
| __classinit__), create or modify properties based on functions |
| with special names ending in __get, __set, and __del. |
| """ |
| for name, value in new_attrs.items(): |
| if (name.endswith('__get') or name.endswith('__set') |
| or name.endswith('__del')): |
| base = name[:-5] |
| if hasattr(cls, base): |
| old_prop = getattr(cls, base) |
| if not isinstance(old_prop, property): |
| raise ValueError( |
| "Attribute %s is a %s, not a property; function %s is named like a property" |
| % (base, type(old_prop), name)) |
| attrs = {'fget': old_prop.fget, |
| 'fset': old_prop.fset, |
| 'fdel': old_prop.fdel, |
| 'doc': old_prop.__doc__} |
| else: |
| attrs = {} |
| attrs['f' + name[-3:]] = value |
| if name.endswith('__get') and value.__doc__: |
| attrs['doc'] = value.__doc__ |
| new_prop = property(**attrs) |
| setattr(cls, base, new_prop) |