Passed
Push — master ( ee1e78...515b92 )
by Konstantinos
01:14
created

artificial_artwork.utils.memoize   A

Complexity

Total Complexity 6

Size/Duplication

Total Lines 63
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 29
dl 0
loc 63
rs 10
c 0
b 0
f 0
wmc 6

3 Methods

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

1 Function

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