neuronum 8.1.0__py3-none-any.whl → 8.2.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.

Potentially problematic release.


This version of neuronum might be problematic. Click here for more details.

cli/main.py CHANGED
@@ -534,7 +534,8 @@ f"""{{
534
534
  "app_metadata": {{
535
535
  "name": "{descr}",
536
536
  "version": "1.0.0",
537
- "author": "{host}"
537
+ "author": "{host}",
538
+ "audience": "private"
538
539
  }},
539
540
  "data_gateways": [
540
541
  {{
@@ -815,107 +816,72 @@ async def async_stop_node():
815
816
  @click.command()
816
817
  def update_node():
817
818
  click.echo("Update your Node")
818
- credentials_folder_path = Path.home() / ".neuronum"
819
- env_path = credentials_folder_path / ".env"
820
- env_data = {}
821
-
822
819
  try:
820
+ env_path = Path.home() / ".neuronum" / ".env"
821
+ env_data = {}
823
822
  with open(env_path, "r") as f:
824
823
  for line in f:
825
- key, value = line.strip().split("=")
826
- env_data[key] = value
824
+ if "=" in line:
825
+ key, value = line.strip().split("=", 1)
826
+ env_data[key] = value
827
827
 
828
828
  host = env_data.get("HOST", "")
829
829
 
830
- except FileNotFoundError:
831
- click.echo("Error: .env with credentials not found")
830
+ with open("config.json", "r") as f:
831
+ config_data = json.load(f)
832
+
833
+ audience = config_data.get("app_metadata", {}).get("audience", "")
834
+ descr = config_data.get("app_metadata", {}).get("name", "")
835
+
836
+ if host.startswith("CMTY_") and audience != "private":
837
+ raise click.ClickException(
838
+ 'Community Cells can only create private Nodes. Set audience to "private".'
839
+ )
840
+ if descr and len(descr) > 25:
841
+ raise click.ClickException(
842
+ 'Description too long. Max 25 characters allowed.'
843
+ )
844
+
845
+ except FileNotFoundError as e:
846
+ click.echo(f"Error: File not found - {e.filename}")
832
847
  return
833
- except Exception as e:
834
- click.echo(f"Error reading .env file: {e}")
848
+ except click.ClickException as e:
849
+ click.echo(e.format_message())
835
850
  return
836
-
837
- if host.startswith("CMTY_"):
838
- node_type = questionary.select(
839
- "Community Cells can only create private Nodes",
840
- choices=["private"]
841
- ).ask()
842
- else:
843
- node_type = questionary.select(
844
- "Who can view your Node?:",
845
- choices=["public", "private", "partners"]
846
- ).ask()
847
- partners = "None"
848
- if node_type == "partners":
849
- prompt_msg = (
850
- "Enter the list of partners who can view this Node.\n"
851
- "Format: partner::cell, partner::cell, partner::cell\n"
852
- "Press Enter to leave the list unchanged"
853
- )
854
- partners = click.prompt(
855
- prompt_msg,
856
- default="None",
857
- show_default=False
858
- ).strip()
859
- descr = click.prompt(
860
- "Update Node description: Type up to 25 characters, or press Enter to leave it unchanged",
861
- default="None",
862
- show_default=False
863
- ).strip()
864
- if descr and len(descr) > 25:
865
- click.echo("Description too long. Max 25 characters allowed.")
851
+ except Exception as e:
852
+ click.echo(f"Error reading files: {e}")
866
853
  return
867
- asyncio.run(async_update_node(node_type, descr, partners))
868
854
 
869
- async def async_update_node(node_type: str, descr: str, partners:str) -> None:
870
- credentials_folder_path = Path.home() / ".neuronum"
871
- env_path = credentials_folder_path / ".env"
872
- env_data = {}
855
+ asyncio.run(async_update_node(env_data, config_data, audience, descr))
873
856
 
874
- try:
875
- with open(env_path, "r") as f:
876
- for line in f:
877
- key, value = line.strip().split("=")
878
- env_data[key] = value
879
857
 
858
+ async def async_update_node(env_data, config_data, audience: str, descr: str):
859
+ try:
880
860
  host = env_data.get("HOST", "")
881
861
  password = env_data.get("PASSWORD", "")
882
862
  network = env_data.get("NETWORK", "")
883
863
  synapse = env_data.get("SYNAPSE", "")
884
864
 
885
- with open('config.json', 'r') as f:
886
- data = json.load(f)
887
-
888
- nodeID = data['data_gateways'][0]['node_id']
889
-
890
- except FileNotFoundError:
891
- click.echo("Error: .env with credentials not found")
892
- return
893
- except Exception as e:
894
- click.echo(f"Error reading .env file: {e}")
895
- return
865
+ node_id = config_data.get("data_gateways", [{}])[0].get("node_id", "")
896
866
 
897
- try:
898
867
  with open("config.json", "r") as f:
899
- config_file = f.read()
868
+ config_file_content = f.read()
900
869
 
901
870
  except FileNotFoundError:
902
- click.echo("Error: Config File not found")
871
+ click.echo("Error: config.json or .env not found")
903
872
  return
904
873
  except Exception as e:
905
- click.echo(f"Error reading Config file: {e}")
874
+ click.echo(f"Error reading files: {e}")
906
875
  return
907
-
908
- if node_type == "partners":
909
- node_type = partners
910
876
 
911
877
  url = f"https://{network}/api/update_node"
912
878
  node = {
913
- "nodeID": nodeID,
879
+ "nodeID": node_id,
914
880
  "host": host,
915
881
  "password": password,
916
882
  "synapse": synapse,
917
- "node_type": node_type,
918
- "config_file": config_file,
883
+ "node_type": audience,
884
+ "config_file": config_file_content,
919
885
  "descr": descr,
920
886
  }
921
887
 
@@ -924,120 +890,73 @@ async def async_update_node(node_type: str, descr: str, partners:str) -> None:
924
890
  async with session.post(url, json=node) as response:
925
891
  response.raise_for_status()
926
892
  data = await response.json()
927
- nodeID = data["nodeID"]
893
+ updated_node_id = data.get("nodeID", node_id)
894
+ click.echo(f"Neuronum Node '{updated_node_id}' updated!")
928
895
  except aiohttp.ClientError as e:
929
896
  click.echo(f"Error sending request: {e}")
930
- return
931
897
 
932
- if node_type == "public":
933
- click.echo(f"Neuronum Node '{nodeID}' updated!")
934
- else:
935
- click.echo(f"Neuronum Node '{nodeID}' updated!")
936
898
 
937
899
 
938
900
  def update_node_at_start():
939
901
  click.echo("Update your Node")
940
- credentials_folder_path = Path.home() / ".neuronum"
941
- env_path = credentials_folder_path / ".env"
942
- env_data = {}
943
-
944
902
  try:
903
+ env_path = Path.home() / ".neuronum" / ".env"
904
+ env_data = {}
945
905
  with open(env_path, "r") as f:
946
906
  for line in f:
947
- key, value = line.strip().split("=")
948
- env_data[key] = value
949
-
950
- host = env_data.get("HOST", "")
951
-
952
- except FileNotFoundError:
953
- click.echo("Error: .env with credentials not found")
954
- return
955
- except Exception as e:
956
- click.echo(f"Error reading .env file: {e}")
957
- return
958
-
959
- if host.startswith("CMTY_"):
960
- node_type = questionary.select(
961
- "Community Cells can only create private Nodes",
962
- choices=["private"]
963
- ).ask()
964
- else:
965
- node_type = questionary.select(
966
- "Who can view your Node?:",
967
- choices=["public", "private", "partners"]
968
- ).ask()
969
- partners = "None"
970
- if node_type == "partners":
971
- prompt_msg = (
972
- "Enter the list of partners who can view this Node.\n"
973
- "Format: partner::cell, partner::cell, partner::cell\n"
974
- "Press Enter to leave the list unchanged"
975
- )
976
- partners = click.prompt(
977
- prompt_msg,
978
- default="None",
979
- show_default=False
980
- ).strip()
981
- descr = click.prompt(
982
- "Update Node description: Type up to 25 characters, or press Enter to leave it unchanged",
983
- default="None",
984
- show_default=False
985
- ).strip()
986
- if descr and len(descr) > 25:
987
- click.echo("Description too long. Max 25 characters allowed.")
988
- return
989
- asyncio.run(async_update_node_at_start(node_type, descr, partners))
990
-
991
- async def async_update_node_at_start(node_type: str, descr: str, partners:str) -> None:
992
- credentials_folder_path = Path.home() / ".neuronum"
993
- env_path = credentials_folder_path / ".env"
994
- env_data = {}
907
+ if "=" in line:
908
+ key, value = line.strip().split("=", 1)
909
+ env_data[key] = value
995
910
 
996
- try:
997
- with open(env_path, "r") as f:
998
- for line in f:
999
- key, value = line.strip().split("=")
1000
- env_data[key] = value
911
+ with open("config.json", "r") as f:
912
+ config_data = json.load(f)
1001
913
 
1002
914
  host = env_data.get("HOST", "")
1003
- password = env_data.get("PASSWORD", "")
1004
- network = env_data.get("NETWORK", "")
1005
- synapse = env_data.get("SYNAPSE", "")
915
+ audience = config_data.get("app_metadata", {}).get("audience", "")
916
+ descr = config_data.get("app_metadata", {}).get("name", "")
917
+
918
+ if host.startswith("CMTY_") and audience != "private":
919
+ raise click.ClickException(
920
+ 'Community Cells can only start private Nodes. Node starting "privately".'
921
+ )
922
+ if descr and len(descr) > 25:
923
+ raise click.ClickException(
924
+ 'Description too long. Max 25 characters allowed.'
925
+ )
926
+
927
+ asyncio.run(_async_update_node_at_start(env_data, config_data, audience, descr))
928
+
929
+ except FileNotFoundError as e:
930
+ click.echo(f"Error: File not found - {e.filename}")
931
+ except click.ClickException as e:
932
+ click.echo(e.format_message())
933
+ except Exception as e:
934
+ click.echo(f"Unexpected error: {e}")
1006
935
 
1007
- with open('config.json', 'r') as f:
1008
- data = json.load(f)
1009
936
 
1010
- nodeID = data['data_gateways'][0]['node_id']
937
+ async def _async_update_node_at_start(env_data, config_data, audience, descr):
938
+ host = env_data.get("HOST", "")
939
+ password = env_data.get("PASSWORD", "")
940
+ network = env_data.get("NETWORK", "")
941
+ synapse = env_data.get("SYNAPSE", "")
1011
942
 
1012
- except FileNotFoundError:
1013
- click.echo("Error: .env with credentials not found")
1014
- return
1015
- except Exception as e:
1016
- click.echo(f"Error reading .env file: {e}")
1017
- return
943
+ node_id = config_data.get("data_gateways", [{}])[0].get("node_id", "")
1018
944
 
1019
945
  try:
1020
946
  with open("config.json", "r") as f:
1021
- config_file = f.read()
1022
-
1023
- except FileNotFoundError:
1024
- click.echo("Error: File not found")
1025
- return
947
+ config_file_content = f.read()
1026
948
  except Exception as e:
1027
- click.echo(f"Error reading file: {e}")
949
+ click.echo(f"Error reading config.json content: {e}")
1028
950
  return
1029
-
1030
- if node_type == "partners":
1031
- node_type = partners
1032
951
 
1033
952
  url = f"https://{network}/api/update_node"
1034
953
  node = {
1035
- "nodeID": nodeID,
954
+ "nodeID": node_id,
1036
955
  "host": host,
1037
956
  "password": password,
1038
957
  "synapse": synapse,
1039
- "node_type": node_type,
1040
- "config_file": config_file,
958
+ "node_type": audience,
959
+ "config_file": config_file_content,
1041
960
  "descr": descr,
1042
961
  }
1043
962
 
@@ -1046,15 +965,10 @@ async def async_update_node_at_start(node_type: str, descr: str, partners:str) -
1046
965
  async with session.post(url, json=node) as response:
1047
966
  response.raise_for_status()
1048
967
  data = await response.json()
1049
- nodeID = data["nodeID"]
968
+ updated_node_id = data.get("nodeID", node_id)
969
+ click.echo(f"Neuronum Node '{updated_node_id}' updated!")
1050
970
  except aiohttp.ClientError as e:
1051
971
  click.echo(f"Error sending request: {e}")
1052
- return
1053
-
1054
- if node_type == "public":
1055
- click.echo(f"Neuronum Node '{nodeID}' updated!")
1056
- else:
1057
- click.echo(f"Neuronum Node '{nodeID}' updated!")
1058
972
 
1059
973
 
1060
974
  @click.command()
neuronum/neuronum.py CHANGED
@@ -35,6 +35,7 @@ class Node:
35
35
  "synapse": self.synapse
36
36
  }
37
37
 
38
+
38
39
  def _load_private_key(self):
39
40
  try:
40
41
  with open(self.private_key_path, "rb") as f:
@@ -43,12 +44,12 @@ class Node:
43
44
  password=None,
44
45
  backend=default_backend()
45
46
  )
46
- print("Private key loaded successfully.")
47
47
  return private_key
48
48
  except FileNotFoundError:
49
49
  print(f"Private key file not found at {self.private_key_path}.")
50
50
  return None
51
51
 
52
+
52
53
  def _load_host(self):
53
54
  credentials_folder_path = Path.home() / ".neuronum"
54
55
  env_path = credentials_folder_path / ".env"
@@ -130,8 +131,6 @@ class Node:
130
131
  f.read(),
131
132
  backend=default_backend()
132
133
  )
133
- print("Public key loaded successfully.")
134
- print(public_key)
135
134
  return public_key
136
135
  except FileNotFoundError:
137
136
  print(f"Public key file not found at {self.public_key_path}. Deriving from private key.")
@@ -147,7 +146,6 @@ class Node:
147
146
  print("Public key not loaded. Cannot generate JWK.")
148
147
  return None
149
148
 
150
- print("Public key loaded successfully.")
151
149
  public_numbers = public_key.public_numbers()
152
150
 
153
151
  x_bytes = public_numbers.x.to_bytes((public_numbers.x.bit_length() + 7) // 8, 'big')
@@ -196,7 +194,7 @@ class Node:
196
194
  try:
197
195
  async with websockets.connect(full_url) as ws:
198
196
  await ws.send(json.dumps(auth_payload))
199
- print("Connected to WebSocket.")
197
+ print("Node syncing...")
200
198
  while True:
201
199
  try:
202
200
  raw_operation = await ws.recv()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: neuronum
3
- Version: 8.1.0
3
+ Version: 8.2.0
4
4
  Summary: The E2E Web Engine
5
5
  Home-page: https://neuronum.net
6
6
  Author: Neuronum Cybernetics
@@ -0,0 +1,10 @@
1
+ cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ cli/main.py,sha256=lNzUeW_cJKS9sTbaWO1wXZvLcvZ_PbUC3vYYTNGDEfs,31747
3
+ neuronum/__init__.py,sha256=qkAz6fpiS2KKnaKwPbS15y7lRCQV-XaWNTkVUarluPk,26
4
+ neuronum/neuronum.py,sha256=4iZjeQ1XTKPhUpojmpkYQiOaNZPZE6t7JUyhLPMOyuA,13183
5
+ neuronum-8.2.0.dist-info/licenses/LICENSE.md,sha256=m7pw_FktMNCs4tcy2UXP3QQP2S_je28P1SepdYoo0Xo,1961
6
+ neuronum-8.2.0.dist-info/METADATA,sha256=WK0q97Q2HOJstFkcaPiotF2LeczYr1afQ__zGYqDkaw,3448
7
+ neuronum-8.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
8
+ neuronum-8.2.0.dist-info/entry_points.txt,sha256=XKYBcRNxGeJpZZkDPsa8HA_RaJ7Km_R_JaUq5T9Nk2U,42
9
+ neuronum-8.2.0.dist-info/top_level.txt,sha256=ru8Fr84cHm6oHr_DcJ8-uaq3RTiuCRFIr6AC8V0zPu4,13
10
+ neuronum-8.2.0.dist-info/RECORD,,
@@ -1,10 +0,0 @@
1
- cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- cli/main.py,sha256=XRRFASq5jdTxmNtK7YOYX4mwjNlbIjlvwJI37vnntLE,33942
3
- neuronum/__init__.py,sha256=qkAz6fpiS2KKnaKwPbS15y7lRCQV-XaWNTkVUarluPk,26
4
- neuronum/neuronum.py,sha256=0haV0eFbUcH_za3HQgiysimErnVv_UBre89cP-q-ATk,13387
5
- neuronum-8.1.0.dist-info/licenses/LICENSE.md,sha256=m7pw_FktMNCs4tcy2UXP3QQP2S_je28P1SepdYoo0Xo,1961
6
- neuronum-8.1.0.dist-info/METADATA,sha256=BDahigYJAPUUhkg6hkoy2V7iMSqpfFfkOC2yVA1i_Ac,3448
7
- neuronum-8.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
8
- neuronum-8.1.0.dist-info/entry_points.txt,sha256=XKYBcRNxGeJpZZkDPsa8HA_RaJ7Km_R_JaUq5T9Nk2U,42
9
- neuronum-8.1.0.dist-info/top_level.txt,sha256=ru8Fr84cHm6oHr_DcJ8-uaq3RTiuCRFIr6AC8V0zPu4,13
10
- neuronum-8.1.0.dist-info/RECORD,,