neuronum 4.0.1__py3-none-any.whl → 5.1.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
@@ -249,10 +249,11 @@ def delete_cell():
249
249
  @click.command()
250
250
  @click.option('--sync', multiple=True, default=None, help="Optional stream IDs for sync.")
251
251
  @click.option('--stream', multiple=True, default=None, help="Optional stream ID for stream.")
252
- def init_node(sync, stream):
253
- asyncio.run(async_init_node(sync, stream))
252
+ @click.option('--app', is_flag=True, help="Generate a Node with app template")
253
+ def init_node(sync, stream, app):
254
+ asyncio.run(async_init_node(sync, stream, app))
254
255
 
255
- async def async_init_node(sync, stream):
256
+ async def async_init_node(sync, stream, app):
256
257
  credentials_folder_path = Path.home() / ".neuronum"
257
258
  env_path = credentials_folder_path / ".env"
258
259
 
@@ -319,13 +320,35 @@ async def async_init_node(sync, stream):
319
320
  await asyncio.to_thread(gitignore_path.write_text, ".env\n")
320
321
 
321
322
  nodemd_path = project_path / "NODE.md"
322
- await asyncio.to_thread(nodemd_path.write_text, """### Getting started template: Neuronum NODE.md
323
- ### Use this .md file to add instructions on how to interact with your Node
323
+ await asyncio.to_thread(nodemd_path.write_text, """### NODE.md: How to interact with this Node
324
324
 
325
325
  ```json
326
326
  {
327
- "Use Case": "Getting started Node streaming: Hello, Neuronum!",
328
- "Requirements": [
327
+ "info": {
328
+ "use_case": "This Node...",
329
+ "github": "https://github.com/user"
330
+ },
331
+ "gateways": [
332
+ {
333
+ "type": "stream",
334
+ "id": "id::stx",
335
+ "link": "https://neuronum.net/stream/id::stx"
336
+ },
337
+ {
338
+ "type": "transmitter",
339
+ "id": "id::tx",
340
+ "link": "https://neuronum.net/tx/id::tx",
341
+ }
342
+ {
343
+ "type": "circuit",
344
+ "id": "id::ctx",
345
+ "link": "https://neuronum.net/circuit/id::ctx",
346
+ }
347
+ ],
348
+ "initialization": {
349
+ "command": "neuronum init-node --sync id::stx"
350
+ },
351
+ "requirements": [
329
352
  {
330
353
  "name": "Python",
331
354
  "version": ">= 3.8",
@@ -333,12 +356,10 @@ async def async_init_node(sync, stream):
333
356
  },
334
357
  {
335
358
  "name": "neuronum",
336
- "version": ">= 4.0.0",
359
+ "version": ">= 5.1.0",
337
360
  "link": "https://pypi.org/project/neuronum/"
338
361
  }
339
- ],
340
- "Installation": "pip install neuronum",
341
- "Initialization": "neuronum init-node"
362
+ ]
342
363
  }
343
364
  ```"""
344
365
  )
@@ -418,7 +439,7 @@ async def main():
418
439
  asyncio.run(main())
419
440
  """)
420
441
 
421
- if not sync and not stream:
442
+ if not sync and not stream and not app:
422
443
  sync_path = project_path / f"sync_{stx.replace('::stx', '')}.py"
