1
|
|
|
"""This module is responsible to provide means of creating (instantiating) objects |
2
|
|
|
representing Datapoints collections.""" |
3
|
|
|
import logging |
4
|
|
|
import json |
5
|
|
|
from typing import Iterable |
6
|
|
|
import attr |
7
|
|
|
from so_magic.utils import Subject |
8
|
|
|
from .datapoints import DatapointsFactory |
9
|
|
|
|
10
|
|
|
logger = logging.getLogger(__name__) |
11
|
|
|
|
12
|
|
|
|
13
|
|
|
# TODO refactor to a composition (not inheritance) implementation of the below class |
14
|
|
|
# reason is that it will be more evident that this class simply combines the |
15
|
|
|
# features of 2 other classes (Subject & DatapointsFactory) to get the job done |
16
|
|
|
@attr.s |
17
|
|
|
class BroadcastingDatapointsFactory(DatapointsFactory): |
18
|
|
|
"""Creates Datapoints objects and informs its subscribers when that happens. |
19
|
|
|
|
20
|
|
|
A factory class that informs its subscribers when a new object that |
21
|
|
|
implements the DatapointsInterface is created (following a request). |
22
|
|
|
|
23
|
|
|
Args: |
24
|
|
|
subject (Subject, optional): the subject of observation; the "thing" that others |
25
|
|
|
listen to |
26
|
|
|
""" |
27
|
|
|
subject: Subject = attr.ib(init=True, default=attr.Factory(Subject)) |
28
|
|
|
name: str = attr.ib(init=False, default='') |
29
|
|
|
# TODO check if above can be removed, along with self.name = getattr(args[0], 'name', '') in 'create' method |
30
|
|
|
|
31
|
|
|
def create(self, datapoints_factory_type: str, *args, **kwargs) -> Iterable: |
32
|
|
|
"""Create new Datapoints and inform subscribers. |
33
|
|
|
|
34
|
|
|
The factory method that returns a new object of DatapointsInterface, by |
35
|
|
|
looking at the registered constructors to delegate the object creation. |
36
|
|
|
|
37
|
|
|
Args: |
38
|
|
|
datapoints_factory_type (str): the name of the "constructor" to use |
39
|
|
|
|
40
|
|
|
Raises: |
41
|
|
|
RuntimeError: [description] |
42
|
|
|
|
43
|
|
|
Returns: |
44
|
|
|
Iterable: instance implementing the DatapointsInterface |
45
|
|
|
""" |
46
|
|
|
self.subject.name = kwargs.pop('id', kwargs.pop('name', kwargs.pop('file_path', ''))) |
47
|
|
|
if kwargs: |
48
|
|
|
msg = f"Kwargs: [{', '.join(f'{k}: {v}' for k, v in kwargs.items())}]" |
49
|
|
|
raise RuntimeError("The 'create' method of DatapointsFactory does not support kwargs:", msg) |
50
|
|
|
self.subject.state = super().create(datapoints_factory_type, *args, **kwargs) |
51
|
|
|
# logger.debug(f"Created datapoints: {json.dumps({ |
52
|
|
|
# 'datapoints': self.subject.state, |
53
|
|
|
# 'name': self.subject.name, |
54
|
|
|
# })}") |
55
|
|
|
print("Created datapoints: {}".format(json.dumps({ |
56
|
|
|
'datapoints': str(self.subject.state), |
57
|
|
|
'name': self.subject.name, |
58
|
|
|
}))) |
59
|
|
|
if args and not hasattr(self, '.name'): |
60
|
|
|
self.name = getattr(args[0], 'name', '') |
61
|
|
|
self.subject.notify() |
62
|
|
|
return self.subject.state |
63
|
|
|
|