neuronum 8.1.0__tar.gz → 8.3.0__tar.gz

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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: neuronum
3
- Version: 8.1.0
3
+ Version: 8.3.0
4
4
  Summary: The E2E Web Engine
5
5
  Home-page: https://neuronum.net
6
6
  Author: Neuronum Cybernetics
@@ -534,7 +534,9 @@ f"""{{
534
534
  "app_metadata": {{
535
535
  "name": "{descr}",
536
536
  "version": "1.0.0",
537
- "author": "{host}"
537
+ "author": "{host}",
538
+ "audience": "private",
539
+ "logo": "https://neuronum.net/static/logo.png"
538
540
  }},
539
541
  "data_gateways": [
540
542
  {{
@@ -815,107 +817,72 @@ async def async_stop_node():
815
817
  @click.command()
816
818
  def update_node():
817
819
  click.echo("Update your Node")
818
- credentials_folder_path = Path.home() / ".neuronum"
819
- env_path = credentials_folder_path / ".env"
820
- env_data = {}
821
-
822
820
  try:
821
+ env_path = Path.home() / ".neuronum" / ".env"
822
+ env_data = {}
823
823
  with open(env_path, "r") as f:
824
824
  for line in f:
825
- key, value = line.strip().split("=")
826
- env_data[key] = value
825
+ if "=" in line:
826
+ key, value = line.strip().split("=", 1)
827
+ env_data[key] = value
827
828
 
828
829
  host = env_data.get("HOST", "")
829
830
 
830
- except FileNotFoundError:
831
- click.echo("Error: .env with credentials not found")
831
+ with open("config.json", "r") as f:
832
+ config_data = json.load(f)
833
+
834
+ audience = config_data.get("app_metadata", {}).get("audience", "")
835
+ descr = config_data.get("app_metadata", {}).get("name", "")
836
+
837
+ if host.startswith("CMTY_") and audience != "private":
838
+ raise click.ClickException(
839
+ 'Community Cells can only create private Nodes. Set audience to "private".'
840
+ )
841
+ if descr and len(descr) > 25:
842
+ raise click.ClickException(
843
+ 'Description too long. Max 25 characters allowed.'
844
+ )
845
+
846
+ except FileNotFoundError as e:
847
+ click.echo(f"Error: File not found - {e.filename}")
832
848
  return
833
- except Exception as e:
834
- click.echo(f"Error reading .env file: {e}")
849
+ except click.ClickException as e:
850
+ click.echo(e.format_message())
835
851
  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.")
852
+ except Exception as e:
853
+ click.echo(f"Error reading files: {e}")
866
854
  return
867
- asyncio.run(async_update_node(node_type, descr, partners))
868
855
 
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 = {}
856
+ asyncio.run(async_update_node(env_data, config_data, audience, descr))
873
857
 
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
858
 
859
+ async def async_update_node(env_data, config_data, audience: str, descr: str):
860
+ try:
880
861
  host = env_data.get("HOST", "")
881
862
  password = env_data.get("PASSWORD", "")
882
863
  network = env_data.get("NETWORK", "")
883
864
  synapse = env_data.get("SYNAPSE", "")
884
865
 
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
866
+ node_id = config_data.get("data_gateways", [{}])[0].get("node_id", "")
896
867
 
897
- try:
898
868
  with open("config.json", "r") as f:
899
- config_file = f.read()
869
+ config_file_content = f.read()
900
870
 
901
871
  except FileNotFoundError:
902
- click.echo("Error: Config File not found")
872
+ click.echo("Error: config.json or .env not found")
903
873
  return
904
874
  except Exception as e:
905
- click.echo(f"Error reading Config file: {e}")
875
+ click.echo(f"Error reading files: {e}")
906
876
  return
907
-
908
- if node_type == "partners":
909
- node_type = partners
910
877
 
911
878
  url = f"https://{network}/api/update_node"
912
879
  node = {
913
- "nodeID": nodeID,
880
+ "nodeID": node_id,
914
881
  "host": host,
915
882
  "password": password,
916
883
  "synapse": synapse,
917
- "node_type": node_type,
918
- "config_file": config_file,
884
+ "node_type": audience,
885
+ "config_file": config_file_content,
919
886
  "descr": descr,
920
887
  }
921
888
 
@@ -924,120 +891,73 @@ async def async_update_node(node_type: str, descr: str, partners:str) -> None:
924
891
  async with session.post(url, json=node) as response:
925
892
  response.raise_for_status()
926
893
  data = await response.json()
927
- nodeID = data["nodeID"]
894
+ updated_node_id = data.get("nodeID", node_id)
895
+ click.echo(f"Neuronum Node '{updated_node_id}' updated!")
928
896
  except aiohttp.ClientError as e:
929
897
  click.echo(f"Error sending request: {e}")
930
- return
931
898
 
932
- if node_type == "public":
933
- click.echo(f"Neuronum Node '{nodeID}' updated!")
934
- else:
935
- click.echo(f"Neuronum Node '{nodeID}' updated!")
936
899
 
937
900
 
938
901
  def update_node_at_start():
939
902
  click.echo("Update your Node")
940
- credentials_folder_path = Path.home() / ".neuronum"
941
- env_path = credentials_folder_path / ".env"
942
- env_data = {}
943
-
944
903
  try:
904
+ env_path = Path.home() / ".neuronum" / ".env"
905
+ env_data = {}
945
906
  with open(env_path, "r") as f:
946
907
  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 = {}
908
+ if "=" in line:
909
+ key, value = line.strip().split("=", 1)
910
+ env_data[key] = value
995
911
 
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
912
+ with open("config.json", "r") as f:
913
+ config_data = json.load(f)
1001
914
 
1002
915
  host = env_data.get("HOST", "")
1003
- password = env_data.get("PASSWORD", "")
1004
- network = env_data.get("NETWORK", "")
1005
- synapse = env_data.get("SYNAPSE", "")
916
+ audience = config_data.get("app_metadata", {}).get("audience", "")
917
+ descr = config_data.get("app_metadata", {}).get("name", "")
918
+
919
+ if host.startswith("CMTY_") and audience != "private":
920
+ raise click.ClickException(
921
+ 'Community Cells can only start private Nodes. Node starting "privately".'
922
+ )
923
+ if descr and len(descr) > 25:
924
+ raise click.ClickException(
925
+ 'Description too long. Max 25 characters allowed.'
926
+ )
927
+
928
+ asyncio.run(_async_update_node_at_start(env_data, config_data, audience, descr))
929
+
930
+ except FileNotFoundError as e:
931
+ click.echo(f"Error: File not found - {e.filename}")
932
+ except click.ClickException as e:
933
+ click.echo(e.format_message())
934
+ except Exception as e:
935
+ click.echo(f"Unexpected error: {e}")
1006
936
 
1007
- with open('config.json', 'r') as f:
1008
- data = json.load(f)
1009
937
 
1010
- nodeID = data['data_gateways'][0]['node_id']
938
+ async def _async_update_node_at_start(env_data, config_data, audience, descr):
939
+ host = env_data.get("HOST", "")
940
+ password = env_data.get("PASSWORD", "")
941
+ network = env_data.get("NETWORK", "")
942
+ synapse = env_data.get("SYNAPSE", "")
1011
943
 
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
944
+ node_id = config_data.get("data_gateways", [{}])[0].get("node_id", "")
1018
945
 
1019
946
  try:
1020
947
  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
948
+ config_file_content = f.read()
1026
949
  except Exception as e:
1027
- click.echo(f"Error reading file: {e}")
950
+ click.echo(f"Error reading config.json content: {e}")
1028
951
  return
1029
-
1030
- if node_type == "partners":
1031
- node_type = partners
1032
952
 
1033
953
  url = f"https://{network}/api/update_node"
1034
954
  node = {
1035
- "nodeID": nodeID,
955
+ "nodeID": node_id,
1036
956
  "host": host,
1037
957
  "password": password,
1038
958
  "synapse": synapse,
1039
- "node_type": node_type,
1040
- "config_file": config_file,
959
+ "node_type": audience,
960
+ "config_file": config_file_content,
1041
961
  "descr": descr,
1042
962
  }
1043
963
 
@@ -1046,15 +966,10 @@ async def async_update_node_at_start(node_type: str, descr: str, partners:str) -
1046
966
  async with session.post(url, json=node) as response:
1047
967
  response.raise_for_status()
1048
968
  data = await response.json()
1049
- nodeID = data["nodeID"]
969
+ updated_node_id = data.get("nodeID", node_id)
970
+ click.echo(f"Neuronum Node '{updated_node_id}' updated!")
1050
971
  except aiohttp.ClientError as e:
1051
972
  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
973
 
1059
974
 
1060
975
  @click.command()
@@ -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.3.0
4
4
  Summary: The E2E Web Engine
5
5
  Home-page: https://neuronum.net
6
6
  Author: Neuronum Cybernetics
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name='neuronum',
5
- version='8.1.0',
5
+ version='8.3.0',
6
6
  author='Neuronum Cybernetics',
7
7
  author_email='welcome@neuronum.net',
8
8
  description='The E2E Web Engine',
File without changes
File without changes
File without changes
File without changes
File without changes