src/pyams_utils/property.py
branchdev-tf
changeset 408 cf2304af0fab
parent 292 b338586588ad
--- a/src/pyams_utils/property.py	Wed Nov 20 19:26:23 2019 +0100
+++ b/src/pyams_utils/property.py	Fri Nov 22 18:51:37 2019 +0100
@@ -10,38 +10,57 @@
 # FOR A PARTICULAR PURPOSE.
 #
 
+"""PyAMS_utils.property module
+
+This module is used to define:
+ - a cached property; this read-only property is evaluated only once; it's value is stored into
+   object's attributes, and so should be freed with the object (so it should behave like a
+   Pyramid's "reify" decorator, but we have kept it for compatibility of existing code)
+ - a class property; this decorator is working like a classic property, but can be assigned to a
+   class; to support class properties, this class also have to decorated with the
+   "classproperty_support" decorator
+
+    >>> from pyams_utils.property import cached_property
+
+    >>> class ClassWithCache:
+    ...     '''Class with cache'''
+    ...     @cached_property
+    ...     def cached_value(self):
+    ...         print("This is a cached value")
+    ...         return 1
+
+    >>> obj = ClassWithCache()
+    >>> obj.cached_value
+    This is a cached value
+    1
+
+On following calls, cached property method shouldn't be called again:
+
+    >>> obj.cached_value
+    1
+
+Class properties are used to define properties on class level:
+
+    >>> from pyams_utils.property import classproperty, classproperty_support
+
+    >>> @classproperty_support
+    ... class ClassWithProperties:
+    ...     '''Class with class properties'''
+    ...
+    ...     class_attribute = 1
+    ...
+    ...     @classproperty
+    ...     def my_class_property(cls):
+    ...         return cls.class_attribute
+
+    >>> ClassWithProperties.my_class_property
+    1
+"""
+
 __docformat__ = 'restructuredtext'
 
 
-# import standard library
-
-# import interfaces
-
-# import packages
-
-
-class cached(object):
-    """Custom property decorator to define a property or function which is calculated only once
-
-    When applied on a function, caching is based on input arguments
-    """
-
-    def __init__(self, function):
-        self._function = function
-        self._cache = {}
-
-    def __call__(self, *args):
-        try:
-            return self._cache[args]
-        except KeyError:
-            self._cache[args] = self._function(*args)
-            return self._cache[args]
-
-    def expire(self, *args):
-        del self._cache[args]
-
-
-class cached_property(object):
+class cached_property:  # pylint: disable=invalid-name
     """A read-only property decorator that is only evaluated once.
 
     The value is cached on the object itself rather than the function or class; this should prevent
@@ -60,9 +79,9 @@
         return result
 
 
-class classproperty:
+class classproperty:  # pylint: disable=invalid-name
     """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
     """
@@ -92,27 +111,30 @@
         self.fdel(obj.__class__)
 
     def getter(self, fget):
+        """Property getter"""
         return type(self)(fget, self.fset, self.fdel, self.__doc__)
 
     def setter(self, fset):
+        """Property setter"""
         return type(self)(self.fget, fset, self.fdel, self.__doc__)
 
     def deleter(self, fdel):
+        """Property deleter"""
         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
+        """Meta class"""
 
     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
+        """Wrapper class"""
     return Wrapper