neuronum 7.0.2__py3-none-any.whl → 7.0.4__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
@@ -249,14 +249,15 @@ def delete_cell():
249
249
 
250
250
 
251
251
  @click.command()
252
- def init_node():
252
+ @click.option('--blank', is_flag=True, help="Generate a Node Template without Stream and Transmitter")
253
+ def init_node(blank):
253
254
  descr = click.prompt("Node description: Type up to 25 characters").strip()
254
255
  if descr and len(descr) > 25:
255
256
  click.echo("Description too long. Max 25 characters allowed.")
256
257
  return
257
- asyncio.run(async_init_node(descr))
258
+ asyncio.run(async_init_node(blank, descr))
258
259
 
259
- async def async_init_node(descr):
260
+ async def async_init_node(blank, descr):
260
261
  credentials_folder_path = Path.home() / ".neuronum"
261
262
  env_path = credentials_folder_path / ".env"
262
263
 
@@ -312,21 +313,359 @@ async def async_init_node(descr):
312
313
  env_path = project_path / ".env"
313
314
  await asyncio.to_thread(env_path.write_text, f"NODE={nodeID}\nHOST={host}\nPASSWORD={password}\nNETWORK={network}\nSYNAPSE={synapse}\n")
314
315
 
315
- stx_descr = f"{nodeID} App"
316
- partners = ["private"]
317
- stxID = await cell.create_stx(stx_descr, partners)
316
+ if blank is False:
317
+ stx_descr = f"{nodeID} App"
318
+ partners = ["private"]
319
+ stxID = await cell.create_stx(stx_descr, partners)
320
+
321
+ tx_descr = f"Greet {nodeID}"
322
+ key_values = {
323
+ "ping": "pong",
324
+ }
325
+ STX = stxID
326
+ label = "ping:pong"
327
+ partners = ["private"]
328
+ txID = await cell.create_tx(tx_descr, key_values, STX, label, partners)
329
+
330
+ app_path = project_path / "app.py"
331
+ app_path.write_text(f"""\
332
+ import asyncio
333
+ import neuronum
334
+ import os
335
+ import json
336
+ from dotenv import load_dotenv
337
+ from jinja2 import Environment, FileSystemLoader
318
338
 
319
- tx_descr = f"Greet {nodeID}"
320
- key_values = {
321
- "ping": "pong",
322
- }
323
- STX = stxID
324
- label = "ping:pong"
325
- partners = ["private"]
326
- txID = await cell.create_tx(tx_descr, key_values, STX, label, partners)
339
+ env = Environment(loader=FileSystemLoader('.'))
340
+ template = env.get_template('ping.html')
341
+
342
+ with open('config.json', 'r') as f:
343
+ data = json.load(f)
344
+ terms_url = data['legals']['terms']
345
+ privacy_url = data['legals']['privacy_policy']
346
+ last_update = data['legals']['last_update']
347
+
348
+
349
+ load_dotenv()
350
+ host = os.getenv("HOST")
351
+ password = os.getenv("PASSWORD")
352
+ network = os.getenv("NETWORK")
353
+ synapse = os.getenv("SYNAPSE")
354
+
355
+ cell = neuronum.Cell(
356
+ host=host,
357
+ password=password,
358
+ network=network,
359
+ synapse=synapse
360
+ )
361
+
362
+ async def main():
363
+ STX = "{stxID}"
364
+ async for operation in cell.sync(STX):
365
+ txID = operation.get("txID")
366
+ client = operation.get("operator")
367
+ ts = operation.get("time")
368
+ data = operation.get("data")
369
+ operation_id = operation.get("operationID")
370
+
371
+ if txID == "{txID}":
372
+
373
+ def render_html_template(client, ts, data, operation_id, terms_url, privacy_url, last_update):
374
+ return template.render(client=client, ts=ts, data=data, operation_id=operation_id, terms_url=terms_url, privacy_url=privacy_url, last_update=last_update)
375
+
376
+ html_content = render_html_template(client, ts, data, operation_id, terms_url, privacy_url, last_update)
377
+
378
+ data = {{
379
+ "json": f"{{operation_id}} - Reply from {nodeID}: Pinged by {{client}} at {{ts}} with data: {{data}}",
380
+ "html": html_content
381
+ }}
382
+
383
+ await cell.notify(f"{{client}}", "{nodeID} Ping","Pinged successfully")
384
+
385
+ await cell.tx_response(txID, client, data)
386
+
387
+ asyncio.run(main())
388
+ """)
389
+
390
+ html_path = project_path / "ping.html"
391
+ html_content = f"""\
392
+ <!DOCTYPE html>
393
+ <html>
394
+ <head>
395
+ <style>
396
+ body {{
397
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
398
+ background-color: #121212;
399
+ color: #e0e0e0;
400
+ margin: 0;
401
+ padding: 0;
402
+ display: flex;
403
+ justify-content: center;
404
+ align-items: center;
405
+ min-height: 100vh;
406
+ }}
407
+
408
+ .container {{
409
+ background-color: #1e1e1e;
410
+ border-radius: 12px;
411
+ padding: 40px;
412
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
413
+ width: 100%;
414
+ max-width: 500px;
415
+ text-align: center;
416
+ box-sizing: border-box;
417
+ }}
418
+
419
+ .logo {{
420
+ width: 80px;
421
+ margin-bottom: 25px;
422
+ filter: drop-shadow(0 0 5px rgba(255, 255, 255, 0.1));
423
+ }}
424
+
425
+ h1 {{
426
+ font-size: 1.5em;
427
+ font-weight: 600;
428
+ margin-bottom: 5px;
429
+ color: #f5f5f5;
430
+ }}
431
+
432
+ .subtitle {{
433
+ font-size: 0.9em;
434
+ color: #a0a0a0;
435
+ margin-bottom: 30px;
436
+ }}
437
+
438
+ .data-row {{
439
+ background-color: #2a2a2a;
440
+ padding: 12px 15px;
441
+ border-radius: 8px;
442
+ margin-bottom: 10px;
443
+ display: flex;
444
+ justify-content: space-between;
445
+ align-items: center;
446
+ }}
447
+
448
+ .data-label {{
449
+ font-weight: 400;
450
+ color: #a0a0a0;
451
+ margin: 0;
452
+ }}
453
+
454
+ .data-value {{
455
+ font-weight: 500;
456
+ color: #e0e0e0;
457
+ margin: 0;
458
+ }}
459
+
460
+ .data-value.truncated {{
461
+ white-space: nowrap;
462
+ overflow: hidden;
463
+ text-overflow: ellipsis;
464
+ max-width: 60%;
465
+ }}
466
+
467
+ .data-value.client {{
468
+ color: #8cafff;
469
+ }}
470
+ .data-value.timestamp {{
471
+ color: #a1e8a1;
472
+ }}
473
+ .data-value.operation-id {{
474
+ color: #f7a2a2;
475
+ }}
476
+ .api-button {{
477
+ background: #01c07d 100%;
478
+ color: white;
479
+ border: none;
480
+ border-radius: 8px;
481
+ padding: 12px 24px;
482
+ font-size: 16px;
483
+ font-weight: bold;
484
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
485
+ cursor: pointer;
486
+ margin-top: 10px;
487
+ }}
488
+ </style>
489
+ </head>
490
+ <body>
491
+ <div class="container">
492
+ <img class="logo" src="https://neuronum.net/static/logo.png" alt="Neuronum Logo">
493
+
494
+ <h1>Reply from {nodeID}</h1>
495
+ <p class="subtitle">Pinged successfully.</p>
496
+
497
+ <div class="data-row">
498
+ <p class="data-label">Client</p>
499
+ <p class="data-value client">{{{{client}}}}</p>
500
+ </div>
501
+
502
+ <div class="data-row">
503
+ <p class="data-label">Timestamp</p>
504
+ <p class="data-value timestamp">{{{{ts}}}}</p>
505
+ </div>
506
+
507
+ <div class="data-row">
508
+ <p class="data-label">Data</p>
509
+ <p class="data-value">{{{{data}}}}</p>
510
+ </div>
511
+
512
+ <div class="data-row">
513
+ <p class="data-label">Operation ID</p>
514
+ <p class="data-value operation-id truncated">{{{{operation_id}}}}</p>
515
+ </div>
516
+
517
+ <button id="send-request-btn" class="api-button">Ping again</button>
518
+ </div>
519
+
520
+ <script>
521
+ document.getElementById('send-request-btn').addEventListener('click', () => {{
522
+ const apiEndpoint = 'https://neuronum.net/api/activate/{txID}';
523
+
524
+ const dataToSend = {{
525
+ "data": {{"ping": "node"}},
526
+ "cell": {{
527
+ "host": CLIENT_CELL,
528
+ "session": CLIENT_SESSION,
529
+ }}
530
+ }};
531
+
532
+ fetch(apiEndpoint, {{
533
+ method: 'POST',
534
+ headers: {{
535
+ 'Content-Type': 'application/json',
536
+ 'Accept': 'application/json'
537
+ }},
538
+ body: JSON.stringify(dataToSend)
539
+ }})
540
+ .then(response => {{
541
+ if (!response.ok) {{
542
+ throw new Error(`HTTP error! status: ${{response.status}}`);
543
+ }}
544
+ return response.json();
545
+ }})
546
+ .then(data => {{
547
+ if (data.success && data.response && data.response.html) {{
548
+ document.open();
549
+ document.write(data.response.html);
550
+ document.close();
551
+ console.log('API Response: Page replaced with new HTML.');
552
+ }} else {{
553
+ console.error('API Response does not contain HTML to replace the page:', data);
554
+ alert('API response error: Expected HTML content to replace the page.');
555
+ }}
556
+ }})
557
+ .catch(error => {{
558
+ console.error('API request failed:', error);
559
+ alert('API request failed. See the console for details.');
560
+ }});
561
+ }});
562
+ </script>
563
+
564
+ <div id="legal-banner" style="border-radius: 10px; margin: 15px; position: fixed; bottom: 0; left: 0; right: 0; background-color: #2a2a2a; color: #e0e0e0; padding: 16px; text-align: center; font-size: 14px; z-index: 9999; box-shadow: 0 -2px 10px rgba(0,0,0,0.5);">
565
+ By continuing, you agree to our
566
+ Terms (<span style="color: #8cafff;">{{{{terms_url}}}}</span>) &
567
+ Privacy Policy (<span style="color: #8cafff;">{{{{privacy_url}}}}</span>)
568
+ <br>
569
+ <button id="accept-legal" style="margin-top: 15px; margin-bottom: 15px; background: #01c07d; color: white; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer;">Accept</button>
570
+ <br>
571
+ Last Update: {{{{last_update}}}}
572
+ </div>
573
+
574
+ <script>
575
+ const banner = document.getElementById('legal-banner');
576
+ const acceptBtn = document.getElementById('accept-legal');
577
+ acceptBtn.addEventListener('click', () => {{
578
+ banner.remove();
579
+ }});
580
+ </script>
581
+
582
+ </body>
583
+ </html>
584
+ """
585
+ html_path.write_text(html_content)
586
+
587
+ config_path = project_path / "config.json"
588
+ await asyncio.to_thread(
589
+ config_path.write_text,
590
+ f"""{{
591
+ "app_metadata": {{
592
+ "name": "{descr}",
593
+ "version": "1.0.0",
594
+ "author": "{host}"
595
+ }},
596
+ "data_gateways": [
597
+ {{
598
+ "type": "transmitter",
599
+ "id": "{txID}",
600
+ "info": "Ping Your Node"
601
+ }}
602
+ ],
603
+ "legals": {{
604
+ "terms": "https://url_to_your/terms",
605
+ "privacy_policy": "https://url_to_your/privacy_policy",
606
+ "last_update" : "DD/MM/YYYY"
607
+ }}
608
+ }}"""
609
+ )
610
+
611
+ nodemd_path = project_path / "NODE.md"
612
+ await asyncio.to_thread(nodemd_path.write_text, f"""### NODE.md of {nodeID}
613
+
614
+ Welcome to your Node's documentation! This guide provides several ways for users to interact with your application.
327
615
 
328
- app_path = project_path / "app.py"
329
- app_path.write_text(f"""\
616
+ ***
617
+
618
+ ### 💻 Using the CLI
619
+
620
+ To ping this Node via the command-line interface, use the following command:
621
+
622
+ `neuronum activate --tx {txID} 'ping:node'`
623
+
624
+ ***
625
+
626
+ ### 🐍 With Python
627
+
628
+ For programmatic access, use the following Python code snippet. This script utilizes the `neuronum` library to activate the transaction and receive a response.
629
+
630
+ ```python
631
+ import asyncio
632
+ import neuronum
633
+
634
+ # Set up Cell connection parameters
635
+ cell = neuronum.Cell(
636
+ host="host", # Cell host
637
+ password="password", # Cell password
638
+ network="neuronum.net", # Cell network
639
+ synapse="synapse" # Cell synapse
640
+ )
641
+
642
+ async def main():
643
+ # Define the transaction ID and data payload
644
+ TX = "{txID}"
645
+ data = {{"ping": "node"}}
646
+
647
+ # Activate the transaction and get the response
648
+ tx_response = await cell.activate_tx(TX, data)
649
+
650
+ # Print the response from the Node
651
+ print(tx_response)
652
+
653
+ # Run the main asynchronous function
654
+ if __name__ == "__main__":
655
+ asyncio.run(main())
656
+ ```
657
+
658
+ 🤖 Via Cellai (Android App - Currently in Testing)
659
+ Download the app from the Google Play Store.
660
+ Send the command "Ping Node" to Cellai
661
+ """)
662
+
663
+ else:
664
+ stxID = "id::stx"
665
+ txID = "id::tx"
666
+
667
+ app_path = project_path / "app.py"
668
+ app_path.write_text(f"""\
330
669
  import asyncio
331
670
  import neuronum
332
671
  import os
@@ -385,8 +724,8 @@ async def main():
385
724
  asyncio.run(main())
386
725
  """)
387
726
 
388
- html_path = project_path / "ping.html"
389
- html_content = f"""\
727
+ html_path = project_path / "ping.html"
728
+ html_content = f"""\
390
729
  <!DOCTYPE html>
391
730
  <html>
392
731
  <head>
@@ -580,11 +919,11 @@ asyncio.run(main())
580
919
  </body>
581
920
  </html>
582
921
  """
583
- html_path.write_text(html_content)
922
+ html_path.write_text(html_content)
584
923
 
585
- config_path = project_path / "config.json"
586
- await asyncio.to_thread(
587
- config_path.write_text,
924
+ config_path = project_path / "config.json"
925
+ await asyncio.to_thread(
926
+ config_path.write_text,
588
927
  f"""{{
589
928
  "app_metadata": {{
590
929
  "name": "{descr}",
@@ -606,8 +945,8 @@ f"""{{
606
945
  }}"""
607
946
  )
608
947
 
609
- nodemd_path = project_path / "NODE.md"
610
- await asyncio.to_thread(nodemd_path.write_text, f"""### NODE.md of {nodeID}
948
+ nodemd_path = project_path / "NODE.md"
949
+ await asyncio.to_thread(nodemd_path.write_text, f"""### NODE.md of {nodeID}
611
950
 
612
951
  Welcome to your Node's documentation! This guide provides several ways for users to interact with your application.
613
952
 
@@ -664,7 +1003,7 @@ Send the command "Ping Node" to Cellai
664
1003
  @click.command()
665
1004
  @click.option('--d', is_flag=True, help="Start node in detached mode")
666
1005
  def start_node(d):
667
- update_node()
1006
+ update_node_at_start()
668
1007
  pid_file = Path.cwd() / "status.txt"
669
1008
  system_name = platform.system()
670
1009
  active_pids = []
@@ -695,7 +1034,7 @@ def start_node(d):
695
1034
  click.echo("Starting Node...")
696
1035
 
697
1036
  project_path = Path.cwd()
698
- script_files = glob.glob("stream.py") + glob.glob("app.py")
1037
+ script_files = glob.glob("app.py")
699
1038
  processes = []
700
1039
 
701
1040
  for script in script_files:
@@ -792,7 +1131,7 @@ def check_node():
792
1131
  @click.command()
793
1132
  @click.option('--d', is_flag=True, help="Restart node in detached mode")
794
1133
  def restart_node(d):
795
- update_node()
1134
+ update_node_at_start()
796
1135
  pid_file = Path.cwd() / "status.txt"
797
1136
  system_name = platform.system()
798
1137
 
@@ -842,7 +1181,7 @@ def restart_node(d):
842
1181
 
843
1182
  click.echo(f"Starting Node {nodeID}...")
844
1183
  project_path = Path.cwd()
845
- script_files = glob.glob("stream.py") + glob.glob("app.py")
1184
+ script_files = glob.glob("app.py")
846
1185
  processes = []
847
1186
 
848
1187
  for script in script_files:
@@ -923,6 +1262,7 @@ async def async_stop_node():
923
1262
  click.echo("Error: Unable to stop some node processes.")
924
1263
 
925
1264
 
1265
+ @click.command()
926
1266
  def update_node():
927
1267
  click.echo("Update your Node")
928
1268
  env_data = {}
@@ -1042,6 +1382,125 @@ async def async_update_node(node_type: str, descr: str, partners:str) -> None:
1042
1382
  click.echo(f"Neuronum Node '{nodeID}' updated!")
1043
1383
 
1044
1384
 
1385
+ def update_node_at_start():
1386
+ click.echo("Update your Node")
1387
+ env_data = {}
1388
+
1389
+ try:
1390
+ with open(".env", "r") as f:
1391
+ for line in f:
1392
+ key, value = line.strip().split("=")
1393
+ env_data[key] = value
1394
+
1395
+ host = env_data.get("HOST", "")
1396
+
1397
+ except FileNotFoundError:
1398
+ click.echo("Error: .env with credentials not found")
1399
+ return
1400
+ except Exception as e:
1401
+ click.echo(f"Error reading .env file: {e}")
1402
+ return
1403
+
1404
+ if host.startswith("CMTY_"):
1405
+ node_type = questionary.select(
1406
+ "Community Cells can only create private Nodes",
1407
+ choices=["private"]
1408
+ ).ask()
1409
+ else:
1410
+ node_type = questionary.select(
1411
+ "Who can view your Node?:",
1412
+ choices=["public", "private", "partners"]
1413
+ ).ask()
1414
+ partners = "None"
1415
+ if node_type == "partners":
1416
+ prompt_msg = (
1417
+ "Enter the list of partners who can view this Node.\n"
1418
+ "Format: partner::cell, partner::cell, partner::cell\n"
1419
+ "Press Enter to leave the list unchanged"
1420
+ )
1421
+ partners = click.prompt(
1422
+ prompt_msg,
1423
+ default="None",
1424
+ show_default=False
1425
+ ).strip()
1426
+ descr = click.prompt(
1427
+ "Update Node description: Type up to 25 characters, or press Enter to leave it unchanged",
1428
+ default="None",
1429
+ show_default=False
1430
+ ).strip()
1431
+ if descr and len(descr) > 25:
1432
+ click.echo("Description too long. Max 25 characters allowed.")
1433
+ return
1434
+ asyncio.run(async_update_node_at_start(node_type, descr, partners))
1435
+
1436
+ async def async_update_node_at_start(node_type: str, descr: str, partners:str) -> None:
1437
+ env_data = {}
1438
+
1439
+ try:
1440
+ with open(".env", "r") as f:
1441
+ for line in f:
1442
+ key, value = line.strip().split("=")
1443
+ env_data[key] = value
1444
+
1445
+ nodeID = env_data.get("NODE", "")
1446
+ host = env_data.get("HOST", "")
1447
+ password = env_data.get("PASSWORD", "")
1448
+ network = env_data.get("NETWORK", "")
1449
+ synapse = env_data.get("SYNAPSE", "")
1450
+
1451
+ except FileNotFoundError:
1452
+ click.echo("Error: .env with credentials not found")
1453
+ return
1454
+ except Exception as e:
1455
+ click.echo(f"Error reading .env file: {e}")
1456
+ return
1457
+
1458
+ try:
1459
+ with open("NODE.md", "r") as f:
1460
+ nodemd_file = f.read()
1461
+
1462
+ with open("config.json", "r") as f:
1463
+ config_file = f.read()
1464
+
1465
+ except FileNotFoundError:
1466
+ click.echo("Error: NODE.md file not found")
1467
+ return
1468
+ except Exception as e:
1469
+ click.echo(f"Error reading NODE.md file: {e}")
1470
+ return
1471
+
1472
+ if node_type == "partners":
1473
+ node_type = partners
1474
+
1475
+ url = f"https://{network}/api/update_node"
1476
+ node = {
1477
+ "nodeID": nodeID,
1478
+ "host": host,
1479
+ "password": password,
1480
+ "synapse": synapse,
1481
+ "node_type": node_type,
1482
+ "nodemd_file": nodemd_file,
1483
+ "config_file": config_file,
1484
+ "descr": descr,
1485
+ }
1486
+
1487
+ async with aiohttp.ClientSession() as session:
1488
+ try:
1489
+ async with session.post(url, json=node) as response:
1490
+ response.raise_for_status()
1491
+ data = await response.json()
1492
+ nodeID = data["nodeID"]
1493
+ node_url = data["node_url"]
1494
+ except aiohttp.ClientError as e:
1495
+ click.echo(f"Error sending request: {e}")
1496
+ return
1497
+
1498
+ if node_type == "public":
1499
+ click.echo(f"Neuronum Node '{nodeID}' updated! Visit: {node_url}")
1500
+ else:
1501
+ click.echo(f"Neuronum Node '{nodeID}' updated!")
1502
+
1503
+
1045
1504
  @click.command()
1046
1505
  def delete_node():
1047
1506
  asyncio.run(async_delete_node())
@@ -1219,6 +1678,7 @@ cli.add_command(view_cell)
1219
1678
  cli.add_command(disconnect_cell)
1220
1679
  cli.add_command(delete_cell)
1221
1680
  cli.add_command(init_node)
1681
+ cli.add_command(update_node)
1222
1682
  cli.add_command(start_node)
1223
1683
  cli.add_command(restart_node)
1224
1684
  cli.add_command(stop_node)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: neuronum
3
- Version: 7.0.2
3
+ Version: 7.0.4
4
4
  Summary: Official client library to interact with the Neuronum Network
5
5
  Home-page: https://neuronum.net
6
6
  Author: Neuronum Cybernetics
@@ -128,7 +128,7 @@ ping.html: A static HTML file used to render web-based responses.
128
128
 
129
129
  Change into Node folder
130
130
  ```sh
131
- cd node_node_id # change directory
131
+ cd Test App_<your_node_id>
132
132
  ```
133
133
 
134
134
  Start your Node:
@@ -154,7 +154,7 @@ cell = neuronum.Cell( # set Cell connection
154
154
  async def main():
155
155
 
156
156
  TX = "id::tx" # select the Transmitter TX
157
- data = {"say": "hello"}
157
+ data = {"ping": "node"}
158
158
  tx_response = await cell.activate_tx(TX, data) # activate TX - > get response back
159
159
  print(tx_response) # print tx response
160
160
 
@@ -163,7 +163,7 @@ asyncio.run(main())
163
163
 
164
164
  #### **CLI-based**
165
165
  ```sh
166
- neuronum activate --tx id::tx 'say:hello'
166
+ neuronum activate --tx id::tx 'ping:node'
167
167
  ```
168
168
 
169
169
  #### **Cellai (in Testing)**
@@ -0,0 +1,10 @@
1
+ cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ cli/main.py,sha256=oj3_-lFGFUlCNlZoKmKK2b9yIvAd6KdXCFNMdNc6fZo,51733
3
+ neuronum/__init__.py,sha256=tAdqNC9rByY_CwG63yAyEe34phBdQ_Vv3FyFpTXQ2wo,45
4
+ neuronum/neuronum.py,sha256=5OjJIAmY7haT6eJ3P767RFk-LTvNFRrlkjB9mOozgN8,17971
5
+ neuronum-7.0.4.dist-info/licenses/LICENSE.md,sha256=m7pw_FktMNCs4tcy2UXP3QQP2S_je28P1SepdYoo0Xo,1961
6
+ neuronum-7.0.4.dist-info/METADATA,sha256=QoAgYz-i7_mhznemchEjnTGI2l2y-Z36ZCZGebPluzM,5871
7
+ neuronum-7.0.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
8
+ neuronum-7.0.4.dist-info/entry_points.txt,sha256=XKYBcRNxGeJpZZkDPsa8HA_RaJ7Km_R_JaUq5T9Nk2U,42
9
+ neuronum-7.0.4.dist-info/top_level.txt,sha256=ru8Fr84cHm6oHr_DcJ8-uaq3RTiuCRFIr6AC8V0zPu4,13
10
+ neuronum-7.0.4.dist-info/RECORD,,
@@ -1,10 +0,0 @@
1
- cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- cli/main.py,sha256=jaRDzs_SRdr_2pkdUntg9IBNKfl5_TMB-RQJbgQMPZc,37766
3
- neuronum/__init__.py,sha256=tAdqNC9rByY_CwG63yAyEe34phBdQ_Vv3FyFpTXQ2wo,45
4
- neuronum/neuronum.py,sha256=5OjJIAmY7haT6eJ3P767RFk-LTvNFRrlkjB9mOozgN8,17971
5
- neuronum-7.0.2.dist-info/licenses/LICENSE.md,sha256=m7pw_FktMNCs4tcy2UXP3QQP2S_je28P1SepdYoo0Xo,1961
6
- neuronum-7.0.2.dist-info/METADATA,sha256=rjaMl_SCEQfxY7dTMnyuv4WxybF7mJqwQOpTddskqo0,5902
7
- neuronum-7.0.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
8
- neuronum-7.0.2.dist-info/entry_points.txt,sha256=XKYBcRNxGeJpZZkDPsa8HA_RaJ7Km_R_JaUq5T9Nk2U,42
9
- neuronum-7.0.2.dist-info/top_level.txt,sha256=ru8Fr84cHm6oHr_DcJ8-uaq3RTiuCRFIr6AC8V0zPu4,13
10
- neuronum-7.0.2.dist-info/RECORD,,