so_magic.utils.memoize   A
last analyzed

Complexity

Total Complexity 6

Size/Duplication

Total Lines 56
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 27
dl 0
loc 56
rs 10
c 0
b 0
f 0
wmc 6

3 Methods

Rating   Name   Duplication   Size   Complexity  
A ObjectsPool.__build_hash() 0 4 1
A ObjectsPool.new_empty() 0 5 2
A ObjectsPool.get_object() 0 15 2

1 Function

Rating   Name   Duplication   Size   Complexity  
A _validate_build_hash_callback() 0 4 1
1
"""Implementation of the object pool"""
2
import types
3
import attr
4
5
__all__ = ['ObjectsPool']
6
7
8
def _validate_build_hash_callback(self, attribute, build_hash_callback):
9
    def method(_self, *args, **kwargs):
10
        return build_hash_callback(*args, **kwargs)
11
    setattr(self, attribute.name, types.MethodType(method, self))
12
13
14
@attr.s
15
class ObjectsPool:
16
    """Class of objects that are able to return a reference to an object upon request.
17
18
    Whenever an object is requested, it is checked whether it exists in the pool.
19
    Then if it exists, a reference is returned, otherwise a new object is
20
    constructed (given the provided callable) and its reference is returned.
21
22
    Arguments:
23
        constructor (callable): able to construct the object given arguments
24
        objects (dict): the data structure representing the object pool
25
    """
26
    @staticmethod
27
    def __build_hash(*args, **kwargs):
28
        r"""Construct a hash out of the input \*args and \*\*kwargs."""
29
        return hash('-'.join([str(_) for _ in args] + [f'{key}={str(value)}' for key, value in kwargs.items()]))
30
31
    constructor = attr.ib()
32
    _build_hash = attr.ib(validator=_validate_build_hash_callback)
33
    _objects = attr.ib(default={})
34
35
    def get_object(self, *args, **kwargs):
36
        r"""Request an object from the pool.
37
38
        Get or create an object given the input parameters. Existence in the pool is done using the
39
        python-build-in hash function. The input \*args and \*\*kwargs serve as
40
        input in the hash function to create unique keys with which to "query" the object pool.
41
42
        Returns:
43
            object: the reference to the object that corresponds to the input
44
            arguments, regardless of whether it was found in the pool or not
45
        """
46
        key = self._build_hash(*args, **kwargs)
47
        if key not in self._objects:
48
            self._objects[key] = self.constructor(*args, **kwargs)
49
        return self._objects[key]
50
51
    @classmethod
52
    def new_empty(cls, constructor, build_hash=None):
53
        if build_hash is None:
54
            build_hash = ObjectsPool.__build_hash
55
        return ObjectsPool(constructor, build_hash)
56