naeural-client 2.6.5__py3-none-any.whl → 2.6.7__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 CHANGED
@@ -1,4 +1,4 @@
1
- __VER__ = "2.6.5"
1
+ __VER__ = "2.6.7"
2
2
 
3
3
  if __name__ == "__main__":
4
4
  with open("pyproject.toml", "rt") as fd:
@@ -50,6 +50,10 @@ class GenericSession(BaseDecentrAIObject):
50
50
  A Session manages `Pipelines` and handles all messages received from the communication server.
51
51
  The Session handles all callbacks that are user-defined and passed as arguments in the API calls.
52
52
  """
53
+
54
+ START_TIMEOUT = 30
55
+
56
+
53
57
  default_config = {
54
58
  "CONFIG_CHANNEL": {
55
59
  "TOPIC": "{}/{}/config"
@@ -164,7 +168,14 @@ class GenericSession(BaseDecentrAIObject):
164
168
  root_topic : str, optional
165
169
  This is the root of the topics used by the SDK. It is used to create the topics for the communication channels.
166
170
  Defaults to "naeural"
171
+
172
+ auto_configuration : bool, optional
173
+ If True, the SDK will attempt to complete the dauth process automatically.
174
+ Defaults to True.
167
175
  """
176
+
177
+ self.__at_least_one_node_peered = False
178
+ self.__at_least_a_netmon_received = False
168
179
 
169
180
  # TODO: maybe read config from file?
170
181
  self._config = {**self.default_config, **config}
@@ -274,6 +285,7 @@ class GenericSession(BaseDecentrAIObject):
274
285
  dauth_endp=None, # get from consts or env
275
286
  add_env=self.__auto_configuration,
276
287
  debug=False,
288
+ sender_alias='ratio1-SDK'
277
289
  )
278
290
  # end bc_engine
279
291
  # END TODO
@@ -466,21 +478,59 @@ class GenericSession(BaseDecentrAIObject):
466
478
  self._dct_node_addr_name[node_addr] = node_id
467
479
  return
468
480
 
469
- def __track_allowed_node(self, node_addr, dict_msg):
481
+ def __track_allowed_node_by_hb(self, node_addr, dict_msg):
470
482
  """
471
- Track if this session is allowed to send messages to node.
483
+ Track if this session is allowed to send messages to node using hb data
472
484
 
473
485
  Parameters
474
486
  ----------
475
487
  node_addr : str
476
488
  The address of the Naeural Edge Protocol edge node that sent the message.
489
+
477
490
  dict_msg : dict
478
- The message received from the communication server.
491
+ The message received from the communication server as a heartbeat of the object from netconfig
479
492
  """
480
493
  node_whitelist = dict_msg.get(HB.EE_WHITELIST, [])
481
494
  node_secured = dict_msg.get(HB.SECURED, False)
495
+
496
+ client_is_allowed = self.bc_engine.contains_current_address(node_whitelist)
497
+
498
+ self._dct_can_send_to_node[node_addr] = not node_secured or client_is_allowed or self.bc_engine.address == node_addr
499
+ return
500
+
501
+ def __track_allowed_node_by_netmon(self, node_addr, dict_msg):
502
+ """
503
+ Track if this session is allowed to send messages to node using net-mon data
504
+
505
+ Parameters
506
+ ----------
507
+ node_addr : str
508
+ The address of the Naeural Edge Protocol edge node that sent the message.
509
+
510
+ dict_msg : dict
511
+ The message received from the communication server as a heartbeat of the object from netconfig
512
+ """
513
+ node_whitelist = dict_msg.get(PAYLOAD_DATA.NETMON_WHITELIST, [])
514
+ node_secured = dict_msg.get(PAYLOAD_DATA.NETMON_NODE_SECURED, False)
515
+
516
+ client_is_allowed = self.bc_engine.contains_current_address(node_whitelist)
482
517
 
483
- self._dct_can_send_to_node[node_addr] = not node_secured or self.bc_engine.address_no_prefix in node_whitelist or self.bc_engine.address == node_addr
518
+ self._dct_can_send_to_node[node_addr] = not node_secured or client_is_allowed or self.bc_engine.address == node_addr
519
+ return
520
+
521
+
522
+ def __process_node_pipelines(self, node_addr, pipelines):
523
+ """
524
+ Given a list of pipeline configurations, create or update the pipelines for a node.
525
+ """
526
+ for config in pipelines:
527
+ pipeline_name = config[PAYLOAD_DATA.NAME]
528
+ pipeline: Pipeline = self._dct_online_nodes_pipelines[node_addr].get(pipeline_name, None)
529
+ if pipeline is not None:
530
+ pipeline._sync_configuration_with_remote({k.upper(): v for k, v in config.items()})
531
+ else:
532
+ self._dct_online_nodes_pipelines[node_addr][pipeline_name] = self.__create_pipeline_from_config(
533
+ node_addr, config)
484
534
  return
485
535
 
486
536
  def __on_heartbeat(self, dict_msg: dict, msg_node_addr, msg_pipeline, msg_signature, msg_instance):
