src/pyams_utils/property.py
changeset 68 7f90df24ceca
parent 6 09a8799da676
child 72 9049384a2bd4
equal deleted inserted replaced
67:8b172808ca6c 68:7f90df24ceca
    18 # import interfaces
    18 # import interfaces
    19 
    19 
    20 # import packages
    20 # import packages
    21 from pyams_utils.request import check_request, get_request_data, set_request_data
    21 from pyams_utils.request import check_request, get_request_data, set_request_data
    22 from pyams_utils.session import get_session_data, set_session_data
    22 from pyams_utils.session import get_session_data, set_session_data
       
    23 from zope.schema.fieldproperty import FieldProperty
       
    24 
       
    25 
       
    26 class DocFieldProperty(FieldProperty):
       
    27     """Field property with doc
       
    28 
       
    29     This field property class extracts it's docstring from parent field description, if any.
       
    30     It's main purpose is for documentation needs.
       
    31     """
       
    32 
       
    33     @property
       
    34     def __doc__(self):
       
    35         return self._FieldProperty__field.description or super(FieldProperty, self).__doc__
    23 
    36 
    24 
    37 
    25 class cached(object):
    38 class cached(object):
    26     """Custom property decorator to define a property or function
    39     """Custom property decorator to define a property or function
    27     which is calculated only once
    40     which is calculated only once
    28        
    41 
    29     When applied on a function, caching is based on input arguments
    42     When applied on a function, caching is based on input arguments
    30     """
    43     """
    31 
    44 
    32     def __init__(self, function):
    45     def __init__(self, function):
    33         self._function = function
    46         self._function = function
    63 
    76 
    64 
    77 
    65 _marker = object()
    78 _marker = object()
    66 
    79 
    67 
    80 
    68 def request_property(key):
    81 def request_property(key, prefix=None):
    69     """Define a method decorator used to store result into request's annotations
    82     """Define a method decorator used to store result into current request's annotations
    70 
    83 
       
    84     If not request is currently running, a new one is created.
    71     `key` is a required argument; if None, the key will be the method's object
    85     `key` is a required argument; if None, the key will be the method's object
    72     """
    86     """
    73 
    87 
    74     def request_decorator(func):
    88     def request_decorator(func):
       
    89 
    75         def wrapper(obj, key, *args, **kwargs):
    90         def wrapper(obj, key, *args, **kwargs):
    76             request = check_request()
    91             request = check_request()
    77             if callable(key):
    92             if callable(key):
    78                 key = key(obj)
    93                 key = key(obj)
    79             if not key:
    94             if not key:
    80                 key = '{0!r}'.format(obj)
    95                 key = '{1}::{0!r}'.format(obj, prefix or func.__name__)
    81             data = get_request_data(request, key, _marker)
    96             data = get_request_data(request, key, _marker)
    82             if data is _marker:
    97             if data is _marker:
    83                 data = func
    98                 data = func
    84                 if callable(data):
    99                 if callable(data):
    85                     data = data(obj, *args, **kwargs)
   100                     data = data(obj, *args, **kwargs)
    86                 set_request_data(request, key, data)
   101                 set_request_data(request, key, data)
    87             return data
   102             return data
       
   103 
    88         return lambda x: wrapper(x, key=key)
   104         return lambda x: wrapper(x, key=key)
    89 
   105 
    90     return request_decorator
   106     return request_decorator
    91 
   107 
    92 
   108 
    93 def session_property(app, key=None):
   109 def session_property(app, key=None, prefix=None):
    94     """Define a method decorator used to store result into request's session
   110     """Define a method decorator used to store result into request's session
    95 
   111 
    96     `app` is an application identifier used to prefix session keys
   112     If no request is currently running, a new one is created.
    97     `key` is session's value key; if None, the key will be the method's object
   113 
       
   114     @app: application identifier used to prefix session keys
       
   115     @key: session's value key; if None, the key will be the method's object
    98     """
   116     """
    99 
   117 
   100     def session_decorator(func):
   118     def session_decorator(func):
       
   119 
   101         def wrapper(obj, app, key, *args, **kwargs):
   120         def wrapper(obj, app, key, *args, **kwargs):
   102             request = check_request()
   121             request = check_request()
   103             if callable(key):
   122             if callable(key):
   104                 key = key(obj)
   123                 key = key(obj)
   105             if not key:
   124             if not key:
   106                 key = '{0!r}'.format(obj)
   125                 key = '{1}::{0!r}'.format(obj, prefix or func.__name__)
   107             data = get_session_data(request, app, key, _marker)
   126             data = get_session_data(request, app, key, _marker)
   108             if data is _marker:
   127             if data is _marker:
   109                 data = func
   128                 data = func
   110                 if callable(data):
   129                 if callable(data):
   111                     data = data(obj, *args, **kwargs)
   130                     data = data(obj, *args, **kwargs)
   112                 set_session_data(request, app, key, data)
   131                 set_session_data(request, app, key, data)
   113             return data
   132             return data
       
   133 
   114         return lambda x: wrapper(x, app=app, key=key)
   134         return lambda x: wrapper(x, app=app, key=key)
   115 
   135 
   116     return session_decorator
   136     return session_decorator