neuronum 2.0.8__py3-none-any.whl → 3.0.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
@@ -1,13 +1,16 @@
1
- import click
2
- import questionary
3
- from pathlib import Path
4
- import requests
5
1
  import subprocess
6
2
  import os
7
3
  import neuronum
8
4
  import json
9
5
  import platform
10
6
  import glob
7
+ import asyncio
8
+ import aiohttp
9
+ import click
10
+ import questionary
11
+ from pathlib import Path
12
+ import requests
13
+
11
14
 
12
15
  @click.group()
13
16
  def cli():
@@ -83,7 +86,6 @@ def create_cell():
83
86
  click.echo(f"Error:'{email}' already assigned!")
84
87
 
85
88
 
86
-
87
89
  @click.command()
88
90
  def connect_cell():
89
91
  email = click.prompt("Enter your Email")
@@ -242,13 +244,15 @@ def delete_cell():
242
244
  click.echo(f"Neuronum Cell '{host}' has been deleted!")
243
245
  else:
244
246
  click.echo(f"Neuronum Cell '{host}' deletion failed!")
245
-
247
+
246
248
 
247
249
  @click.command()
248
250
  @click.option('--sync', multiple=True, default=None, help="Optional stream IDs for sync.")
249
251
  @click.option('--stream', multiple=True, default=None, help="Optional stream ID for stream.")
250
252
  def init_node(sync, stream):
253
+ asyncio.run(async_init_node(sync, stream))
251
254
 
255
+ async def async_init_node(sync, stream):
252
256
  credentials_folder_path = Path.home() / ".neuronum"
253
257
  env_path = credentials_folder_path / ".env"
254
258
 
@@ -273,15 +277,17 @@ def init_node(sync, stream):
273
277
  return
274
278
 
275
279
  url = f"https://{network}/api/init_node"
276
- node = {"host": host, "password": password, "synapse": synapse}
280
+ node_payload = {"host": host, "password": password, "synapse": synapse}
277
281
 
278
- try:
279
- response = requests.post(url, json=node)
280
- response.raise_for_status()
281
- nodeID = response.json()["nodeID"]
282
- except requests.exceptions.RequestException as e:
283
- click.echo(f"Error sending request: {e}")
284
- return
282
+ async with aiohttp.ClientSession() as session:
283
+ try:
284
+ async with session.post(url, json=node_payload) as response:
285
+ response.raise_for_status()
286
+ data = await response.json()
287
+ nodeID = data["nodeID"]
288
+ except aiohttp.ClientError as e:
289
+ click.echo(f"Error sending request: {e}")
290
+ return
285
291
 
286
292
  node_filename = "node_" + nodeID.replace("::node", "")
287
293
  project_path = Path(node_filename)
@@ -294,35 +300,29 @@ def init_node(sync, stream):
294
300
  synapse=synapse
295
301
  )
296
302
 
297
- cells = cell.list_cells()
298
- tx = cell.list_tx()
299
- ctx = cell.list_ctx()
300
- stx = cell.list_stx()
301
- contracts = cell.list_contracts()
302
- nodes = cell.list_nodes()
303
-
304
- cells_path = project_path / "cells.json"
305
- tx_path = project_path / "transmitters.json"
306
- ctx_path = project_path / "circuits.json"
307
- stx_path = project_path / "streams.json"
308
- contracts_path = project_path / "contracts.json"
309
- nodes_path = project_path / "nodes.json"
310
-
311
- cells_path.write_text(json.dumps(cells, indent=4))
312
- tx_path.write_text(json.dumps(tx, indent=4))
313
- ctx_path.write_text(json.dumps(ctx, indent=4))
314
- stx_path.write_text(json.dumps(stx, indent=4))
315
- contracts_path.write_text(json.dumps(contracts, indent=4))
316
- nodes_path.write_text(json.dumps(nodes, indent=4))
303
+ cells = await cell.list_cells()
304
+ tx = await cell.list_tx()
305
+ ctx = await cell.list_ctx()
306
+ stx = await cell.list_stx()
307
+ contracts = await cell.list_contracts()
308
+ nodes = await cell.list_nodes()
309
+
310
+ await asyncio.to_thread((project_path / "cells.json").write_text, json.dumps(cells, indent=4))
311
+ await asyncio.to_thread((project_path / "transmitters.json").write_text, json.dumps(tx, indent=4))
312
+ await asyncio.to_thread((project_path / "circuits.json").write_text, json.dumps(ctx, indent=4))
313
+ await asyncio.to_thread((project_path / "streams.json").write_text, json.dumps(stx, indent=4))
314
+ await asyncio.to_thread((project_path / "contracts.json").write_text, json.dumps(contracts, indent=4))
315
+ await asyncio.to_thread((project_path / "nodes.json").write_text, json.dumps(nodes, indent=4))
317
316
 
