properties.py 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. from __future__ import unicode_literals
  2. import six
  3. class NonDataProperty(object):
  4. """Much like the property builtin, but only implements __get__,
  5. making it a non-data property, and can be subsequently reset.
  6. See http://users.rcn.com/python/download/Descriptor.htm for more
  7. information.
  8. >>> class X(object):
  9. ... @NonDataProperty
  10. ... def foo(self):
  11. ... return 3
  12. >>> x = X()
  13. >>> x.foo
  14. 3
  15. >>> x.foo = 4
  16. >>> x.foo
  17. 4
  18. """
  19. def __init__(self, fget):
  20. assert fget is not None, "fget cannot be none"
  21. assert six.callable(fget), "fget must be callable"
  22. self.fget = fget
  23. def __get__(self, obj, objtype=None):
  24. if obj is None:
  25. return self
  26. return self.fget(obj)
  27. # from http://stackoverflow.com/a/5191224
  28. class ClassPropertyDescriptor(object):
  29. def __init__(self, fget, fset=None):
  30. self.fget = fget
  31. self.fset = fset
  32. def __get__(self, obj, klass=None):
  33. if klass is None:
  34. klass = type(obj)
  35. return self.fget.__get__(obj, klass)()
  36. def __set__(self, obj, value):
  37. if not self.fset:
  38. raise AttributeError("can't set attribute")
  39. type_ = type(obj)
  40. return self.fset.__get__(obj, type_)(value)
  41. def setter(self, func):
  42. if not isinstance(func, (classmethod, staticmethod)):
  43. func = classmethod(func)
  44. self.fset = func
  45. return self
  46. def classproperty(func):
  47. if not isinstance(func, (classmethod, staticmethod)):
  48. func = classmethod(func)
  49. return ClassPropertyDescriptor(func)