@@ -516,19 +566,20 @@ class GenericSession(BaseDecentrAIObject):
516
566
 
517
567
  msg_active_configs = dict_msg.get(HB.CONFIG_STREAMS)
518
568
  if msg_active_configs is None:
519
- return
569
+ msg_active_configs = []
570
+ # at this point we dont return if no active configs are present
571
+ # as the protocol should NOT send a heartbeat with active configs to
572
+ # the entire network, only to the interested parties via net-config
520
573
 
521
574
  # default action
522
575
  if msg_node_addr not in self._dct_online_nodes_pipelines:
576
+ # this is ok here although we dont get the pipelines from the heartbeat
523
577
  self._dct_online_nodes_pipelines[msg_node_addr] = {}
524
- for config in msg_active_configs:
525
- pipeline_name = config[PAYLOAD_DATA.NAME]
526
- pipeline: Pipeline = self._dct_online_nodes_pipelines[msg_node_addr].get(pipeline_name, None)
527
- if pipeline is not None:
528
- pipeline._sync_configuration_with_remote({k.upper(): v for k, v in config.items()})
529
- else:
530
- self._dct_online_nodes_pipelines[msg_node_addr][pipeline_name] = self.__create_pipeline_from_config(
531
- msg_node_addr, config)
578
+
579
+ if len(msg_active_configs) > 0:
580
+ # this is for legacy and custom implementation where heartbeats still contain
581
+ # the pipeline configuration.
582
+ self.__process_node_pipelines(msg_node_addr, msg_active_configs)
532
583
 
533
584
  # TODO: move this call in `__on_message_default_callback`
534
585
  if self.__maybe_ignore_message(msg_node_addr):
@@ -543,7 +594,7 @@ class GenericSession(BaseDecentrAIObject):
543
594
 
544
595
  self.D("Received hb from: {}".format(msg_node_addr), verbosity=2)
545
596
 
546
- self.__track_allowed_node(msg_node_addr, dict_msg)
597
+ self.__track_allowed_node_by_hb(msg_node_addr, dict_msg)
547
598
 
548
599
  # call the custom callback, if defined
549
600
  if self.custom_on_heartbeat is not None:
@@ -613,7 +664,8 @@ class GenericSession(BaseDecentrAIObject):
613
664
  self,
614
665
  dict_msg: dict,
615
666
  msg_pipeline : str,
616
- msg_signature : str
667
+ msg_signature : str,
668
+ sender_addr: str,
617
669
  ):
618
670
  REQUIRED_PIPELINE = DEFAULT_PIPELINES.ADMIN_PIPELINE
619
671
  REQUIRED_SIGNATURE = PLUGIN_SIGNATURES.NET_MON_01
@@ -624,6 +676,7 @@ class GenericSession(BaseDecentrAIObject):
624
676
  ee_id = dict_msg.get(PAYLOAD_DATA.EE_ID, None)
625
677
  current_network = dict_msg.get(PAYLOAD_DATA.NETMON_CURRENT_NETWORK, {})
626
678
  if current_network:
679
+ self.__at_least_a_netmon_received = True
627
680
  all_addresses = [
628
681
  x[PAYLOAD_DATA.NETMON_ADDRESS] for x in current_network.values()
629
682
  ]
@@ -633,10 +686,30 @@ class GenericSession(BaseDecentrAIObject):
633
686
  ]
634
687
  self.P(f"Net config from <{sender_addr}> `{ee_id}`: {len(online_addresses)}/{len(all_addresses)}", color='y')
635
688
  self.__current_network_statuses[sender_addr] = current_network
689
+
690
+ for _ , node_data in current_network.items():
691
+ node_addr = node_data.get("address", None)
692
+ if node_addr is not None:
693
+ self.__track_allowed_node_by_netmon(node_addr, node_data)
694
+ nr_peers = sum([v for k, v in self._dct_can_send_to_node.items()])
695
+ if nr_peers > 0 and not self.__at_least_one_node_peered:
696
+ self.__at_least_one_node_peered = True
697
+ self.P(f"Received {PLUGIN_SIGNATURES.NET_MON_01} from {sender_addr}, so far {nr_peers} peers that allow me: {json.dumps(self._dct_can_send_to_node, indent=2)}", color='g')
698
+ # end for each node in network map
636
699
  # end if current_network is valid
637
700
  # end if NET_MON_01
638
701
  return
639
702
 
703
+
704
+ def __maybe_process_net_config(
705
+ self,
706
+ dict_msg: dict,
707
+ msg_pipeline : str,
708
+ msg_signature : str,
709
+ sender_addr: str,
710
+ ):
711
+ return
712
+
640
713
 
641
714
  # TODO: maybe convert dict_msg to Payload object
642
715
  # also maybe strip the dict from useless info for the user of the sdk
@@ -656,12 +729,16 @@ class GenericSession(BaseDecentrAIObject):
656
729
  ----------
657
730
  dict_msg : dict
658
731
  The message received from the communication server
