naeural-client 2.4.6__py3-none-any.whl → 2.5.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.
- naeural_client/__init__.py +1 -1
- naeural_client/_ver.py +1 -1
- naeural_client/base/generic_session.py +172 -33
- naeural_client/base/payload/payload.py +16 -2
- naeural_client/base/pipeline.py +49 -5
- naeural_client/base/webapp_pipeline.py +114 -0
- naeural_client/base_decentra_object.py +5 -3
- naeural_client/bc/base.py +13 -2
- naeural_client/cli/cli.py +4 -3
- naeural_client/cli/cli_commands.py +14 -7
- naeural_client/cli/nodes.py +16 -5
- naeural_client/const/__init__.py +1 -1
- naeural_client/const/apps.py +6 -2
- naeural_client/const/payload.py +10 -0
- naeural_client/default/instance/__init__.py +2 -2
- naeural_client/default/instance/{custom_web_app_01_plugin.py → custom_webapi_01_plugin.py} +2 -2
- naeural_client/logging/base_logger.py +4 -2
- naeural_client/utils/config.py +35 -6
- {naeural_client-2.4.6.dist-info → naeural_client-2.5.0.dist-info}/METADATA +2 -1
- {naeural_client-2.4.6.dist-info → naeural_client-2.5.0.dist-info}/RECORD +23 -22
- {naeural_client-2.4.6.dist-info → naeural_client-2.5.0.dist-info}/WHEEL +0 -0
- {naeural_client-2.4.6.dist-info → naeural_client-2.5.0.dist-info}/entry_points.txt +0 -0
- {naeural_client-2.4.6.dist-info → naeural_client-2.5.0.dist-info}/licenses/LICENSE +0 -0
naeural_client/__init__.py
CHANGED
@@ -11,5 +11,5 @@ from .base_decentra_object import BaseDecentrAIObject
|
|
11
11
|
from .plugins_manager_mixin import _PluginsManagerMixin
|
12
12
|
from .logging import Logger
|
13
13
|
from .code_cheker import BaseCodeChecker
|
14
|
-
from .const import PLUGIN_SIGNATURES
|
14
|
+
from .const import PLUGIN_SIGNATURES, PAYLOAD_DATA
|
15
15
|
from .default.instance import PLUGIN_TYPES
|
naeural_client/_ver.py
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
import json
|
2
2
|
import os
|
3
3
|
import traceback
|
4
|
-
|
4
|
+
import pandas as pd
|
5
|
+
|
6
|
+
from collections import deque, OrderedDict
|
5
7
|
from datetime import datetime as dt
|
6
8
|
from threading import Lock, Thread
|
7
9
|
from time import sleep
|
@@ -9,15 +11,22 @@ from time import time as tm
|
|
9
11
|
|
10
12
|
from ..base_decentra_object import BaseDecentrAIObject
|
11
13
|
from ..bc import DefaultBlockEngine
|
12
|
-
from ..const import
|
14
|
+
from ..const import (
|
15
|
+
COMMANDS, ENVIRONMENT, HB, PAYLOAD_DATA, STATUS_TYPE,
|
16
|
+
PLUGIN_SIGNATURES, DEFAULT_PIPELINES,
|
17
|
+
BLOCKCHAIN_CONFIG
|
18
|
+
)
|
13
19
|
from ..const import comms as comm_ct
|
14
20
|
from ..io_formatter import IOFormatterWrapper
|
15
21
|
from ..logging import Logger
|
16
22
|
from ..utils import load_dotenv
|
17
23
|
from .payload import Payload
|
18
24
|
from .pipeline import Pipeline
|
25
|
+
from .webapp_pipeline import WebappPipeline
|
19
26
|
from .transaction import Transaction
|
20
|
-
from ..utils.config import load_user_defined_config, get_user_config_file
|
27
|
+
from ..utils.config import load_user_defined_config, get_user_config_file, get_user_folder
|
28
|
+
|
29
|
+
# from ..default.instance import PLUGIN_TYPES # circular import
|
21
30
|
|
22
31
|
# TODO: add support for remaining commands from EE
|
23
32
|
|
@@ -48,30 +57,35 @@ class GenericSession(BaseDecentrAIObject):
|
|
48
57
|
}
|
49
58
|
|
50
59
|
|
51
|
-
def __init__(
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
60
|
+
def __init__(
|
61
|
+
self, *,
|
62
|
+
host=None,
|
63
|
+
port=None,
|
64
|
+
user=None,
|
65
|
+
pwd=None,
|
66
|
+
secured=None,
|
67
|
+
name='pySDK',
|
68
|
+
encrypt_comms=True,
|
69
|
+
config={},
|
70
|
+
filter_workers=None,
|
71
|
+
log: Logger = None,
|
72
|
+
on_payload=None,
|
73
|
+
on_notification=None,
|
74
|
+
on_heartbeat=None,
|
75
|
+
debug_silent=True,
|
76
|
+
silent=False,
|
77
|
+
verbosity=1,
|
78
|
+
dotenv_path=None,
|
79
|
+
show_commands=False,
|
80
|
+
blockchain_config=BLOCKCHAIN_CONFIG,
|
81
|
+
bc_engine=None,
|
82
|
+
formatter_plugins_locations=['plugins.io_formatters'],
|
83
|
+
root_topic="naeural",
|
84
|
+
local_cache_base_folder=None,
|
85
|
+
local_cache_app_folder='_local_cache',
|
86
|
+
use_home_folder=False,
|
87
|
+
**kwargs
|
88
|
+
) -> None:
|
75
89
|
"""
|
76
90
|
A Session is a connection to a communication server which provides the channel to interact with nodes from the Naeural Edge Protocol network.
|
77
91
|
A Session manages `Pipelines` and handles all messages received from the communication server.
|
@@ -165,6 +179,9 @@ class GenericSession(BaseDecentrAIObject):
|
|
165
179
|
self.online_timeout = 60
|
166
180
|
self.filter_workers = filter_workers
|
167
181
|
self.__show_commands = show_commands
|
182
|
+
|
183
|
+
# this is used to store data received from net-mon instances
|
184
|
+
self.__current_network_statuses = {}
|
168
185
|
|
169
186
|
pwd = pwd or kwargs.get('password', kwargs.get('pass', None))
|
170
187
|
user = user or kwargs.get('username', None)
|
@@ -194,11 +211,28 @@ class GenericSession(BaseDecentrAIObject):
|
|
194
211
|
self.__open_transactions_lock = Lock()
|
195
212
|
|
196
213
|
self.__create_user_callback_threads()
|
214
|
+
|
215
|
+
if local_cache_app_folder is None:
|
216
|
+
local_cache_app_folder = '_local_cache'
|
217
|
+
#
|
218
|
+
|
219
|
+
if os.path.exists(os.path.join(".", local_cache_app_folder)) and local_cache_base_folder is None:
|
220
|
+
local_cache_base_folder = '.'
|
221
|
+
# end if
|
222
|
+
|
223
|
+
if local_cache_base_folder is None or use_home_folder:
|
224
|
+
# use_home_folder allows us to use the home folder as the base folder
|
225
|
+
local_cache_base_folder = get_user_folder()
|
226
|
+
# end if
|
227
|
+
|
228
|
+
|
197
229
|
super(GenericSession, self).__init__(
|
198
230
|
log=log,
|
199
231
|
DEBUG=not debug_silent,
|
200
232
|
create_logger=True,
|
201
233
|
silent=self.silent,
|
234
|
+
local_cache_base_folder=local_cache_base_folder,
|
235
|
+
local_cache_app_folder=local_cache_app_folder,
|
202
236
|
)
|
203
237
|
return
|
204
238
|
|
@@ -425,6 +459,8 @@ class GenericSession(BaseDecentrAIObject):
|
|
425
459
|
self._dct_online_nodes_last_heartbeat[msg_node_addr] = dict_msg
|
426
460
|
|
427
461
|
msg_node_id = dict_msg[PAYLOAD_DATA.EE_ID]
|
462
|
+
# track the node based on heartbeat - a normal heartbeat means the node is online
|
463
|
+
# however this can lead to long wait times for the first heartbeat for all nodes
|
428
464
|
self.__track_online_node(msg_node_addr, msg_node_id)
|
429
465
|
|
430
466
|
msg_active_configs = dict_msg.get(HB.CONFIG_STREAMS)
|
@@ -520,11 +556,48 @@ class GenericSession(BaseDecentrAIObject):
|
|
520
556
|
self.custom_on_notification(self, msg_node_addr, Payload(dict_msg))
|
521
557
|
|
522
558
|
return
|
559
|
+
|
560
|
+
|
561
|
+
def __maybe_process_net_mon(
|
562
|
+
self,
|
563
|
+
dict_msg: dict,
|
564
|
+
msg_pipeline : str,
|
565
|
+
msg_signature : str
|
566
|
+
):
|
567
|
+
REQUIRED_PIPELINE = DEFAULT_PIPELINES.ADMIN_PIPELINE
|
568
|
+
REQUIRED_SIGNATURE = PLUGIN_SIGNATURES.NET_MON_01
|
569
|
+
if msg_pipeline.lower() == REQUIRED_PIPELINE.lower() and msg_signature.upper() == REQUIRED_SIGNATURE.upper():
|
570
|
+
# handle net mon message
|
571
|
+
sender_addr = dict_msg.get(PAYLOAD_DATA.EE_SENDER, None)
|
572
|
+
path = dict_msg.get(PAYLOAD_DATA.EE_PAYLOAD_PATH, [None, None, None, None])
|
573
|
+
ee_id = dict_msg.get(PAYLOAD_DATA.EE_ID, None)
|
574
|
+
current_network = dict_msg.get(PAYLOAD_DATA.NETMON_CURRENT_NETWORK, {})
|
575
|
+
if current_network:
|
576
|
+
all_addresses = [
|
577
|
+
x[PAYLOAD_DATA.NETMON_ADDRESS] for x in current_network.values()
|
578
|
+
]
|
579
|
+
online_addresses = [
|
580
|
+
x[PAYLOAD_DATA.NETMON_ADDRESS] for x in current_network.values()
|
581
|
+
if x[PAYLOAD_DATA.NETMON_STATUS_KEY] == PAYLOAD_DATA.NETMON_STATUS_ONLINE
|
582
|
+
]
|
583
|
+
self.P(f"Net config from <{sender_addr}> `{ee_id}`: {len(online_addresses)}/{len(all_addresses)}", color='y')
|
584
|
+
self.__current_network_statuses[sender_addr] = current_network
|
585
|
+
# end if current_network is valid
|
586
|
+
# end if NET_MON_01
|
587
|
+
return
|
588
|
+
|
523
589
|
|
524
590
|
# TODO: maybe convert dict_msg to Payload object
|
525
591
|
# also maybe strip the dict from useless info for the user of the sdk
|
526
592
|
# Add try-except + sleep
|
527
|
-
def __on_payload(
|
593
|
+
def __on_payload(
|
594
|
+
self,
|
595
|
+
dict_msg: dict,
|
596
|
+
msg_node_addr,
|
597
|
+
msg_pipeline,
|
598
|
+
msg_signature,
|
599
|
+
msg_instance
|
600
|
+
) -> None:
|
528
601
|
"""
|
529
602
|
Handle a payload message received from the communication server.
|
530
603
|
|
@@ -546,6 +619,8 @@ class GenericSession(BaseDecentrAIObject):
|
|
546
619
|
|
547
620
|
if self.__maybe_ignore_message(msg_node_addr):
|
548
621
|
return
|
622
|
+
|
623
|
+
self.__maybe_process_net_mon(dict_msg, msg_pipeline, msg_signature)
|
549
624
|
|
550
625
|
# call the pipeline and instance defined callbacks
|
551
626
|
for pipeline in self.own_pipelines:
|
@@ -1182,6 +1257,7 @@ class GenericSession(BaseDecentrAIObject):
|
|
1182
1257
|
on_data=None,
|
1183
1258
|
on_notification=None,
|
1184
1259
|
max_wait_time=0,
|
1260
|
+
pipeline_type=None,
|
1185
1261
|
**kwargs) -> Pipeline:
|
1186
1262
|
"""
|
1187
1263
|
Create a new pipeline on a node. A pipeline is the equivalent of the "config file" used by the Naeural Edge Protocol edge node team internally.
|
@@ -1249,7 +1325,8 @@ class GenericSession(BaseDecentrAIObject):
|
|
1249
1325
|
raise Exception("Unable to attach to pipeline. Node does not exist")
|
1250
1326
|
|
1251
1327
|
node_addr = self.__get_node_address(node)
|
1252
|
-
|
1328
|
+
pipeline_type = pipeline_type or Pipeline
|
1329
|
+
pipeline = pipeline_type(
|
1253
1330
|
self,
|
1254
1331
|
self.log,
|
1255
1332
|
node_addr=node_addr,
|
@@ -1699,9 +1776,11 @@ class GenericSession(BaseDecentrAIObject):
|
|
1699
1776
|
*,
|
1700
1777
|
node,
|
1701
1778
|
name,
|
1702
|
-
signature
|
1779
|
+
signature,
|
1780
|
+
ngrok_edge_label=None,
|
1703
1781
|
endpoints=None,
|
1704
1782
|
use_ngrok=True,
|
1783
|
+
extra_debug=False,
|
1705
1784
|
**kwargs
|
1706
1785
|
):
|
1707
1786
|
"""
|
@@ -1717,7 +1796,7 @@ class GenericSession(BaseDecentrAIObject):
|
|
1717
1796
|
Name of the web app.
|
1718
1797
|
|
1719
1798
|
signature : str, optional
|
1720
|
-
The signature of the plugin that will be used. Defaults to PLUGIN_SIGNATURES.
|
1799
|
+
The signature of the plugin that will be used. Defaults to PLUGIN_SIGNATURES.CUSTOM_WEBAPI_01.
|
1721
1800
|
|
1722
1801
|
endpoints : list[dict], optional
|
1723
1802
|
A list of dictionaries defining the endpoint configuration. Defaults to None.
|
@@ -1728,9 +1807,16 @@ class GenericSession(BaseDecentrAIObject):
|
|
1728
1807
|
|
1729
1808
|
"""
|
1730
1809
|
|
1731
|
-
|
1810
|
+
ngrok_use_api = True
|
1811
|
+
|
1812
|
+
# if isinstance(signature, str):
|
1813
|
+
|
1814
|
+
|
1815
|
+
pipeline: WebappPipeline = self.create_pipeline(
|
1732
1816
|
node=node,
|
1733
1817
|
name=name,
|
1818
|
+
pipeline_type=WebappPipeline,
|
1819
|
+
extra_debug=extra_debug,
|
1734
1820
|
# default TYPE is "Void"
|
1735
1821
|
)
|
1736
1822
|
|
@@ -1738,6 +1824,8 @@ class GenericSession(BaseDecentrAIObject):
|
|
1738
1824
|
signature=signature,
|
1739
1825
|
instance_id=self.log.get_unique_id(),
|
1740
1826
|
use_ngrok=use_ngrok,
|
1827
|
+
ngrok_edge_label=ngrok_edge_label,
|
1828
|
+
ngrok_use_api=ngrok_use_api,
|
1741
1829
|
**kwargs
|
1742
1830
|
)
|
1743
1831
|
|
@@ -2058,4 +2146,55 @@ class GenericSession(BaseDecentrAIObject):
|
|
2058
2146
|
|
2059
2147
|
@property
|
2060
2148
|
def client_address(self):
|
2061
|
-
return self.get_client_address()
|
2149
|
+
return self.get_client_address()
|
2150
|
+
|
2151
|
+
def get_network_known_nodes(self, timeout=10, online_only=False, supervisors_only=False):
|
2152
|
+
"""
|
2153
|
+
This function will return a Pandas dataframe known nodes in the network based on
|
2154
|
+
all the net-mon messages received so far.
|
2155
|
+
"""
|
2156
|
+
mapping = OrderedDict({
|
2157
|
+
'Address': PAYLOAD_DATA.NETMON_ADDRESS,
|
2158
|
+
'Alias' : PAYLOAD_DATA.NETMON_EEID,
|
2159
|
+
'Last state': PAYLOAD_DATA.NETMON_STATUS_KEY,
|
2160
|
+
'Ago (s)' : PAYLOAD_DATA.NETMON_LAST_SEEN,
|
2161
|
+
'Last probe' : PAYLOAD_DATA.NETMON_LAST_REMOTE_TIME,
|
2162
|
+
'Node zone' : PAYLOAD_DATA.NETMON_NODE_UTC,
|
2163
|
+
'Supervisor' : PAYLOAD_DATA.NETMON_IS_SUPERVISOR,
|
2164
|
+
})
|
2165
|
+
reverse_mapping = {v: k for k, v in mapping.items()}
|
2166
|
+
res = OrderedDict()
|
2167
|
+
for k in mapping:
|
2168
|
+
res[k] = []
|
2169
|
+
start = tm()
|
2170
|
+
while (tm() - start) < timeout:
|
2171
|
+
if len(self.__current_network_statuses) > 0:
|
2172
|
+
break
|
2173
|
+
sleep(0.1)
|
2174
|
+
# end while
|
2175
|
+
if len(self.__current_network_statuses) > 0:
|
2176
|
+
best_info = {}
|
2177
|
+
best_super = None
|
2178
|
+
for supervisor, net_info in self.__current_network_statuses.items():
|
2179
|
+
if len(net_info) > len(best_info):
|
2180
|
+
best_info = net_info
|
2181
|
+
best_super = supervisor
|
2182
|
+
# done found best supervisor
|
2183
|
+
for _, node_info in best_info.items():
|
2184
|
+
is_online = node_info.get(PAYLOAD_DATA.NETMON_STATUS_KEY, None) == PAYLOAD_DATA.NETMON_STATUS_ONLINE
|
2185
|
+
is_supervisor = node_info.get(PAYLOAD_DATA.NETMON_IS_SUPERVISOR, False)
|
2186
|
+
if online_only and not is_online:
|
2187
|
+
continue
|
2188
|
+
if supervisors_only and not is_supervisor:
|
2189
|
+
continue
|
2190
|
+
for key, column in reverse_mapping.items():
|
2191
|
+
val = node_info.get(key, None)
|
2192
|
+
if key == PAYLOAD_DATA.NETMON_LAST_REMOTE_TIME:
|
2193
|
+
# val hols a string '2024-12-23 23:50:16.462155' and must be converted to a datetime
|
2194
|
+
val = dt.strptime(val, '%Y-%m-%d %H:%M:%S.%f')
|
2195
|
+
# strip the microseconds
|
2196
|
+
val = val.replace(microsecond=0)
|
2197
|
+
res[column].append(val)
|
2198
|
+
# end for
|
2199
|
+
# end if
|
2200
|
+
return pd.DataFrame(res), best_super
|
@@ -64,6 +64,19 @@ class Payload(UserDict):
|
|
64
64
|
except ModuleNotFoundError:
|
65
65
|
raise "This functionality requires the PIL library. To use this feature, please install it using 'pip install pillow'"
|
66
66
|
return image
|
67
|
+
|
68
|
+
def __getattr__(self, key):
|
69
|
+
try:
|
70
|
+
return self.data[key]
|
71
|
+
except KeyError as e:
|
72
|
+
raise AttributeError(f"{self.__class__.__name__} object has no attribute '{key}'") from e
|
73
|
+
|
74
|
+
def __setattr__(self, key, value):
|
75
|
+
# If we're setting 'data' itself, just call super()
|
76
|
+
if key == 'data':
|
77
|
+
super().__setattr__(key, value)
|
78
|
+
else:
|
79
|
+
self.data[key] = value
|
67
80
|
|
68
81
|
|
69
82
|
if __name__ == "__main__":
|
@@ -71,9 +84,10 @@ if __name__ == "__main__":
|
|
71
84
|
payload = Payload()
|
72
85
|
payload.data = {
|
73
86
|
"IMG": "iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABKklEQVR42mNkAAwOyKg",
|
74
|
-
"TEST" : "TEST"
|
87
|
+
"TEST" : "TEST VALUE"
|
75
88
|
}
|
76
89
|
|
77
90
|
print(type(payload), payload)
|
78
91
|
print(type(payload.data), payload.data)
|
79
|
-
print(json.dumps(payload.data, indent=2))
|
92
|
+
print(json.dumps(payload.data, indent=2))
|
93
|
+
print(payload.TEST)
|
naeural_client/base/pipeline.py
CHANGED
@@ -28,7 +28,21 @@ class Pipeline(BaseCodeChecker):
|
|
28
28
|
`Plugin` == `Signature`
|
29
29
|
"""
|
30
30
|
|
31
|
-
def __init__(
|
31
|
+
def __init__(
|
32
|
+
self,
|
33
|
+
session,
|
34
|
+
log,
|
35
|
+
*,
|
36
|
+
node_addr,
|
37
|
+
name,
|
38
|
+
config={},
|
39
|
+
plugins=[],
|
40
|
+
on_data=None,
|
41
|
+
on_notification=None,
|
42
|
+
is_attached=False,
|
43
|
+
existing_config=None,
|
44
|
+
**kwargs
|
45
|
+
) -> None:
|
32
46
|
"""
|
33
47
|
A `Pipeline` is a an object that encapsulates a one-to-many, data acquisition to data processing, flow of data.
|
34
48
|
|
@@ -112,9 +126,24 @@ class Pipeline(BaseCodeChecker):
|
|
112
126
|
self.on_notification_callbacks = []
|
113
127
|
|
114
128
|
if on_data is not None:
|
115
|
-
|
129
|
+
if isinstance(on_data, list):
|
130
|
+
for cb in on_data:
|
131
|
+
if cb is not None:
|
132
|
+
self.on_data_callbacks.append(cb)
|
133
|
+
elif callable(on_data):
|
134
|
+
self.on_data_callbacks.append(on_data)
|
135
|
+
else:
|
136
|
+
raise ValueError("on_data should be a callable or a list of callables")
|
137
|
+
|
116
138
|
if on_notification is not None:
|
117
|
-
|
139
|
+
if isinstance(on_notification, list):
|
140
|
+
for cb in on_data:
|
141
|
+
if cb is not None:
|
142
|
+
self.on_notification_callbacks.append(cb)
|
143
|
+
elif callable(on_notification):
|
144
|
+
self.on_notification_callbacks.append(on_notification)
|
145
|
+
else:
|
146
|
+
raise ValueError("on_notification should be a callable or a list of callables")
|
118
147
|
|
119
148
|
self.lst_plugin_instances: list[Instance] = []
|
120
149
|
|
@@ -798,7 +827,16 @@ class Pipeline(BaseCodeChecker):
|
|
798
827
|
"""
|
799
828
|
return self.__was_last_operation_successful
|
800
829
|
|
801
|
-
def create_plugin_instance(
|
830
|
+
def create_plugin_instance(
|
831
|
+
self,
|
832
|
+
*,
|
833
|
+
signature,
|
834
|
+
instance_id,
|
835
|
+
config={},
|
836
|
+
on_data=None,
|
837
|
+
on_notification=None,
|
838
|
+
**kwargs
|
839
|
+
) -> Instance:
|
802
840
|
"""
|
803
841
|
Create a new instance of a desired plugin, with a given configuration. This instance is attached to this pipeline,
|
804
842
|
meaning it processes data from this pipelines data source. Parameters can be passed either in the `config` dict, or as `kwargs`.
|
@@ -988,7 +1026,13 @@ class Pipeline(BaseCodeChecker):
|
|
988
1026
|
**kwargs
|
989
1027
|
)
|
990
1028
|
|
991
|
-
def deploy(
|
1029
|
+
def deploy(
|
1030
|
+
self,
|
1031
|
+
with_confirmation=True,
|
1032
|
+
wait_confirmation=True,
|
1033
|
+
timeout=10,
|
1034
|
+
verbose=False
|
1035
|
+
):
|
992
1036
|
"""
|
993
1037
|
This method is used to deploy the pipeline on the Naeural Edge Protocol edge node.
|
994
1038
|
Here we collect all the proposed configurations and send them to the Naeural Edge Protocol edge node.
|
@@ -0,0 +1,114 @@
|
|
1
|
+
import time
|
2
|
+
from .pipeline import Pipeline
|
3
|
+
|
4
|
+
|
5
|
+
|
6
|
+
class WebappPipeline(Pipeline):
|
7
|
+
|
8
|
+
def __init__(
|
9
|
+
self,
|
10
|
+
session,
|
11
|
+
log,
|
12
|
+
*,
|
13
|
+
node_addr,
|
14
|
+
name,
|
15
|
+
config={},
|
16
|
+
plugins=[],
|
17
|
+
is_attached=False,
|
18
|
+
on_data=None,
|
19
|
+
on_notification=None,
|
20
|
+
existing_config=None,
|
21
|
+
extra_debug=False,
|
22
|
+
**kwargs
|
23
|
+
) -> None:
|
24
|
+
"""
|
25
|
+
This is a special type of pipeline that is used to deploy webapps.
|
26
|
+
It will override the deploy method to return the ngrok URL as well as the on_data method to extract the ngrok URL.
|
27
|
+
"""
|
28
|
+
self.ngrok_url = None
|
29
|
+
self.__extra_debug = extra_debug
|
30
|
+
_on_data = [self.__check_payloads, on_data]
|
31
|
+
super().__init__(
|
32
|
+
session,
|
33
|
+
log,
|
34
|
+
node_addr=node_addr,
|
35
|
+
name=name,
|
36
|
+
config=config,
|
37
|
+
plugins=plugins,
|
38
|
+
is_attached=is_attached,
|
39
|
+
on_data=_on_data,
|
40
|
+
on_notification=on_notification,
|
41
|
+
existing_config=existing_config,
|
42
|
+
|
43
|
+
**kwargs
|
44
|
+
)
|
45
|
+
return
|
46
|
+
|
47
|
+
|
48
|
+
def __check_payloads(self, session, plugin_signature, plugin_instance, data):
|
49
|
+
"""
|
50
|
+
Check if the payload if from ngrok and extract the ngrok URL.
|
51
|
+
|
52
|
+
Parameters
|
53
|
+
----------
|
54
|
+
|
55
|
+
|
56
|
+
session : Session
|
57
|
+
The session object that received the payload.
|
58
|
+
|
59
|
+
plugin_signature : str
|
60
|
+
The signature of the plugin that sent the payload.
|
61
|
+
|
62
|
+
plugin_instance : str
|
63
|
+
The instance of the plugin that sent the payload.
|
64
|
+
|
65
|
+
data : Payload
|
66
|
+
The payload received from the edge node.
|
67
|
+
|
68
|
+
|
69
|
+
"""
|
70
|
+
if self.__extra_debug:
|
71
|
+
self.P(f"Received payload from {plugin_signature} ({plugin_instance})")
|
72
|
+
if "NGROK_URL" in data:
|
73
|
+
self.ngrok_url = data["NGROK_URL"]
|
74
|
+
return
|
75
|
+
|
76
|
+
def create_plugin_instance(
|
77
|
+
self,
|
78
|
+
*,
|
79
|
+
signature,
|
80
|
+
instance_id,
|
81
|
+
config={},
|
82
|
+
ngrok_edge_label=None,
|
83
|
+
**kwargs
|
84
|
+
):
|
85
|
+
|
86
|
+
if ngrok_edge_label is not None:
|
87
|
+
self.ngrok_url = "URL_DEFINED_IN_EDGE_LABEL"
|
88
|
+
|
89
|
+
return super().create_plugin_instance(
|
90
|
+
signature=signature,
|
91
|
+
instance_id=instance_id,
|
92
|
+
config=config,
|
93
|
+
ngrok_edge_label=ngrok_edge_label,
|
94
|
+
**kwargs
|
95
|
+
)
|
96
|
+
|
97
|
+
def deploy(self, verbose=False, timeout=15, **kwargs):
|
98
|
+
"""
|
99
|
+
Deploy the pipeline and return the URL of the webapp.
|
100
|
+
|
101
|
+
Returns
|
102
|
+
-------
|
103
|
+
str
|
104
|
+
The URL of the webapp.
|
105
|
+
"""
|
106
|
+
res = super().deploy(verbose=verbose, timeout=timeout, **kwargs)
|
107
|
+
# now we wait for the ngrok url to be available
|
108
|
+
start = time.time()
|
109
|
+
while self.ngrok_url is None:
|
110
|
+
elapsed = time.time() - start
|
111
|
+
if elapsed > timeout:
|
112
|
+
raise Exception("Timeout waiting for ngrok url")
|
113
|
+
# return the ngrok url
|
114
|
+
return self.ngrok_url
|
@@ -25,6 +25,8 @@ class BaseDecentrAIObject(object):
|
|
25
25
|
prefix_log=None,
|
26
26
|
log_at_startup=False,
|
27
27
|
silent=False,
|
28
|
+
local_cache_base_folder='.',
|
29
|
+
local_cache_app_folder='_local_cache',
|
28
30
|
**kwargs):
|
29
31
|
|
30
32
|
super(BaseDecentrAIObject, self).__init__()
|
@@ -34,10 +36,10 @@ class BaseDecentrAIObject(object):
|
|
34
36
|
raise ValueError("Logger object is invalid: {}".format(log))
|
35
37
|
else:
|
36
38
|
log = Logger(
|
37
|
-
"
|
39
|
+
"R1",
|
38
40
|
DEBUG=DEBUG,
|
39
|
-
base_folder=
|
40
|
-
app_folder=
|
41
|
+
base_folder=local_cache_base_folder,
|
42
|
+
app_folder=local_cache_app_folder,
|
41
43
|
silent=silent,
|
42
44
|
)
|
43
45
|
# endif
|
naeural_client/bc/base.py
CHANGED
@@ -280,12 +280,23 @@ class BaseBlockEngine:
|
|
280
280
|
|
281
281
|
ensure_ascii_payloads: bool
|
282
282
|
flag that controls if the payloads are encoded as ascii or not. Default `False` for JS compatibility.
|
283
|
+
|
284
|
+
user_config: bool
|
285
|
+
flag that controls if the keys are stored in the user private folder or in the data folder of the _local_cache
|
283
286
|
|
284
287
|
"""
|
285
288
|
_lock: Lock = Lock()
|
286
289
|
__instances = {}
|
287
290
|
|
288
|
-
def __new__(
|
291
|
+
def __new__(
|
292
|
+
cls,
|
293
|
+
name,
|
294
|
+
log,
|
295
|
+
config,
|
296
|
+
ensure_ascii_payloads=False,
|
297
|
+
verbosity=1,
|
298
|
+
user_config=False
|
299
|
+
):
|
289
300
|
with cls._lock:
|
290
301
|
if name not in cls.__instances:
|
291
302
|
instance = super(BaseBlockEngine, cls).__new__(cls)
|
@@ -328,7 +339,7 @@ class BaseBlockEngine:
|
|
328
339
|
pem_name = config.get(BCct.K_PEM_FILE, '_pk.pem')
|
329
340
|
pem_folder = config.get(BCct.K_PEM_LOCATION, 'data')
|
330
341
|
pem_fn = os.path.join(log.get_target_folder(pem_folder), pem_name)
|
331
|
-
#endif pem is defined in ~/.naeural/
|
342
|
+
#endif pem is defined in ~/.naeural/ or in the data folder of the _local_cache
|
332
343
|
self.__pem_file = pem_fn
|
333
344
|
self._init()
|
334
345
|
return
|
naeural_client/cli/cli.py
CHANGED
@@ -14,8 +14,8 @@ def build_parser():
|
|
14
14
|
argparse.ArgumentParser
|
15
15
|
Configured argument parser.
|
16
16
|
"""
|
17
|
-
|
18
|
-
parser = argparse.ArgumentParser(description=
|
17
|
+
title = f"nepctl v{version} - CLI for Naeural Edge Protocol SDK package"
|
18
|
+
parser = argparse.ArgumentParser(description=title)
|
19
19
|
subparsers = parser.add_subparsers(dest="command", help="Available commands")
|
20
20
|
|
21
21
|
for command, subcommands in CLI_COMMANDS.items():
|
@@ -25,8 +25,9 @@ def build_parser():
|
|
25
25
|
# Nested subcommands
|
26
26
|
command_subparsers = command_parser.add_subparsers(dest="subcommand")
|
27
27
|
for subcommand, subcmd_info in subcommands.items():
|
28
|
+
description = subcmd_info.get("description", f"{subcommand} command")
|
28
29
|
subcommand_parser = command_subparsers.add_parser(
|
29
|
-
subcommand, help=
|
30
|
+
subcommand, help=description
|
30
31
|
)
|
31
32
|
if isinstance(subcmd_info, dict) and "params" in subcmd_info:
|
32
33
|
for param, description in subcmd_info["params"].items():
|
@@ -2,7 +2,7 @@ from naeural_client.cli.nodes import (
|
|
2
2
|
get_nodes, get_supervisors,
|
3
3
|
restart_node, shutdown_node
|
4
4
|
)
|
5
|
-
from naeural_client.utils.config import show_config, reset_config
|
5
|
+
from naeural_client.utils.config import show_config, reset_config, show_address
|
6
6
|
|
7
7
|
|
8
8
|
# Define the available commands
|
@@ -11,30 +11,37 @@ CLI_COMMANDS = {
|
|
11
11
|
"nodes": {
|
12
12
|
"func": get_nodes,
|
13
13
|
"params": {
|
14
|
-
"--all": "Get all nodes",
|
15
|
-
"--
|
14
|
+
"--all": "Get all known nodes", # DONE
|
15
|
+
"--online" : "Get only online nodes", # DONE
|
16
|
+
# "--peered": "Get only peered nodes"
|
16
17
|
}
|
17
18
|
},
|
18
19
|
"supervisors": {
|
19
|
-
"func": get_supervisors,
|
20
|
+
"func": get_supervisors, # DONE
|
20
21
|
},
|
21
22
|
},
|
22
23
|
"config": {
|
23
24
|
"show": {
|
24
|
-
"func": show_config,
|
25
|
+
"func": show_config, # DONE
|
26
|
+
"description": "Show the current configuration including the location",
|
25
27
|
},
|
26
28
|
"reset": {
|
27
29
|
"func": reset_config,
|
30
|
+
"description": "Reset the configuration to default",
|
28
31
|
},
|
32
|
+
"addr": {
|
33
|
+
"func": show_address, # DONE
|
34
|
+
"description": "Show the current client address",
|
35
|
+
}
|
29
36
|
},
|
30
37
|
"restart": {
|
31
|
-
"func": restart_node,
|
38
|
+
"func": restart_node, # TODO
|
32
39
|
"params": {
|
33
40
|
"node": "The node to restart"
|
34
41
|
}
|
35
42
|
},
|
36
43
|
"shutdown": {
|
37
|
-
"func": shutdown_node,
|
44
|
+
"func": shutdown_node, # TODO
|
38
45
|
"params": {
|
39
46
|
"node": "The node to shutdown"
|
40
47
|
}
|
naeural_client/cli/nodes.py
CHANGED
@@ -10,12 +10,20 @@ def get_nodes(args):
|
|
10
10
|
3. Wait for the second net mon message via Session and show progress.
|
11
11
|
4. Get the active nodes union via Session and display the nodes marking those peered vs non-peered.
|
12
12
|
"""
|
13
|
+
from naeural_client import Session
|
14
|
+
sess = Session(silent=True)
|
13
15
|
if args.all:
|
14
|
-
|
15
|
-
|
16
|
-
log_with_color("
|
16
|
+
df, supervisor = sess.get_network_known_nodes()
|
17
|
+
log_with_color(f"Network historical map as seen by <{supervisor}>:", color='b')
|
18
|
+
log_with_color(f"{df}")
|
19
|
+
elif args.online:
|
20
|
+
df, supervisor = sess.get_network_known_nodes(online_only=True)
|
21
|
+
log_with_color(f"Online nodes as seen by <{supervisor}>:", color='b')
|
22
|
+
log_with_color(f"{df}")
|
17
23
|
else:
|
18
|
-
|
24
|
+
df, supervisor = sess.get_network_known_nodes(online_only=True)
|
25
|
+
log_with_color(f"Online nodes as seen by <{supervisor}>:", color='b')
|
26
|
+
log_with_color(f"{df}")
|
19
27
|
return
|
20
28
|
|
21
29
|
|
@@ -23,7 +31,10 @@ def get_supervisors(args):
|
|
23
31
|
"""
|
24
32
|
This function is used to get the information about the supervisors.
|
25
33
|
"""
|
26
|
-
|
34
|
+
from naeural_client import Session
|
35
|
+
sess = Session(silent=True)
|
36
|
+
df, supervisor = sess.get_network_known_nodes(online_only=True, supervisors_only=True)
|
37
|
+
log_with_color(f"Supervisors reported by <{supervisor}>:\n{df}")
|
27
38
|
return
|
28
39
|
|
29
40
|
|
naeural_client/const/__init__.py
CHANGED
@@ -7,4 +7,4 @@ from .payload import STATUS_TYPE, PAYLOAD_DATA, COMMANDS, NOTIFICATION_CODES, NE
|
|
7
7
|
from .base import CONFIG_STREAM, BIZ_PLUGIN_DATA, PLUGIN_INFO, BLOCKCHAIN_CONFIG
|
8
8
|
from . import heartbeat as HB
|
9
9
|
from .environment import ENVIRONMENT
|
10
|
-
from .apps import PLUGIN_SIGNATURES
|
10
|
+
from .apps import PLUGIN_SIGNATURES, DEFAULT_PIPELINES
|
naeural_client/const/apps.py
CHANGED
@@ -5,8 +5,12 @@ class PLUGIN_SIGNATURES:
|
|
5
5
|
"""
|
6
6
|
NET_MON_01 = 'NET_MON_01'
|
7
7
|
VIEW_SCENE_01 = 'VIEW_SCENE_01'
|
8
|
-
|
8
|
+
CUSTOM_WEBAPI_01 = 'CUSTOM_CODE_FASTAPI_01'
|
9
9
|
CHAIN_DIST_CUSTOM_JOB_01 = 'PROCESS_REAL_TIME_COLLECTED_DATA_CUSTOM_EXEC_CHAIN_DIST'
|
10
10
|
TELEGRAM_BASIC_BOT_01 = 'TELEGRAM_BASIC_BOT_01'
|
11
11
|
TELEGRAM_CONVERSATIONAL_BOT_01 = 'TELEGRAM_CONVERSATIONAL_BOT_01'
|
12
|
-
# INSERT_NEW_PLUGIN_HERE
|
12
|
+
# INSERT_NEW_PLUGIN_HERE
|
13
|
+
|
14
|
+
|
15
|
+
class DEFAULT_PIPELINES:
|
16
|
+
ADMIN_PIPELINE = 'admin_pipeline'
|
naeural_client/const/payload.py
CHANGED
@@ -195,6 +195,16 @@ class PAYLOAD_DATA:
|
|
195
195
|
|
196
196
|
ID_TAGS = 'ID_TAGS'
|
197
197
|
|
198
|
+
NETMON_CURRENT_NETWORK = 'CURRENT_NETWORK'
|
199
|
+
NETMON_STATUS_KEY = "working"
|
200
|
+
NETMON_STATUS_ONLINE = "ONLINE"
|
201
|
+
NETMON_ADDRESS = "address"
|
202
|
+
NETMON_EEID = "eeid"
|
203
|
+
NETMON_LAST_REMOTE_TIME = 'last_remote_time'
|
204
|
+
NETMON_NODE_UTC = 'node_utc'
|
205
|
+
NETMON_LAST_SEEN = 'last_seen_sec'
|
206
|
+
NETMON_IS_SUPERVISOR = 'is_supervisor'
|
207
|
+
|
198
208
|
|
199
209
|
class NET_CONFIG:
|
200
210
|
STORE_COMMAND = "SET_CONFIG"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
from .net_mon_01_plugin import NetMon01
|
2
2
|
from .view_scene_01_plugin import ViewScene01
|
3
|
-
from .
|
3
|
+
from .custom_webapi_01_plugin import CustomWebapi01
|
4
4
|
from .chain_dist_custom_job_01_plugin import ChainDistCustomJob01
|
5
5
|
from .telegram_basic_bot_01_plugin import BasicTelegramBot01
|
6
6
|
|
@@ -11,6 +11,6 @@ class PLUGIN_TYPES:
|
|
11
11
|
"""
|
12
12
|
NET_MON_01 = NetMon01
|
13
13
|
VIEW_SCENE_01 = ViewScene01
|
14
|
-
|
14
|
+
CUSTOM_WEBAPI_01 = CustomWebapi01
|
15
15
|
CHAIN_DIST_CUSTOM_JOB_01 = ChainDistCustomJob01
|
16
16
|
TELEGRAM_BASIC_BOT_01 = BasicTelegramBot01
|
@@ -1,8 +1,8 @@
|
|
1
1
|
from ...base import Instance, Pipeline
|
2
2
|
from ...const import PLUGIN_SIGNATURES
|
3
3
|
|
4
|
-
class
|
5
|
-
signature = PLUGIN_SIGNATURES.
|
4
|
+
class CustomWebapi01(Instance):
|
5
|
+
signature = PLUGIN_SIGNATURES.CUSTOM_WEBAPI_01
|
6
6
|
|
7
7
|
def get_proposed_endpoints(self):
|
8
8
|
from copy import deepcopy
|
@@ -29,11 +29,13 @@ _HTML_END = "</pre></BODY>"
|
|
29
29
|
|
30
30
|
COLORS = {
|
31
31
|
'n': "\x1b[1;37m", # normal white
|
32
|
-
'd': "\
|
32
|
+
'd': "\033[90m", # dark gray
|
33
|
+
# 'd': "\x1b[0;37m", # grey white
|
33
34
|
'r': "\x1b[1;31m",
|
34
35
|
'g': "\x1b[1;32m",
|
35
36
|
'y': "\x1b[1;33m",
|
36
|
-
'b': "\x1b[1;34m",
|
37
|
+
# 'b': "\x1b[1;34m",
|
38
|
+
'b': "\x1b[1;36m", # changed to bright cyan
|
37
39
|
'm': "\x1b[1;35m",
|
38
40
|
'c': "\x1b[1;36m", # bright cyan
|
39
41
|
'v': "\x1b[0;36m", # dim cyan
|
naeural_client/utils/config.py
CHANGED
@@ -31,7 +31,8 @@ def log_with_color(s, color='n'):
|
|
31
31
|
'r': '\033[31m', # Red
|
32
32
|
'g': '\033[32m', # Green
|
33
33
|
'y': '\033[33m', # Yellow
|
34
|
-
'b': "\x1b[1;34m", # bright blue
|
34
|
+
# 'b': "\x1b[1;34m", # bright blue
|
35
|
+
'b': "\x1b[1;36m", # bright cyan
|
35
36
|
'w': '\033[97m', # Light white
|
36
37
|
'c': "\x1b[1;36m", # bright cyan
|
37
38
|
'n': '\033[37m', # Dark white (default)
|
@@ -54,7 +55,7 @@ def get_user_config_file():
|
|
54
55
|
"""
|
55
56
|
return get_user_folder() / "config"
|
56
57
|
|
57
|
-
def reset_config(args):
|
58
|
+
def reset_config(*args, **kwargs):
|
58
59
|
"""
|
59
60
|
Resets the configuration by creating a ~/.naeural folder and populating
|
60
61
|
~/.naeural/config with values from a local .env file, if it exists.
|
@@ -71,22 +72,49 @@ def reset_config(args):
|
|
71
72
|
if current_env_file.exists():
|
72
73
|
# Copy .env content to ~/.naeural/config
|
73
74
|
shutil.copy(current_env_file, config_file)
|
74
|
-
log_with_color(
|
75
|
+
log_with_color(
|
76
|
+
f"Configuration has been reset using {current_env_file} into {config_file}",
|
77
|
+
color='y'
|
78
|
+
)
|
79
|
+
log_with_color(f"Please REVIEW the configuration in the file {config_file}", color='b')
|
75
80
|
else:
|
76
81
|
# Create an empty config file
|
77
82
|
with config_file.open("wt") as file:
|
78
83
|
file.write(ENV_TEMPLATE)
|
79
|
-
log_with_color(
|
84
|
+
log_with_color(
|
85
|
+
f"Configuration has been reset to default in {config_file}:\n{ENV_TEMPLATE}",
|
86
|
+
color='y'
|
87
|
+
)
|
88
|
+
log_with_color(f"Please UPDATE the configuration in the file {config_file}", color='b')
|
89
|
+
return
|
80
90
|
|
91
|
+
def show_address(*args):
|
92
|
+
"""
|
93
|
+
Displays the current client address.
|
94
|
+
"""
|
95
|
+
from naeural_client import Session
|
96
|
+
sess = Session(
|
97
|
+
silent=True
|
98
|
+
)
|
99
|
+
log_with_color(f"{sess.get_client_address()}", color='b')
|
100
|
+
return
|
81
101
|
|
82
|
-
def show_config(args):
|
102
|
+
def show_config(*args):
|
83
103
|
"""
|
84
104
|
Displays the current configuration from ~/.naeural/config.
|
85
105
|
"""
|
106
|
+
from naeural_client import Session
|
107
|
+
sess = Session(
|
108
|
+
silent=True
|
109
|
+
)
|
110
|
+
|
111
|
+
user_folder = get_user_folder()
|
86
112
|
config_file = get_user_config_file()
|
87
113
|
|
114
|
+
log_with_color(f"NEP SDK folder: {user_folder}", color='b')
|
115
|
+
log_with_color(f"SDK Client address: {sess.get_client_address()}", color='b')
|
88
116
|
if config_file.exists():
|
89
|
-
log_with_color(f"Current configuration ({config_file}):")
|
117
|
+
log_with_color(f"Current configuration ({config_file}):", color='y')
|
90
118
|
with config_file.open("r") as file:
|
91
119
|
log_with_color(file.read())
|
92
120
|
else:
|
@@ -127,5 +155,6 @@ def maybe_init_config():
|
|
127
155
|
config_file = get_user_config_file()
|
128
156
|
|
129
157
|
if not config_file.exists():
|
158
|
+
log_with_color(f"No configuration file found at {config_file}. Initializing configuration...", color="y")
|
130
159
|
reset_config()
|
131
160
|
load_user_defined_config()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: naeural_client
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.5.0
|
4
4
|
Summary: `naeural_client` is the Python SDK required for client app development for the Naeural Edge Protocol Edge Protocol framework
|
5
5
|
Project-URL: Homepage, https://github.com/NaeuralEdgeProtocol/naeural_client
|
6
6
|
Project-URL: Bug Tracker, https://github.com/NaeuralEdgeProtocol/naeural_client/issues
|
@@ -13,6 +13,7 @@ Requires-Python: >=3.8
|
|
13
13
|
Requires-Dist: cryptography>=39.0.0
|
14
14
|
Requires-Dist: numpy
|
15
15
|
Requires-Dist: paho-mqtt
|
16
|
+
Requires-Dist: pandas
|
16
17
|
Requires-Dist: pika
|
17
18
|
Requires-Dist: pyaml
|
18
19
|
Requires-Dist: pyopenssl>=23.0.0
|
@@ -1,27 +1,28 @@
|
|
1
|
-
naeural_client/__init__.py,sha256=
|
2
|
-
naeural_client/_ver.py,sha256=
|
3
|
-
naeural_client/base_decentra_object.py,sha256=
|
1
|
+
naeural_client/__init__.py,sha256=GP8WSrn87sjTPO-QRNL2PG8JK5Mixbiea_HrtbG8RAQ,592
|
2
|
+
naeural_client/_ver.py,sha256=2q08grJY82pFxv33pcuzXra7I7shn846wWbTMRTO0vQ,330
|
3
|
+
naeural_client/base_decentra_object.py,sha256=C4iwZTkhKNBS4VHlJs5DfElRYLo4Q9l1V1DNVSk1fyQ,4412
|
4
4
|
naeural_client/plugins_manager_mixin.py,sha256=X1JdGLDz0gN1rPnTN_5mJXR8JmqoBFQISJXmPR9yvCo,11106
|
5
5
|
naeural_client/base/__init__.py,sha256=hACh83_cIv7-PwYMM3bQm2IBmNqiHw-3PAfDfAEKz9A,259
|
6
6
|
naeural_client/base/distributed_custom_code_presets.py,sha256=cvz5R88P6Z5V61Ce1vHVVh8bOkgXd6gve_vdESDNAsg,2544
|
7
|
-
naeural_client/base/generic_session.py,sha256=
|
7
|
+
naeural_client/base/generic_session.py,sha256=0DQsq3-4i61-7flElK5lx-AzK3uwrDvJGbHzbUmH3gU,82553
|
8
8
|
naeural_client/base/instance.py,sha256=kcZJmjLBtx8Bjj_ysIOx1JmLA-qSpG7E28j5rq6IYus,20444
|
9
|
-
naeural_client/base/pipeline.py,sha256=
|
9
|
+
naeural_client/base/pipeline.py,sha256=b4uNHrEIOlAtw4PGUx20dxwBhDck5__SrVXaHcSi8ZA,58251
|
10
10
|
naeural_client/base/plugin_template.py,sha256=qGaXByd_JZFpjvH9GXNbT7KaitRxIJB6-1IhbKrZjq4,138123
|
11
11
|
naeural_client/base/responses.py,sha256=ZKBZmRhYDv8M8mQ5C_ahGsQvtWH4b9ImRcuerQdZmNw,6937
|
12
12
|
naeural_client/base/transaction.py,sha256=bfs6td5M0fINgPQNxhrl_AUjb1YiilLDQ-Cd_o3OR_E,5146
|
13
|
+
naeural_client/base/webapp_pipeline.py,sha256=QmPLVmhP0CPdi0YuvbZEH4APYz2Amtw3gyOu4bVodYA,2740
|
13
14
|
naeural_client/base/payload/__init__.py,sha256=y8fBI8tG2ObNfaXFWjyWZXwu878FRYj_I8GIbHT4GKE,29
|
14
|
-
naeural_client/base/payload/payload.py,sha256=
|
15
|
+
naeural_client/base/payload/payload.py,sha256=x-au7l67Z_vfn_4R2C_pjZCaFuUVXHngJiGOfIAYVdE,2690
|
15
16
|
naeural_client/bc/__init__.py,sha256=FQj23D1PrY06NUOARiKQi4cdj0-VxnoYgYDEht8lpr8,158
|
16
|
-
naeural_client/bc/base.py,sha256=
|
17
|
+
naeural_client/bc/base.py,sha256=R-bz2pIe-rSdfp5cracN68kH68MwqvWcA-ATLw9qL6s,31707
|
17
18
|
naeural_client/bc/chain.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
18
19
|
naeural_client/bc/ec.py,sha256=mWjodWCRgC3omVXOA9jtNdtPVNn2kMKV3Dcjt9oFUCQ,22974
|
19
20
|
naeural_client/certs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
20
21
|
naeural_client/certs/r9092118.ala.eu-central-1.emqxsl.com.crt,sha256=y-6io0tseyx9-a4Pmde1z1gPULtJNSYUpG_YFkYaMKU,1337
|
21
22
|
naeural_client/cli/README.md,sha256=WPdI_EjzAbUW1aPyj1sSR8rLydcJKZtoiaEtklQrjHo,74
|
22
|
-
naeural_client/cli/cli.py,sha256=
|
23
|
-
naeural_client/cli/cli_commands.py,sha256=
|
24
|
-
naeural_client/cli/nodes.py,sha256=
|
23
|
+
naeural_client/cli/cli.py,sha256=ipbZzc-Hg7mE5ivoWM7MzJI9GXfCaYQn8PXJc6FRbF4,2818
|
24
|
+
naeural_client/cli/cli_commands.py,sha256=VK7jGCl-C5Bel6RUz5Qcf5mAT7at7bEUn52OV1xdff8,1309
|
25
|
+
naeural_client/cli/nodes.py,sha256=MkDFfw02iW_qNP9mPolJbGHPByL__ZHSpGODunbz80M,1953
|
25
26
|
naeural_client/code_cheker/__init__.py,sha256=pwkdeZGVL16ZA4Qf2mRahEhoOvKhL7FyuQbMFLr1E5M,33
|
26
27
|
naeural_client/code_cheker/base.py,sha256=lT5DRIFO5rqzsMNCmdMRfkAeevmezozehyfgmhnKpuI,19074
|
27
28
|
naeural_client/code_cheker/checker.py,sha256=QWupeM7ToancVIq1tRUxRNUrI8B5l5eoY0kDU4-O5aE,7365
|
@@ -29,19 +30,19 @@ naeural_client/comm/__init__.py,sha256=za3B2HUKNXzYtjElMgGM9xbxNsdQfFY4JB_YzdyFk
|
|
29
30
|
naeural_client/comm/amqp_wrapper.py,sha256=hzj6ih07DnLQy2VSfA88giDIFHaCp9uSdGLTA-IFE4s,8535
|
30
31
|
naeural_client/comm/mqtt_wrapper.py,sha256=Ig3bFZkCbWd4y_Whn2PPa91Z3aLgNbNPau6Tn5yLPZ8,16167
|
31
32
|
naeural_client/const/README.md,sha256=6OHesr-f5NBuuJGryEoi_TCu2XdlhfQYlDKx_IJoXeg,177
|
32
|
-
naeural_client/const/__init__.py,sha256=
|
33
|
-
naeural_client/const/apps.py,sha256=
|
33
|
+
naeural_client/const/__init__.py,sha256=OtrSiHyTzrie5dyC1gWrYXYmg5cVMdwe0gxAlrHXCLg,466
|
34
|
+
naeural_client/const/apps.py,sha256=aZ9oiBT8MC1Vm7e0TyerRvQ7z4m0-GHR67BXdLnv5lE,573
|
34
35
|
naeural_client/const/base.py,sha256=-NeZPwE0JrbTHmlI9BOmgzaGu5jUZHl9vOZ4hhh_QQo,3100
|
35
36
|
naeural_client/const/comms.py,sha256=La6JXWHexH8CfcBCKyT4fCIoeaoZlcm7KtZ57ab4ZgU,2201
|
36
37
|
naeural_client/const/environment.py,sha256=iytmTDgbOjvORPwHQmc0K0r-xJx7dnnzNnqAJJiFCDA,870
|
37
38
|
naeural_client/const/formatter.py,sha256=AW3bWlqf39uaqV4BBUuW95qKYfF2OkkU4f9hy3kSVhM,200
|
38
39
|
naeural_client/const/heartbeat.py,sha256=jGHmKfeHTFOXJaKUT3o_ocnQyF-EpcLeunW-ifkYKfU,2534
|
39
40
|
naeural_client/const/misc.py,sha256=Y6x00YDtY1_nAk4OvikCLlfp8ggn11WQYTBGYzFlJPk,211
|
40
|
-
naeural_client/const/payload.py,sha256=
|
41
|
+
naeural_client/const/payload.py,sha256=fHhhdSv1o_5Ldy72jO7m3YZtMmJOpOHaVhfjbNCuuzo,6446
|
41
42
|
naeural_client/default/__init__.py,sha256=ozU6CMMuWl0LhG8Ae3LrZ65a6tLrptfscVYGf83zjxM,46
|
42
|
-
naeural_client/default/instance/__init__.py,sha256=
|
43
|
+
naeural_client/default/instance/__init__.py,sha256=w1de6OMj9a5GPGF-Wl1b_I_YAy9fWBEss2QnyPPyaB0,546
|
43
44
|
naeural_client/default/instance/chain_dist_custom_job_01_plugin.py,sha256=QtHi3uXKsVs9eyMgbnvBVbMylErhV1Du4X2-7zDL7Y0,1915
|
44
|
-
naeural_client/default/instance/
|
45
|
+
naeural_client/default/instance/custom_webapi_01_plugin.py,sha256=EEjW9c2EQatMktOjO5picyDYDSrppc6_TmMNI8lgFeA,4784
|
45
46
|
naeural_client/default/instance/net_mon_01_plugin.py,sha256=u85i2AiYHkLJnam0wOx-m71hlp0EYyNtk3JwbkOrvHg,1208
|
46
47
|
naeural_client/default/instance/telegram_basic_bot_01_plugin.py,sha256=P_W2K_ng7svbhoIoYGvkGxa4v9UUoxuOAAgtoM36wDo,161
|
47
48
|
naeural_client/default/instance/telegram_conversational_bot_01_plugin.py,sha256=XkyE-uNbtFnTSGA1nOf-XNmUipAUjhg0xXV1glRb7gc,179
|
@@ -56,7 +57,7 @@ naeural_client/io_formatter/default/a_dummy.py,sha256=qr9eUizQ-NN5jdXVzkaZKMaf9K
|
|
56
57
|
naeural_client/io_formatter/default/aixp1.py,sha256=MX0TeUR4APA-qN3vUC6uzcz8Pssz5lgrQWo7td5Ri1A,3052
|
57
58
|
naeural_client/io_formatter/default/default.py,sha256=gEy78cP2D5s0y8vQh4aHuxqz7D10gGfuiKF311QhrpE,494
|
58
59
|
naeural_client/logging/__init__.py,sha256=b79X45VC6c37u32flKB2GAK9f-RR0ocwP0JDCy0t7QQ,33
|
59
|
-
naeural_client/logging/base_logger.py,sha256=
|
60
|
+
naeural_client/logging/base_logger.py,sha256=himUkM_48-YXS4u0zJ_5jSd564PeXNpa8uttpgKkljA,66032
|
60
61
|
naeural_client/logging/small_logger.py,sha256=m12hCb_H4XifJYYfgCAOUDkcXm-h4pSODnFf277OFVI,2937
|
61
62
|
naeural_client/logging/logger_mixins/__init__.py,sha256=yQO7umlRvz63FeWpi-F9GRmC_MOHcNW6R6pwvZZBy3A,600
|
62
63
|
naeural_client/logging/logger_mixins/class_instance_mixin.py,sha256=xUXE2VZgmrlrSrvw0f6GF1jlTnVLeVkIiG0bhlBfq3o,2741
|
@@ -78,10 +79,10 @@ naeural_client/logging/tzlocal/win32.py,sha256=zBoj0vFVrGhnCm_f7xmYzGym4-fV-4Ij2
|
|
78
79
|
naeural_client/logging/tzlocal/windows_tz.py,sha256=Sv9okktjZJfRGGUOOppsvQuX_eXyXUxkSKCAFmWT9Hw,34203
|
79
80
|
naeural_client/utils/__init__.py,sha256=mAnke3-MeRzz3nhQvhuHqLnpaaCSmDxicd7Ck9uwpmI,77
|
80
81
|
naeural_client/utils/comm_utils.py,sha256=4cS9llRr_pK_3rNgDcRMCQwYPO0kcNU7AdWy_LtMyCY,1072
|
81
|
-
naeural_client/utils/config.py,sha256=
|
82
|
+
naeural_client/utils/config.py,sha256=PORcwfYdy-z9hwYzBag1RR6Lv5lWUtWVxZAyN9cjWxA,4562
|
82
83
|
naeural_client/utils/dotenv.py,sha256=_AgSo35n7EnQv5yDyu7C7i0kHragLJoCGydHjvOkrYY,2008
|
83
|
-
naeural_client-2.
|
84
|
-
naeural_client-2.
|
85
|
-
naeural_client-2.
|
86
|
-
naeural_client-2.
|
87
|
-
naeural_client-2.
|
84
|
+
naeural_client-2.5.0.dist-info/METADATA,sha256=DflO3VEWNE0AS_t41VVwQZFQLceR-e93ag5Hid7vppc,14493
|
85
|
+
naeural_client-2.5.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
86
|
+
naeural_client-2.5.0.dist-info/entry_points.txt,sha256=PNdyotDaQBAslZREx5luVyj0kqpQnwNACwkFNTPIHU4,55
|
87
|
+
naeural_client-2.5.0.dist-info/licenses/LICENSE,sha256=cvOsJVslde4oIaTCadabXnPqZmzcBO2f2zwXZRmJEbE,11311
|
88
|
+
naeural_client-2.5.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|