423
444
  sync_path.write_text(f"""\
424
445
  import asyncio
@@ -476,6 +497,56 @@ async def main():
476
497
  }}
477
498
  await cell.stream(label, data)
478
499
 
500
+ asyncio.run(main())
501
+ """)
502
+
503
+ if app:
504
+ app_path = project_path / "app.py"
505
+ app_path.write_text(f"""\
506
+ import asyncio
507
+ import neuronum
508
+ import os
509
+ from dotenv import load_dotenv
510
+
511
+ load_dotenv()
512
+ host = os.getenv("HOST")
513
+ password = os.getenv("PASSWORD")
514
+ network = os.getenv("NETWORK")
515
+ synapse = os.getenv("SYNAPSE")
516
+
517
+ cell = neuronum.Cell(
518
+ host=host,
519
+ password=password,
520
+ network=network,
521
+ synapse=synapse
522
+ )
523
+
524
+ async def main():
525
+ STX = "id::stx"
526
+ async for operation in cell.sync(STX):
527
+ txID = operation.get("txID")
528
+
529
+ if txID == "id::tx":
530
+ client = operation.get("operator")
531
+ data = {{
532
+ "response": "TX activated!"
533
+ }}
534
+ await cell.tx_response(txID, client, data)
535
+
536
+ if txID == "id::tx":
537
+ client = operation.get("operator")
538
+ data = {{
539
+ "response": "TX activated!"
540
+ }}
541
+ await cell.tx_response(txID, client, data)
542
+
543
+ if txID == "id::tx":
544
+ client = operation.get("operator")
545
+ data = {{
546
+ "response": "TX activated!"
547
+ }}
548
+ await cell.tx_response(txID, client, data)
549
+
479
550
  asyncio.run(main())
480
551
  """)
481
552
 
@@ -488,7 +559,7 @@ def start_node(d):
488
559
  click.echo("Starting Node...")
489
560
 
490
561
  project_path = Path.cwd()
491
- script_files = glob.glob("sync_*.py") + glob.glob("stream_*.py")
562
+ script_files = glob.glob("sync_*.py") + glob.glob("stream_*.py") + glob.glob("app.py")
492
563
 
493
564
  processes = []
494
565
  system_name = platform.system()
neuronum/neuronum.py CHANGED
@@ -13,6 +13,7 @@ class Cell:
13
13
  self.synapse = synapse
14
14
  self.queue = asyncio.Queue()
15
15
 
16
+
16
17
  def to_dict(self) -> dict:
17
18
  return {
18
19
  "host": self.host,
@@ -20,8 +21,98 @@ class Cell:
20
21
  "synapse": self.synapse
21
22
  }
22
23
 
24
+
23
25
  def __repr__(self) -> str:
24
26
  return f"Cell(host={self.host}, password={self.password}, network={self.network}, synapse={self.synapse})"
27
+
28
+
29
+ async def stream(self, label: str, data: dict, stx: Optional[str] = None, retry_delay: int = 3):
30
+ context = ssl.create_default_context()
31
+ context.check_hostname = True
32
+ context.verify_mode = ssl.CERT_REQUIRED
33
+
34
+ while True:
35
+ try:
36
+ reader, writer = await asyncio.open_connection(self.network, 55555, ssl=context, server_hostname=self.network)
37
+
38
+ credentials = f"{self.host}\n{self.password}\n{self.synapse}\n{stx}\n"
39
+ writer.write(credentials.encode("utf-8"))
40
+ await writer.drain()
41
+
42
+ response = await reader.read(1024)
43
+ response_text = response.decode("utf-8").strip()
44
+
45
+ if "Authentication successful" not in response_text:
46
+ print("Authentication failed, retrying...")
47
+ writer.close()
48
+ await writer.wait_closed()
49
+ await asyncio.sleep(retry_delay)
50
+ continue
51
+
52
+ stream_payload = {
53
+ "label": label,
54
+ "data": data,
55
+ }
56
+
57
+ writer.write(json.dumps(stream_payload).encode("utf-8"))
58
+ await writer.drain()
59
+
60
+ response = await reader.read(1024)
61
+ response_text = response.decode("utf-8").strip()
62
+
63
+ if response_text == "Sent":
64
+ print(f"Success: {response_text} - {stream_payload}")
65
+ break
66
+ else:
67
+ print(f"Error sending: {stream_payload}")
68
+
69
+ except (ssl.SSLError, ConnectionError) as e:
70
+ print(f"Connection error: {e}, retrying...")
71
+ await asyncio.sleep(retry_delay)
72
+
73
+ except Exception as e:
74
+ print(f"Unexpected error: {e}, retrying...")
75
+ await asyncio.sleep(retry_delay)
76
+
77
+ finally:
78
+ if 'writer' in locals():
79
+ writer.close()
80
+ await writer.wait_closed()
81
+
82
+
83
+ async def sync(self, stx: Optional[str] = None) -> AsyncGenerator[str, None]:
84
+ full_url = f"wss://{self.network}/sync/{stx}"
85
+
86
+ auth_payload = {
87
+ "host": self.host,
88
+ "password": self.password,
89
+ "synapse": self.synapse,
90
+ }
91
+
92
+ try:
93
+ async with websockets.connect(full_url) as ws:
94
+ await ws.send(json.dumps(auth_payload))
95
+ print("Listening to Stream...")
96
+
97
+ try:
98
+ while True:
99
+ try:
100
+ raw_operation = await ws.recv()
101
+ operation = json.loads(raw_operation)
102
+ yield operation
103
+
104
+ except asyncio.TimeoutError:
105
+ print("No initial data received. Continuing to listen...")
106
+ continue
107
+
108
+ except asyncio.CancelledError:
109
+ print("Connection closed.")
110
+
111
+ except websockets.exceptions.WebSocketException as e:
112
+ print(f"WebSocket error occurred: {e}")
113
+
114
+ except Exception as e:
115
+ print(f"An unexpected error occurred: {e}")
25
116
 