318
317
  env_path = project_path / ".env"
319
- env_path.write_text(f"NODE={nodeID}\nHOST={host}\nPASSWORD={password}\nNETWORK={network}\nSYNAPSE={synapse}\n")
318
+ await asyncio.to_thread(env_path.write_text, f"NODE={nodeID}\nHOST={host}\nPASSWORD={password}\nNETWORK={network}\nSYNAPSE={synapse}\n")
320
319
 
321
320
  gitignore_path = project_path / ".gitignore"
322
- gitignore_path.write_text(".env\n")
321
+ await asyncio.to_thread(gitignore_path.write_text, ".env\n")
323
322
 
324
323
  nodemd_path = project_path / "NODE.md"
325
- nodemd_path.write_text("## Use this NODE.md file to add instructions on how to interact with your node\n")
324
+ await asyncio.to_thread(nodemd_path.write_text, "## Use this NODE.md file to add instructions on how to interact with your node\n")
325
+
326
326
 
327
327
  stx = sync[0] if sync else (stream[0] if stream else host.replace("::cell", "::stx"))
328
328
 
@@ -330,6 +330,7 @@ def init_node(sync, stream):
330
330
  for stx in sync:
331
331
  sync_path = project_path / f"sync_{stx.replace('::stx', '')}.py"
332
332
  sync_path.write_text(f"""\
333
+ import asyncio
333
334
  import neuronum
334
335
  import os
335
336
  from dotenv import load_dotenv
@@ -347,15 +348,17 @@ cell = neuronum.Cell(
347
348
  synapse=synapse
348
349
  )
349
350
 
350
- STX = "{stx}"
351
- stream = cell.sync(STX)
352
- for operation in stream:
353
- label = operation.get("label")
354
- data = operation.get("data")
355
- ts = operation.get("time")
356
- stxID = operation.get("stxID")
357
- operator = operation.get("operator")
358
- print(label, data, ts, stxID, operator)
351
+ async def main():
352
+ STX = "{stx}"
353
+ async for operation in cell.sync(STX):
354
+ label = operation.get("label")
355
+ data = operation.get("data")
356
+ ts = operation.get("time")
357
+ stxID = operation.get("stxID")
358
+ operator = operation.get("operator")
359
+ print(label, data, ts, stxID, operator)
360
+
361
+ asyncio.run(main())
359
362
  """)
360
363
 
361
364
 
@@ -363,6 +366,7 @@ for operation in stream:
363
366
  for stx in stream:
364
367
  stream_path = project_path / f"stream_{stx.replace('::stx', '')}.py"
365
368
  stream_path.write_text(f"""\
369
+ import asyncio
366
370
  import neuronum
367
371
  import os
368
372
  from dotenv import load_dotenv
@@ -380,20 +384,25 @@ cell = neuronum.Cell(
380
384
  synapse=synapse
381
385
  )
382
386
 
383
- STX = "{stx}"
384
- label = "your_label"
385
- while True:
386
- data = {{
387
- "key1": "value1",
388
- "key2": "value2",
389
- "key3": "value3",
390
- }}
391
- cell.stream(label, data, STX)
387
+ async def main():
388
+ STX = "{stx}"
389
+ label = "your_label"
390
+
391
+ while True:
392
+ data = {{
393
+ "key1": "value1",
394
+ "key2": "value2",
395
+ "key3": "value3",
396
+ }}
397
+ await cell.stream(label, data, STX)
398
+
399
+ asyncio.run(main())
392
400
  """)
393
401
 
394
402
  if not sync and not stream:
395
403
  sync_path = project_path / f"sync_{stx.replace('::stx', '')}.py"
