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