naeural-client 2.2.6__py3-none-any.whl → 2.3.1__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/_ver.py +1 -1
- naeural_client/base/generic_session.py +55 -11
- naeural_client/base_decentra_object.py +8 -2
- naeural_client/bc/base.py +63 -7
- naeural_client/bc/ec.py +144 -1
- naeural_client/cli/README.md +7 -0
- naeural_client/cli/cli.py +48 -0
- naeural_client/cli/cli_commands.py +15 -0
- naeural_client/cli/nodes.py +22 -0
- naeural_client/logging/base_logger.py +63 -27
- naeural_client/logging/small_logger.py +2 -0
- naeural_client/utils/config.py +130 -0
- {naeural_client-2.2.6.dist-info → naeural_client-2.3.1.dist-info}/METADATA +5 -4
- {naeural_client-2.2.6.dist-info → naeural_client-2.3.1.dist-info}/RECORD +17 -11
- naeural_client-2.3.1.dist-info/entry_points.txt +2 -0
- {naeural_client-2.2.6.dist-info → naeural_client-2.3.1.dist-info}/WHEEL +0 -0
- {naeural_client-2.2.6.dist-info → naeural_client-2.3.1.dist-info}/licenses/LICENSE +0 -0
naeural_client/_ver.py
CHANGED
@@ -17,9 +17,12 @@ from ..utils import load_dotenv
|
|
17
17
|
from .payload import Payload
|
18
18
|
from .pipeline import Pipeline
|
19
19
|
from .transaction import Transaction
|
20
|
+
from ..utils.config import load_user_defined_config, get_user_config_file
|
20
21
|
|
21
22
|
# TODO: add support for remaining commands from EE
|
22
23
|
|
24
|
+
DEBUG_MQTT_SERVER = "r9092118.ala.eu-central-1.emqxsl.com"
|
25
|
+
|
23
26
|
|
24
27
|
class GenericSession(BaseDecentrAIObject):
|
25
28
|
"""
|
@@ -59,7 +62,8 @@ class GenericSession(BaseDecentrAIObject):
|
|
59
62
|
on_payload=None,
|
60
63
|
on_notification=None,
|
61
64
|
on_heartbeat=None,
|
62
|
-
|
65
|
+
debug_silent=True,
|
66
|
+
silent=False,
|
63
67
|
verbosity=1,
|
64
68
|
dotenv_path=None,
|
65
69
|
show_commands=False,
|
@@ -120,8 +124,14 @@ class GenericSession(BaseDecentrAIObject):
|
|
120
124
|
Callback that handles heartbeats received from this network.
|
121
125
|
As arguments, it has a reference to this Session object, the node name and the heartbeat payload.
|
122
126
|
Defaults to None.
|
123
|
-
|
127
|
+
|
128
|
+
debug_silent : bool, optional
|
124
129
|
This flag will disable debug logs, set to 'False` for a more verbose log, by default True
|
130
|
+
|
131
|
+
silent : bool, optional
|
132
|
+
This flag will disable all logs, set to 'False` for a more verbose log, by default False
|
133
|
+
The logs will still be recored in the log file even if this flag is set to True.
|
134
|
+
|
125
135
|
dotenv_path : str, optional
|
126
136
|
Path to the .env file, by default None. If None, the path will be searched in the current working directory and in the directories of the files from the call stack.
|
127
137
|
root_topic : str, optional
|
@@ -142,6 +152,7 @@ class GenericSession(BaseDecentrAIObject):
|
|
142
152
|
|
143
153
|
self.log = log
|
144
154
|
self.name = name
|
155
|
+
self.silent = silent
|
145
156
|
|
146
157
|
self._verbosity = verbosity
|
147
158
|
self.encrypt_comms = encrypt_comms
|
@@ -158,7 +169,10 @@ class GenericSession(BaseDecentrAIObject):
|
|
158
169
|
pwd = pwd or kwargs.get('password', kwargs.get('pass', None))
|
159
170
|
user = user or kwargs.get('username', None)
|
160
171
|
host = host or kwargs.get('hostname', None)
|
172
|
+
|
173
|
+
## now we prepare config via ~/.naeural/config or .env
|
161
174
|
self.__fill_config(host, port, user, pwd, secured, dotenv_path)
|
175
|
+
## end config
|
162
176
|
|
163
177
|
self.custom_on_payload = on_payload
|
164
178
|
self.custom_on_heartbeat = on_heartbeat
|
@@ -180,15 +194,30 @@ class GenericSession(BaseDecentrAIObject):
|
|
180
194
|
self.__open_transactions_lock = Lock()
|
181
195
|
|
182
196
|
self.__create_user_callback_threads()
|
183
|
-
super(GenericSession, self).__init__(
|
197
|
+
super(GenericSession, self).__init__(
|
198
|
+
log=log,
|
199
|
+
DEBUG=not debug_silent,
|
200
|
+
create_logger=True,
|
201
|
+
silent=self.silent,
|
202
|
+
)
|
184
203
|
return
|
185
204
|
|
186
205
|
def startup(self):
|
187
|
-
|
206
|
+
# start the blockchain engine assuming config is already set
|
207
|
+
self.__start_blockchain(
|
208
|
+
self.__bc_engine, self.__blockchain_config,
|
209
|
+
user_config=self.__user_config_loaded,
|
210
|
+
)
|
211
|
+
# end bc_engine
|
188
212
|
self.formatter_wrapper = IOFormatterWrapper(self.log, plugin_search_locations=self.__formatter_plugins_locations)
|
189
213
|
|
190
214
|
self._connect()
|
191
215
|
|
216
|
+
self.P("Created {} comms session '{}' from <{}> SDKv{}.".format(
|
217
|
+
"decrypted" if not self.encrypt_comms else "encrypted",
|
218
|
+
self.name, self.bc_engine.address, self.log.version
|
219
|
+
))
|
220
|
+
|
192
221
|
if not self.encrypt_comms:
|
193
222
|
self.P(
|
194
223
|
"Warning: Emitted messages will not be encrypted.\n"
|
@@ -546,7 +575,7 @@ class GenericSession(BaseDecentrAIObject):
|
|
546
575
|
|
547
576
|
# Main loop
|
548
577
|
if True:
|
549
|
-
def __start_blockchain(self, bc_engine, blockchain_config):
|
578
|
+
def __start_blockchain(self, bc_engine, blockchain_config, user_config=False):
|
550
579
|
if bc_engine is not None:
|
551
580
|
self.bc_engine = bc_engine
|
552
581
|
return
|
@@ -557,6 +586,7 @@ class GenericSession(BaseDecentrAIObject):
|
|
557
586
|
name=self.name,
|
558
587
|
config=blockchain_config,
|
559
588
|
verbosity=self._verbosity,
|
589
|
+
user_config=user_config,
|
560
590
|
)
|
561
591
|
except:
|
562
592
|
raise ValueError("Failure in private blockchain setup:\n{}".format(traceback.format_exc()))
|
@@ -780,15 +810,19 @@ class GenericSession(BaseDecentrAIObject):
|
|
780
810
|
host : str
|
781
811
|
The hostname of the server.
|
782
812
|
Can be retrieved from the environment variables AIXP_HOSTNAME, AIXP_HOST
|
813
|
+
|
783
814
|
port : int
|
784
815
|
The port.
|
785
816
|
Can be retrieved from the environment variable AIXP_PORT
|
817
|
+
|
786
818
|
user : str
|
787
819
|
The user name.
|
788
820
|
Can be retrieved from the environment variables AIXP_USERNAME, AIXP_USER
|
821
|
+
|
789
822
|
pwd : str
|
790
823
|
The password.
|
791
824
|
Can be retrieved from the environment variables AIXP_PASSWORD, AIXP_PASS, AIXP_PWD
|
825
|
+
|
792
826
|
dotenv_path : str, optional
|
793
827
|
Path to the .env file, by default None. If None, the path will be searched in the current working directory and in the directories of the files from the call stack.
|
794
828
|
|
@@ -798,11 +832,21 @@ class GenericSession(BaseDecentrAIObject):
|
|
798
832
|
Missing credentials
|
799
833
|
"""
|
800
834
|
|
801
|
-
#
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
835
|
+
# if the ~/.naeural/config file exists, load the credentials from there else try to load them from .env
|
836
|
+
if not load_user_defined_config():
|
837
|
+
# this method will search for the credentials in the environment variables
|
838
|
+
# the path to env file, if not specified, will be search in the following order:
|
839
|
+
# 1. current working directory
|
840
|
+
# 2-N. directories of the files from the call stack
|
841
|
+
load_dotenv(dotenv_path=dotenv_path, verbose=False)
|
842
|
+
if not self.silent:
|
843
|
+
print("Loaded credentials from environment variables.", flush=True)
|
844
|
+
self.__user_config_loaded = False
|
845
|
+
else:
|
846
|
+
if not self.silent:
|
847
|
+
print(f"Loaded credentials from `{get_user_config_file()}`.", flush=True)
|
848
|
+
self.__user_config_loaded = True
|
849
|
+
# endif config loading from ~ or ./.env
|
806
850
|
|
807
851
|
possible_user_values = [
|
808
852
|
user,
|
@@ -849,7 +893,7 @@ class GenericSession(BaseDecentrAIObject):
|
|
849
893
|
os.getenv(ENVIRONMENT.EE_HOST),
|
850
894
|
os.getenv(ENVIRONMENT.EE_MQTT_HOST),
|
851
895
|
self._config.get(comm_ct.HOST),
|
852
|
-
|
896
|
+
DEBUG_MQTT_SERVER,
|
853
897
|
]
|
854
898
|
|
855
899
|
host = next((x for x in possible_host_values if x is not None), None)
|
@@ -24,6 +24,7 @@ class BaseDecentrAIObject(object):
|
|
24
24
|
show_prefixes=False,
|
25
25
|
prefix_log=None,
|
26
26
|
log_at_startup=False,
|
27
|
+
silent=False,
|
27
28
|
**kwargs):
|
28
29
|
|
29
30
|
super(BaseDecentrAIObject, self).__init__()
|
@@ -32,7 +33,13 @@ class BaseDecentrAIObject(object):
|
|
32
33
|
if not create_logger:
|
33
34
|
raise ValueError("Logger object is invalid: {}".format(log))
|
34
35
|
else:
|
35
|
-
log = Logger(
|
36
|
+
log = Logger(
|
37
|
+
"DEF",
|
38
|
+
DEBUG=DEBUG,
|
39
|
+
base_folder='.',
|
40
|
+
app_folder='_local_cache',
|
41
|
+
silent=silent,
|
42
|
+
)
|
36
43
|
# endif
|
37
44
|
|
38
45
|
self.log = log
|
@@ -79,7 +86,6 @@ class BaseDecentrAIObject(object):
|
|
79
86
|
msg = "{} {}".format(self.prefix_log, s)
|
80
87
|
# endif
|
81
88
|
# endif
|
82
|
-
|
83
89
|
_r = self.log.P(msg, show_time=t, color=color, **kwargs)
|
84
90
|
return _r
|
85
91
|
|
naeural_client/bc/base.py
CHANGED
@@ -12,6 +12,8 @@ from copy import deepcopy
|
|
12
12
|
|
13
13
|
from cryptography.hazmat.primitives import serialization
|
14
14
|
|
15
|
+
from ..utils.config import get_user_folder
|
16
|
+
|
15
17
|
|
16
18
|
class BCct:
|
17
19
|
SIGN = 'EE_SIGN'
|
@@ -21,6 +23,7 @@ class BCct:
|
|
21
23
|
ADDR_PREFIX_OLD = "aixp_"
|
22
24
|
ADDR_PREFIX = "0xai_"
|
23
25
|
|
26
|
+
K_USER_CONFIG_PEM_FILE = 'NAEURAL_PEM_FILE'
|
24
27
|
K_PEM_FILE = 'PEM_FILE'
|
25
28
|
K_PASSWORD = 'PASSWORD'
|
26
29
|
K_PEM_LOCATION = 'PEM_LOCATION'
|
@@ -270,7 +273,7 @@ class BaseBlockEngine:
|
|
270
273
|
_lock: Lock = Lock()
|
271
274
|
__instances = {}
|
272
275
|
|
273
|
-
def __new__(cls, name, log, config, ensure_ascii_payloads=False, verbosity=1):
|
276
|
+
def __new__(cls, name, log, config, ensure_ascii_payloads=False, verbosity=1, user_config=False):
|
274
277
|
with cls._lock:
|
275
278
|
if name not in cls.__instances:
|
276
279
|
instance = super(BaseBlockEngine, cls).__new__(cls)
|
@@ -278,6 +281,7 @@ class BaseBlockEngine:
|
|
278
281
|
name=name, log=log, config=config,
|
279
282
|
ensure_ascii_payloads=ensure_ascii_payloads,
|
280
283
|
verbosity=verbosity,
|
284
|
+
user_config=user_config,
|
281
285
|
)
|
282
286
|
cls.__instances[name] = instance
|
283
287
|
else:
|
@@ -291,6 +295,7 @@ class BaseBlockEngine:
|
|
291
295
|
log=None,
|
292
296
|
ensure_ascii_payloads=False,
|
293
297
|
verbosity=1,
|
298
|
+
user_config=False,
|
294
299
|
):
|
295
300
|
|
296
301
|
self.__name = name
|
@@ -304,11 +309,15 @@ class BaseBlockEngine:
|
|
304
309
|
self.__config = config
|
305
310
|
self.__ensure_ascii_payloads = ensure_ascii_payloads
|
306
311
|
|
307
|
-
|
308
|
-
|
309
|
-
|
312
|
+
if user_config:
|
313
|
+
user_folder = get_user_folder()
|
314
|
+
pem_fn = str(user_folder / '_naeural.pem')
|
315
|
+
else:
|
316
|
+
pem_name = config.get(BCct.K_PEM_FILE, '_pk.pem')
|
317
|
+
pem_folder = config.get(BCct.K_PEM_LOCATION, 'data')
|
318
|
+
pem_fn = os.path.join(log.get_target_folder(pem_folder), pem_name)
|
319
|
+
#endif pem is defined in ~/.naeural/config
|
310
320
|
self.__pem_file = pem_fn
|
311
|
-
|
312
321
|
self._init()
|
313
322
|
return
|
314
323
|
|
@@ -353,9 +362,13 @@ class BaseBlockEngine:
|
|
353
362
|
password=self.__password,
|
354
363
|
fn=self.__pem_file,
|
355
364
|
)
|
356
|
-
self.__public_key = self._get_pk(private_key=self.__private_key)
|
365
|
+
self.__public_key = self._get_pk(private_key=self.__private_key)
|
357
366
|
self.__address = self._pk_to_address(self.__public_key)
|
358
|
-
|
367
|
+
### Ethereum
|
368
|
+
self.__eth_address = self._get_eth_address()
|
369
|
+
self.__eth_account = self._get_eth_account()
|
370
|
+
### end Ethereum
|
371
|
+
self.P("Address: {} / ETH: {}".format(self.address, self.eth_address), boxed=True, verbosity=1)
|
359
372
|
self.P("Allowed list of senders: {}".format(self.allowed_list), verbosity=1)
|
360
373
|
return
|
361
374
|
|
@@ -363,6 +376,11 @@ class BaseBlockEngine:
|
|
363
376
|
def private_key(self):
|
364
377
|
return self.__private_key
|
365
378
|
|
379
|
+
|
380
|
+
@property
|
381
|
+
def public_key(self):
|
382
|
+
return self.private_key.public_key()
|
383
|
+
|
366
384
|
|
367
385
|
@staticmethod
|
368
386
|
def _compute_hash(data : bytes, method='SHA256'):
|
@@ -717,6 +735,32 @@ class BaseBlockEngine:
|
|
717
735
|
|
718
736
|
"""
|
719
737
|
raise NotImplementedError()
|
738
|
+
|
739
|
+
|
740
|
+
def _get_eth_address(self):
|
741
|
+
"""
|
742
|
+
Returns the Ethereum address for the current pk
|
743
|
+
|
744
|
+
Returns
|
745
|
+
-------
|
746
|
+
eth_address : str
|
747
|
+
the Ethereum address.
|
748
|
+
|
749
|
+
"""
|
750
|
+
raise NotImplementedError()
|
751
|
+
|
752
|
+
|
753
|
+
def _get_eth_acccount(self):
|
754
|
+
"""
|
755
|
+
Returns the Ethereum account for the current sk
|
756
|
+
|
757
|
+
Returns
|
758
|
+
-------
|
759
|
+
eth_account : str
|
760
|
+
the Ethereum account.
|
761
|
+
|
762
|
+
"""
|
763
|
+
raise NotImplementedError()
|
720
764
|
|
721
765
|
|
722
766
|
|
@@ -1045,3 +1089,15 @@ class BaseBlockEngine:
|
|
1045
1089
|
"""
|
1046
1090
|
raise NotImplementedError()
|
1047
1091
|
|
1092
|
+
|
1093
|
+
### Ethereum
|
1094
|
+
|
1095
|
+
@property
|
1096
|
+
def eth_address(self):
|
1097
|
+
return self.__eth_address
|
1098
|
+
|
1099
|
+
@property
|
1100
|
+
def eth_account(self):
|
1101
|
+
return self.__eth_account
|
1102
|
+
|
1103
|
+
### end Ethereum
|
naeural_client/bc/ec.py
CHANGED
@@ -11,6 +11,11 @@ from cryptography.hazmat.backends import default_backend
|
|
11
11
|
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
|
12
12
|
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
|
13
13
|
|
14
|
+
from web3 import Web3
|
15
|
+
from eth_account import Account
|
16
|
+
from eth_utils import keccak, to_checksum_address
|
17
|
+
from eth_account.messages import encode_defunct
|
18
|
+
|
14
19
|
from .base import BaseBlockEngine, VerifyMessage, BCct
|
15
20
|
|
16
21
|
|
@@ -18,6 +23,7 @@ from .base import BaseBlockEngine, VerifyMessage, BCct
|
|
18
23
|
class BaseBCEllipticCurveEngine(BaseBlockEngine):
|
19
24
|
MAX_ADDRESS_VALUE = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
|
20
25
|
|
26
|
+
|
21
27
|
def _get_pk(self, private_key : ec.EllipticCurvePrivateKey) -> ec.EllipticCurvePublicKey:
|
22
28
|
"""
|
23
29
|
Simple wrapper to generate pk from sk
|
@@ -233,6 +239,7 @@ class BaseBCEllipticCurveEngine(BaseBlockEngine):
|
|
233
239
|
data=bpublic_key
|
234
240
|
)
|
235
241
|
return public_key
|
242
|
+
|
236
243
|
|
237
244
|
def __derive_shared_key(self, peer_public_key : str, info : str = BCct.DEFAULT_INFO, debug : bool = False):
|
238
245
|
"""
|
@@ -266,6 +273,7 @@ class BaseBCEllipticCurveEngine(BaseBlockEngine):
|
|
266
273
|
if debug:
|
267
274
|
print('derived-shared_key: ', base64.b64encode(derived_key))
|
268
275
|
return derived_key
|
276
|
+
|
269
277
|
|
270
278
|
def encrypt(
|
271
279
|
self,
|
@@ -380,5 +388,140 @@ class BaseBCEllipticCurveEngine(BaseBlockEngine):
|
|
380
388
|
|
381
389
|
result = plaintext.decode()
|
382
390
|
except Exception as exc:
|
391
|
+
if debug:
|
392
|
+
self.P("Error decrypting from <{}> (compressed_flag `{}`): {}".format(
|
393
|
+
sender_address, compressed_flag, exc), color='r'
|
394
|
+
)
|
383
395
|
result = None
|
384
|
-
return result
|
396
|
+
return result
|
397
|
+
|
398
|
+
|
399
|
+
|
400
|
+
### ETH
|
401
|
+
|
402
|
+
def _get_eth_address(self, pk=None):
|
403
|
+
if pk is None:
|
404
|
+
pk = self.public_key
|
405
|
+
raw_public_key = pk.public_numbers()
|
406
|
+
|
407
|
+
# Compute Ethereum-compatible address
|
408
|
+
x = raw_public_key.x.to_bytes(32, 'big')
|
409
|
+
y = raw_public_key.y.to_bytes(32, 'big')
|
410
|
+
uncompressed_key = b'\x04' + x + y
|
411
|
+
keccak_hash = keccak(uncompressed_key[1:]) # Remove 0x04 prefix
|
412
|
+
eth_address = "0x" + keccak_hash[-20:].hex()
|
413
|
+
eth_address = to_checksum_address(eth_address)
|
414
|
+
return eth_address
|
415
|
+
|
416
|
+
def _get_eth_account(self):
|
417
|
+
private_key_bytes = self.private_key.private_numbers().private_value.to_bytes(32, 'big')
|
418
|
+
return Account.from_key(private_key_bytes)
|
419
|
+
|
420
|
+
|
421
|
+
def node_address_to_eth_address(self, address):
|
422
|
+
"""
|
423
|
+
Converts a node address to an Ethereum address.
|
424
|
+
|
425
|
+
Parameters
|
426
|
+
----------
|
427
|
+
address : str
|
428
|
+
The node address convert.
|
429
|
+
|
430
|
+
Returns
|
431
|
+
-------
|
432
|
+
str
|
433
|
+
The Ethereum address.
|
434
|
+
"""
|
435
|
+
public_key = self._address_to_pk(address)
|
436
|
+
return self._get_eth_address(pk=public_key)
|
437
|
+
|
438
|
+
|
439
|
+
|
440
|
+
def eth_hash_message(self, types, values, as_hex=False):
|
441
|
+
"""
|
442
|
+
Hashes a message using the keccak256 algorithm.
|
443
|
+
|
444
|
+
Parameters
|
445
|
+
----------
|
446
|
+
types : list
|
447
|
+
The types of the values.
|
448
|
+
|
449
|
+
values : list of any
|
450
|
+
The values to hash.
|
451
|
+
|
452
|
+
Returns
|
453
|
+
-------
|
454
|
+
bytes
|
455
|
+
The hash of the message in hexadecimal format.
|
456
|
+
"""
|
457
|
+
message = Web3.solidity_keccak(types, values)
|
458
|
+
if as_hex:
|
459
|
+
return message.hex()
|
460
|
+
return message
|
461
|
+
|
462
|
+
|
463
|
+
def eth_sign_message(self, types, values):
|
464
|
+
"""
|
465
|
+
Signs a message using the private key.
|
466
|
+
|
467
|
+
Parameters
|
468
|
+
----------
|
469
|
+
types : list
|
470
|
+
The types of the values.
|
471
|
+
|
472
|
+
values : list of any
|
473
|
+
The values to sign.
|
474
|
+
|
475
|
+
Returns
|
476
|
+
-------
|
477
|
+
str
|
478
|
+
The signature of the message.
|
479
|
+
"""
|
480
|
+
message_hash = self.eth_hash_message(types, values, as_hex=False)
|
481
|
+
signable_message = encode_defunct(primitive=message_hash)
|
482
|
+
signed_message = Account.sign_message(signable_message, private_key=self.eth_account.key)
|
483
|
+
if hasattr(signed_message, "message_hash"): # backward compatibility
|
484
|
+
signed_message_hash = signed_message.message_hash
|
485
|
+
else:
|
486
|
+
signed_message_hash = signed_message.messageHash
|
487
|
+
return {
|
488
|
+
"message_hash": message_hash.hex(),
|
489
|
+
"r": hex(signed_message.r),
|
490
|
+
"s": hex(signed_message.s),
|
491
|
+
"v": signed_message.v,
|
492
|
+
"signature": signed_message.signature.hex(),
|
493
|
+
"signed_message": signed_message_hash.hex(),
|
494
|
+
"sender" : self.eth_address,
|
495
|
+
}
|
496
|
+
|
497
|
+
def eth_sign_node_epochs(self, node, epochs, epochs_vals, signature_only=True):
|
498
|
+
"""
|
499
|
+
Signs the node availability
|
500
|
+
|
501
|
+
Parameters
|
502
|
+
----------
|
503
|
+
node : str
|
504
|
+
The node address.
|
505
|
+
|
506
|
+
epochs : list of int
|
507
|
+
The epochs to sign.
|
508
|
+
|
509
|
+
epochs_vals : list of int
|
510
|
+
The values for each epoch.
|
511
|
+
|
512
|
+
signature_only : bool, optional
|
513
|
+
Whether to return only the signature. The default is True.
|
514
|
+
|
515
|
+
Returns
|
516
|
+
-------
|
517
|
+
str
|
518
|
+
The signature of the message.
|
519
|
+
"""
|
520
|
+
types = ["string", "uint256[]", "uint256[]"]
|
521
|
+
values = [node, epochs, epochs_vals]
|
522
|
+
result = self.eth_sign_message(types, values)
|
523
|
+
if signature_only:
|
524
|
+
return result["signature"]
|
525
|
+
return result
|
526
|
+
|
527
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import argparse
|
2
|
+
|
3
|
+
from naeural_client.utils.config import maybe_init_config, log_with_color
|
4
|
+
from naeural_client.cli.cli_commands import CLI_COMMANDS
|
5
|
+
|
6
|
+
from naeural_client import version
|
7
|
+
|
8
|
+
def build_parser():
|
9
|
+
"""
|
10
|
+
Dynamically builds the argument parser based on CLI_COMMANDS.
|
11
|
+
|
12
|
+
Returns
|
13
|
+
-------
|
14
|
+
argparse.ArgumentParser
|
15
|
+
Configured argument parser.
|
16
|
+
"""
|
17
|
+
descr = f"nepctl v{version} - CLI for Naeural Edge Protocol SDK package"
|
18
|
+
|
19
|
+
|
20
|
+
parser = argparse.ArgumentParser(description=descr)
|
21
|
+
subparsers = parser.add_subparsers(dest="command", help="Available commands")
|
22
|
+
|
23
|
+
# Iterate over top-level commands
|
24
|
+
for command, subcommands in CLI_COMMANDS.items():
|
25
|
+
command_parser = subparsers.add_parser(command, help=f"{command} commands")
|
26
|
+
if isinstance(subcommands, dict): # Nested subcommands
|
27
|
+
command_subparsers = command_parser.add_subparsers(dest="subcommand")
|
28
|
+
for subcommand, func in subcommands.items():
|
29
|
+
subcommand_parser = command_subparsers.add_parser(
|
30
|
+
subcommand, help=f"{subcommand} command"
|
31
|
+
)
|
32
|
+
subcommand_parser.set_defaults(func=func)
|
33
|
+
else:
|
34
|
+
command_parser.set_defaults(func=subcommands)
|
35
|
+
|
36
|
+
return parser
|
37
|
+
|
38
|
+
def main():
|
39
|
+
maybe_init_config()
|
40
|
+
parser = build_parser()
|
41
|
+
args = parser.parse_args()
|
42
|
+
if hasattr(args, "func"):
|
43
|
+
args.func() # Call the dynamically loaded function
|
44
|
+
else:
|
45
|
+
parser.print_help()
|
46
|
+
|
47
|
+
if __name__ == "__main__":
|
48
|
+
main()
|
@@ -0,0 +1,15 @@
|
|
1
|
+
from naeural_client.cli.nodes import get_nodes, get_supervisors
|
2
|
+
from naeural_client.utils.config import show_config, reset_config
|
3
|
+
|
4
|
+
|
5
|
+
# Define the available commands
|
6
|
+
CLI_COMMANDS = {
|
7
|
+
"get": {
|
8
|
+
"nodes": get_nodes,
|
9
|
+
"supervisors": get_supervisors,
|
10
|
+
},
|
11
|
+
"config": {
|
12
|
+
"show": show_config,
|
13
|
+
"reset": reset_config,
|
14
|
+
},
|
15
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
from naeural_client.utils.config import log_with_color
|
2
|
+
|
3
|
+
|
4
|
+
def get_nodes():
|
5
|
+
"""
|
6
|
+
This function is used to get the information about the nodes and it will perform the following:
|
7
|
+
|
8
|
+
1. Create a Session object.
|
9
|
+
2. Wait for the first net mon message via Session and show progress.
|
10
|
+
3. Wait for the second net mon message via Session and show progress.
|
11
|
+
4. Get the active nodes union via Session and display the nodes marking those peered vs non-peered.
|
12
|
+
"""
|
13
|
+
log_with_color("Getting nodes information", color="b")
|
14
|
+
return
|
15
|
+
|
16
|
+
|
17
|
+
def get_supervisors():
|
18
|
+
"""
|
19
|
+
This function is used to get the information about the supervisors.
|
20
|
+
"""
|
21
|
+
log_with_color("Getting supervisors information", color='b')
|
22
|
+
return
|
@@ -78,7 +78,8 @@ class BaseLogger(object):
|
|
78
78
|
DEBUG=True,
|
79
79
|
data_config_subfolder=None,
|
80
80
|
check_additional_configs=False,
|
81
|
-
append_spaces=True,
|
81
|
+
append_spaces=True,
|
82
|
+
silent=False,
|
82
83
|
default_color='n',
|
83
84
|
):
|
84
85
|
|
@@ -91,6 +92,7 @@ class BaseLogger(object):
|
|
91
92
|
self.no_folders_no_save = no_folders_no_save
|
92
93
|
self.max_lines = max_lines
|
93
94
|
self.HTML = HTML
|
95
|
+
self.silent = silent
|
94
96
|
self.DEBUG = DEBUG
|
95
97
|
self.log_suffix = lib_name
|
96
98
|
self.default_color = default_color
|
@@ -145,13 +147,15 @@ class BaseLogger(object):
|
|
145
147
|
|
146
148
|
# START: bundling -- se also properties
|
147
149
|
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
|
150
|
+
if not self.silent:
|
148
151
|
print(' Running in a PyInstaller bundle')
|
149
|
-
|
150
|
-
|
152
|
+
self.__is_bundled = True
|
153
|
+
self.__bundle_path = sys._MEIPASS
|
151
154
|
else:
|
155
|
+
if not self.silent:
|
152
156
|
print(' Running in a normal Python process')
|
153
|
-
|
154
|
-
|
157
|
+
self.__is_bundled = False
|
158
|
+
self.__bundle_path = None
|
155
159
|
# END: bundling -- se also properties
|
156
160
|
|
157
161
|
self.analyze_processor_platform()
|
@@ -187,7 +191,7 @@ class BaseLogger(object):
|
|
187
191
|
color='green',
|
188
192
|
boxed=True,
|
189
193
|
)
|
190
|
-
self.
|
194
|
+
self.P(" Timezone: {}.".format(self.timezone),color='green')
|
191
195
|
|
192
196
|
|
193
197
|
if self.DEBUG:
|
@@ -634,10 +638,10 @@ class BaseLogger(object):
|
|
634
638
|
|
635
639
|
|
636
640
|
|
637
|
-
def _logger(self, logstr, show=
|
641
|
+
def _logger(self, logstr, show=None, noprefix=False, show_time=False, color=None):
|
638
642
|
"""
|
639
643
|
log processing method
|
640
|
-
"""
|
644
|
+
"""
|
641
645
|
with self.managed_lock_logger():
|
642
646
|
# now that we have locking in place we no longer need to cancel in-thread logging
|
643
647
|
# if not self.is_main_thread:
|
@@ -722,7 +726,9 @@ class BaseLogger(object):
|
|
722
726
|
# endfor
|
723
727
|
return
|
724
728
|
|
725
|
-
def _add_log(self, logstr, show=
|
729
|
+
def _add_log(self, logstr, show=None, noprefix=False, show_time=False, color=None):
|
730
|
+
if show is None:
|
731
|
+
show = not self.silent
|
726
732
|
if type(logstr) != str:
|
727
733
|
logstr = str(logstr)
|
728
734
|
if logstr == "":
|
@@ -741,23 +747,24 @@ class BaseLogger(object):
|
|
741
747
|
logstr = logstr[1:]
|
742
748
|
prefix = "\n" + prefix
|
743
749
|
res_log = logstr
|
744
|
-
if len(logstr) == 0 or logstr[0] != '[':
|
750
|
+
if (len(logstr) == 0 or logstr[0] != '[') and not noprefix:
|
745
751
|
prefix = prefix + ' '
|
746
752
|
logstr = prefix + logstr
|
747
753
|
if show_time:
|
748
754
|
logstr += " [{:.2f}s]".format(elapsed)
|
749
755
|
print_logstr = logstr
|
756
|
+
if color is None:
|
757
|
+
color = self.default_color
|
758
|
+
if not self.__first_print and show:
|
759
|
+
if not self.silent:
|
760
|
+
BaseLogger.print_color("<Logging with default color: {}>".format(color), color=color)
|
761
|
+
self.__first_print = True
|
750
762
|
if show:
|
751
763
|
if self.append_spaces:
|
752
764
|
spaces = " " * max(60 - len(print_logstr), 0)
|
753
765
|
else:
|
754
766
|
spaces = ''
|
755
767
|
print_logstr = print_logstr + spaces
|
756
|
-
if color is None:
|
757
|
-
color = self.default_color
|
758
|
-
if not self.__first_print:
|
759
|
-
BaseLogger.print_color("<Logging with default color: {}>".format(color), color=color)
|
760
|
-
self.__first_print = True
|
761
768
|
#endif use default color
|
762
769
|
BaseLogger.print_color(print_logstr, color=color)
|
763
770
|
if color.lower()[0] in ['e', 'r']:
|
@@ -841,16 +848,36 @@ class BaseLogger(object):
|
|
841
848
|
)
|
842
849
|
return
|
843
850
|
|
844
|
-
def verbose_log(self, str_msg, show_time=False, noprefix=False, color=None):
|
851
|
+
def verbose_log(self, str_msg, show_time=False, noprefix=False, color=None, show=None):
|
845
852
|
return self._logger(
|
846
853
|
str_msg,
|
847
|
-
show=
|
854
|
+
show=show,
|
848
855
|
show_time=show_time,
|
849
856
|
noprefix=noprefix, color=color
|
850
857
|
)
|
851
858
|
|
852
|
-
def P(
|
853
|
-
|
859
|
+
def P(
|
860
|
+
self,
|
861
|
+
str_msg,
|
862
|
+
show_time=False,
|
863
|
+
noprefix=False,
|
864
|
+
color=None,
|
865
|
+
boxed=False,
|
866
|
+
show=None,
|
867
|
+
**kwargs
|
868
|
+
):
|
869
|
+
"""
|
870
|
+
Will print & log a message. If show is None it will be set to not self.silent.
|
871
|
+
"""
|
872
|
+
return self.p(
|
873
|
+
str_msg,
|
874
|
+
show_time=show_time,
|
875
|
+
noprefix=noprefix,
|
876
|
+
color=color,
|
877
|
+
boxed=boxed,
|
878
|
+
show=show,
|
879
|
+
**kwargs
|
880
|
+
)
|
854
881
|
|
855
882
|
def D(self, str_msg, show_time=False, noprefix=False, color=None, **kwargs):
|
856
883
|
if False:
|
@@ -891,17 +918,18 @@ class BaseLogger(object):
|
|
891
918
|
|
892
919
|
return msg
|
893
920
|
|
894
|
-
def p(self, str_msg, show_time=False, noprefix=False, color=None, boxed=False, **kwargs):
|
921
|
+
def p(self, str_msg, show_time=False, noprefix=False, color=None, boxed=False, show=None, **kwargs):
|
895
922
|
if boxed:
|
896
923
|
msg = self.__convert_to_box(str_msg, **kwargs)
|
897
|
-
self._logger(msg, show=
|
924
|
+
self._logger(msg, show=show, noprefix=noprefix, color=color)
|
898
925
|
else:
|
899
926
|
return self._logger(
|
900
927
|
str_msg,
|
901
|
-
show=
|
928
|
+
show=show,
|
902
929
|
show_time=show_time,
|
903
930
|
noprefix=noprefix, color=color
|
904
931
|
)
|
932
|
+
|
905
933
|
|
906
934
|
def Pmd(self, s=''):
|
907
935
|
print_func = None
|
@@ -955,10 +983,10 @@ class BaseLogger(object):
|
|
955
983
|
if type(str_text) != str:
|
956
984
|
str_text = str(str_text)
|
957
985
|
str_final = str_msg + "\n" + textwrap.indent(str_text, n * " ")
|
958
|
-
self._logger(str_final, show=
|
986
|
+
self._logger(str_final, show=None, show_time=False)
|
959
987
|
return
|
960
988
|
|
961
|
-
def log(self, str_msg, show=
|
989
|
+
def log(self, str_msg, show=None, show_time=False, color=None):
|
962
990
|
return self._logger(str_msg, show=show, show_time=show_time, color=color)
|
963
991
|
|
964
992
|
def _generate_log_path(self):
|
@@ -1037,7 +1065,8 @@ class BaseLogger(object):
|
|
1037
1065
|
self._app_folder = self.config_data["APP_FOLDER"]
|
1038
1066
|
#endif no defaults for base/app folders
|
1039
1067
|
|
1040
|
-
|
1068
|
+
if not self.silent:
|
1069
|
+
print("Loaded config [{}]".format(config_file), flush=True)
|
1041
1070
|
self.config_file = config_file
|
1042
1071
|
else:
|
1043
1072
|
self.config_data = {
|
@@ -1045,6 +1074,8 @@ class BaseLogger(object):
|
|
1045
1074
|
'APP_FOLDER' : self._app_folder
|
1046
1075
|
}
|
1047
1076
|
self.config_file = "default_config.txt"
|
1077
|
+
if not self.silent:
|
1078
|
+
print("No config file provided. Using default config.", flush=True)
|
1048
1079
|
#endif have or not config file
|
1049
1080
|
|
1050
1081
|
self.config_data = {
|
@@ -1053,13 +1084,18 @@ class BaseLogger(object):
|
|
1053
1084
|
}
|
1054
1085
|
|
1055
1086
|
matches = self.replace_secrets(self.config_data)
|
1056
|
-
|
1087
|
+
if not self.silent:
|
1088
|
+
if len(matches) > 0:
|
1089
|
+
print(" Config modified with following env vars: {}".format(matches))
|
1090
|
+
else:
|
1091
|
+
print(" No secrets/template found in config")
|
1057
1092
|
|
1058
1093
|
self._base_folder = self.expand_tilda(self._base_folder)
|
1059
1094
|
self._base_folder = self._get_cloud_base_folder(self._base_folder)
|
1060
1095
|
self._root_folder = os.path.abspath(self._base_folder)
|
1061
1096
|
self._base_folder = os.path.join(self._base_folder, self._app_folder)
|
1062
|
-
|
1097
|
+
if not self.silent:
|
1098
|
+
print("BASE: {}".format(self._base_folder), flush=True)
|
1063
1099
|
|
1064
1100
|
self._normalize_path_sep()
|
1065
1101
|
|
@@ -41,6 +41,7 @@ class Logger(
|
|
41
41
|
max_lines=None,
|
42
42
|
HTML=False,
|
43
43
|
DEBUG=True,
|
44
|
+
silent=False,
|
44
45
|
data_config_subfolder=None,
|
45
46
|
check_additional_configs=False,
|
46
47
|
default_color='n',
|
@@ -58,6 +59,7 @@ class Logger(
|
|
58
59
|
max_lines=max_lines,
|
59
60
|
HTML=HTML,
|
60
61
|
DEBUG=DEBUG,
|
62
|
+
silent=silent,
|
61
63
|
data_config_subfolder=data_config_subfolder,
|
62
64
|
check_additional_configs=check_additional_configs,
|
63
65
|
default_color=default_color,
|
@@ -0,0 +1,130 @@
|
|
1
|
+
import os
|
2
|
+
from pathlib import Path
|
3
|
+
import shutil
|
4
|
+
|
5
|
+
ENV_TEMPLATE = """
|
6
|
+
|
7
|
+
EE_MQTT_HOST=r9092118.ala.eu-central-1.emqxsl.com
|
8
|
+
EE_MQTT_PORT=8883
|
9
|
+
EE_MQTT_USER=
|
10
|
+
EE_MQTT=
|
11
|
+
|
12
|
+
EE_SECURED=true
|
13
|
+
|
14
|
+
TARGET_NODE=
|
15
|
+
"""
|
16
|
+
|
17
|
+
def log_with_color(s, color='n'):
|
18
|
+
"""
|
19
|
+
Prints the string `s` to the console in the specified color.
|
20
|
+
|
21
|
+
Parameters
|
22
|
+
----------
|
23
|
+
s : str
|
24
|
+
The string to be logged.
|
25
|
+
color : str, optional
|
26
|
+
The color code:
|
27
|
+
'r' for red, 'g' for green, 'y' for yellow,
|
28
|
+
'b' for blue, 'w' for light white, 'n' for dark white (default).
|
29
|
+
"""
|
30
|
+
color_codes = {
|
31
|
+
'r': '\033[31m', # Red
|
32
|
+
'g': '\033[32m', # Green
|
33
|
+
'y': '\033[33m', # Yellow
|
34
|
+
'b': '\033[34m', # Blue
|
35
|
+
'w': '\033[97m', # Light white
|
36
|
+
'n': '\033[37m', # Dark white (default)
|
37
|
+
}
|
38
|
+
|
39
|
+
reset_code = '\033[0m' # Reset color
|
40
|
+
color_code = color_codes.get(color, color_codes['n'])
|
41
|
+
print(f"{color_code}{s}{reset_code}", flush=True)
|
42
|
+
|
43
|
+
|
44
|
+
def get_user_folder():
|
45
|
+
"""
|
46
|
+
Returns the user folder.
|
47
|
+
"""
|
48
|
+
return Path.home() / ".naeural"
|
49
|
+
|
50
|
+
def get_user_config_file():
|
51
|
+
"""
|
52
|
+
Returns the user configuration file.
|
53
|
+
"""
|
54
|
+
return get_user_folder() / "config"
|
55
|
+
|
56
|
+
def reset_config():
|
57
|
+
"""
|
58
|
+
Resets the configuration by creating a ~/.naeural folder and populating
|
59
|
+
~/.naeural/config with values from a local .env file, if it exists.
|
60
|
+
"""
|
61
|
+
# Define the target config folder and file
|
62
|
+
config_dir = get_user_folder()
|
63
|
+
config_file = get_user_config_file()
|
64
|
+
|
65
|
+
# Create the ~/.naeural folder if it doesn't exist
|
66
|
+
config_dir.mkdir(parents=True, exist_ok=True)
|
67
|
+
|
68
|
+
# Check if the current folder has a .env file
|
69
|
+
current_env_file = Path(".env")
|
70
|
+
if current_env_file.exists():
|
71
|
+
# Copy .env content to ~/.naeural/config
|
72
|
+
shutil.copy(current_env_file, config_file)
|
73
|
+
log_with_color(f"Configuration has been reset using {current_env_file} into {config_file}", color='y')
|
74
|
+
else:
|
75
|
+
# Create an empty config file
|
76
|
+
with config_file.open("wt") as file:
|
77
|
+
file.write(ENV_TEMPLATE)
|
78
|
+
log_with_color(f"Configuration has been reset to default in {config_file}:\n{ENV_TEMPLATE}", color='y')
|
79
|
+
|
80
|
+
|
81
|
+
def show_config():
|
82
|
+
"""
|
83
|
+
Displays the current configuration from ~/.naeural/config.
|
84
|
+
"""
|
85
|
+
config_file = get_user_config_file()
|
86
|
+
|
87
|
+
if config_file.exists():
|
88
|
+
log_with_color(f"Current configuration ({config_file}):")
|
89
|
+
with config_file.open("r") as file:
|
90
|
+
log_with_color(file.read())
|
91
|
+
else:
|
92
|
+
log_with_color(f"No configuration found at {config_file}. Please run `reset_config` first.", color="r")
|
93
|
+
return
|
94
|
+
|
95
|
+
|
96
|
+
def load_user_defined_config(verbose=False):
|
97
|
+
"""
|
98
|
+
Loads the ~/.naeural/config file into the current environment.
|
99
|
+
"""
|
100
|
+
config_file = get_user_config_file()
|
101
|
+
result = False
|
102
|
+
|
103
|
+
if config_file.exists():
|
104
|
+
with config_file.open("r") as file:
|
105
|
+
for line in file:
|
106
|
+
# Ignore comments and empty lines
|
107
|
+
if line.strip() and not line.strip().startswith("#"):
|
108
|
+
key, value = line.strip().split("=", 1)
|
109
|
+
value = value.strip()
|
110
|
+
# if at least one key-value pair is found, set the result to True
|
111
|
+
if value != "":
|
112
|
+
result = True
|
113
|
+
os.environ[key.strip()] = value
|
114
|
+
if verbose:
|
115
|
+
log_with_color(f"Configuration from {config_file} has been loaded into the environment.", color='b')
|
116
|
+
else:
|
117
|
+
if verbose:
|
118
|
+
log_with_color(f"No configuration file found at {config_file}. Please run `reset_config` first.", color="r")
|
119
|
+
return result
|
120
|
+
|
121
|
+
|
122
|
+
def maybe_init_config():
|
123
|
+
"""
|
124
|
+
Initializes the configuration if it doesn't exist yet.
|
125
|
+
"""
|
126
|
+
config_file = get_user_config_file()
|
127
|
+
|
128
|
+
if not config_file.exists():
|
129
|
+
reset_config()
|
130
|
+
load_user_defined_config()
|
@@ -1,10 +1,10 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: naeural_client
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.3.1
|
4
4
|
Summary: `naeural_client` is the Python SDK required for client app development for the Naeural Edge Protocol Edge Protocol framework
|
5
|
-
Project-URL: Homepage, https://github.com/
|
6
|
-
Project-URL: Bug Tracker, https://github.com/
|
7
|
-
Author-email:
|
5
|
+
Project-URL: Homepage, https://github.com/NaeuralEdgeProtocol/naeural_client
|
6
|
+
Project-URL: Bug Tracker, https://github.com/NaeuralEdgeProtocol/naeural_client/issues
|
7
|
+
Author-email: Andrei Ionut Damian <andrei.damian@me.com>, Cristan Bleotiu <cristibleotiu@gmail.com>, Stefan Saraev <saraevstefan@gmail.com>
|
8
8
|
Classifier: License :: OSI Approved :: MIT License
|
9
9
|
Classifier: Operating System :: OS Independent
|
10
10
|
Classifier: Programming Language :: Python :: 3
|
@@ -16,6 +16,7 @@ Requires-Dist: pika
|
|
16
16
|
Requires-Dist: pyaml
|
17
17
|
Requires-Dist: pyopenssl>=23.0.0
|
18
18
|
Requires-Dist: python-dateutil
|
19
|
+
Requires-Dist: web3
|
19
20
|
Description-Content-Type: text/markdown
|
20
21
|
|
21
22
|
# naeural_client SDK
|
@@ -1,10 +1,10 @@
|
|
1
1
|
naeural_client/__init__.py,sha256=UKEDGS0wFYyxwmhEAKJGecO2vYbIfRYUP4SQgnK10IE,578
|
2
|
-
naeural_client/_ver.py,sha256=
|
3
|
-
naeural_client/base_decentra_object.py,sha256=
|
2
|
+
naeural_client/_ver.py,sha256=31pw4Zp2s9RPTWeYsyGqbi2Dc3lW0dqZ4WsTZckfaww,330
|
3
|
+
naeural_client/base_decentra_object.py,sha256=wXjl65gWxxkhV6Tq48wFfNGITvdYdkKPT-wLurGB5vc,4287
|
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=I1M2dxFMWe6FVxOs_n54DjYpWDIRGn9UJOqWo0YdBjA,77367
|
8
8
|
naeural_client/base/instance.py,sha256=kcZJmjLBtx8Bjj_ysIOx1JmLA-qSpG7E28j5rq6IYus,20444
|
9
9
|
naeural_client/base/pipeline.py,sha256=KwcPWD2XMvHotWFMpcnIycFhqiNnZuyUTUWiLU0PM5Y,57519
|
10
10
|
naeural_client/base/plugin_template.py,sha256=qGaXByd_JZFpjvH9GXNbT7KaitRxIJB6-1IhbKrZjq4,138123
|
@@ -13,11 +13,15 @@ naeural_client/base/transaction.py,sha256=bfs6td5M0fINgPQNxhrl_AUjb1YiilLDQ-Cd_o
|
|
13
13
|
naeural_client/base/payload/__init__.py,sha256=y8fBI8tG2ObNfaXFWjyWZXwu878FRYj_I8GIbHT4GKE,29
|
14
14
|
naeural_client/base/payload/payload.py,sha256=v50D7mBBD2WwWzvpbRGMSr-X6vv5ie21IY1aDxTqe1c,2275
|
15
15
|
naeural_client/bc/__init__.py,sha256=FQj23D1PrY06NUOARiKQi4cdj0-VxnoYgYDEht8lpr8,158
|
16
|
-
naeural_client/bc/base.py,sha256=
|
16
|
+
naeural_client/bc/base.py,sha256=GI9CbI2RVgIBXpOoRjrhXt45tONlBDMrybX_BcL3_Os,29513
|
17
17
|
naeural_client/bc/chain.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
18
|
-
naeural_client/bc/ec.py,sha256=
|
18
|
+
naeural_client/bc/ec.py,sha256=raIGI7BpSH8xU_Bg7RpKv9KEW3F6PuAdL5miZfvw7iI,14027
|
19
19
|
naeural_client/certs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
20
20
|
naeural_client/certs/r9092118.ala.eu-central-1.emqxsl.com.crt,sha256=y-6io0tseyx9-a4Pmde1z1gPULtJNSYUpG_YFkYaMKU,1337
|
21
|
+
naeural_client/cli/README.md,sha256=WPdI_EjzAbUW1aPyj1sSR8rLydcJKZtoiaEtklQrjHo,74
|
22
|
+
naeural_client/cli/cli.py,sha256=eKzO8hu_436e3svGPNSpn6q4EiEcaTIKPhgn5QOJJVw,1426
|
23
|
+
naeural_client/cli/cli_commands.py,sha256=NluWqnsyuabu0EKNM6MDUBtnfloH7oqCOrkfJs8Ajjk,353
|
24
|
+
naeural_client/cli/nodes.py,sha256=y3yKKLzyZe-zu4H-cgqDqmZ8jt1s4RA6QdqeUD7z4i0,713
|
21
25
|
naeural_client/code_cheker/__init__.py,sha256=pwkdeZGVL16ZA4Qf2mRahEhoOvKhL7FyuQbMFLr1E5M,33
|
22
26
|
naeural_client/code_cheker/base.py,sha256=lT5DRIFO5rqzsMNCmdMRfkAeevmezozehyfgmhnKpuI,19074
|
23
27
|
naeural_client/code_cheker/checker.py,sha256=QWupeM7ToancVIq1tRUxRNUrI8B5l5eoY0kDU4-O5aE,7365
|
@@ -52,8 +56,8 @@ naeural_client/io_formatter/default/a_dummy.py,sha256=qr9eUizQ-NN5jdXVzkaZKMaf9K
|
|
52
56
|
naeural_client/io_formatter/default/aixp1.py,sha256=MX0TeUR4APA-qN3vUC6uzcz8Pssz5lgrQWo7td5Ri1A,3052
|
53
57
|
naeural_client/io_formatter/default/default.py,sha256=gEy78cP2D5s0y8vQh4aHuxqz7D10gGfuiKF311QhrpE,494
|
54
58
|
naeural_client/logging/__init__.py,sha256=b79X45VC6c37u32flKB2GAK9f-RR0ocwP0JDCy0t7QQ,33
|
55
|
-
naeural_client/logging/base_logger.py,sha256=
|
56
|
-
naeural_client/logging/small_logger.py,sha256=
|
59
|
+
naeural_client/logging/base_logger.py,sha256=IEhDnR6vn_nMBE4OwzUHO_71wuvAtCXjHHx4yeRxm6s,65880
|
60
|
+
naeural_client/logging/small_logger.py,sha256=m12hCb_H4XifJYYfgCAOUDkcXm-h4pSODnFf277OFVI,2937
|
57
61
|
naeural_client/logging/logger_mixins/__init__.py,sha256=yQO7umlRvz63FeWpi-F9GRmC_MOHcNW6R6pwvZZBy3A,600
|
58
62
|
naeural_client/logging/logger_mixins/class_instance_mixin.py,sha256=xUXE2VZgmrlrSrvw0f6GF1jlTnVLeVkIiG0bhlBfq3o,2741
|
59
63
|
naeural_client/logging/logger_mixins/computer_vision_mixin.py,sha256=TrtG7ayM2ab-4jjIkIWAQaFi9cVfiINAWrJCt8mCCFI,13213
|
@@ -74,8 +78,10 @@ naeural_client/logging/tzlocal/win32.py,sha256=zBoj0vFVrGhnCm_f7xmYzGym4-fV-4Ij2
|
|
74
78
|
naeural_client/logging/tzlocal/windows_tz.py,sha256=Sv9okktjZJfRGGUOOppsvQuX_eXyXUxkSKCAFmWT9Hw,34203
|
75
79
|
naeural_client/utils/__init__.py,sha256=mAnke3-MeRzz3nhQvhuHqLnpaaCSmDxicd7Ck9uwpmI,77
|
76
80
|
naeural_client/utils/comm_utils.py,sha256=4cS9llRr_pK_3rNgDcRMCQwYPO0kcNU7AdWy_LtMyCY,1072
|
81
|
+
naeural_client/utils/config.py,sha256=0IngDOJjtopdi06VdtKPRv6qCBOTEt_Ww4l4MIBKhZw,3624
|
77
82
|
naeural_client/utils/dotenv.py,sha256=_AgSo35n7EnQv5yDyu7C7i0kHragLJoCGydHjvOkrYY,2008
|
78
|
-
naeural_client-2.
|
79
|
-
naeural_client-2.
|
80
|
-
naeural_client-2.
|
81
|
-
naeural_client-2.
|
83
|
+
naeural_client-2.3.1.dist-info/METADATA,sha256=qrRjlmz_8n-D5mCQuYYArpPEzcmQ8CY4b0RkUT_VuIM,14449
|
84
|
+
naeural_client-2.3.1.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
|
85
|
+
naeural_client-2.3.1.dist-info/entry_points.txt,sha256=PNdyotDaQBAslZREx5luVyj0kqpQnwNACwkFNTPIHU4,55
|
86
|
+
naeural_client-2.3.1.dist-info/licenses/LICENSE,sha256=cvOsJVslde4oIaTCadabXnPqZmzcBO2f2zwXZRmJEbE,11311
|
87
|
+
naeural_client-2.3.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|