"""
Provides an 'attribute' class for one-use descriptors.
"""

attribute = None

class _MetaAttribute(type):
    def __new__(meta, name, bases, dict):
        # for reals, yo.
        for kw in ['get', 'set', 'delete']:
            if kw in dict:
                dict[kw] = staticmethod(dict[kw])
        secretClass = type.__new__(meta, name, bases, dict)
        if attribute is None:
            return secretClass
        return secretClass()

class attribute(object):
    """
    Convenience class for providing one-shot descriptors, similar to
    'property'.  For example:

        >>> from epsilon.descriptor import attribute
        >>> class Dynamo(object):
        ...  class dynamic(attribute):
        ...   def get(self):
        ...    self.dynCount += 1
        ...    return self.dynCount
        ...   def set(self, value):
        ...    self.dynCount += value
        ...  dynCount = 0
        ...
        >>> d = Dynamo()
        >>> d.dynamic
        1
        >>> d.dynamic
        2
        >>> d.dynamic = 6
        >>> d.dynamic
        9
        >>> d.dynamic
        10
        >>> del d.dynamic
        Traceback (most recent call last):
            ...
        AttributeError: attribute cannot be removed
    """

    __metaclass__ = _MetaAttribute

    def __get__(self, oself, type):
        """
        Private implementation of descriptor interface.
        """
        if oself is None:
            return self
        return self.get(oself)

    def __set__(self, oself, value):
        """
        Private implementation of descriptor interface.
        """
        return self.set(oself, value)

    def __delete__(self, oself):
        """
        Private implementation of descriptor interface.
        """
        return self.delete(oself)

    def set(self, value):
        """
        Implement this method to provide attribute setting.  Default behavior
        is that attributes are not settable.
        """
        raise AttributeError('read only attribute')

    def get(self):
        """
        Implement this method to provide attribute retrieval.  Default behavior
        is that unset attributes do not have any value.
        """
        raise AttributeError('attribute has no value')

    def delete(self):
        """
        Implement this method to provide attribute deletion.  Default behavior
        is that attributes cannot be deleted.
        """
        raise AttributeError('attribute cannot be removed')


__all__ = ['attribute']


syntax highlighted by Code2HTML, v. 0.9.1