naeural-client 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. naeural_client/__init__.py +13 -0
  2. naeural_client/_ver.py +13 -0
  3. naeural_client/base/__init__.py +6 -0
  4. naeural_client/base/distributed_custom_code_presets.py +44 -0
  5. naeural_client/base/generic_session.py +1763 -0
  6. naeural_client/base/instance.py +616 -0
  7. naeural_client/base/payload/__init__.py +1 -0
  8. naeural_client/base/payload/payload.py +66 -0
  9. naeural_client/base/pipeline.py +1499 -0
  10. naeural_client/base/plugin_template.py +5209 -0
  11. naeural_client/base/responses.py +209 -0
  12. naeural_client/base/transaction.py +157 -0
  13. naeural_client/base_decentra_object.py +143 -0
  14. naeural_client/bc/__init__.py +3 -0
  15. naeural_client/bc/base.py +1046 -0
  16. naeural_client/bc/chain.py +0 -0
  17. naeural_client/bc/ec.py +324 -0
  18. naeural_client/certs/__init__.py +0 -0
  19. naeural_client/certs/r9092118.ala.eu-central-1.emqxsl.com.crt +22 -0
  20. naeural_client/code_cheker/__init__.py +1 -0
  21. naeural_client/code_cheker/base.py +520 -0
  22. naeural_client/code_cheker/checker.py +294 -0
  23. naeural_client/comm/__init__.py +2 -0
  24. naeural_client/comm/amqp_wrapper.py +338 -0
  25. naeural_client/comm/mqtt_wrapper.py +539 -0
  26. naeural_client/const/README.md +3 -0
  27. naeural_client/const/__init__.py +9 -0
  28. naeural_client/const/base.py +101 -0
  29. naeural_client/const/comms.py +80 -0
  30. naeural_client/const/environment.py +26 -0
  31. naeural_client/const/formatter.py +7 -0
  32. naeural_client/const/heartbeat.py +111 -0
  33. naeural_client/const/misc.py +20 -0
  34. naeural_client/const/payload.py +190 -0
  35. naeural_client/default/__init__.py +1 -0
  36. naeural_client/default/instance/__init__.py +4 -0
  37. naeural_client/default/instance/chain_dist_custom_job_01_plugin.py +54 -0
  38. naeural_client/default/instance/custom_web_app_01_plugin.py +118 -0
  39. naeural_client/default/instance/net_mon_01_plugin.py +45 -0
  40. naeural_client/default/instance/view_scene_01_plugin.py +28 -0
  41. naeural_client/default/session/mqtt_session.py +72 -0
  42. naeural_client/io_formatter/__init__.py +2 -0
  43. naeural_client/io_formatter/base/__init__.py +1 -0
  44. naeural_client/io_formatter/base/base_formatter.py +80 -0
  45. naeural_client/io_formatter/default/__init__.py +3 -0
  46. naeural_client/io_formatter/default/a_dummy.py +51 -0
  47. naeural_client/io_formatter/default/aixp1.py +113 -0
  48. naeural_client/io_formatter/default/default.py +22 -0
  49. naeural_client/io_formatter/io_formatter_manager.py +96 -0
  50. naeural_client/logging/__init__.py +1 -0
  51. naeural_client/logging/base_logger.py +2056 -0
  52. naeural_client/logging/logger_mixins/__init__.py +12 -0
  53. naeural_client/logging/logger_mixins/class_instance_mixin.py +92 -0
  54. naeural_client/logging/logger_mixins/computer_vision_mixin.py +443 -0
  55. naeural_client/logging/logger_mixins/datetime_mixin.py +344 -0
  56. naeural_client/logging/logger_mixins/download_mixin.py +421 -0
  57. naeural_client/logging/logger_mixins/general_serialization_mixin.py +242 -0
  58. naeural_client/logging/logger_mixins/json_serialization_mixin.py +481 -0
  59. naeural_client/logging/logger_mixins/pickle_serialization_mixin.py +301 -0
  60. naeural_client/logging/logger_mixins/process_mixin.py +63 -0
  61. naeural_client/logging/logger_mixins/resource_size_mixin.py +81 -0
  62. naeural_client/logging/logger_mixins/timers_mixin.py +501 -0
  63. naeural_client/logging/logger_mixins/upload_mixin.py +260 -0
  64. naeural_client/logging/logger_mixins/utils_mixin.py +675 -0
  65. naeural_client/logging/small_logger.py +93 -0
  66. naeural_client/logging/tzlocal/__init__.py +20 -0
  67. naeural_client/logging/tzlocal/unix.py +231 -0
  68. naeural_client/logging/tzlocal/utils.py +113 -0
  69. naeural_client/logging/tzlocal/win32.py +151 -0
  70. naeural_client/logging/tzlocal/windows_tz.py +718 -0
  71. naeural_client/plugins_manager_mixin.py +273 -0
  72. naeural_client/utils/__init__.py +2 -0
  73. naeural_client/utils/comm_utils.py +44 -0
  74. naeural_client/utils/dotenv.py +75 -0
  75. naeural_client-2.0.0.dist-info/METADATA +365 -0
  76. naeural_client-2.0.0.dist-info/RECORD +78 -0
  77. naeural_client-2.0.0.dist-info/WHEEL +4 -0
  78. naeural_client-2.0.0.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,72 @@