732
+
659
733
  msg_node_addr : str
660
734
  The address of the Naeural Edge Protocol edge node that sent the message.
735
+
661
736
  msg_pipeline : str
662
737
  The name of the pipeline that sent the message.
738
+
663
739
  msg_signature : str
664
740
  The signature of the plugin that sent the message.
741
+
665
742
  msg_instance : str
666
743
  The name of the instance that sent the message.
667
744
  """
@@ -671,7 +748,19 @@ class GenericSession(BaseDecentrAIObject):
671
748
  if self.__maybe_ignore_message(msg_node_addr):
672
749
  return
673
750
 
674
- self.__maybe_process_net_mon(dict_msg, msg_pipeline, msg_signature)
751
+ self.__maybe_process_net_mon(
752
+ dict_msg=dict_msg,
753
+ msg_pipeline=msg_pipeline,
754
+ msg_signature=msg_signature,
755
+ sender_addr=msg_node_addr
756
+ )
757
+
758
+ self.__maybe_process_net_config(
759
+ dict_msg=dict_msg,
760
+ msg_pipeline=msg_pipeline,
761
+ msg_signature=msg_signature,
762
+ sender_addr=msg_node_addr
763
+ )
675
764
 
676
765
  # call the pipeline and instance defined callbacks
677
766
  for pipeline in self.own_pipelines:
@@ -727,6 +816,8 @@ class GenericSession(BaseDecentrAIObject):
727
816
 
728
817
  self.__running_main_loop_thread = True
729
818
  self._main_loop_thread.start()
819
+
820
+ # we could wait here for `self.__at_least_one_node_peered` but is not a good idea
730
821
  return
731
822
 
732
823
  def __handle_open_transactions(self):
@@ -847,10 +938,16 @@ class GenericSession(BaseDecentrAIObject):
847
938
  This method runs on a separate thread from the main thread, and it is responsible for handling all messages received from the communication server.
848
939
  We use it like this to avoid blocking the main thread, which is used by the user.
849
940
  """
941
+ self.__start_main_loop_time = tm()
850
942
  while self.__running_main_loop_thread:
851
943
  self.__maybe_reconnect()
852
944
  self.__handle_open_transactions()
853
945
  sleep(0.1)
946
+ if not self.__at_least_a_netmon_received:
947
+ if (tm() - self.__start_main_loop_time) > self.START_TIMEOUT:
948
+ msg = "Timeout waiting for NET_MON_01 message. Exiting..."
949
+ self.P(msg, color='r', show=True)
950
+ break
854
951
  # end while self.running
855
952
 
856
953
  self.P("Main loop thread exiting...", verbosity=2)
@@ -900,7 +997,7 @@ class GenericSession(BaseDecentrAIObject):
900
997
 
901
998
  return
902
999
 
903
- def sleep(self, wait=True):
1000
+ def sleep(self, wait=True, close_session=True, close_pipelines=False):
904
1001
  """
905
1002
  Sleep for a given amount of time.
906
1003
 
@@ -926,7 +1023,37 @@ class GenericSession(BaseDecentrAIObject):
926
1023
  callable_loop_condition = callable(wait) and wait()
927
1024
  except KeyboardInterrupt:
928
1025
  self.P("CTRL+C detected. Stopping loop.", color='r', verbosity=1)
1026
+
1027
+ if close_session:
1028
+ self.close(close_pipelines, wait_close=True)
929
1029
  return
1030
+
1031
+ def wait(
1032
+ self,
1033
+ seconds=10,
1034
+ close_session_on_timeout=True,
1035
+ close_pipeline_on_timeout=False
1036
+ ):
1037
+ """
1038
+ Wait for a given amount of time.
1039
+
1040
+ Parameters
1041
+ ----------
1042
+ seconds : int, float, optional
1043
+ The amount of time to wait, by default 10
1044
+
1045
+ close_session_on_timeout : bool, optional
1046
+ If `True`, will close the session when the time is up, by default True
1047
+
1048
+ close_pipeline_on_timeout : bool, optional
1049
+ If `True`, will close the pipelines when the time is up, by default False
1050
+ """
1051
+ self.run(
1052
+ wait=seconds,
1053
+ close_session=close_session_on_timeout,
1054
+ close_pipelines=close_pipeline_on_timeout
1055
+ )
1056
+ return
930
1057
 
931
1058
  # Utils
932
1059
  if True:
@@ -2352,6 +2479,7 @@ class GenericSession(BaseDecentrAIObject):
2352
2479
  allowed_only=False,
2353
2480
  supervisor=None,
2354
2481
  df_only=False,
2482
+ debug=False,
2355
2483
  ):
2356
2484
  """
2357
2485
  This function will return a Pandas dataframe known nodes in the network based on
@@ -2400,10 +2528,11 @@ class GenericSession(BaseDecentrAIObject):
2400
2528
  'Address': PAYLOAD_DATA.NETMON_ADDRESS,
2401
2529
  'Alias' : PAYLOAD_DATA.NETMON_EEID,