26
117
 
27
118
  async def create_tx(self, descr: str, key_values: dict, stx: str, label: str, partners: list):
@@ -73,7 +164,6 @@ class Cell:
73
164
 
74
165
  async def activate_tx(self, txID: str, data: dict):
75
166
  url = f"https://{self.network}/api/activate_tx/{txID}"
76
-
77
167
  TX = {
78
168
  "data": data,
79
169
  "cell": self.to_dict()
@@ -82,10 +172,40 @@ class Cell:
82
172
  async with aiohttp.ClientSession() as session:
83
173
  try:
84
174
  async with session.post(url, json=TX) as response:
85
- response.raise_for_status()
86
175
  response.raise_for_status()
87
176
  data = await response.json()
88
- print(data["message"])
177
+ if data["success"] == "activated":
178
+ async for operation in self.sync():
179
+ label = operation.get("label")
180
+ if label == "tx_response":
181
+ operation_txID = operation.get("txID")
182
+ if operation_txID == txID:
183
+ return operation.get("data")
184
+ else:
185
+ print(data["success"], data["message"])
186
+
187
+ except aiohttp.ClientError as e:
188
+ print(f"Error sending request: {e}")
189
+ except Exception as e:
190
+ print(f"Unexpected error: {e}")
191
+
192
+
193
+ async def tx_response(self, txID: str, client: str, data: dict):
194
+ url = f"https://{self.network}/api/tx_response/{txID}"
195
+
196
+ tx_response = {
197
+ "client": client,
198
+ "data": data,
199
+ "cell": self.to_dict()
200
+ }
201
+
202
+ async with aiohttp.ClientSession() as session:
203
+ try:
204
+ for _ in range(2):
205
+ async with session.post(url, json=tx_response) as response:
206
+ response.raise_for_status()
207
+ data = await response.json()
208
+ print(data["message"])
89
209
 
90
210
  except aiohttp.ClientError as e:
91
211
  print(f"Error sending request: {e}")
@@ -368,80 +488,4 @@ class Cell:
368
488
  print(f"Unexpected error: {e}")
369
489
 
370
490
 
371
- async def stream(self, label: str, data: dict, stx: Optional[str] = None):
372
- context = ssl.create_default_context()
373
- context.check_hostname = True
374
- context.verify_mode = ssl.CERT_REQUIRED
375
-
376
- try:
377
- reader, writer = await asyncio.open_connection(self.network, 55555, ssl=context, server_hostname=self.network)
378
-
379
- credentials = f"{self.host}\n{self.password}\n{self.synapse}\n{stx}\n"
380
- writer.write(credentials.encode("utf-8"))
381
- await writer.drain()
382
-
383
- response = await reader.read(1024)
384
- response_text = response.decode("utf-8")
385
-
386
- if "Authentication successful" not in response_text:
387
- print("Authentication failed")
388
- writer.close()
389
- await writer.wait_closed()
390
- return
391
-
392
- stream_payload = {
393
- "label": label,
394
- "data": data,
395
- }
396
-
397
- writer.write(json.dumps(stream_payload).encode("utf-8"))
398
- await writer.drain()
399
- print(f"Sent: {stream_payload}")
400
-
401
- except ssl.SSLError as e:
402
- print(f"SSL error occurred: {e}")
403
-
404
- except Exception as e:
405
- print(f"An unexpected error occurred: {e}")
406
-
407
- finally:
408
- writer.close()
409
- await writer.wait_closed()
410
-
411
-
412
- async def sync(self, stx: Optional[str] = None) -> AsyncGenerator[str, None]:
413
- full_url = f"wss://{self.network}/sync/{stx}"
414
-
415
- auth_payload = {
416
- "host": self.host,
417
- "password": self.password,
418
- "synapse": self.synapse,
419
- }
420
-
421
- try:
422
- async with websockets.connect(full_url) as ws:
423
- await ws.send(json.dumps(auth_payload))
424
- print("Listening to Stream...")
425
-
426
- try:
427
- while True:
428
- try:
429
- raw_operation = await ws.recv()
430
- operation = json.loads(raw_operation)
431
- yield operation
432
-
433
- except asyncio.TimeoutError:
434
- print("No initial data received. Continuing to listen...")
435
- continue
436
-
437
- except asyncio.CancelledError:
438
- print("Connection closed.")
439
-
440
- except websockets.exceptions.WebSocketException as e:
441
- print(f"WebSocket error occurred: {e}")
442
-
443
- except Exception as e:
444
- print(f"An unexpected error occurred: {e}")
445
-
446
-
447
491
  __all__ = ['Cell']
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: neuronum
3
- Version: 4.0.1
3
+ Version: 5.1.0
4
4
  Summary: Official client library to interact with the Neuronum Network
5
5
  Home-page: https://neuronum.net
6
6
  Author: Neuronum Cybernetics
@@ -35,23 +35,23 @@ Dynamic: summary
35
35
  [![Website](https://img.shields.io/badge/Website-Neuronum-blue)](https://neuronum.net) [![Documentation](https://img.shields.io/badge/Docs-Read%20now-green)](https://github.com/neuronumcybernetics/neuronum)
36
36
 
37
37
 
38
- ### **Getting Started Goals**
38
+ ## **Getting Started Goals**
39
39
  - Learn about Neuronum
40
40
  - Connect to Neuronum
41
41
  - Build on Neuronum
42
42
 
43
43
 
44
44
  ### **About Neuronum**
45
- Neuronum is a framework to build serverless data gateways automating the processing and distribution of data transmission, storage, and streaming.
45
+ Neuronum is a framework to build serverless connected app & data gateways automating the processing and distribution of data transmission, storage, and streaming.
46
46
 
47
47
 
48
- ### **Neuronum Attributes**
48
+ ### **Features**
49
49
  **Cell & Nodes**
50
50
  - Cell: Account to connect and interact with Neuronum
51
- - Nodes: Soft- and Hardware components hosting data gateways
51
+ - Nodes: Soft- and Hardware components hosting gateways
52
52
 
53
- **Data Gateways**
54
- - Transmitters (TX): Automate data transfer in standardized formats
53
+ **Gateways**
54
+ - Transmitters (TX): Securely transmit and receive data packages
55
55
  - Circuits (CTX): Store data in cloud-based key-value-label databases
56
56
  - Streams (STX): Stream, synchronize, and control data in real time
57
57
 
@@ -75,6 +75,12 @@ Create Cell:
75
75
  neuronum create-cell # create Cell / Cell type / Cell network
76
76
  ```
77
77
 
78
+ or
79
+
80
+ Connect Cell:
81
+ ```sh
82
+ neuronum connect-cell # connect Cell
83
+ ```
78
84
 
79
85
  View connected Cell:
80
86
  ```sh
@@ -86,11 +92,25 @@ neuronum view-cell # view Cell / output = Connected Cell: '
86
92
 
87
93
 
88
94
  ### **Build on Neuronum**
95
+ **Node Examples:**
96
+ Visit: https://github.com/neuronumcybernetics/neuronum/tree/main/how_tos/nodes
97
+
89
98
  Initialize Node (default template):
90
99
  ```sh
91
100
  neuronum init-node # initialize a Node with default template
92
101
  ```
93
102
 
103
+ Start Node:
104
+ ```sh
105
+ neuronum start-node # start Node
106
+ ```
94
107
 
95
- **Node Examples:**
96
- Visit: https://github.com/neuronumcybernetics/neuronum/tree/main/how_tos/nodes
108
+ Stop Node:
109
+ ```sh
110
+ neuronum stop-node # stop Node
111
+ ```
112
+
113
+ Connect Node to Neuronum:
114
+ ```sh
115
+ neuronum connect-node # connect Node
116
+ ```
@@ -0,0 +1,10 @@
1
+ cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ cli/main.py,sha256=tklC9GhJCB-zR26djn9D3ke6P6SGR2Jq66mG1a1Si3g,26848
3
+ neuronum/__init__.py,sha256=Drsm263_w3_VWgl1YsKLUr8WwVodqV3TSjqpxLjyq_M,46
4
+ neuronum/neuronum.py,sha256=qzxc9csSEnGX8wRC_14vzjJPQsCTC8wswhXno1Ih_Xw,17166
5
+ neuronum-5.1.0.dist-info/licenses/LICENSE,sha256=UiZjNHiCyRP6WoZfbYQh9cv4JW96wIofKXmzBJrYSUk,1125
6
+ neuronum-5.1.0.dist-info/METADATA,sha256=zgR264a9Ukp5wE7tIfNkbqCOpGB_vdA3vWqvJSnYZZc,3060
7
+ neuronum-5.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
8
+ neuronum-5.1.0.dist-info/entry_points.txt,sha256=XKYBcRNxGeJpZZkDPsa8HA_RaJ7Km_R_JaUq5T9Nk2U,42
9
+ neuronum-5.1.0.dist-info/top_level.txt,sha256=ru8Fr84cHm6oHr_DcJ8-uaq3RTiuCRFIr6AC8V0zPu4,13
10
+ neuronum-5.1.0.dist-info/RECORD,,
@@ -1,10 +0,0 @@
1
- cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- cli/main.py,sha256=g7Y-W1G7C1firXHsEnBFyqa52nSk6GVzcax_6up0Ezg,24991
3
- neuronum/__init__.py,sha256=Drsm263_w3_VWgl1YsKLUr8WwVodqV3TSjqpxLjyq_M,46
4
- neuronum/neuronum.py,sha256=botQ0FJIf5e00MqfUeIcD6aAchys9vSsQ3ymj8YzGMc,15223
5
- neuronum-4.0.1.dist-info/licenses/LICENSE,sha256=UiZjNHiCyRP6WoZfbYQh9cv4JW96wIofKXmzBJrYSUk,1125
6
- neuronum-4.0.1.dist-info/METADATA,sha256=SVe3ktDGVnjOpjl4PXi0QtIFOgW84Mr0TzfDJpivwsY,2725
7
- neuronum-4.0.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
8
- neuronum-4.0.1.dist-info/entry_points.txt,sha256=XKYBcRNxGeJpZZkDPsa8HA_RaJ7Km_R_JaUq5T9Nk2U,42
9
- neuronum-4.0.1.dist-info/top_level.txt,sha256=ru8Fr84cHm6oHr_DcJ8-uaq3RTiuCRFIr6AC8V0zPu4,13
10
- neuronum-4.0.1.dist-info/RECORD,,