naeural-client 2.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.
- naeural_client/__init__.py +13 -0
- naeural_client/_ver.py +13 -0
- naeural_client/base/__init__.py +6 -0
- naeural_client/base/distributed_custom_code_presets.py +44 -0
- naeural_client/base/generic_session.py +1763 -0
- naeural_client/base/instance.py +616 -0
- naeural_client/base/payload/__init__.py +1 -0
- naeural_client/base/payload/payload.py +66 -0
- naeural_client/base/pipeline.py +1499 -0
- naeural_client/base/plugin_template.py +5209 -0
- naeural_client/base/responses.py +209 -0
- naeural_client/base/transaction.py +157 -0
- naeural_client/base_decentra_object.py +143 -0
- naeural_client/bc/__init__.py +3 -0
- naeural_client/bc/base.py +1046 -0
- naeural_client/bc/chain.py +0 -0
- naeural_client/bc/ec.py +324 -0
- naeural_client/certs/__init__.py +0 -0
- naeural_client/certs/r9092118.ala.eu-central-1.emqxsl.com.crt +22 -0
- naeural_client/code_cheker/__init__.py +1 -0
- naeural_client/code_cheker/base.py +520 -0
- naeural_client/code_cheker/checker.py +294 -0
- naeural_client/comm/__init__.py +2 -0
- naeural_client/comm/amqp_wrapper.py +338 -0
- naeural_client/comm/mqtt_wrapper.py +539 -0
- naeural_client/const/README.md +3 -0
- naeural_client/const/__init__.py +9 -0
- naeural_client/const/base.py +101 -0
- naeural_client/const/comms.py +80 -0
- naeural_client/const/environment.py +26 -0
- naeural_client/const/formatter.py +7 -0
- naeural_client/const/heartbeat.py +111 -0
- naeural_client/const/misc.py +20 -0
- naeural_client/const/payload.py +190 -0
- naeural_client/default/__init__.py +1 -0
- naeural_client/default/instance/__init__.py +4 -0
- naeural_client/default/instance/chain_dist_custom_job_01_plugin.py +54 -0
- naeural_client/default/instance/custom_web_app_01_plugin.py +118 -0
- naeural_client/default/instance/net_mon_01_plugin.py +45 -0
- naeural_client/default/instance/view_scene_01_plugin.py +28 -0
- naeural_client/default/session/mqtt_session.py +72 -0
- naeural_client/io_formatter/__init__.py +2 -0
- naeural_client/io_formatter/base/__init__.py +1 -0
- naeural_client/io_formatter/base/base_formatter.py +80 -0
- naeural_client/io_formatter/default/__init__.py +3 -0
- naeural_client/io_formatter/default/a_dummy.py +51 -0
- naeural_client/io_formatter/default/aixp1.py +113 -0
- naeural_client/io_formatter/default/default.py +22 -0
- naeural_client/io_formatter/io_formatter_manager.py +96 -0
- naeural_client/logging/__init__.py +1 -0
- naeural_client/logging/base_logger.py +2056 -0
- naeural_client/logging/logger_mixins/__init__.py +12 -0
- naeural_client/logging/logger_mixins/class_instance_mixin.py +92 -0
- naeural_client/logging/logger_mixins/computer_vision_mixin.py +443 -0
- naeural_client/logging/logger_mixins/datetime_mixin.py +344 -0
- naeural_client/logging/logger_mixins/download_mixin.py +421 -0
- naeural_client/logging/logger_mixins/general_serialization_mixin.py +242 -0
- naeural_client/logging/logger_mixins/json_serialization_mixin.py +481 -0
- naeural_client/logging/logger_mixins/pickle_serialization_mixin.py +301 -0
- naeural_client/logging/logger_mixins/process_mixin.py +63 -0
- naeural_client/logging/logger_mixins/resource_size_mixin.py +81 -0
- naeural_client/logging/logger_mixins/timers_mixin.py +501 -0
- naeural_client/logging/logger_mixins/upload_mixin.py +260 -0
- naeural_client/logging/logger_mixins/utils_mixin.py +675 -0
- naeural_client/logging/small_logger.py +93 -0
- naeural_client/logging/tzlocal/__init__.py +20 -0
- naeural_client/logging/tzlocal/unix.py +231 -0
- naeural_client/logging/tzlocal/utils.py +113 -0
- naeural_client/logging/tzlocal/win32.py +151 -0
- naeural_client/logging/tzlocal/windows_tz.py +718 -0
- naeural_client/plugins_manager_mixin.py +273 -0
- naeural_client/utils/__init__.py +2 -0
- naeural_client/utils/comm_utils.py +44 -0
- naeural_client/utils/dotenv.py +75 -0
- naeural_client-2.0.0.dist-info/METADATA +365 -0
- naeural_client-2.0.0.dist-info/RECORD +78 -0
- naeural_client-2.0.0.dist-info/WHEEL +4 -0
- naeural_client-2.0.0.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,365 @@
|
|
1
|
+
Metadata-Version: 2.3
|
2
|
+
Name: naeural_client
|
3
|
+
Version: 2.0.0
|
4
|
+
Summary: `naeural_client` is the Python SDK required for client app development for the Naeural Edge Protocol framework
|
5
|
+
Project-URL: Homepage, https://github.com/NaeuralEdgeProtocol/naeural_client
|
6
|
+
Project-URL: Bug Tracker, https://github.com/NaeuralEdgeProtocol/naeural_client/issues
|
7
|
+
Author-email: Stefan Saraev <saraevstefan@gmail.com>, Andrei Ionut Damian <andrei.damian@me.com>, Cristan Bleotiu <cristibleotiu@gmail.com>
|
8
|
+
License-File: LICENSE
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
10
|
+
Classifier: Operating System :: OS Independent
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
12
|
+
Requires-Python: >=3.8
|
13
|
+
Requires-Dist: cryptography>=39.0.0
|
14
|
+
Requires-Dist: numpy
|
15
|
+
Requires-Dist: paho-mqtt
|
16
|
+
Requires-Dist: pika
|
17
|
+
Requires-Dist: pyaml
|
18
|
+
Requires-Dist: pyopenssl>=23.0.0
|
19
|
+
Requires-Dist: python-dateutil
|
20
|
+
Description-Content-Type: text/markdown
|
21
|
+
|
22
|
+
# PyE2 SDK
|
23
|
+
|
24
|
+
This is the Python SDK package that allows interactions, development and deployment of jobs in Naeural network. The SDK enables low-code development and deployment of end-to-end AI (and not only) cooperative application pipelines within the Naeural Execution Engine processing nodes ecosystem. For further information please see [Naeural AI OS - Decentralized ubiquitous computing MLOps execution engine](https://arxiv.org/pdf/2306.08708).
|
25
|
+
|
26
|
+
## Dependencies
|
27
|
+
|
28
|
+
This packet depends on the following packets: `pika`, `paho-mqtt`, `numpy`, `pyopenssl>=23.0.0`, `cryptography>=39.0.0`, `python-dateutil`, `pyaml`.
|
29
|
+
|
30
|
+
## Installation
|
31
|
+
|
32
|
+
```shell
|
33
|
+
python -m pip install PyE2
|
34
|
+
```
|
35
|
+
|
36
|
+
## Documentation
|
37
|
+
|
38
|
+
Minimal documentation will be presented here. The complete documentation is
|
39
|
+
Work in Progress.
|
40
|
+
|
41
|
+
Code examples are located in the `tutorials` folder in the project's repository.
|
42
|
+
|
43
|
+
## Quick start guides
|
44
|
+
|
45
|
+
Here you will find a selection of guides and documentation snippets to get
|
46
|
+
you started with the `PyE2` SDK. These are only the most important aspects,
|
47
|
+
selected from the documentation and from the code examples. For more
|
48
|
+
in-depth information, please consult the examples from the repository
|
49
|
+
and the documentation.
|
50
|
+
|
51
|
+
### Naming conventions & FAQs
|
52
|
+
|
53
|
+
The following are the same:
|
54
|
+
|
55
|
+
- `Signature == Plugin's name`
|
56
|
+
- `Plugin ~ Instance` (Only in the context of talking about a running plugin (instance); people tend to omit the word `instance`)
|
57
|
+
- `Node == Worker` (Unless it is in the context of a distributed job, the 2 words refer to the same thing)
|
58
|
+
|
59
|
+
## Hello world tutorial
|
60
|
+
|
61
|
+
Below is a simple "Hello world!" style application that aims to show how simple and straightforward it is to distribute existing Python code to multiple edge node workers.
|
62
|
+
|
63
|
+
To execute this code, you can check [tutorials/video_presentation/1. hello_world.ipynb](./tutorials/video_presentation/1.%20hello_world.ipynb)
|
64
|
+
|
65
|
+
### 1. Create `.env` file
|
66
|
+
|
67
|
+
Copy the `tutorials/.example_env` file to your project directory and rename it to `.env`.
|
68
|
+
|
69
|
+
Fill in the empty variables with appropriate values.
|
70
|
+
|
71
|
+
### 2. Create new / Use test private key
|
72
|
+
|
73
|
+
**Disclaimer: You should never publish sensitive information such as private keys.**
|
74
|
+
|
75
|
+
To experiment on our test net, you can use the provided private key to communicate with the 3 nodes in the test network.
|
76
|
+
|
77
|
+
#### Create new private key
|
78
|
+
|
79
|
+
When first connecting to our network, the sdk will search in the current working directory for an existing private key. If not found, the SDK will create one at `$(cwd)/_local_cache/_data/_pk_sdk.pem`.
|
80
|
+
|
81
|
+
#### Using an existing private key
|
82
|
+
|
83
|
+
To use an existing private key, create in the working directory the directory tree `_local_cache/_data/` and add the `_pk_sdk.pem` file there.
|
84
|
+
|
85
|
+
To use our provided key. copy it from `tutorials/_example_pk_sdk.pem` to `local_cache/_data/` and change its name to `_pk_sdk.pem`.
|
86
|
+
|
87
|
+
### 3. Local Execution
|
88
|
+
|
89
|
+
We want to find all $168$ prime numbers in the interval $1$ - $1000$. For this we can run the following code on our local machine.
|
90
|
+
|
91
|
+
This code has segments running on multiple threads using a ThreadPool.
|
92
|
+
|
93
|
+
```python
|
94
|
+
import numpy as np
|
95
|
+
from concurrent.futures import ThreadPoolExecutor
|
96
|
+
|
97
|
+
|
98
|
+
def local_brute_force_prime_number_generator():
|
99
|
+
def is_prime(n):
|
100
|
+
if n <= 1:
|
101
|
+
return False
|
102
|
+
for i in range(2, int(np.sqrt(n)) + 1):
|
103
|
+
if n % i == 0:
|
104
|
+
return False
|
105
|
+
return True
|
106
|
+
|
107
|
+
random_numbers = np.random.randint(1, 1000, 20)
|
108
|
+
|
109
|
+
thread_pool = ThreadPoolExecutor(max_workers=4)
|
110
|
+
are_primes = list(thread_pool.map(is_prime, random_numbers))
|
111
|
+
|
112
|
+
prime_numbers = []
|
113
|
+
for i in range(len(random_numbers)):
|
114
|
+
if are_primes[i]:
|
115
|
+
prime_numbers.append(random_numbers[i])
|
116
|
+
|
117
|
+
return prime_numbers
|
118
|
+
|
119
|
+
|
120
|
+
if __name__ == "__main__":
|
121
|
+
found_so_far = []
|
122
|
+
|
123
|
+
print_step = 0
|
124
|
+
|
125
|
+
while len(found_so_far) < 168:
|
126
|
+
# compute a batch of prime numbers
|
127
|
+
prime_numbers = local_brute_force_prime_number_generator()
|
128
|
+
|
129
|
+
# keep only the new prime numbers
|
130
|
+
for prime_number in prime_numbers:
|
131
|
+
if prime_number not in found_so_far:
|
132
|
+
found_so_far.append(prime_number)
|
133
|
+
# end for
|
134
|
+
|
135
|
+
# show progress
|
136
|
+
if print_step % 50 == 0:
|
137
|
+
print("Found so far: {}: {}\n".format(len(found_so_far), sorted(found_so_far)))
|
138
|
+
|
139
|
+
print_step += 1
|
140
|
+
# end while
|
141
|
+
|
142
|
+
# show final result
|
143
|
+
print("Found so far: {}: {}\n".format(len(found_so_far), sorted(found_so_far)))
|
144
|
+
```
|
145
|
+
|
146
|
+
We can see that we have a `local_brute_force_prime_number_generator` method which will generate a random sample of $20$ numbers that will be checked if they are prime or not.
|
147
|
+
|
148
|
+
The rest of the code handles how the numbers generated with this method are kept.
|
149
|
+
Because we want to find $168$ unique numbers, we append to the list of found primes only the numbers that are not present yet.
|
150
|
+
|
151
|
+
At the end, we want to show a list of all the numbers found.
|
152
|
+
|
153
|
+
### 4. Remote Execution
|
154
|
+
|
155
|
+
For this example we would like to use multiple edge nodes to find the prime numbers faster.
|
156
|
+
|
157
|
+
To execute this code on our network, a series of changes must be made to the `local_brute_force_prime_number_generator` method.
|
158
|
+
These changes are the only ones a developer has to do to deploy his own custom code on the network.
|
159
|
+
|
160
|
+
For this, we will create a new method, `remote_brute_force_prime_number_generator`, which will use the exposed edge node API methods.
|
161
|
+
|
162
|
+
```python
|
163
|
+
from PyE2 import CustomPluginTemplate
|
164
|
+
|
165
|
+
# through the `plugin` object we get access to the edge node API
|
166
|
+
# the CustomPluginTemplate class acts as a documentation for all the available methods and attributes
|
167
|
+
# since we do not allow imports in the custom code due to security reasons, the `plugin` object
|
168
|
+
# exposes common modules to the user
|
169
|
+
def remote_brute_force_prime_number_generator(plugin: CustomPluginTemplate):
|
170
|
+
def is_prime(n):
|
171
|
+
if n <= 1:
|
172
|
+
return False
|
173
|
+
# we use the `plugin.np` instead of the `np` module
|
174
|
+
for i in range(2, int(plugin.np.sqrt(n)) + 1):
|
175
|
+
if n % i == 0:
|
176
|
+
return False
|
177
|
+
return True
|
178
|
+
|
179
|
+
# we use the `plugin.np` instead of the `np` module
|
180
|
+
random_numbers = plugin.np.random.randint(1, 1000, 20)
|
181
|
+
|
182
|
+
# we use the `plugin.threadapi_map` instead of the `ThreadPoolExecutor.map`
|
183
|
+
are_primes = plugin.threadapi_map(is_prime, random_numbers, n_threads=4)
|
184
|
+
|
185
|
+
prime_numbers = []
|
186
|
+
for i in range(len(random_numbers)):
|
187
|
+
if are_primes[i]:
|
188
|
+
prime_numbers.append(random_numbers[i])
|
189
|
+
|
190
|
+
return prime_numbers
|
191
|
+
```
|
192
|
+
|
193
|
+
This are all the changes we have to do to deploy this code in the network.
|
194
|
+
|
195
|
+
Now lets connect to the network and see what nodes are online.
|
196
|
+
We will use the `on_heartbeat` callback to print the nodes.
|
197
|
+
|
198
|
+
```python
|
199
|
+
from PyE2 import Session
|
200
|
+
from time import sleep
|
201
|
+
|
202
|
+
def on_heartbeat(session: Session, node: str, heartbeat: dict):
|
203
|
+
# the `.P` method is used to print messages in the console and store them in the log file
|
204
|
+
session.P("{} is online".format(node))
|
205
|
+
return
|
206
|
+
|
207
|
+
|
208
|
+
if __name__ == '__main__':
|
209
|
+
# create a session
|
210
|
+
# the network credentials are read from the .env file automatically
|
211
|
+
session = Session(
|
212
|
+
on_heartbeat=on_heartbeat
|
213
|
+
)
|
214
|
+
|
215
|
+
# run the program for 15 seconds to show all the nodes that are online
|
216
|
+
sleep(15)
|
217
|
+
|
218
|
+
```
|
219
|
+
|
220
|
+
Next we will select an online node. This node will be our entrypoint in the network.
|
221
|
+
|
222
|
+
The available nodes in our test net are:
|
223
|
+
|
224
|
+
```
|
225
|
+
0xai_A8SY7lEqBtf5XaGyB6ipdk5C30vSf3HK4xELp3iplwLe naeural-1
|
226
|
+
0xai_Amfnbt3N-qg2-qGtywZIPQBTVlAnoADVRmSAsdDhlQ-6 naeural-2
|
227
|
+
0xai_ApltAljEgWk3g8x2QcSa0sS3hT1P4dyCchd04zFSMy5e naeural-3
|
228
|
+
```
|
229
|
+
|
230
|
+
We will send a task to this node. Since we want to distribute the task of finding prime numbers to multiple nodes, this selected node will handle distribution of tasks and collection of the results.
|
231
|
+
|
232
|
+
```python
|
233
|
+
node = "0xai_A8SY7lEqBtf5XaGyB6ipdk5C30vSf3HK4xELp3iplwLe" # naeural-1
|
234
|
+
|
235
|
+
# we usually wait for the node to be online before sending the task
|
236
|
+
# but in this case we are sure that the node is online because we
|
237
|
+
# have received heartbeats from it during the sleep period
|
238
|
+
|
239
|
+
# session.wait_for_node(node)
|
240
|
+
```
|
241
|
+
|
242
|
+
Our selected node will periodically output partial results with the prime numbers found so far by the worker nodes. We want to consume these results.
|
243
|
+
|
244
|
+
Thus, we need to implement a callback method that will handle this.
|
245
|
+
|
246
|
+
```python
|
247
|
+
from PyE2 import Pipeline
|
248
|
+
|
249
|
+
# a flag used to close the session when the task is finished
|
250
|
+
finished = False
|
251
|
+
|
252
|
+
def locally_process_partial_results(pipeline: Pipeline, full_payload):
|
253
|
+
global finished
|
254
|
+
found_so_far = full_payload.get("DATA")
|
255
|
+
|
256
|
+
if found_so_far:
|
257
|
+
pipeline.P("Found so far: {}: {}\n\n".format(len(found_so_far), sorted(found_so_far)))
|
258
|
+
|
259
|
+
progress = full_payload.get("PROGRESS")
|
260
|
+
if progress == 100:
|
261
|
+
pipeline.P("FINISHED\n\n")
|
262
|
+
finished = True
|
263
|
+
|
264
|
+
return
|
265
|
+
```
|
266
|
+
|
267
|
+
Now we are ready to deploy our job to the network.
|
268
|
+
|
269
|
+
```python
|
270
|
+
from PyE2 import DistributedCustomCodePresets as Presets
|
271
|
+
|
272
|
+
_, _ = session.create_chain_dist_custom_job(
|
273
|
+
# this is the main node, our entrypoint
|
274
|
+
node=node,
|
275
|
+
|
276
|
+
# this function is executed on the main node
|
277
|
+
# this handles what we want to do with primes found by a worker node after an iteration
|
278
|
+
# we want to store only the unique prime numbers
|
279
|
+
# we cam either write a custom code to pass here or we can use a preset
|
280
|
+
main_node_process_real_time_collected_data=Presets.PROCESS_REAL_TIME_COLLECTED_DATA__KEEP_UNIQUES_IN_AGGREGATED_COLLECTED_DATA,
|
281
|
+
|
282
|
+
# this function is executed on the main node
|
283
|
+
# this handles the finish condition of our distributed job
|
284
|
+
# we want to finish when we have found 168 prime numbers
|
285
|
+
# so more than 167 prime numbers
|
286
|
+
# we cam either write a custom code to pass here or we can use a preset
|
287
|
+
main_node_finish_condition=Presets.FINISH_CONDITION___AGGREGATED_DATA_MORE_THAN_X,
|
288
|
+
main_node_finish_condition_kwargs={
|
289
|
+
"X": 167
|
290
|
+
},
|
291
|
+
|
292
|
+
# this function is executed on the main node
|
293
|
+
# this handles the final processing of the results
|
294
|
+
# this function prepares data for the final result of the distributed job
|
295
|
+
# we want to aggregate all the prime numbers found by the worker nodes in a single list
|
296
|
+
# we cam either write a custom code to pass here or we can use a preset
|
297
|
+
main_node_aggregate_collected_data=Presets.AGGREGATE_COLLECTED_DATA___AGGREGATE_COLLECTED_DATA,
|
298
|
+
|
299
|
+
# how many worker nodes we want to use for this task
|
300
|
+
nr_remote_worker_nodes=2,
|
301
|
+
|
302
|
+
# this is the function that will be executed on the worker nodes
|
303
|
+
# this function generates prime numbers using brute force
|
304
|
+
# we simply pass the function reference
|
305
|
+
worker_node_code=remote_brute_force_prime_number_generator,
|
306
|
+
|
307
|
+
# this is the function that will be executed on the client
|
308
|
+
# this is the callback function that processes the partial results
|
309
|
+
# in our case we want to print the partial results
|
310
|
+
on_data=locally_process_partial_results,
|
311
|
+
|
312
|
+
# we want to deploy the job immediately
|
313
|
+
deploy=True
|
314
|
+
)
|
315
|
+
```
|
316
|
+
|
317
|
+
Last but not least, we want to close the session when the distributed job finished.
|
318
|
+
|
319
|
+
```python
|
320
|
+
# we wait until the finished flag is set to True
|
321
|
+
# we want to release the resources allocated on the selected node when the job is finished
|
322
|
+
session.run(wait=lambda: not finished, close_pipelines=True)
|
323
|
+
```
|
324
|
+
|
325
|
+
|
326
|
+
# Project Financing Disclaimer
|
327
|
+
|
328
|
+
This project includes open-source components that have been developed with the support of financing grants SMIS 143488 and SMIS 156084, provided by the Romanian Competitiveness Operational Programme. We are grateful for this support, which has enabled us to advance our work and share these resources with the community.
|
329
|
+
|
330
|
+
The content and information provided within this repository are solely the responsibility of the authors and do not necessarily reflect the views of the funding agencies. The funding received under these grants has been instrumental in supporting specific parts of this open source project, allowing for broader dissemination and collaborative development.
|
331
|
+
|
332
|
+
For any inquiries related to the funding and its impact on this project, please contact the authors directly.
|
333
|
+
|
334
|
+
|
335
|
+
# Citation
|
336
|
+
|
337
|
+
```bibtex
|
338
|
+
@misc{PyE2,
|
339
|
+
author = {Stefan Saraev, Andrei Damian},
|
340
|
+
title = {PyE2: Python SDK for Naeural Edge Protocol},
|
341
|
+
year = {2024},
|
342
|
+
howpublished = {\url{https://github.com/NaeuralEdgeProtocol/PyE2}},
|
343
|
+
}
|
344
|
+
```
|
345
|
+
|
346
|
+
```bibtex
|
347
|
+
@misc{project_funding_acknowledgment1,
|
348
|
+
author = {Damian, Bleotiu, Saraev, Constantinescu},
|
349
|
+
title = {SOLIS – Sistem Omogen multi-Locație cu funcționalități Inteligente și Sustenabile”
|
350
|
+
SMIS 143488},
|
351
|
+
howpublished = {\url{https://github.com/NaeuralEdgeProtocol/}},
|
352
|
+
note = {This project includes open-source components developed with support from the Romanian Competitiveness Operational Programme under grants SMIS 143488. The content is solely the responsibility of the authors and does not necessarily reflect the views of the funding agencies.},
|
353
|
+
year = {2021-2022}
|
354
|
+
}
|
355
|
+
```
|
356
|
+
|
357
|
+
```bibtex
|
358
|
+
@misc{project_funding_acknowledgment2,
|
359
|
+
author = {Damian, Bleotiu, Saraev, Constantinescu, Milik, Lupaescu},
|
360
|
+
title = {ReDeN – Rețea Descentralizată Neurală SMIS 156084},
|
361
|
+
howpublished = {\url{https://github.com/NaeuralEdgeProtocol/}},
|
362
|
+
note = {This project includes open-source components developed with support from the Romanian Competitiveness Operational Programme under grants SMIS 143488. The content is solely the responsibility of the authors and does not necessarily reflect the views of the funding agencies.},
|
363
|
+
year = {2023-2024}
|
364
|
+
}
|
365
|
+
```
|
@@ -0,0 +1,78 @@
|
|
1
|
+
naeural_client/__init__.py,sha256=ZNoadMrxrd1EZqxni0zpoqjFIBrS8Jg-vfZrr7xwe9I,498
|
2
|
+
naeural_client/_ver.py,sha256=yNDcOu9DDQRie1_Z8yaUGkhX8uMLmP-NN5ZbHOb4IgA,330
|
3
|
+
naeural_client/base_decentra_object.py,sha256=TBBnShUybWhjcbEIT8_27FGzxcQUVh23jm-HlaD9Qbw,4173
|
4
|
+
naeural_client/plugins_manager_mixin.py,sha256=X1JdGLDz0gN1rPnTN_5mJXR8JmqoBFQISJXmPR9yvCo,11106
|
5
|
+
naeural_client/base/__init__.py,sha256=hACh83_cIv7-PwYMM3bQm2IBmNqiHw-3PAfDfAEKz9A,259
|
6
|
+
naeural_client/base/distributed_custom_code_presets.py,sha256=cvz5R88P6Z5V61Ce1vHVVh8bOkgXd6gve_vdESDNAsg,2544
|
7
|
+
naeural_client/base/generic_session.py,sha256=Dop4vI8mjB30OUFuMZ3gEDwvzDOXGqCrWsENtS-PRnI,65979
|
8
|
+
naeural_client/base/instance.py,sha256=pZSYC_WQNa5YqU2cVN9vbDyCg8ums8EQCd5Cx95a_VQ,19942
|
9
|
+
naeural_client/base/pipeline.py,sha256=21V9SN1v86iMm80jOikZIkooyBF9FMs_3_0Q9-Qp4sc,57288
|
10
|
+
naeural_client/base/plugin_template.py,sha256=NUVZrSy-YFxs5ZWCzS-eyYJzut1oJaWIdol8Cky3Lzs,129442
|
11
|
+
naeural_client/base/responses.py,sha256=ZKBZmRhYDv8M8mQ5C_ahGsQvtWH4b9ImRcuerQdZmNw,6937
|
12
|
+
naeural_client/base/transaction.py,sha256=Mo-2QLxl8PSR_t-XJGb9bXAXZ-6r4g0SS4hDOng4GAU,5136
|
13
|
+
naeural_client/base/payload/__init__.py,sha256=y8fBI8tG2ObNfaXFWjyWZXwu878FRYj_I8GIbHT4GKE,29
|
14
|
+
naeural_client/base/payload/payload.py,sha256=wejtDRg-hZZAzJD4Ud-AEW67gEbs1kNriimul95lyj4,1951
|
15
|
+
naeural_client/bc/__init__.py,sha256=FQj23D1PrY06NUOARiKQi4cdj0-VxnoYgYDEht8lpr8,158
|
16
|
+
naeural_client/bc/base.py,sha256=QK6QdONTpT9N--H7CHk8pwRxwJUGK4nvhNTfKxQeztQ,28328
|
17
|
+
naeural_client/bc/chain.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
18
|
+
naeural_client/bc/ec.py,sha256=8ryEvc3__lVXSoYxd1WoTy9c8uC5Q_8R1uME7CeloIg,8578
|
19
|
+
naeural_client/certs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
20
|
+
naeural_client/certs/r9092118.ala.eu-central-1.emqxsl.com.crt,sha256=y-6io0tseyx9-a4Pmde1z1gPULtJNSYUpG_YFkYaMKU,1337
|
21
|
+
naeural_client/code_cheker/__init__.py,sha256=pwkdeZGVL16ZA4Qf2mRahEhoOvKhL7FyuQbMFLr1E5M,33
|
22
|
+
naeural_client/code_cheker/base.py,sha256=cJzQD_Y-Z7lkiiQY65oJQAVABOmYez7TZB8xYSiuRl8,16669
|
23
|
+
naeural_client/code_cheker/checker.py,sha256=QWupeM7ToancVIq1tRUxRNUrI8B5l5eoY0kDU4-O5aE,7365
|
24
|
+
naeural_client/comm/__init__.py,sha256=za3B2HUKNXzYtjElMgGM9xbxNsdQfFY4JB_YzdyFkVU,76
|
25
|
+
naeural_client/comm/amqp_wrapper.py,sha256=hzj6ih07DnLQy2VSfA88giDIFHaCp9uSdGLTA-IFE4s,8535
|
26
|
+
naeural_client/comm/mqtt_wrapper.py,sha256=Ig3bFZkCbWd4y_Whn2PPa91Z3aLgNbNPau6Tn5yLPZ8,16167
|
27
|
+
naeural_client/const/README.md,sha256=6OHesr-f5NBuuJGryEoi_TCu2XdlhfQYlDKx_IJoXeg,177
|
28
|
+
naeural_client/const/__init__.py,sha256=nm0maDn_l44UQkJy4XLHnOcpHMypkVvYYDFkezi6_rk,380
|
29
|
+
naeural_client/const/base.py,sha256=V94oaT7xYrrTGxmLJlynxmbFujVX0G9wIfC8TilH5MU,2548
|
30
|
+
naeural_client/const/comms.py,sha256=La6JXWHexH8CfcBCKyT4fCIoeaoZlcm7KtZ57ab4ZgU,2201
|
31
|
+
naeural_client/const/environment.py,sha256=RygVb5l6oCYTt45Mupw0Gi44NbhpsnIpiiVu5TpCijg,580
|
32
|
+
naeural_client/const/formatter.py,sha256=AW3bWlqf39uaqV4BBUuW95qKYfF2OkkU4f9hy3kSVhM,200
|
33
|
+
naeural_client/const/heartbeat.py,sha256=jGHmKfeHTFOXJaKUT3o_ocnQyF-EpcLeunW-ifkYKfU,2534
|
34
|
+
naeural_client/const/misc.py,sha256=1ypROmZsOyp_8zG2LARwPeo-YfXuyYqZnml0elTP4kw,211
|
35
|
+
naeural_client/const/payload.py,sha256=k24vH9iJIBBPnCXx7HAEuli2fNAETK7h8ZuVKyKLgbk,5725
|
36
|
+
naeural_client/default/__init__.py,sha256=ozU6CMMuWl0LhG8Ae3LrZ65a6tLrptfscVYGf83zjxM,46
|
37
|
+
naeural_client/default/instance/__init__.py,sha256=k1YZhbhLh7-Q7avnvwuQ2Ij-BhGbTlgwiWsOj9cS9xU,205
|
38
|
+
naeural_client/default/instance/chain_dist_custom_job_01_plugin.py,sha256=-YO26dH3774wkMbj0Z0GACpVeVYblkxV4KhidtPEqcI,1891
|
39
|
+
naeural_client/default/instance/custom_web_app_01_plugin.py,sha256=gjckmyp0yoN24ouxelgc2Eb2p7YxrrAoSRQpshPZFDY,3991
|
40
|
+
naeural_client/default/instance/net_mon_01_plugin.py,sha256=1k1Ul6pKyhSfAYbcfj38t404Z3KyMVvfhlMJdzIgV-c,1154
|
41
|
+
naeural_client/default/instance/view_scene_01_plugin.py,sha256=bQtkQKrZRvzenlH3JYVvBXe2Tow5qdKYlmuvjpBLYn4,666
|
42
|
+
naeural_client/default/session/mqtt_session.py,sha256=dpQcBhhVZDo458v0IqJMZb1CsTn-TxXhYjNlyJp9Rp8,2414
|
43
|
+
naeural_client/io_formatter/__init__.py,sha256=_wy7c-Z9kgb26jN7uNTDq88G7xZ3wI_ObuQd3QWNPkQ,85
|
44
|
+
naeural_client/io_formatter/io_formatter_manager.py,sha256=MiZ70cGVD6hR99QiEk9wvJ_vADxpI-y2bTb0ITlMNI0,3451
|
45
|
+
naeural_client/io_formatter/base/__init__.py,sha256=VmLHY35NCRR46lgjhcrwtFxmJIVOjX2ADV9wOXt9CKA,41
|
46
|
+
naeural_client/io_formatter/base/base_formatter.py,sha256=skrXCKBXirPl1aVCIUm0XxWY-ZHRi3QdLzeEL-2CIaQ,2337
|
47
|
+
naeural_client/io_formatter/default/__init__.py,sha256=zOm2tsOk6fXvyCXxsXDnsNs6BUrUOr0DoLf4ccWlY_w,109
|
48
|
+
naeural_client/io_formatter/default/a_dummy.py,sha256=qr9eUizQ-NN5jdXVzkaZKMaf9KS41MpPN_iDoTN_Qd0,1148
|
49
|
+
naeural_client/io_formatter/default/aixp1.py,sha256=MX0TeUR4APA-qN3vUC6uzcz8Pssz5lgrQWo7td5Ri1A,3052
|
50
|
+
naeural_client/io_formatter/default/default.py,sha256=gEy78cP2D5s0y8vQh4aHuxqz7D10gGfuiKF311QhrpE,494
|
51
|
+
naeural_client/logging/__init__.py,sha256=b79X45VC6c37u32flKB2GAK9f-RR0ocwP0JDCy0t7QQ,33
|
52
|
+
naeural_client/logging/base_logger.py,sha256=XlHzuFhVrjTZUq_67unZIF-wT87UoZt6zR7fAdS08SE,65164
|
53
|
+
naeural_client/logging/small_logger.py,sha256=6wljiHP1moCkgohRnr2EX095eM2RtdJ5B3cytbO_Ow4,2887
|
54
|
+
naeural_client/logging/logger_mixins/__init__.py,sha256=yQO7umlRvz63FeWpi-F9GRmC_MOHcNW6R6pwvZZBy3A,600
|
55
|
+
naeural_client/logging/logger_mixins/class_instance_mixin.py,sha256=l6XTrcwT6mNriXlynUHt5oTEyie2Ym37tXpBqQyMc9o,2721
|
56
|
+
naeural_client/logging/logger_mixins/computer_vision_mixin.py,sha256=TrtG7ayM2ab-4jjIkIWAQaFi9cVfiINAWrJCt8mCCFI,13213
|
57
|
+
naeural_client/logging/logger_mixins/datetime_mixin.py,sha256=teSLMr4_nubo9qAjjZhNF4rGQ9IU_o7ezYTS7EeahBg,11258
|
58
|
+
naeural_client/logging/logger_mixins/download_mixin.py,sha256=dz8DoTKLDVjT02syQwrAVjjdp1EHwTClPubkUQMJ_vc,13270
|
59
|
+
naeural_client/logging/logger_mixins/general_serialization_mixin.py,sha256=h1PUXxuDExoBBn8h_3GpFV-Pc_fQqkAc1ZcR5mPyQtI,7420
|
60
|
+
naeural_client/logging/logger_mixins/json_serialization_mixin.py,sha256=fNluF1s3dqWGffY3Y_o8521EZS_vV711SH0rICugNNM,14442
|
61
|
+
naeural_client/logging/logger_mixins/pickle_serialization_mixin.py,sha256=-J6hHmlCbaAOQkF6KBGCzkIHvMkA0bgIZfpj1WPiWIA,9165
|
62
|
+
naeural_client/logging/logger_mixins/process_mixin.py,sha256=RupUq6IaK0xuZtIP51zasxBfbZ4NSiN2pg7d9D_ZO74,1884
|
63
|
+
naeural_client/logging/logger_mixins/resource_size_mixin.py,sha256=nPn_ipoUP7uq0FxvBGNf55ttwqbDskAAfvGZO4a8DW0,2277
|
64
|
+
naeural_client/logging/logger_mixins/timers_mixin.py,sha256=TDqEj4qv_VV3AaQdoR4FunE6dJxeN19nkfles7aQL3E,17295
|
65
|
+
naeural_client/logging/logger_mixins/upload_mixin.py,sha256=lu2DzJqkHzEek0nGavAK4YJBXgBvKG8Hlf0YVHHAEqI,7677
|
66
|
+
naeural_client/logging/logger_mixins/utils_mixin.py,sha256=jOgKxPr094qLrwwwcpz_beUQEITLB7tYOerrdUJw79U,19537
|
67
|
+
naeural_client/logging/tzlocal/__init__.py,sha256=PBLaZSFatmJp2fX4Bwalwc5LgWX9Vcw-FWHnBvW1k8E,384
|
68
|
+
naeural_client/logging/tzlocal/unix.py,sha256=Cgpzg1jxrcSivyT5xFRX69W5XkF5ollvXPr976RIbmA,7268
|
69
|
+
naeural_client/logging/tzlocal/utils.py,sha256=6F2QE3b8xiKwBriQaT0jrgBeyrKhCj6b-eSCEywLSMg,3094
|
70
|
+
naeural_client/logging/tzlocal/win32.py,sha256=zBoj0vFVrGhnCm_f7xmYzGym4-fV-4Ij29r0QXC_-x4,4462
|
71
|
+
naeural_client/logging/tzlocal/windows_tz.py,sha256=Sv9okktjZJfRGGUOOppsvQuX_eXyXUxkSKCAFmWT9Hw,34203
|
72
|
+
naeural_client/utils/__init__.py,sha256=mAnke3-MeRzz3nhQvhuHqLnpaaCSmDxicd7Ck9uwpmI,77
|
73
|
+
naeural_client/utils/comm_utils.py,sha256=4cS9llRr_pK_3rNgDcRMCQwYPO0kcNU7AdWy_LtMyCY,1072
|
74
|
+
naeural_client/utils/dotenv.py,sha256=_AgSo35n7EnQv5yDyu7C7i0kHragLJoCGydHjvOkrYY,2008
|
75
|
+
naeural_client-2.0.0.dist-info/METADATA,sha256=9odw_xC8Ez_UagxNCJ_wPIKa9d6ymi7Q5K_q8mObIb8,14239
|
76
|
+
naeural_client-2.0.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
77
|
+
naeural_client-2.0.0.dist-info/licenses/LICENSE,sha256=7P07j9ez3_ovbZ8L_ZJuPXVOgqTS19-ECkezwOtFqOI,11340
|
78
|
+
naeural_client-2.0.0.dist-info/RECORD,,
|
@@ -0,0 +1,201 @@
|
|
1
|
+
Apache License
|
2
|
+
Version 2.0, January 2004
|
3
|
+
http://www.apache.org/licenses/
|
4
|
+
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
6
|
+
|
7
|
+
1. Definitions.
|
8
|
+
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
11
|
+
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
13
|
+
the copyright owner that is granting the License.
|
14
|
+
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
16
|
+
other entities that control, are controlled by, or are under common
|
17
|
+
control with that entity. For the purposes of this definition,
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
19
|
+
direction or management of such entity, whether by contract or
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
22
|
+
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
24
|
+
exercising permissions granted by this License.
|
25
|
+
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
27
|
+
including but not limited to software source code, documentation
|
28
|
+
source, and configuration files.
|
29
|
+
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
31
|
+
transformation or translation of a Source form, including but
|
32
|
+
not limited to compiled object code, generated documentation,
|
33
|
+
and conversions to other media types.
|
34
|
+
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
36
|
+
Object form, made available under the License, as indicated by a
|
37
|
+
copyright notice that is included in or attached to the work
|
38
|
+
(an example is provided in the Appendix below).
|
39
|
+
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
46
|
+
the Work and Derivative Works thereof.
|
47
|
+
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
49
|
+
the original version of the Work and any modifications or additions
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
61
|
+
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
64
|
+
subsequently incorporated within the Work.
|
65
|
+
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
72
|
+
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
78
|
+
where such license applies only to those patent claims licensable
|
79
|
+
by such Contributor that are necessarily infringed by their
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
82
|
+
institute patent litigation against any entity (including a
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
85
|
+
or contributory patent infringement, then any patent licenses
|
86
|
+
granted to You under this License for that Work shall terminate
|
87
|
+
as of the date such litigation is filed.
|
88
|
+
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
91
|
+
modifications, and in Source or Object form, provided that You
|
92
|
+
meet the following conditions:
|
93
|
+
|
94
|
+
(a) You must give any other recipients of the Work or
|
95
|
+
Derivative Works a copy of this License; and
|
96
|
+
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
98
|
+
stating that You changed the files; and
|
99
|
+
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
102
|
+
attribution notices from the Source form of the Work,
|
103
|
+
excluding those notices that do not pertain to any part of
|
104
|
+
the Derivative Works; and
|
105
|
+
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
108
|
+
include a readable copy of the attribution notices contained
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
111
|
+
of the following places: within a NOTICE text file distributed
|
112
|
+
as part of the Derivative Works; within the Source form or
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
114
|
+
within a display generated by the Derivative Works, if and
|
115
|
+
wherever such third-party notices normally appear. The contents
|
116
|
+
of the NOTICE file are for informational purposes only and
|
117
|
+
do not modify the License. You may add Your own attribution
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
120
|
+
that such additional attribution notices cannot be construed
|
121
|
+
as modifying the License.
|
122
|
+
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
124
|
+
may provide additional or different license terms and conditions
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
128
|
+
the conditions stated in this License.
|
129
|
+
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
133
|
+
this License, without any additional terms or conditions.
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
135
|
+
the terms of any separate license agreement you may have executed
|
136
|
+
with Licensor regarding such Contributions.
|
137
|
+
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
140
|
+
except as required for reasonable and customary use in describing the
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
142
|
+
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
152
|
+
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
158
|
+
incidental, or consequential damages of any character arising as a
|
159
|
+
result of this License or out of the use or inability to use the
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
162
|
+
other commercial damages or losses), even if such Contributor
|
163
|
+
has been advised of the possibility of such damages.
|
164
|
+
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
168
|
+
or other liability obligations and/or rights consistent with this
|
169
|
+
License. However, in accepting such obligations, You may act only
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
174
|
+
of your accepting any such warranty or additional liability.
|
175
|
+
|
176
|
+
END OF TERMS AND CONDITIONS
|
177
|
+
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
179
|
+
|
180
|
+
To apply the Apache License to your work, attach the following
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
182
|
+
replaced with your own identifying information. (Don't include
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
184
|
+
comment syntax for the file format. We also recommend that a
|
185
|
+
file or class name and description of purpose be included on the
|
186
|
+
same "printed page" as the copyright notice for easier
|
187
|
+
identification within third-party archives.
|
188
|
+
|
189
|
+
Copyright 2024 Naeural.AI
|
190
|
+
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
192
|
+
you may not use this file except in compliance with the License.
|
193
|
+
You may obtain a copy of the License at
|
194
|
+
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
196
|
+
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
200
|
+
See the License for the specific language governing permissions and
|
201
|
+
limitations under the License.
|