2402
2530
  'Seen ago' : PAYLOAD_DATA.NETMON_LAST_SEEN,
2403
- 'Last state': PAYLOAD_DATA.NETMON_STATUS_KEY,
2531
+ 'Version' : PAYLOAD_DATA.NETMON_NODE_VERSION,
2532
+ 'State': PAYLOAD_DATA.NETMON_STATUS_KEY,
2404
2533
  'Last probe' : PAYLOAD_DATA.NETMON_LAST_REMOTE_TIME,
2405
2534
  'Zone' : PAYLOAD_DATA.NETMON_NODE_UTC,
2406
- 'Supervisor' : PAYLOAD_DATA.NETMON_IS_SUPERVISOR,
2535
+ 'Oracle' : PAYLOAD_DATA.NETMON_IS_SUPERVISOR,
2407
2536
  'Peered' : PAYLOAD_DATA.NETMON_WHITELIST,
2408
2537
  })
2409
2538
  reverse_mapping = {v: k for k, v in mapping.items()}
@@ -2441,6 +2570,7 @@ class GenericSession(BaseDecentrAIObject):
2441
2570
  # the following will get the whitelist for the current inspected node
2442
2571
  # without calling self.get_allowed_nodes but instead using the netmon data
2443
2572
  whitelist = node_info.get(PAYLOAD_DATA.NETMON_WHITELIST, [])
2573
+ version = node_info.get(PAYLOAD_DATA.NETMON_NODE_VERSION, '0.0.0')
2444
2574
  client_is_allowed = self.bc_engine.contains_current_address(whitelist)
2445
2575
  if allowed_only and not client_is_allowed:
2446
2576
  continue
@@ -2464,6 +2594,8 @@ class GenericSession(BaseDecentrAIObject):
2464
2594
  val = self.bc_engine._add_prefix(val)
2465
2595
  elif key == PAYLOAD_DATA.NETMON_WHITELIST:
2466
2596
  val = client_is_allowed
2597
+ elif key in [PAYLOAD_DATA.NETMON_STATUS_KEY, PAYLOAD_DATA.NETMON_NODE_VERSION]:
2598
+ val = val.split(' ')[0]
2467
2599
  res[column].append(val)
2468
2600
  # end for
2469
2601
  # end if
@@ -2475,6 +2607,9 @@ class GenericSession(BaseDecentrAIObject):
2475
2607
  SESSION_CT.NETSTATS_NR_SUPERVISORS : len(self.__current_network_statuses),
2476
2608
  SESSION_CT.NETSTATS_ELAPSED : elapsed,
2477
2609
  })
2610
+ if debug:
2611
+ self.P(f"Peering:\n{json.dumps(self._dct_can_send_to_node, indent=2)}", color='y')
2612
+ self.P(f"Used netmon data from {best_super} ({best_super_alias}):\n{json.dumps(best_info, indent=2)}", color='y')
2478
2613
  if df_only:
2479
2614
  return dct_result[SESSION_CT.NETSTATS_REPORT]
2480
2615
  return dct_result
naeural_client/bc/base.py CHANGED
@@ -16,7 +16,11 @@ from cryptography.hazmat.primitives import serialization
16
16
 
17
17
  from ..utils.config import get_user_folder
18
18
 
19
- from ..const.base import BCctbase, BCct, DAUTH_SUBKEY, DAUTH_URL
19
+ from ..const.base import (
20
+ BCctbase, BCct,
21
+ DAUTH_SUBKEY, DAUTH_URL, DAUTH_ENV_KEY,
22
+ DAUTH_NONCE, DAUTH_VARS,
23
+ )
20
24
 
21
25
 
22
26
 
@@ -1216,7 +1220,8 @@ class BaseBlockEngine:
1216
1220
  ### end Ethereum
1217
1221
 
1218
1222
 
1219
- def dauth_autocomplete(self, dauth_endp=None, add_env=True, debug=False, max_tries=5):
1223
+ def dauth_autocomplete(self, dauth_endp=None, add_env=True, debug=False, max_tries=5, **kwargs):
1224
+ MIN_LEN = 10
1220
1225
  dct_env = {}
1221
1226
  dct_result = {}
1222
1227
  done = False
@@ -1224,25 +1229,34 @@ class BaseBlockEngine:
1224
1229
  in_env = False
1225
1230
  url = dauth_endp
1226
1231
 
1227
- if url is None:
1232
+ if not isinstance(url, str) or len(url) < MIN_LEN:
1228
1233
  if isinstance(DAUTH_URL, str) and len(DAUTH_URL) > 0:
1229
1234
  url = DAUTH_URL
1230
- else:
1231
- url = os.environ.get('DAUTH_URL')
1235
+
1236
+ if DAUTH_ENV_KEY in os.environ:
1232
1237
  in_env = True
1238
+ url = os.environ[DAUTH_ENV_KEY]
1233
1239
 
1234
1240
  if isinstance(url, str) and len(url) > 0:
1235
1241
  if dauth_endp is None:
