Cache ===== The system provides a Python object that acts as a persistent datastore across multiple Python executions from within the same `python-policy`. One example use case is the following: A DHCP script stores an option of a Discovery packet in cache, a RADIUS script retrieves it from the cache, and adds it in the RADIUS Accounting Request packet. `config>python>python-policy>cache` needs to be configured before `alc.cache` can be used. See section `Python cache support` of `Triple Play Service Delivery Architecture Guide` for more information. .. _alc_dot_cache: The :data:`alc.cache` context-manager ------------------------------------- The :data:`alc.cache` object, which is an instance of class :data:`alc.Cache`, is a context-manager that provides the actual cache object and a context in which this object can be used. .. note:: Only the pre-provided :data:`alc.cache` object should be used in script, the class :data:`alc.Cache` should not be used directly. To interact with the cache, a reference to the cache object needs to be retrieved using the "with" syntax: >>> with alc.cache as cache: ... # cache can be interacted with using the variable "cache" Outside the scope created by the with-statement, the cache object does not exist and cannot be used. The :class:`alc.Cache` class ----------------------------- .. class:: alc.Cache .. method:: set(key, value, lifetime=600, /) Associate the value with the key for a duration of the specified lifetime. If the entry already exists, the value and lifetime are updated. :param bytes key: key :param bytes value: value :param int lifetime: time in seconds during which the entry remains valid in the cache. After this time, the entry is removed from the cache. The value must be in the range of the minimal to maximum value configured in `python-policy`. :raises ValueError: when the lifetime parameter is negative or zero .. method:: get(key, /) Retrieves the value previously associated with the specified key. If the entry does not exist or has timed out, `None` is returned. :param bytes key: key :rtype: bytes or None .. method:: get_lifetime(key, /) Retrieves the lifetime of the entry for the specified key. If the entry does not exist or has timed out, `None`` is returned. :param bytes key: key :rtype: int or None .. method:: set_lifetime(key, lifetime, /) Updates the lifetime of the entry for the specified key. The value can both be increased or decreased, given it is in the range of the minimal to maximum value configured in `python-policy`. If the entry has timed out, no update is done. :param bytes key: key :param int lifetime: time in seconds during which the entry remains valid in the cache. The value must be in the range of the minimal to maximum value configured in `python-policy`. :raises ValueError: when the lifetime parameter is negative or zero .. method:: clear(key, /) Removes the entry for the specified key. If the entry does not exist (anymore), nothing is done. :param bytes key: key .. _breaking-cache: Breaking changes ---------------- .. _breaking-cache-context-manager: Context manager ^^^^^^^^^^^^^^^ .. warning:: The alc.cache object is now a context-manager that returns the actual cache object Non-existing entries ^^^^^^^^^^^^^^^^^^^^ .. warning:: The following actions on a non-existing entry don't raise a KeyError exception: * `get()` (returns `None`) * `clear()` * `get_lifetime()` * `set_lifetime()` Examples -------- Save ^^^^ The following example saves a cache entry with as parameters: - key: the User-Name attribute in the RADIUS message - value: `please remember this for me` - lifetime: 86400 seconds :: import alc # Perform any operations before needing the cache username = alc.radius.attributes[1] if username is not None: # using the "with" syntax, get a reference to the cache with alc.cache as cache: cache.set(username, b"please remember this for me", 86400) # other operations not needing the cache are best done outside of this scope print("entry saved in cache") Get ^^^ The following example gets a cache entry with as key the User-Name attribute in the RADIUS message: :: import alc # Perform any operations before needing the cache username = alc.radius.attributes[1] if username is not None: # using the "with" syntax, get a reference to the cache and fetch the value with alc.cache as cache: value = cache.get(username) # other operations not needing the cache are best done outside of this scope if value is None: print("entry not found in cache") else: print("entry found in cache: {}".format(value))