--- a/src/pyams_utils/property.py Tue May 16 11:27:28 2017 +0200
+++ b/src/pyams_utils/property.py Thu Jun 01 15:18:11 2017 +0200
@@ -140,3 +140,61 @@
return lambda x: wrapper(x, app=app, key=key)
return session_decorator
+
+
+class classproperty:
+ """Same decorator as property(), but passes obj.__class__ instead of obj to fget/fset/fdel.
+
+ Original code for property emulation:
+ https://docs.python.org/3.5/howto/descriptor.html#properties
+ """
+ def __init__(self, fget=None, fset=None, fdel=None, doc=None):
+ self.fget = fget
+ self.fset = fset
+ self.fdel = fdel
+ if doc is None and fget is not None:
+ doc = fget.__doc__
+ self.__doc__ = doc
+
+ def __get__(self, obj, objtype=None):
+ if obj is None:
+ return self
+ if self.fget is None:
+ raise AttributeError("Unreadable attribute")
+ return self.fget(obj.__class__)
+
+ def __set__(self, obj, value):
+ if self.fset is None:
+ raise AttributeError("Can't set attribute")
+ self.fset(obj.__class__, value)
+
+ def __delete__(self, obj):
+ if self.fdel is None:
+ raise AttributeError("Can't delete attribute")
+ self.fdel(obj.__class__)
+
+ def getter(self, fget):
+ return type(self)(fget, self.fset, self.fdel, self.__doc__)
+
+ def setter(self, fset):
+ return type(self)(self.fget, fset, self.fdel, self.__doc__)
+
+ def deleter(self, fdel):
+ return type(self)(self.fget, self.fset, fdel, self.__doc__)
+
+
+def classproperty_support(cls):
+ """Class decorator to add metaclass to a class.
+
+ Metaclass uses to add descriptors to class attributes
+ """
+ class Meta(type):
+ pass
+
+ for name, obj in vars(cls).items():
+ if isinstance(obj, classproperty):
+ setattr(Meta, name, property(obj.fget, obj.fset, obj.fdel))
+
+ class Wrapper(cls, metaclass=Meta):
+ pass
+ return Wrapper