1236
- self.P("Found dAuth URL in environment: '{}'".format(url), color='g')
1242
+ if in_env:
1243
+ self.P("Found dAuth URL in environment: '{}'".format(url), color='g')
1244
+ else:
1245
+ self.P("Using default dAuth URL: '{}'".format(url), color='g')
1237
1246
 
1238
1247
  while not done:
1239
1248
  self.P(f"Trying dAuth `{url}` information... (try {tries})")
1240
1249
  try:
1241
- nonce_data = {
1242
- 'nonce' : str(uuid.uuid4())[:8]
1250
+ to_send = {
1251
+ **kwargs,
1252
+ DAUTH_NONCE : str(uuid.uuid4())[:8],
1243
1253
  }
1244
- self.sign(nonce_data)
1245
- response = requests.post(url, json={'body' : nonce_data})
1254
+ ######
1255
+ if len(kwargs) == 0:
1256
+ to_send['sender_alias'] = 'direct-call'
1257
+ ######
1258
+ self.sign(to_send)
1259
+ response = requests.post(url, json={'body' : to_send})
1246
1260
  if response.status_code == 200:
1247
1261
  dct_response = response.json()
1248
1262
  if debug:
@@ -1275,4 +1289,7 @@ class BaseBlockEngine:
1275
1289
  if tries >= max_tries:
1276
1290
  done = True
1277
1291
  #end while
1292
+ else:
1293
+ self.P(f"dAuth URL is not invalid: {url}", color='r')
1294
+ #end if url is valid
1278
1295
  return dct_env
@@ -49,6 +49,9 @@ def get_nodes(args):
49
49
  supervisor=supervisor_addr,
50
50
  )
51
51
  df, supervisor, super_alias, nr_supers, elapsed = res
52
+ if args.online:
53
+ FILTERED = ['State']
54
+ df = df[[c for c in df.columns if c not in FILTERED]]
52
55
 
53
56
  prefix = "Online n" if (args.online or args.peered) else "N"
54
57
  if supervisor == "ERROR":
@@ -72,6 +75,8 @@ def get_supervisors(args):
72
75
  supervisors_only=True,
73
76
  )
74
77
  df, supervisor, super_alias, nr_supers, elapsed = res
78
+ FILTERED = ['Oracle', 'State']
79
+ df = df[[c for c in df.columns if c not in FILTERED]]
75
80
 
76
81
  if supervisor == "ERROR":
77
82
  log_with_color(f"No supervisors or no comms available in {elapsed:.1f}s. Please check your settings.", color='r')
@@ -1,24 +1,27 @@
1
1
  EE_ID = 'EE_ID'
2
2
  SB_ID = 'SB_ID' # change to SB_ID = EE_ID post mod from sb to ee
3
3
 
4
+ class BCctbase:
5
+ SIGN = 'EE_SIGN'
6
+ SENDER = 'EE_SENDER'
7
+ HASH = 'EE_HASH'
8
+
9
+ ETH_SIGN = 'EE_ETH_SIGN'
10
+ ETH_SENDER= 'EE_ETH_SENDER'
11
+
4
12
 
5
13
  DAUTH_URL = 'https://dauth.ratio1.ai/get_auth_data'
6
14
  DAUTH_SUBKEY = 'auth'
15
+ DAUTH_ENV_KEY = 'DAUTH_URL'
16
+ DAUTH_NONCE = 'nonce'
17
+ DAUTH_VARS = [DAUTH_NONCE, BCctbase.SIGN, BCctbase.SENDER, BCctbase.HASH]
18
+
7
19
 
8
20
  class LocalInfo:
9
21
  LOCAL_INFO_FILE = 'local_info.json'
10
22
  K_ADDRESS = 'address'
11
23
  K_ALIAS = 'alias'
12
24
  K_ETH_ADDRESS = 'eth_address'
13
-
14
-
15
- class BCctbase:
16
- SIGN = 'EE_SIGN'
17
- SENDER = 'EE_SENDER'
18
- HASH = 'EE_HASH'
19
-
20
- ETH_SIGN = 'EE_ETH_SIGN'
21
- ETH_SENDER= 'EE_ETH_SENDER'
22
25
 
23
26
 
24
27
  class BCct:
@@ -23,6 +23,7 @@ EE_ADDR = 'EE_ADDR'
23
23
  EE_WHITELIST = 'EE_WHITELIST'
24
24
  EE_IS_SUPER = 'EE_IS_SUPER'
25
25
  EE_FORMATTER = 'EE_FORMATTER'
26
+ EE_ID = 'EE_ID'
26
27
 
27
28
  SECURED = 'SECURED'
28
29
 
@@ -205,6 +205,8 @@ class PAYLOAD_DATA:
205
205
  NETMON_LAST_SEEN = 'last_seen_sec'
206
206
  NETMON_IS_SUPERVISOR = 'is_supervisor'
207
207
  NETMON_WHITELIST = 'whitelist'
208
+ NETMON_NODE_SECURED = 'secured'
209
+ NETMON_NODE_VERSION = 'version'
208
210
 