1
+ import json
2
+
3
+ from ...base import GenericSession
4
+ from ...comm import MQTTWrapper
5
+ from ...const import comms as comm_ct
6
+
7
+
8
+ class MqttSession(GenericSession):
9
+ def startup(self):
10
+ self._default_communicator = MQTTWrapper(
11
+ log=self.log,
12
+ config=self._config,
13
+ send_channel_name=comm_ct.COMMUNICATION_CONFIG_CHANNEL,
14
+ recv_channel_name=comm_ct.COMMUNICATION_PAYLOADS_CHANNEL,
15
+ comm_type=comm_ct.COMMUNICATION_DEFAULT,
16
+ recv_buff=self._payload_messages,
17
+ connection_name=self.name,
18
+ verbosity=self._verbosity,
19
+ )
20
+
21
+ self._heartbeats_communicator = MQTTWrapper(
22
+ log=self.log,
23
+ config=self._config,
24
+ recv_channel_name=comm_ct.COMMUNICATION_CTRL_CHANNEL,
25
+ comm_type=comm_ct.COMMUNICATION_HEARTBEATS,
26
+ recv_buff=self._hb_messages,
27
+ connection_name=self.name,
28
+ verbosity=self._verbosity,
29
+ )
30
+
31
+ self._notifications_communicator = MQTTWrapper(
32
+ log=self.log,
33
+ config=self._config,
34
+ recv_channel_name=comm_ct.COMMUNICATION_NOTIF_CHANNEL,
35
+ comm_type=comm_ct.COMMUNICATION_NOTIFICATIONS,
36
+ recv_buff=self._notif_messages,
37
+ connection_name=self.name,
38
+ verbosity=self._verbosity,
39
+ )
40
+ return super(MqttSession, self).startup()
41
+
42
+ @property
43
+ def _connected(self):
44
+ """
45
+ Check if the session is connected to the communication server.
46
+ """
47
+ return self._default_communicator.connected and self._heartbeats_communicator.connected and self._notifications_communicator.connected
48
+
49
+ def _connect(self) -> None:
50
+ if self._default_communicator.connection is None:
51
+ self._default_communicator.server_connect()
52
+ self._default_communicator.subscribe()
53
+ if self._heartbeats_communicator.connection is None:
54
+ self._heartbeats_communicator.server_connect()
55
+ self._heartbeats_communicator.subscribe()
56
+ if self._notifications_communicator.connection is None:
57
+ self._notifications_communicator.server_connect()
58
+ self._notifications_communicator.subscribe()
59
+ return
60
+
61
+ def _communication_close(self, **kwargs):
62
+ self._default_communicator.release()
63
+ self._heartbeats_communicator.release()
64
+ self._notifications_communicator.release()
65
+ return
66
+
67
+ def _send_payload(self, to, msg):
68
+ payload = json.dumps(msg)
69
+
70
+ self._default_communicator._send_to = to
71
+ self._default_communicator.send(payload)
72
+ return
@@ -0,0 +1,2 @@
1
+ from .io_formatter_manager import IOFormatterWrapper
2
+ from .base import BaseFormatter
@@ -0,0 +1 @@
1
+ from .base_formatter import BaseFormatter
@@ -0,0 +1,80 @@
1
+ import traceback
2
+ from time import time
3
+
4
+ from ...const import PAYLOAD_DATA
5
+
6
+
7
+ class BaseFormatter(object):
8
+
9
+ def __init__(self, log, signature, **kwargs):
10
+ self.signature = signature
11
+ self.log = log
12
+ super(BaseFormatter, self).__init__()
13
+ return
14
+
15
+ def P(self, *args, **kwargs):
16
+ return self.log.P(*args, **kwargs)
17
+
18
+ def _decode_streams(self, dct_config_streams):
19
+ """
20
+ Maybe implement
21
+ """
22
+ return dct_config_streams
23
+
24
+ def _encode_output(self, output):
25
+ """
26
+ Maybe implement
27
+ """
28
+ return output
29
+
30
+ def _decode_output(self, encoded_output):
31
+ """
32
+ Maybe implement
33
+ """
34
+ return encoded_output
35
+
36
+ def decode_streams(self, dct_config_streams):
37
+ try:
38
+ dct_config_streams = self._decode_streams(dct_config_streams)
39
+ except Exception as e:
40
+ dct_config_streams = {}
41
+ msg = "ERROR! Could not decode streams!\n{}".format(e)
42
+ self.P(msg)
43
+ self.P(traceback.format_exc(), color='r')
44
+
45
+ return dct_config_streams
46
+
47
+ def encode_output(self, output):
48
+ tm = time()
49
+ self.log.start_timer('encode', section='Formatter_' + str(self.signature))
50
+ try:
51
+ encoded_output = self._encode_output(output)
52
+ except Exception as e:
53
+ encoded_output = {}
54
+ msg = "ERROR! Could not encode output {}\n{}".format(output, e)
55
+ self.P(msg)
56
+ self.P(traceback.format_exc(), color='r')
57
+ # end try-except
58
+
59
+ elapsed = time() - tm
60
+ self.log.stop_timer('encode', section='Formatter_' + str(self.signature))
61
+ return encoded_output, elapsed
62
+
63
+ def decode_output(self, encoded_output):
64
+ ee_impl = encoded_output.get(PAYLOAD_DATA.EE_FORMATTER, encoded_output.get(PAYLOAD_DATA.SB_IMPLEMENTATION, None))
65
+ if ee_impl is None or (isinstance(ee_impl, str) and ee_impl.lower() != self.signature.lower()):
66
+ return encoded_output
67
+
68
+ self.log.start_timer('decode', section='Formatter_' + str(self.signature))
69
+ try:
70
+ output = self._decode_output(encoded_output)
71
+ except Exception as e:
72
+ output = {}
73
+ msg = "ERROR! Could not decode {}\n{}".format(encoded_output, e)
74
+ self.P(msg)
75
+ self.P(traceback.format_exc(), color='r')
76
+ # end try-except
77
+ self.log.stop_timer('decode', section='Formatter_' + str(self.signature))
78
+ if isinstance(output, dict):
79
+ output[PAYLOAD_DATA.EE_FORMATTER] = ee_impl
80
+ return output
@@ -0,0 +1,3 @@
1
+ from .a_dummy import ADummyFormatter
2
+ from .default import DefaultFormatter
3
+ from .aixp1 import Aixp1Formatter
@@ -0,0 +1,51 @@
1
+
2
+ from ...io_formatter.base import BaseFormatter
3
+ import re
4
+
5
+
6
+ def camel_to_upper_snake(name):
7
+ name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
8
+ return re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).upper()
9
+
10
+
11
+ def snake_to_camel(name):
12
+ name = name.lower()
13
+
14
+ words = []
15
+ for i, x in enumerate(name.split('_')):
16
+ if i > 0:
17
+ words.append(x.title())
18
+ else:
19
+ words.append(x)
20
+
21
+ return ''.join(words)
22
+
23
+
24
+ class ADummyFormatter(BaseFormatter):
25
+
26
+ def __init__(self, **kwargs):
27
+ super(ADummyFormatter, self).__init__(**kwargs)
28
+ return
29
+
30
+ def _decode_streams(self, dct_config_streams):
31
+ return dct_config_streams
32
+
33
+ def _encode_output(self, output):
34
+ # transforms the first level keys to camelCase
35
+ new_output = {}
36
+
37
+ for k, v in output.items():
38
+ k_camel_case = snake_to_camel(k)
39
+ new_output[k_camel_case] = v
40
+
41
+ return new_output
42
+
43
+ def _decode_output(self, encoded_output):
44
+ # it is used mainly for map-reduce jobs in reduce phase!
45
+ decoded_output = {}
46
+
47
+ for k, v in encoded_output.items():
48
+ k_snake_case = camel_to_upper_snake(k)
49
+ decoded_output[k_snake_case] = v
50
+
51
+ return decoded_output
@@ -0,0 +1,113 @@
1
+ # local dependencies
2
+ from ...io_formatter.base import BaseFormatter
3
+
4
+
5
+ class Aixp1Formatter(BaseFormatter):
6
+
7
+ def __init__(self, log, **kwargs):
8
+ super(Aixp1Formatter, self).__init__(
9
+ log=log, prefix_log='[INV-FORM]', **kwargs)
10
+ return
11
+
12
+ def startup(self):
13
+ pass
14
+
15
+ def _encode_output(self, output):
16
+ event_type = output.pop('EE_EVENT_TYPE', None)
17
+
18
+ # below fields are not required as they will be decorated post-formatting anyway
19
+ output.pop('EE_MESSAGE_ID', None)
20
+ output.pop('EE_MESSAGE_SEQ', None)
21
+ output.pop('EE_TOTAL_MESSAGES', None)
22
+
23
+ output.pop('EE_TIMESTAMP', None)
24
+ output.pop('EE_ID', None)
25
+ output.pop('STREAM_NAME', None)
26
+ output.pop('SIGNATURE', None)
27
+ output.pop('INSTANCE_ID', None)
28
+
29
+ output.pop('EE_TIMEZONE', None)
30
+ output.pop('EE_VERSION', None)
31
+ output.pop('EE_TZ', None)
32
+
33
+ output.pop('INITIATOR_ID', None)
34
+ output.pop('SESSION_ID', None)
35
+ # end non-managed fields
36
+
37
+ lvl_0_dct = {
38
+ "DATA": {
39
+ },
40
+ }
41
+
42
+ lvl_1_dct = lvl_0_dct['DATA']
43
+
44
+ if event_type == 'PAYLOAD':
45
+ # add payload context
46
+ output.pop('STREAM')
47
+ output.pop('PIPELINE')
48
+
49
+ # Plugin meta
50
+ if True:
51
+ lvl_1_dct['PLUGIN_META'] = {}
52
+ plugin_meta_keys = [k for k in output.keys() if k.startswith('_P_')]
53
+ for k in plugin_meta_keys:
54
+ lvl_1_dct['PLUGIN_META'][k] = output.pop(k, None)
55
+ # end for
56
+
57
+ # Pipeline meta
58
+ if True:
59
+ lvl_1_dct['PIPELINE_META'] = {}
60
+ pipeline_meta_keys = [k for k in output.keys() if k.startswith('_C_')]
61
+ for k in pipeline_meta_keys:
62
+ lvl_1_dct['PIPELINE_META'][k] = output.pop(k, None)
63
+ # end for
64
+
65
+ # endif payload
66
+
67
+ for k, v in output.items():
68
+ lvl_1_dct[k] = v
69
+
70
+ return lvl_0_dct
71
+
72
+ def _decode_output(self, encoded_output):
73
+ # Pop the unimportant stuff
74
+ encoded_output.get('EE_FORMATTER', None)
75
+
76
+ node_id, pipeline, signature, instance_id = encoded_output.get('EE_PAYLOAD_PATH', [None, None, None, None])
77
+
78
+ encoded_output['EE_ID'] = node_id
79
+
80
+ if encoded_output['EE_EVENT_TYPE'] != 'HEARTBEAT':
81
+ encoded_output['STREAM_NAME'] = pipeline
82
+
83
+ if pipeline is not None:
84
+ encoded_output['SIGNATURE'] = signature
85
+
86
+ if instance_id is not None:
87
+ encoded_output['INSTANCE_ID'] = instance_id
88
+
89
+ lvl_1_dct = encoded_output.pop('DATA')
90
+ if encoded_output['EE_EVENT_TYPE'] == 'PAYLOAD':
91
+ encoded_output['STREAM'] = pipeline
92
+ encoded_output['PIPELINE'] = pipeline
93
+
94
+ # Plugin meta
95
+ plugin_meta = lvl_1_dct.pop('PLUGIN_META', {}) or {}
96
+ for k, v in plugin_meta.items():
97
+ encoded_output[k] = v
98
+
99
+ # Pipeline meta
100
+ pipeline_meta = lvl_1_dct.pop('PIPELINE_META', {}) or {}
101
+ for k, v in pipeline_meta.items():
102
+ encoded_output[k] = v
103
+
104
+ encoded_output['PLUGIN_CATEGORY'] = 'general'
105
+ a = 1
106
+
107
+ for k, v in lvl_1_dct.items():
108
+ encoded_output[k] = v
109
+
110
+ return encoded_output
111
+
112
+ def _decode_streams(self, dct_config_streams):
113
+ return dct_config_streams
@@ -0,0 +1,22 @@
1
+ # local dependencies
2
+ from ...io_formatter.base import BaseFormatter
3
+
4
+
5
+ class DefaultFormatter(BaseFormatter):
6
+
7
+ def __init__(self, log, **kwargs):
8
+ super(DefaultFormatter, self).__init__(
9
+ log=log, prefix_log='[DEFAULT-FMT]', **kwargs)
10
+ return
11
+
12
+ def startup(self):
13
+ pass
14
+
15
+ def _encode_output(self, output):
16
+ return output
17
+
18
+ def _decode_output(self, encoded_output):
19
+ return encoded_output
20
+
21
+ def _decode_streams(self, dct_config_streams):
22
+ return dct_config_streams
@@ -0,0 +1,96 @@
1
+ from time import time
2
+
3
+ from ..plugins_manager_mixin import _PluginsManagerMixin
4
+ from ..const import PAYLOAD_DATA
5
+ from ..io_formatter.default import Aixp1Formatter, DefaultFormatter
6
+
7
+
8
+ class IOFormatterWrapper(_PluginsManagerMixin):
9
+ FORMATTER_CLASSES = [DefaultFormatter, Aixp1Formatter]
10
+
11
+ def __init__(self, log, plugin_search_locations=['plugins.io_formatters'], plugin_search_suffix='Formatter', **kwargs):
12
+ super(IOFormatterWrapper, self).__init__()
13
+ self._dct_formatters = {}
14
+ self.log = log
15
+ self.plugin_search_locations = plugin_search_locations
16
+ self.plugin_search_suffix = plugin_search_suffix
17
+
18
+ self._last_search_invalid_formatter = {}
19
+
20
+ self.__init_formatters()
21
+ return
22
+
23
+ def __init_formatters(self):
24
+ formatter_names_and_classes = [(cls.__name__.lower().split('formatter')[0], cls) for cls in self.FORMATTER_CLASSES]
25
+ for formatter_name, formatter_class in formatter_names_and_classes:
26
+ try:
27
+ self._dct_formatters[formatter_name] = formatter_class(log=self.log, signature=formatter_name)
28
+ self.D("Successfully created IO formatter {}.".format(formatter_name))
29
+ except Exception as exc:
30
+ msg = "Exception '{}' when initializing io_formatter plugin {}".format(exc, formatter_name)
31
+ self.P(msg, color='r')
32
+
33
+ return
34
+
35
+ def _get_formatter_name_from_payload(self, msg):
36
+ return msg.get(PAYLOAD_DATA.EE_FORMATTER, msg.get(PAYLOAD_DATA.SB_IMPLEMENTATION, ''))
37
+
38
+ def _get_plugin_class(self, name):
39
+ _module_name, _class_name, _class_def, _class_config = self._get_module_name_and_class(
40
+ locations=self.plugin_search_locations,
41
+ name=name,
42
+ suffix=self.plugin_search_suffix,
43
+ safe_locations=[],
44
+ )
45
+
46
+ if _class_def is None:
47
+ msg = "Error loading io_formatter plugin '{}'".format(name)
48
+ self.D(msg, color='r')
49
+ return _class_def
50
+
51
+ def formatter_ready(self, name):
52
+ return name in self._dct_formatters or name is None or name == ''
53
+
54
+ def get_formatter_by_name(self, name):
55
+ return self._create_formatter(name)
56
+
57
+ def _create_formatter(self, name):
58
+ # TODO: change name to maybe_create_formatter
59
+ if name is None or name == '':
60
+ # check if we want to create a default formatter
61
+ return self._dct_formatters['default']
62
+
63
+ if name in self._dct_formatters:
64
+ # formatter already created
65
+ if self._dct_formatters[name] is None:
66
+ # formatter is not available
67
+ if name not in self._last_search_invalid_formatter:
68
+ self._last_search_invalid_formatter[name] = 0
69
+ if time() - self._last_search_invalid_formatter[name] < 10 * 60:
70
+ return self._dct_formatters[name]
71
+ else:
72
+ return self._dct_formatters[name]
73
+ # end if name in self._dct_formatters
74
+
75
+ self.D("Creating formatter '{}'".format(name))
76
+ _cls = self._get_plugin_class(name)
77
+
78
+ formatter = None
79
+
80
+ if _cls is not None:
81
+ formatter = _cls(log=self.log, signature=name.lower())
82
+ self.D("Successfully created IO formatter {}.".format(name))
83
+ else:
84
+ self._last_search_invalid_formatter[name] = time()
85
+ self._dct_formatters[name] = formatter
86
+ return formatter
87
+
88
+ def get_required_formatter_from_payload(self, payload):
89
+ name = self._get_formatter_name_from_payload(payload)
90
+ return self._create_formatter(name)
91
+
92
+ def D(self, *args, **kwargs):
93
+ return self.log.D(*args, **kwargs)
94
+
95
+ def P(self, *args, **kwargs):
96
+ return self.log.P(*args, **kwargs)
@@ -0,0 +1 @@
1
+ from .small_logger import Logger