396
404
  sync_path.write_text(f"""\
405
+ import asyncio
397
406
  import neuronum
398
407
  import os
399
408
  from dotenv import load_dotenv
@@ -410,16 +419,52 @@ cell = neuronum.Cell(
410
419
  network=network,
411
420
  synapse=synapse
412
421
  )
413
-
414
- STX = "{stx}"
415
- stream = cell.sync(STX)
416
- for operation in stream:
417
- message = operation.get("data").get("message")
418
- print(message)
422
+
423
+ async def main():
424
+ STX = "{stx}"
425
+ async for operation in cell.sync(STX):
426
+ message = operation.get("data").get("message")
427
+ print(message)
428
+
429
+ asyncio.run(main())
419
430
  """)
420
431
 
421
432
  stream_path = project_path / f"stream_{stx.replace('::stx', '')}.py"
422
433
  stream_path.write_text(f"""\
434
+ import asyncio
435
+ import neuronum
436
+ import os
437
+ from dotenv import load_dotenv
438
+
439
+ load_dotenv()
440
+ host = os.getenv("HOST")
441
+ password = os.getenv("PASSWORD")
442
+ network = os.getenv("NETWORK")
443
+ synapse = os.getenv("SYNAPSE")
444
+
445
+ cell = neuronum.Cell(
446
+ host=host,
447
+ password=password,
448
+ network=network,
449
+ synapse=synapse
450
+ )
451
+
452
+ async def main():
453
+ STX = "{stx}"
454
+ label = "Welcome to Neuronum"
455
+
456
+ while True:
457
+ data = {{
458
+ "message": "Hello, Neuronum!"
459
+ }}
460
+ await cell.stream(label, data, STX)
461
+
462
+ asyncio.run(main())
463
+ """)
464
+
465
+ scan_path = project_path / f"scan.py"
466
+ scan_path.write_text(f"""\
467
+ import asyncio
423
468
  import neuronum
424
469
  import os
425
470
  from dotenv import load_dotenv
@@ -436,28 +481,32 @@ cell = neuronum.Cell(
436
481
  network=network,
437
482
  synapse=synapse
438
483
  )
439
-
440
- STX = "{stx}"
441
- label = "Welcome to Neuronum"
442
- while True:
443
- data = {{
444
- "message": "Hello, Neuronum!"
445
- }}
446
- cell.stream(label, data, STX)
484
+
485
+ async def main():
486
+ async for cp in cell.scan():
487
+ print(cp)
488
+
489
+ asyncio.run(main())
447
490
  """)
448
491
 
449
492
  click.echo(f"Neuronum Node '{nodeID}' initialized!")
450
493
 
451
494
 
452
-
453
495
  @click.command()
454
496
  def start_node():
497
+ scan_type = questionary.select(
498
+ "Scan for Neuronum Cells and Nodes (Ensure Bluetooth is enabled)",
499
+ choices=["On", "Off"]
500
+ ).ask()
501
+
455
502
  click.echo("Starting Node...")
456
503
 
457
504
  project_path = Path.cwd()
458
-
459
505
  script_files = glob.glob("sync_*.py") + glob.glob("stream_*.py")
460
506
 
507
+ if scan_type == "On":
508
+ script_files += glob.glob("scan.py")
509
+
461
510
  processes = []
462
511
 
463
512
  for script in script_files:
@@ -473,13 +522,19 @@ def start_node():
473
522
  with open("node_pid.txt", "w") as f:
474
523
  f.write("\n".join(map(str, processes)))
475
524
 
476
- click.echo(f"Node started successfully!")
525
+ click.echo("Node started successfully!")
526
+
477
527
 
478
528
 
479
529
  @click.command()
480
530
  def stop_node():
531
+ asyncio.run(async_stop_node())
532
+
533
+ async def async_stop_node():
481
534
  click.echo("Stopping Node...")
482
535
 
536
+ node_pid_path = Path("node_pid.txt")
537
+
483
538
  try:
484
539
  with open("node_pid.txt", "r") as f:
485
540
  pids = [int(pid.strip()) for pid in f.readlines()]
@@ -489,18 +544,14 @@ def stop_node():
489
544
  for pid in pids:
490
545
  try:
491
546
  if system_name == "Windows":