209
211
 
210
212
  class NET_CONFIG:
@@ -212,4 +214,5 @@ class NET_CONFIG:
212
214
  REQUEST_COMMAND = "GET_CONFIG"
213
215
  NET_CONFIG_DATA = 'NET_CONFIG_DATA'
214
216
  OPERATION = 'OP'
215
- DESTINATION = 'DEST'
217
+ DESTINATION = 'DEST'
218
+ DATA = 'DATA'
@@ -91,6 +91,7 @@ class BaseLogger(object):
91
91
  if os.name == 'nt':
92
92
  os.system('color')
93
93
  self.__lib__ = lib_name
94
+ self.__folder_setup_done = False
94
95
  self.append_spaces = append_spaces
95
96
  self.show_time = show_time
96
97
  self.no_folders_no_save = no_folders_no_save
@@ -1112,35 +1113,41 @@ class BaseLogger(object):
1112
1113
  BaseLogger.print_color(" Config modified with following env vars: {}".format(matches))
1113
1114
  else:
1114
1115
  BaseLogger.print_color(" No secrets/template found in config")
1116
+
1117
+ if not self.__folder_setup_done:
1118
+ # if not already done lets setup de folders
1119
+ self._base_folder = self.expand_tilda(self._base_folder)
1120
+ self._base_folder = self._get_cloud_base_folder(self._base_folder)
1121
+ self._root_folder = os.path.abspath(self._base_folder)
1122
+ self._base_folder = os.path.join(self._base_folder, self._app_folder)
1123
+
1124
+ if not self.silent:
1125
+ BaseLogger.print_color("BASE: {}".format(self._base_folder))
1115
1126
 
1116
- self._base_folder = self.expand_tilda(self._base_folder)
1117
- self._base_folder = self._get_cloud_base_folder(self._base_folder)
1118
- self._root_folder = os.path.abspath(self._base_folder)
1119
- self._base_folder = os.path.join(self._base_folder, self._app_folder)
1120
- if not self.silent:
1121
- BaseLogger.print_color("BASE: {}".format(self._base_folder))
1122
-
1123
- self._normalize_path_sep()
1124
-
1125
- if not os.path.isdir(self._base_folder):
1126
- BaseLogger.print_color(
1127
- f"WARNING! Invalid app base folder '{self._base_folder}'! We create it automatically!",
1128
- color='r'
1129
- )
1130
- #endif
1131
-
1132
- self._logs_dir = os.path.join(self._base_folder, self.get_logs_dir_name())
1133
- self._outp_dir = os.path.join(self._base_folder, self.get_output_dir_name())
1134
- self._data_dir = os.path.join(self._base_folder, self.get_data_dir_name())
1135
- self._modl_dir = os.path.join(self._base_folder, self.get_models_dir_name())
1127
+ self._normalize_path_sep()
1136
1128
 
1137
- self._setup_folders([
1138
- self._outp_dir,
1139
- self._logs_dir,
1140
- self._data_dir,
1141
- self._modl_dir
1142
- ])
1129
+ if not os.path.isdir(self._base_folder):
1130
+ BaseLogger.print_color(
1131
+ f"WARNING! Invalid app base folder '{self._base_folder}'! We create it automatically!",
1132
+ color='r'
1133
+ )
1134
+ #endif
1143
1135
 
1136
+ self._logs_dir = os.path.join(self._base_folder, self.get_logs_dir_name())
1137
+ self._outp_dir = os.path.join(self._base_folder, self.get_output_dir_name())
1138
+ self._data_dir = os.path.join(self._base_folder, self.get_data_dir_name())
1139
+ self._modl_dir = os.path.join(self._base_folder, self.get_models_dir_name())
1140
+
1141
+ self._setup_folders([
1142
+ self._outp_dir,
1143
+ self._logs_dir,
1144
+ self._data_dir,
1145
+ self._modl_dir
1146
+ ])
1147
+ self.__folder_setup_done = True
1148
+ else:
1149
+ BaseLogger.print_color("Folders already configured.", color='y')
1150
+ #endif apply only first time
1144
1151
  return
1145
1152
 
1146
1153
  @staticmethod
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: naeural_client
3
- Version: 2.6.5
3
+ Version: 2.6.7
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
@@ -1,10 +1,10 @@
1
1
  naeural_client/__init__.py,sha256=YimqgDbjLuywsf8zCWE0EaUXH4MBUrqLxt0TDV558hQ,632
2
- naeural_client/_ver.py,sha256=K8Ggo0pxcVDMTTIUZNTmOjYMJwXrhAp0u3PmdDsfomc,330
2
+ naeural_client/_ver.py,sha256=JsLDMeu4NffEd4NS65d7liD0rlX3L2uRFFHlk7P3w1g,330
3
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=o-qY5Ml72597qM04cgugqzkN9n74LBLrDVOUEZmmgUs,92433
7
+ naeural_client/base/generic_session.py,sha256=eDHuM8fnp7FOtlSoYkQrU0b3Uc7QC775uqNvenV-S2o,97516
8
8
  naeural_client/base/instance.py,sha256=kcZJmjLBtx8Bjj_ysIOx1JmLA-qSpG7E28j5rq6IYus,20444
