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
|
|
|
|