Spaces:
Sleeping
Sleeping
| from ._common import * | |
| __all__ = [ | |
| 'NamedConstant', 'Constant', | |
| ] | |
| # NamedConstant | |
| NamedConstant = None | |
| class NamedConstantDict(dict): | |
| """Track constant order and ensure names are not reused. | |
| NamedConstantMeta will use the names found in self._names as the | |
| Constant names. | |
| """ | |
| def __init__(self): | |
| super(NamedConstantDict, self).__init__() | |
| self._names = [] | |
| def __setitem__(self, key, value): | |
| """Changes anything not dundered or not a constant descriptor. | |
| If an constant name is used twice, an error is raised; duplicate | |
| values are not checked for. | |
| Single underscore (sunder) names are reserved. | |
| """ | |
| if is_sunder(key): | |
| raise ValueError( | |
| '_sunder_ names, such as %r, are reserved for future NamedConstant use' | |
| % (key, ) | |
| ) | |
| elif is_dunder(key): | |
| pass | |
| elif key in self._names: | |
| # overwriting an existing constant? | |
| raise TypeError('attempt to reuse name: %r' % (key, )) | |
| elif isinstance(value, constant) or not is_descriptor(value): | |
| if key in self: | |
| # overwriting a descriptor? | |
| raise TypeError('%s already defined as: %r' % (key, self[key])) | |
| self._names.append(key) | |
| super(NamedConstantDict, self).__setitem__(key, value) | |
| class NamedConstantMeta(type): | |
| """ | |
| Block attempts to reassign NamedConstant attributes. | |
| """ | |
| def __prepare__(metacls, cls, bases, **kwds): | |
| return NamedConstantDict() | |
| def __new__(metacls, cls, bases, clsdict): | |
| if type(clsdict) is dict: | |
| original_dict = clsdict | |
| clsdict = NamedConstantDict() | |
| for k, v in original_dict.items(): | |
| clsdict[k] = v | |
| newdict = {} | |
| constants = {} | |
| for name, obj in clsdict.items(): | |
| if name in clsdict._names: | |
| constants[name] = obj | |
| continue | |
| elif isinstance(obj, nonmember): | |
| obj = obj.value | |
| newdict[name] = obj | |
| newcls = super(NamedConstantMeta, metacls).__new__(metacls, cls, bases, newdict) | |
| newcls._named_constant_cache_ = {} | |
| newcls._members_ = {} | |
| for name, obj in constants.items(): | |
| new_k = newcls.__new__(newcls, name, obj) | |
| newcls._members_[name] = new_k | |
| return newcls | |
| def __bool__(cls): | |
| return True | |
| def __delattr__(cls, attr): | |
| cur_obj = cls.__dict__.get(attr) | |
| if NamedConstant is not None and isinstance(cur_obj, NamedConstant): | |
| raise AttributeError('cannot delete constant <%s.%s>' % (cur_obj.__class__.__name__, cur_obj._name_)) | |
| super(NamedConstantMeta, cls).__delattr__(attr) | |
| def __iter__(cls): | |
| return (k for k in cls._members_.values()) | |
| def __reversed__(cls): | |
| return (k for k in reversed(cls._members_.values())) | |
| def __len__(cls): | |
| return len(cls._members_) | |
| __nonzero__ = __bool__ | |
| def __setattr__(cls, name, value): | |
| """Block attempts to reassign NamedConstants. | |
| """ | |
| cur_obj = cls.__dict__.get(name) | |
| if NamedConstant is not None and isinstance(cur_obj, NamedConstant): | |
| raise AttributeError('cannot rebind constant <%s.%s>' % (cur_obj.__class__.__name__, cur_obj._name_)) | |
| super(NamedConstantMeta, cls).__setattr__(name, value) | |
| constant_dict = _Addendum( | |
| dict=NamedConstantMeta.__prepare__('NamedConstant', (object, )), | |
| doc="NamedConstants protection.\n\n Derive from this class to lock NamedConstants.\n\n", | |
| ns=globals(), | |
| ) | |
| def __new__(cls, name, value=None, doc=None): | |
| if value is None: | |
| # lookup, name is value | |
| value = name | |
| for name, obj in cls.__dict__.items(): | |
| if isinstance(obj, cls) and obj._value_ == value: | |
| return obj | |
| else: | |
| raise ValueError('%r does not exist in %r' % (value, cls.__name__)) | |
| cur_obj = cls.__dict__.get(name) | |
| if isinstance(cur_obj, NamedConstant): | |
| raise AttributeError('cannot rebind constant <%s.%s>' % (cur_obj.__class__.__name__, cur_obj._name_)) | |
| elif isinstance(value, constant): | |
| doc = doc or value.__doc__ | |
| value = value.value | |
| metacls = cls.__class__ | |
| if isinstance(value, NamedConstant): | |
| # constants from other classes are reduced to their actual value | |
| value = value._value_ | |
| actual_type = type(value) | |
| value_type = cls._named_constant_cache_.get(actual_type) | |
| if value_type is None: | |
| value_type = type(cls.__name__, (cls, type(value)), {}) | |
| cls._named_constant_cache_[type(value)] = value_type | |
| obj = actual_type.__new__(value_type, value) | |
| obj._name_ = name | |
| obj._value_ = value | |
| obj.__doc__ = doc | |
| cls._members_[name] = obj | |
| metacls.__setattr__(cls, name, obj) | |
| return obj | |
| def __repr__(self): | |
| return "<%s.%s: %r>" % ( | |
| self.__class__.__name__, self._name_, self._value_) | |
| def __reduce_ex__(self, proto): | |
| return getattr, (self.__class__, self._name_) | |
| NamedConstant = NamedConstantMeta('NamedConstant', (object, ), constant_dict.resolve()) | |
| Constant = NamedConstant | |
| del constant_dict | |