9
9
  naeural_client/base/pipeline.py,sha256=b4uNHrEIOlAtw4PGUx20dxwBhDck5__SrVXaHcSi8ZA,58251
10
10
  naeural_client/base/plugin_template.py,sha256=qGaXByd_JZFpjvH9GXNbT7KaitRxIJB6-1IhbKrZjq4,138123
@@ -14,7 +14,7 @@ naeural_client/base/webapp_pipeline.py,sha256=QmPLVmhP0CPdi0YuvbZEH4APYz2Amtw3gy
14
14
  naeural_client/base/payload/__init__.py,sha256=y8fBI8tG2ObNfaXFWjyWZXwu878FRYj_I8GIbHT4GKE,29
15
15
  naeural_client/base/payload/payload.py,sha256=x-au7l67Z_vfn_4R2C_pjZCaFuUVXHngJiGOfIAYVdE,2690
16
16
  naeural_client/bc/__init__.py,sha256=FQj23D1PrY06NUOARiKQi4cdj0-VxnoYgYDEht8lpr8,158
17
- naeural_client/bc/base.py,sha256=Nlt-8PQrUcN5W2j67hZYmUNRZVQh-QXTqya06rwlFoA,34733
17
+ naeural_client/bc/base.py,sha256=gp0ckE-D_9fIvfFj53ULZiIOz9-yhSuOD8F9bKDrrVM,35220
18
18
  naeural_client/bc/chain.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  naeural_client/bc/ec.py,sha256=qI8l7YqiS4MNftlx-tF7IZUswrSeQc7KMn5OZ0fEaJs,23370
20
20
  naeural_client/certs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -22,7 +22,7 @@ naeural_client/certs/r9092118.ala.eu-central-1.emqxsl.com.crt,sha256=y-6io0tseyx
22
22
  naeural_client/cli/README.md,sha256=WPdI_EjzAbUW1aPyj1sSR8rLydcJKZtoiaEtklQrjHo,74
23
23
  naeural_client/cli/cli.py,sha256=c0ZavVwArQEGv8tueTnz3aGKTuUe6Sqmm5oTUFUVIUE,3816
24
24
  naeural_client/cli/cli_commands.py,sha256=VffU1tpG1CGae6z4GtcAdktAlEAfIiXq9n2oHAx1kAI,1944
25
- naeural_client/cli/nodes.py,sha256=Oq7bh7kkU79doBLEa8ANU6OiWv83mJvyjFyZqwpKx1s,4595
25
+ naeural_client/cli/nodes.py,sha256=9KA-O6C6fwNEx2Cu9rPBXC_ijU4J6ucZcnPw7ubc7bc,4785
26
26
  naeural_client/code_cheker/__init__.py,sha256=pwkdeZGVL16ZA4Qf2mRahEhoOvKhL7FyuQbMFLr1E5M,33
27
27
  naeural_client/code_cheker/base.py,sha256=lT5DRIFO5rqzsMNCmdMRfkAeevmezozehyfgmhnKpuI,19074
28
28
  naeural_client/code_cheker/checker.py,sha256=QWupeM7ToancVIq1tRUxRNUrI8B5l5eoY0kDU4-O5aE,7365
@@ -32,13 +32,13 @@ naeural_client/comm/mqtt_wrapper.py,sha256=Ig3bFZkCbWd4y_Whn2PPa91Z3aLgNbNPau6Tn
32
32
  naeural_client/const/README.md,sha256=6OHesr-f5NBuuJGryEoi_TCu2XdlhfQYlDKx_IJoXeg,177
33
33
  naeural_client/const/__init__.py,sha256=MM6Zib6i7M2qWcMkLtLx14zqU-lE-u2uPHjNvbh2jAM,478
34
34
  naeural_client/const/apps.py,sha256=gIONTZUkqPveu3DwelyJWpbFMeIR9l6DlaNg-xEfK1A,611
35
- naeural_client/const/base.py,sha256=ToCqp_JW6mq3J2Ul2dJ3Xhp8gxSg7rg4nTYjIPtvDOI,4220
35
+ naeural_client/const/base.py,sha256=8e3qrYFpVGl7swMGQm9Yjj_40ghpvLHYsbeTQNWD_w8,4344
36
36
  naeural_client/const/comms.py,sha256=La6JXWHexH8CfcBCKyT4fCIoeaoZlcm7KtZ57ab4ZgU,2201
37
37
  naeural_client/const/environment.py,sha256=iytmTDgbOjvORPwHQmc0K0r-xJx7dnnzNnqAJJiFCDA,870
38
38
  naeural_client/const/formatter.py,sha256=AW3bWlqf39uaqV4BBUuW95qKYfF2OkkU4f9hy3kSVhM,200