492
- subprocess.run(
493
- ["taskkill", "/F", "/PID", str(pid)],
494
- stdout=subprocess.DEVNULL,
495
- stderr=subprocess.DEVNULL
496
- )
547
+ await asyncio.to_thread(subprocess.run, ["taskkill", "/F", "/PID", str(pid)], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
497
548
  else:
498
- os.kill(pid, 9)
549
+ await asyncio.to_thread(os.kill, pid, 9)
499
550
  except ProcessLookupError:
500
551
  click.echo(f"Warning: Process {pid} already stopped or does not exist.")
501
552
 
502
- os.remove("node_pid.txt")
503
- click.echo(f"Node stopped successfully!")
553
+ await asyncio.to_thread(os.remove, node_pid_path)
554
+ click.echo("Node stopped successfully!")
504
555
 
505
556
  except FileNotFoundError:
506
557
  click.echo("Error: No active node process found.")
@@ -510,6 +561,9 @@ def stop_node():
510
561
 
511
562
  @click.command()
512
563
  def register_node():
564
+ asyncio.run(async_register_node())
565
+
566
+ async def async_register_node():
513
567
  env_data = {}
514
568
  try:
515
569
  with open(".env", "r") as f:
@@ -559,21 +613,27 @@ def register_node():
559
613
  "nodemd_file": nodemd_file
560
614
  }
561
615
 
562
- try:
563
- response = requests.post(url, json=node)
564
- response.raise_for_status()
565
- nodeID = response.json()["nodeID"]
566
- node_url = response.json()["node_url"]
567
- except requests.exceptions.RequestException as e:
568
- click.echo(f"Error sending request: {e}")
569
- return
616
+ async with aiohttp.ClientSession() as session:
617
+ try:
618
+ async with session.post(url, json=node) as response:
619
+ response.raise_for_status()
620
+ data = await response.json()
621
+ nodeID = data["nodeID"]
622
+ node_url = data["node_url"]
623
+ except aiohttp.ClientError as e:
624
+ click.echo(f"Error sending request: {e}")
625
+ return
570
626
 
571
627
  click.echo(f"Neuronum Node '{nodeID}' registered! Visit: {node_url}")
572
628
 
573
629
 
574
630
  @click.command()
575
631
  def update_node():
632
+ asyncio.run(async_update_node())
633
+
634
+ async def async_update_node():
576
635
  env_data = {}
636
+
577
637
  try:
578
638
  with open(".env", "r") as f:
579
639
  for line in f:
@@ -587,26 +647,25 @@ def update_node():
587
647
  synapse = env_data.get("SYNAPSE", "")
588
648
 
589
649
  except FileNotFoundError:
590
- print("Error: .env with credentials not found")
650
+ click.echo("Error: .env with credentials not found")
591
651
  return
592
652
  except Exception as e:
593
- print(f"Error reading .env file: {e}")
653
+ click.echo(f"Error reading .env file: {e}")
594
654
  return
595
655
 
596
656
  try:
597
- with open("NODE.md", "r") as f:
598
- nodemd_file = f.read()
657
+ with open("NODE.md", "r") as f:
658
+ nodemd_file = f.read()
599
659
 
600
660
  except FileNotFoundError:
601
- print("Error: NODE.md file not found")
661
+ click.echo("Error: NODE.md file not found")
602
662
  return
603
663
  except Exception as e:
604
- print(f"Error reading NODE.md file: {e}")
664
+ click.echo(f"Error reading NODE.md file: {e}")
605
665
  return
606
666
 
607
667
  url = f"https://{network}/api/update_node"
