Passed
Push — master ( 5f2d49...176334 )
by Konstantinos
49s queued 12s
created

so_magic.utils.memoize.ObjectsPool.get_object()   A

Complexity

Conditions 2

Size

Total Lines 15
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nop 3
dl 0
loc 15
rs 10
c 0
b 0
f 0
1
"""Implementation of the object pool"""
2
import types
3
import attr
4
5
__all__ = ['ObjectsPool']
6
7
8
def _convert_to_method(function):
9
    def _function(_self, *args, **kwargs):
10
        return function(*args, **kwargs)
11
    return _function
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 unique string out of the input \*args and \*\*kwargs."""
29
        return hash('-'.join([str(_) for _ in args] + ['{key}={value}'.format(key=k, value=str(v)) for k, v in kwargs]))
30
31
    constructor = attr.ib(init=True)
32
    _objects = attr.ib(init=True, default={})
33
    _build_hash = attr.ib(default=attr.Factory(lambda self: types.MethodType(
34
        _convert_to_method(ObjectsPool.__build_hash), self), takes_self=True))
35
36
    def get_object(self, *args, **kwargs):
37
        r"""Request an object from the pool.
38
39
        Get or create an object given the input parameters. Existence in the pool is done using the
40
        python-build-in hash function. The input \*args and \*\*kwargs serve as
41
        input in the hash function to create unique keys with which to "query" the object pool.
42
43
        Returns:
44
            object: the reference to the object that corresponds to the input
45
            arguments, regardless of whether it was found in the pool or not
46
        """
47
        key = self._build_hash(*args, **kwargs)
48
        if key not in self._objects:
49
            self._objects[key] = self.constructor(*args, **kwargs)
50
        return self._objects[key]
51
52
    @classmethod
53
    def new_empty(cls, constructor, build_hash=None):
54
        if build_hash is None:
55
            build_hash = ObjectsPool.__build_hash
56
        return ObjectsPool(constructor, {}, build_hash)
57