neuronum 5.8.3__tar.gz → 5.8.5__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.
- {neuronum-5.8.3/neuronum.egg-info → neuronum-5.8.5}/PKG-INFO +92 -4
- {neuronum-5.8.3 → neuronum-5.8.5}/README.md +91 -3
- {neuronum-5.8.3 → neuronum-5.8.5}/cli/main.py +20 -4
- {neuronum-5.8.3 → neuronum-5.8.5}/neuronum/neuronum.py +19 -15
- {neuronum-5.8.3 → neuronum-5.8.5/neuronum.egg-info}/PKG-INFO +92 -4
- {neuronum-5.8.3 → neuronum-5.8.5}/setup.py +1 -1
- {neuronum-5.8.3 → neuronum-5.8.5}/LICENSE.md +0 -0
- {neuronum-5.8.3 → neuronum-5.8.5}/cli/__init__.py +0 -0
- {neuronum-5.8.3 → neuronum-5.8.5}/neuronum/__init__.py +0 -0
- {neuronum-5.8.3 → neuronum-5.8.5}/neuronum.egg-info/SOURCES.txt +0 -0
- {neuronum-5.8.3 → neuronum-5.8.5}/neuronum.egg-info/dependency_links.txt +0 -0
- {neuronum-5.8.3 → neuronum-5.8.5}/neuronum.egg-info/entry_points.txt +0 -0
- {neuronum-5.8.3 → neuronum-5.8.5}/neuronum.egg-info/requires.txt +0 -0
- {neuronum-5.8.3 → neuronum-5.8.5}/neuronum.egg-info/top_level.txt +0 -0
- {neuronum-5.8.3 → neuronum-5.8.5}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: neuronum
|
|
3
|
-
Version: 5.8.
|
|
3
|
+
Version: 5.8.5
|
|
4
4
|
Summary: Official client library to interact with the Neuronum Network
|
|
5
5
|
Home-page: https://neuronum.net
|
|
6
6
|
Author: Neuronum Cybernetics
|
|
@@ -34,7 +34,7 @@ Dynamic: summary
|
|
|
34
34
|
<h1 align="center">
|
|
35
35
|
<img src="https://neuronum.net/static/neuronum.svg" alt="Neuronum" width="80">
|
|
36
36
|
</h1>
|
|
37
|
-
<h4 align="center">Neuronum:
|
|
37
|
+
<h4 align="center">Neuronum: Build Apps that Connect the World</h4>
|
|
38
38
|
|
|
39
39
|
<p align="center">
|
|
40
40
|
<a href="https://neuronum.net">
|
|
@@ -64,7 +64,7 @@ In this brief getting started guide, you will:
|
|
|
64
64
|
------------------
|
|
65
65
|
|
|
66
66
|
### **About Neuronum**
|
|
67
|
-
Neuronum empowers developers to build & connect apps, services, and devices into serverless networks able to exchange data in real time
|
|
67
|
+
Neuronum empowers developers to build, ship & connect apps, services, and devices into serverless networks able to exchange data in real time
|
|
68
68
|
|
|
69
69
|
### **Features**
|
|
70
70
|
**Cell & Nodes**
|
|
@@ -104,7 +104,7 @@ neuronum connect-cell # connect Cell
|
|
|
104
104
|
|
|
105
105
|
|
|
106
106
|
### **Build On Neuronum**
|
|
107
|
-
[
|
|
107
|
+
To dive deeper into Neuronum App development, visit & build with [Node Examples](https://github.com/neuronumcybernetics/neuronum/tree/main/features/nodes/examples)
|
|
108
108
|
|
|
109
109
|
|
|
110
110
|
Initialize a Node (app template):
|
|
@@ -112,6 +112,94 @@ Initialize a Node (app template):
|
|
|
112
112
|
neuronum init-node --app # initialize a Node with app template
|
|
113
113
|
```
|
|
114
114
|
|
|
115
|
+
This command prompts you to enter a Node description (e.g Getting Started Node) and creates a new directory named node_<node_id> containing the following files:
|
|
116
|
+
|
|
117
|
+
.env
|
|
118
|
+
```env
|
|
119
|
+
NODE=your_node_id
|
|
120
|
+
HOST=your_cell_id
|
|
121
|
+
PASSWORD=your_password
|
|
122
|
+
NETWORK=neuronum.net
|
|
123
|
+
SYNAPSE=your_synapse # auth token
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
app.py
|
|
127
|
+
```python
|
|
128
|
+
import asyncio
|
|
129
|
+
import neuronum
|
|
130
|
+
import os
|
|
131
|
+
from dotenv import load_dotenv
|
|
132
|
+
|
|
133
|
+
load_dotenv()
|
|
134
|
+
host = os.getenv("HOST")
|
|
135
|
+
password = os.getenv("PASSWORD")
|
|
136
|
+
network = os.getenv("NETWORK")
|
|
137
|
+
synapse = os.getenv("SYNAPSE")
|
|
138
|
+
|
|
139
|
+
cell = neuronum.Cell(
|
|
140
|
+
host=host,
|
|
141
|
+
password=password,
|
|
142
|
+
network=network,
|
|
143
|
+
synapse=synapse
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
async def main():
|
|
147
|
+
STX = "id::stx"
|
|
148
|
+
async for operation in cell.sync(STX):
|
|
149
|
+
txID = operation.get("txID")
|
|
150
|
+
client = operation.get("operator")
|
|
151
|
+
|
|
152
|
+
if txID == "id::tx":
|
|
153
|
+
data = {
|
|
154
|
+
"json": f"Hello {client}",
|
|
155
|
+
"html": f"""
|
|
156
|
+
<!DOCTYPE html>
|
|
157
|
+
<html>
|
|
158
|
+
<head>
|
|
159
|
+
<meta charset="UTF-8">
|
|
160
|
+
<title>Greeting Node</title>
|
|
161
|
+
</head>
|
|
162
|
+
<body>
|
|
163
|
+
<div class="card">
|
|
164
|
+
<h1>Hello, {client}</h1>
|
|
165
|
+
</div>
|
|
166
|
+
</body>
|
|
167
|
+
</html>
|
|
168
|
+
"""
|
|
169
|
+
|
|
170
|
+
}
|
|
171
|
+
await cell.tx_response(txID, client, data)
|
|
172
|
+
|
|
173
|
+
asyncio.run(main())
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
NODE.md
|
|
177
|
+
```
|
|
178
|
+
```json
|
|
179
|
+
{
|
|
180
|
+
"gateways": [
|
|
181
|
+
{
|
|
182
|
+
"type": "stream",
|
|
183
|
+
"id": "id::stx",
|
|
184
|
+
"link": "https://neuronum.net/stream/id::stx",
|
|
185
|
+
"info": "stream info"
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"type": "transmitter",
|
|
189
|
+
"id": "id::tx",
|
|
190
|
+
"link": "https://neuronum.net/tx/id::tx",
|
|
191
|
+
"info": "transmitter info"
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"type": "circuit",
|
|
195
|
+
"id": "id::ctx",
|
|
196
|
+
"link": "https://neuronum.net/circuit/id::ctx",
|
|
197
|
+
"info": "circuit info"
|
|
198
|
+
}
|
|
199
|
+
]
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
115
203
|
Change into Node folder
|
|
116
204
|
```sh
|
|
117
205
|
cd node_node_id # change directory
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<h1 align="center">
|
|
2
2
|
<img src="https://neuronum.net/static/neuronum.svg" alt="Neuronum" width="80">
|
|
3
3
|
</h1>
|
|
4
|
-
<h4 align="center">Neuronum:
|
|
4
|
+
<h4 align="center">Neuronum: Build Apps that Connect the World</h4>
|
|
5
5
|
|
|
6
6
|
<p align="center">
|
|
7
7
|
<a href="https://neuronum.net">
|
|
@@ -31,7 +31,7 @@ In this brief getting started guide, you will:
|
|
|
31
31
|
------------------
|
|
32
32
|
|
|
33
33
|
### **About Neuronum**
|
|
34
|
-
Neuronum empowers developers to build & connect apps, services, and devices into serverless networks able to exchange data in real time
|
|
34
|
+
Neuronum empowers developers to build, ship & connect apps, services, and devices into serverless networks able to exchange data in real time
|
|
35
35
|
|
|
36
36
|
### **Features**
|
|
37
37
|
**Cell & Nodes**
|
|
@@ -71,7 +71,7 @@ neuronum connect-cell # connect Cell
|
|
|
71
71
|
|
|
72
72
|
|
|
73
73
|
### **Build On Neuronum**
|
|
74
|
-
[
|
|
74
|
+
To dive deeper into Neuronum App development, visit & build with [Node Examples](https://github.com/neuronumcybernetics/neuronum/tree/main/features/nodes/examples)
|
|
75
75
|
|
|
76
76
|
|
|
77
77
|
Initialize a Node (app template):
|
|
@@ -79,6 +79,94 @@ Initialize a Node (app template):
|
|
|
79
79
|
neuronum init-node --app # initialize a Node with app template
|
|
80
80
|
```
|
|
81
81
|
|
|
82
|
+
This command prompts you to enter a Node description (e.g Getting Started Node) and creates a new directory named node_<node_id> containing the following files:
|
|
83
|
+
|
|
84
|
+
.env
|
|
85
|
+
```env
|
|
86
|
+
NODE=your_node_id
|
|
87
|
+
HOST=your_cell_id
|
|
88
|
+
PASSWORD=your_password
|
|
89
|
+
NETWORK=neuronum.net
|
|
90
|
+
SYNAPSE=your_synapse # auth token
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
app.py
|
|
94
|
+
```python
|
|
95
|
+
import asyncio
|
|
96
|
+
import neuronum
|
|
97
|
+
import os
|
|
98
|
+
from dotenv import load_dotenv
|
|
99
|
+
|
|
100
|
+
load_dotenv()
|
|
101
|
+
host = os.getenv("HOST")
|
|
102
|
+
password = os.getenv("PASSWORD")
|
|
103
|
+
network = os.getenv("NETWORK")
|
|
104
|
+
synapse = os.getenv("SYNAPSE")
|
|
105
|
+
|
|
106
|
+
cell = neuronum.Cell(
|
|
107
|
+
host=host,
|
|
108
|
+
password=password,
|
|
109
|
+
network=network,
|
|
110
|
+
synapse=synapse
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
async def main():
|
|
114
|
+
STX = "id::stx"
|
|
115
|
+
async for operation in cell.sync(STX):
|
|
116
|
+
txID = operation.get("txID")
|
|
117
|
+
client = operation.get("operator")
|
|
118
|
+
|
|
119
|
+
if txID == "id::tx":
|
|
120
|
+
data = {
|
|
121
|
+
"json": f"Hello {client}",
|
|
122
|
+
"html": f"""
|
|
123
|
+
<!DOCTYPE html>
|
|
124
|
+
<html>
|
|
125
|
+
<head>
|
|
126
|
+
<meta charset="UTF-8">
|
|
127
|
+
<title>Greeting Node</title>
|
|
128
|
+
</head>
|
|
129
|
+
<body>
|
|
130
|
+
<div class="card">
|
|
131
|
+
<h1>Hello, {client}</h1>
|
|
132
|
+
</div>
|
|
133
|
+
</body>
|
|
134
|
+
</html>
|
|
135
|
+
"""
|
|
136
|
+
|
|
137
|
+
}
|
|
138
|
+
await cell.tx_response(txID, client, data)
|
|
139
|
+
|
|
140
|
+
asyncio.run(main())
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
NODE.md
|
|
144
|
+
```
|
|
145
|
+
```json
|
|
146
|
+
{
|
|
147
|
+
"gateways": [
|
|
148
|
+
{
|
|
149
|
+
"type": "stream",
|
|
150
|
+
"id": "id::stx",
|
|
151
|
+
"link": "https://neuronum.net/stream/id::stx",
|
|
152
|
+
"info": "stream info"
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
"type": "transmitter",
|
|
156
|
+
"id": "id::tx",
|
|
157
|
+
"link": "https://neuronum.net/tx/id::tx",
|
|
158
|
+
"info": "transmitter info"
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
"type": "circuit",
|
|
162
|
+
"id": "id::ctx",
|
|
163
|
+
"link": "https://neuronum.net/circuit/id::ctx",
|
|
164
|
+
"info": "circuit info"
|
|
165
|
+
}
|
|
166
|
+
]
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
82
170
|
Change into Node folder
|
|
83
171
|
```sh
|
|
84
172
|
cd node_node_id # change directory
|
|
@@ -841,10 +841,23 @@ async def async_stop_node():
|
|
|
841
841
|
|
|
842
842
|
@click.command()
|
|
843
843
|
def update_node():
|
|
844
|
+
click.echo("Update your Node")
|
|
844
845
|
node_type = questionary.select(
|
|
845
|
-
"
|
|
846
|
-
choices=["public", "private"]
|
|
846
|
+
"Who can view your Node?:",
|
|
847
|
+
choices=["public", "private", "partners"]
|
|
847
848
|
).ask()
|
|
849
|
+
partners = "None"
|
|
850
|
+
if node_type == "partners":
|
|
851
|
+
prompt_msg = (
|
|
852
|
+
"Enter the list of partners who can view this Node.\n"
|
|
853
|
+
"Format: partner::cell, partner::cell, partner::cell\n"
|
|
854
|
+
"Press Enter to leave the list unchanged"
|
|
855
|
+
)
|
|
856
|
+
partners = click.prompt(
|
|
857
|
+
prompt_msg,
|
|
858
|
+
default="None",
|
|
859
|
+
show_default=False
|
|
860
|
+
).strip()
|
|
848
861
|
descr = click.prompt(
|
|
849
862
|
"Update Node description: Type up to 25 characters, or press Enter to leave it unchanged",
|
|
850
863
|
default="None",
|
|
@@ -853,9 +866,9 @@ def update_node():
|
|
|
853
866
|
if descr and len(descr) > 25:
|
|
854
867
|
click.echo("Description too long. Max 25 characters allowed.")
|
|
855
868
|
return
|
|
856
|
-
asyncio.run(async_update_node(node_type, descr))
|
|
869
|
+
asyncio.run(async_update_node(node_type, descr, partners))
|
|
857
870
|
|
|
858
|
-
async def async_update_node(node_type: str, descr: str) -> None:
|
|
871
|
+
async def async_update_node(node_type: str, descr: str, partners:str) -> None:
|
|
859
872
|
env_data = {}
|
|
860
873
|
|
|
861
874
|
try:
|
|
@@ -887,6 +900,9 @@ async def async_update_node(node_type: str, descr: str) -> None:
|
|
|
887
900
|
except Exception as e:
|
|
888
901
|
click.echo(f"Error reading NODE.md file: {e}")
|
|
889
902
|
return
|
|
903
|
+
|
|
904
|
+
if node_type == "partners":
|
|
905
|
+
node_type = partners
|
|
890
906
|
|
|
891
907
|
url = f"https://{network}/api/update_node"
|
|
892
908
|
node = {
|
|
@@ -82,17 +82,18 @@ class Cell:
|
|
|
82
82
|
|
|
83
83
|
async def sync(self, stx: Optional[str] = None) -> AsyncGenerator[str, None]:
|
|
84
84
|
full_url = f"wss://{self.network}/sync/{stx}"
|
|
85
|
-
|
|
86
85
|
auth_payload = {
|
|
87
86
|
"host": self.host,
|
|
88
87
|
"password": self.password,
|
|
89
88
|
"synapse": self.synapse,
|
|
90
89
|
}
|
|
91
90
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
91
|
+
while True:
|
|
92
|
+
try:
|
|
93
|
+
async with websockets.connect(full_url) as ws:
|
|
94
|
+
await ws.send(json.dumps(auth_payload))
|
|
95
|
+
print("Connected to WebSocket.")
|
|
96
|
+
|
|
96
97
|
while True:
|
|
97
98
|
try:
|
|
98
99
|
raw_operation = await ws.recv()
|
|
@@ -100,17 +101,20 @@ class Cell:
|
|
|
100
101
|
yield operation
|
|
101
102
|
|
|
102
103
|
except asyncio.TimeoutError:
|
|
103
|
-
print("No
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
104
|
+
print("No data received. Continuing...")
|
|
105
|
+
except websockets.exceptions.ConnectionClosedError as e:
|
|
106
|
+
print(f"Connection closed with error: {e}. Reconnecting...")
|
|
107
|
+
break
|
|
108
|
+
except Exception as e:
|
|
109
|
+
print(f"Unexpected error in recv loop: {e}")
|
|
110
|
+
break
|
|
111
|
+
|
|
112
|
+
except websockets.exceptions.WebSocketException as e:
|
|
113
|
+
print(f"WebSocket error occurred: {e}. Retrying in 5 seconds...")
|
|
114
|
+
except Exception as e:
|
|
115
|
+
print(f"General error occurred: {e}. Retrying in 5 seconds...")
|
|
111
116
|
|
|
112
|
-
|
|
113
|
-
print(f"An unexpected error occurred: {e}")
|
|
117
|
+
await asyncio.sleep(3)
|
|
114
118
|
|
|
115
119
|
|
|
116
120
|
async def create_tx(self, descr: str, key_values: dict, stx: str, label: str, partners: list):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: neuronum
|
|
3
|
-
Version: 5.8.
|
|
3
|
+
Version: 5.8.5
|
|
4
4
|
Summary: Official client library to interact with the Neuronum Network
|
|
5
5
|
Home-page: https://neuronum.net
|
|
6
6
|
Author: Neuronum Cybernetics
|
|
@@ -34,7 +34,7 @@ Dynamic: summary
|
|
|
34
34
|
<h1 align="center">
|
|
35
35
|
<img src="https://neuronum.net/static/neuronum.svg" alt="Neuronum" width="80">
|
|
36
36
|
</h1>
|
|
37
|
-
<h4 align="center">Neuronum:
|
|
37
|
+
<h4 align="center">Neuronum: Build Apps that Connect the World</h4>
|
|
38
38
|
|
|
39
39
|
<p align="center">
|
|
40
40
|
<a href="https://neuronum.net">
|
|
@@ -64,7 +64,7 @@ In this brief getting started guide, you will:
|
|
|
64
64
|
------------------
|
|
65
65
|
|
|
66
66
|
### **About Neuronum**
|
|
67
|
-
Neuronum empowers developers to build & connect apps, services, and devices into serverless networks able to exchange data in real time
|
|
67
|
+
Neuronum empowers developers to build, ship & connect apps, services, and devices into serverless networks able to exchange data in real time
|
|
68
68
|
|
|
69
69
|
### **Features**
|
|
70
70
|
**Cell & Nodes**
|
|
@@ -104,7 +104,7 @@ neuronum connect-cell # connect Cell
|
|
|
104
104
|
|
|
105
105
|
|
|
106
106
|
### **Build On Neuronum**
|
|
107
|
-
[
|
|
107
|
+
To dive deeper into Neuronum App development, visit & build with [Node Examples](https://github.com/neuronumcybernetics/neuronum/tree/main/features/nodes/examples)
|
|
108
108
|
|
|
109
109
|
|
|
110
110
|
Initialize a Node (app template):
|
|
@@ -112,6 +112,94 @@ Initialize a Node (app template):
|
|
|
112
112
|
neuronum init-node --app # initialize a Node with app template
|
|
113
113
|
```
|
|
114
114
|
|
|
115
|
+
This command prompts you to enter a Node description (e.g Getting Started Node) and creates a new directory named node_<node_id> containing the following files:
|
|
116
|
+
|
|
117
|
+
.env
|
|
118
|
+
```env
|
|
119
|
+
NODE=your_node_id
|
|
120
|
+
HOST=your_cell_id
|
|
121
|
+
PASSWORD=your_password
|
|
122
|
+
NETWORK=neuronum.net
|
|
123
|
+
SYNAPSE=your_synapse # auth token
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
app.py
|
|
127
|
+
```python
|
|
128
|
+
import asyncio
|
|
129
|
+
import neuronum
|
|
130
|
+
import os
|
|
131
|
+
from dotenv import load_dotenv
|
|
132
|
+
|
|
133
|
+
load_dotenv()
|
|
134
|
+
host = os.getenv("HOST")
|
|
135
|
+
password = os.getenv("PASSWORD")
|
|
136
|
+
network = os.getenv("NETWORK")
|
|
137
|
+
synapse = os.getenv("SYNAPSE")
|
|
138
|
+
|
|
139
|
+
cell = neuronum.Cell(
|
|
140
|
+
host=host,
|
|
141
|
+
password=password,
|
|
142
|
+
network=network,
|
|
143
|
+
synapse=synapse
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
async def main():
|
|
147
|
+
STX = "id::stx"
|
|
148
|
+
async for operation in cell.sync(STX):
|
|
149
|
+
txID = operation.get("txID")
|
|
150
|
+
client = operation.get("operator")
|
|
151
|
+
|
|
152
|
+
if txID == "id::tx":
|
|
153
|
+
data = {
|
|
154
|
+
"json": f"Hello {client}",
|
|
155
|
+
"html": f"""
|
|
156
|
+
<!DOCTYPE html>
|
|
157
|
+
<html>
|
|
158
|
+
<head>
|
|
159
|
+
<meta charset="UTF-8">
|
|
160
|
+
<title>Greeting Node</title>
|
|
161
|
+
</head>
|
|
162
|
+
<body>
|
|
163
|
+
<div class="card">
|
|
164
|
+
<h1>Hello, {client}</h1>
|
|
165
|
+
</div>
|
|
166
|
+
</body>
|
|
167
|
+
</html>
|
|
168
|
+
"""
|
|
169
|
+
|
|
170
|
+
}
|
|
171
|
+
await cell.tx_response(txID, client, data)
|
|
172
|
+
|
|
173
|
+
asyncio.run(main())
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
NODE.md
|
|
177
|
+
```
|
|
178
|
+
```json
|
|
179
|
+
{
|
|
180
|
+
"gateways": [
|
|
181
|
+
{
|
|
182
|
+
"type": "stream",
|
|
183
|
+
"id": "id::stx",
|
|
184
|
+
"link": "https://neuronum.net/stream/id::stx",
|
|
185
|
+
"info": "stream info"
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"type": "transmitter",
|
|
189
|
+
"id": "id::tx",
|
|
190
|
+
"link": "https://neuronum.net/tx/id::tx",
|
|
191
|
+
"info": "transmitter info"
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"type": "circuit",
|
|
195
|
+
"id": "id::ctx",
|
|
196
|
+
"link": "https://neuronum.net/circuit/id::ctx",
|
|
197
|
+
"info": "circuit info"
|
|
198
|
+
}
|
|
199
|
+
]
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
115
203
|
Change into Node folder
|
|
116
204
|
```sh
|
|
117
205
|
cd node_node_id # change directory
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|