608
-
609
- node = {
668
+ node_payload = {
610
669
  "nodeID": nodeID,
611
670
  "host": host,
612
671
  "password": password,
@@ -614,50 +673,48 @@ def update_node():
614
673
  "nodemd_file": nodemd_file
615
674
  }
616
675
 
617
- try:
618
- response = requests.post(url, json=node)
619
- response.raise_for_status()
620
- nodeID = response.json()["nodeID"]
621
- node_url = response.json()["node_url"]
622
- except requests.exceptions.RequestException as e:
623
- click.echo(f"Error sending request: {e}")
624
- return
625
-
676
+ async with aiohttp.ClientSession() as session:
677
+ try:
678
+ async with session.post(url, json=node_payload) as response:
679
+ response.raise_for_status()
680
+ data = await response.json()
681
+ nodeID = data["nodeID"]
682
+ node_url = data["node_url"]
683
+ except aiohttp.ClientError as e:
684
+ click.echo(f"Error sending request: {e}")
685
+ return
626
686
 
627
687
  cell = neuronum.Cell(
628
- host=host,
629
- password=password,
630
- network=network,
631
- synapse=synapse
688
+ host=host,
689
+ password=password,
690
+ network=network,
691
+ synapse=synapse
632
692
  )
633
693
 
634
- cells = cell.list_cells()
635
- tx = cell.list_tx()
636
- ctx = cell.list_ctx()
637
- stx = cell.list_stx()
638
- contracts = cell.list_contracts()
639
- nodes = cell.list_nodes()
640
-
641
- cells_path = Path("cells.json")
642
- tx_path = Path("transmitters.json")
643
- ctx_path = Path("circuits.json")
644
- stx_path = Path("streams.json")
645
- contracts_path = Path("contracts.json")
646
- nodes_path = Path("nodes.json")
647
-
648
- cells_path.write_text(json.dumps(cells, indent=4))
649
- tx_path.write_text(json.dumps(tx, indent=4))
650
- ctx_path.write_text(json.dumps(ctx, indent=4))
651
- stx_path.write_text(json.dumps(stx, indent=4))
652
- contracts_path.write_text(json.dumps(contracts, indent=4))
653
- nodes_path.write_text(json.dumps(nodes, indent=4))
694
+ cells = await cell.list_cells()
695
+ tx = await cell.list_tx()
696
+ ctx = await cell.list_ctx()
697
+ stx = await cell.list_stx()
698
+ contracts = await cell.list_contracts()
699
+ nodes = await cell.list_nodes()
700
+
701
+ await asyncio.to_thread(Path("cells.json").write_text, json.dumps(cells, indent=4))
702
+ await asyncio.to_thread(Path("transmitters.json").write_text, json.dumps(tx, indent=4))
703
+ await asyncio.to_thread(Path("circuits.json").write_text, json.dumps(ctx, indent=4))
704
+ await asyncio.to_thread(Path("streams.json").write_text, json.dumps(stx, indent=4))
705
+ await asyncio.to_thread(Path("contracts.json").write_text, json.dumps(contracts, indent=4))
706
+ await asyncio.to_thread(Path("nodes.json").write_text, json.dumps(nodes, indent=4))
654
707
 
655
708
  click.echo(f"Neuronum Node '{nodeID}' updated! Visit: {node_url}")
656
709
 
657
710
 
658
711
  @click.command()
659
712
  def delete_node():
713
+ asyncio.run(async_delete_node())
714
+
715
+ async def async_delete_node():
660
716
  env_data = {}
717
+
661
718
  try:
662
719
  with open(".env", "r") as f:
663
720
  for line in f:
@@ -671,40 +728,42 @@ def delete_node():
671
728
  synapse = env_data.get("SYNAPSE", "")
672
729
 
673
730
  except FileNotFoundError:
674
- print("Error: .env with credentials not found")
731
+ click.echo("Error: .env with credentials not found")
675
732
  return
676
733
  except Exception as e:
677
- print(f"Error reading .env file: {e}")
734
+ click.echo(f"Error reading .env file: {e}")
678
735
  return
679
736
 
680
737
  url = f"https://{network}/api/delete_node"
681
-
682
- node = {
738
+ node_payload = {
683
739
  "nodeID": nodeID,
684
740
  "host": host,
685
741
  "password": password,
686
742
  "synapse": synapse
687
743
  }
688
744
 
689
- try:
690
- response = requests.post(url, json=node)
691
- response.raise_for_status()
692
- nodeID = response.json()["nodeID"]
693
- except requests.exceptions.RequestException as e:
694
- click.echo(f"Error sending request: {e}")
695
- return
745
+ async with aiohttp.ClientSession() as session:
746
+ try:
747
+ async with session.post(url, json=node_payload) as response:
748
+ response.raise_for_status()
749
+ data = await response.json()
750
+ nodeID = data["nodeID"]
751
+ except aiohttp.ClientError as e:
752
+ click.echo(f"Error sending request: {e}")
753
+ return
696
754
 
697
755
  click.echo(f"Neuronum Node '{nodeID}' deleted!")
698
756
 
699
757
 
700
- @click.command()
701
- def call_cellai():
702
- try:
703
- from cellai import cellai
704
- cellai.main()
705
- except ImportError:
758
+ @click.command()
759
+ def call_cellai():
760
+ try:
761
+ from cellai import cellai
762
+ cellai.main()
763
+ except ImportError:
706
764
  click.echo("Cellai not found. Please check the necessary dependencies.")
707
765
 
766
+
708
767
  cli.add_command(create_cell)
709
768
  cli.add_command(connect_cell)
710
769
  cli.add_command(view_cell)