39
- naeural_client/const/heartbeat.py,sha256=jGHmKfeHTFOXJaKUT3o_ocnQyF-EpcLeunW-ifkYKfU,2534
39
+ naeural_client/const/heartbeat.py,sha256=xHZBX_NzHTklwA2_AEKR0SGdlbavMT4nirqjQg8WlTU,2550
40
40
  naeural_client/const/misc.py,sha256=VDCwwpf5bl9ltx9rzT2WPVP8B3mZFRufU1tSS5MO240,413
41
- naeural_client/const/payload.py,sha256=vHKxSrPXnfBTBwD_xp9Aw7nue0_gxz4r01YjXRYiTIM,6479
41
+ naeural_client/const/payload.py,sha256=cKfl2RO1VowrLM0KlYoZQIcwFs_mOCC9xzEZtj0pS9E,6563
42
42
  naeural_client/default/__init__.py,sha256=ozU6CMMuWl0LhG8Ae3LrZ65a6tLrptfscVYGf83zjxM,46
43
43
  naeural_client/default/instance/__init__.py,sha256=w1de6OMj9a5GPGF-Wl1b_I_YAy9fWBEss2QnyPPyaB0,546
44
44
  naeural_client/default/instance/chain_dist_custom_job_01_plugin.py,sha256=QtHi3uXKsVs9eyMgbnvBVbMylErhV1Du4X2-7zDL7Y0,1915
@@ -57,7 +57,7 @@ naeural_client/io_formatter/default/a_dummy.py,sha256=qr9eUizQ-NN5jdXVzkaZKMaf9K
57
57
  naeural_client/io_formatter/default/aixp1.py,sha256=MX0TeUR4APA-qN3vUC6uzcz8Pssz5lgrQWo7td5Ri1A,3052
58
58
  naeural_client/io_formatter/default/default.py,sha256=gEy78cP2D5s0y8vQh4aHuxqz7D10gGfuiKF311QhrpE,494
59
59
  naeural_client/logging/__init__.py,sha256=b79X45VC6c37u32flKB2GAK9f-RR0ocwP0JDCy0t7QQ,33
60
- naeural_client/logging/base_logger.py,sha256=u4_hrMYr-oi5yAtgrzR_RtKu5kakwKvkTPBYwgOQNuY,66525
60
+ naeural_client/logging/base_logger.py,sha256=a5_8SG6SZFmWKpD5gPemDWbWoin66-GZasHrqj0WUNA,66859
61
61
  naeural_client/logging/small_logger.py,sha256=m12hCb_H4XifJYYfgCAOUDkcXm-h4pSODnFf277OFVI,2937
62
62
  naeural_client/logging/logger_mixins/__init__.py,sha256=yQO7umlRvz63FeWpi-F9GRmC_MOHcNW6R6pwvZZBy3A,600
63
63
  naeural_client/logging/logger_mixins/class_instance_mixin.py,sha256=xUXE2VZgmrlrSrvw0f6GF1jlTnVLeVkIiG0bhlBfq3o,2741
@@ -81,8 +81,8 @@ naeural_client/utils/__init__.py,sha256=mAnke3-MeRzz3nhQvhuHqLnpaaCSmDxicd7Ck9uw
81
81
  naeural_client/utils/comm_utils.py,sha256=4cS9llRr_pK_3rNgDcRMCQwYPO0kcNU7AdWy_LtMyCY,1072
82
82
  naeural_client/utils/config.py,sha256=v7xHikr6Z5Sbvf3opYeMhYzGWD2pe0HlRwa-aGJzUh8,6323
83
83
  naeural_client/utils/dotenv.py,sha256=_AgSo35n7EnQv5yDyu7C7i0kHragLJoCGydHjvOkrYY,2008
84
- naeural_client-2.6.5.dist-info/METADATA,sha256=VpAH9R-lILu90wGG7dygKOYE-MeSwZev5U2axV3O7Eg,14618
85
- naeural_client-2.6.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
86
- naeural_client-2.6.5.dist-info/entry_points.txt,sha256=PNdyotDaQBAslZREx5luVyj0kqpQnwNACwkFNTPIHU4,55
87
- naeural_client-2.6.5.dist-info/licenses/LICENSE,sha256=cvOsJVslde4oIaTCadabXnPqZmzcBO2f2zwXZRmJEbE,11311
88
- naeural_client-2.6.5.dist-info/RECORD,,
84
+ naeural_client-2.6.7.dist-info/METADATA,sha256=K2k5IH3c1fzOL9HUUAt3mFehDDKPbjIIBkLDBnIsqgU,14618
85
+ naeural_client-2.6.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
86
+ naeural_client-2.6.7.dist-info/entry_points.txt,sha256=PNdyotDaQBAslZREx5luVyj0kqpQnwNACwkFNTPIHU4,55
87
+ naeural_client-2.6.7.dist-info/licenses/LICENSE,sha256=cvOsJVslde4oIaTCadabXnPqZmzcBO2f2zwXZRmJEbE,11311
88
+ naeural_client-2.6.7.dist-info/RECORD,,