mapepire-python 0.1.5__tar.gz → 0.1.7__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.
- {mapepire_python-0.1.5 → mapepire_python-0.1.7}/PKG-INFO +172 -86
- {mapepire_python-0.1.5 → mapepire_python-0.1.7}/README.md +166 -83
- mapepire_python-0.1.7/mapepire_python/__init__.py +49 -0
- mapepire_python-0.1.7/mapepire_python/asyncio/__init__.py +47 -0
- mapepire_python-0.1.7/mapepire_python/asyncio/connection.py +82 -0
- mapepire_python-0.1.7/mapepire_python/asyncio/cursor.py +99 -0
- mapepire_python-0.1.7/mapepire_python/asyncio/utils.py +23 -0
- mapepire_python-0.1.7/mapepire_python/base_job.py +78 -0
- mapepire_python-0.1.7/mapepire_python/client/__init__.py +3 -0
- {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python/client/query.py +43 -4
- {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python/client/sql_job.py +16 -7
- {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python/client/websocket.py +1 -1
- mapepire_python-0.1.7/mapepire_python/core/__init__.py +27 -0
- mapepire_python-0.1.7/mapepire_python/core/connection.py +86 -0
- mapepire_python-0.1.7/mapepire_python/core/cursor.py +201 -0
- mapepire_python-0.1.7/mapepire_python/core/exceptions.py +97 -0
- mapepire_python-0.1.7/mapepire_python/core/utils.py +78 -0
- {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python/data_types.py +10 -10
- mapepire_python-0.1.7/mapepire_python/pool/__init__.py +4 -0
- {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python/pool/pool_client.py +6 -2
- {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python/pool/pool_job.py +31 -16
- {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python/pool/pool_query.py +3 -3
- {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python/query_manager.py +5 -6
- {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python/version.py +1 -1
- {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python.egg-info/PKG-INFO +172 -86
- {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python.egg-info/SOURCES.txt +12 -0
- {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python.egg-info/requires.txt +3 -0
- {mapepire_python-0.1.5 → mapepire_python-0.1.7}/pyproject.toml +7 -3
- mapepire_python-0.1.5/mapepire_python/base_job.py +0 -42
- {mapepire_python-0.1.5 → mapepire_python-0.1.7}/LICENSE +0 -0
- {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python/py.typed +0 -0
- {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python/ssl.py +0 -0
- {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python.egg-info/dependency_links.txt +0 -0
- {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python.egg-info/top_level.txt +0 -0
- {mapepire_python-0.1.5 → mapepire_python-0.1.7}/setup.cfg +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: mapepire-python
|
|
3
|
-
Version: 0.1.
|
|
4
|
-
Author-email:
|
|
3
|
+
Version: 0.1.7
|
|
4
|
+
Author-email: Adam Shedivy <adam.shedivy@ibm.com>, Irfan Sharif <IrfanSharif@ibm.com>
|
|
5
5
|
License: Apache License
|
|
6
6
|
Version 2.0, January 2004
|
|
7
7
|
https://www.apache.org/licenses/
|
|
@@ -212,19 +212,22 @@ Classifier: Development Status :: 3 - Alpha
|
|
|
212
212
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
213
213
|
Classifier: Programming Language :: Python :: 3
|
|
214
214
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
215
|
-
Requires-Python: >=3.
|
|
215
|
+
Requires-Python: >=3.9
|
|
216
216
|
Description-Content-Type: text/markdown
|
|
217
217
|
License-File: LICENSE
|
|
218
218
|
Requires-Dist: dataclasses-json>=0.6.4
|
|
219
219
|
Requires-Dist: websocket-client>=1.2.1
|
|
220
220
|
Requires-Dist: websockets
|
|
221
221
|
Requires-Dist: pyee
|
|
222
|
+
Requires-Dist: pep249abc
|
|
222
223
|
Provides-Extra: dev
|
|
223
224
|
Requires-Dist: ruff; extra == "dev"
|
|
224
225
|
Requires-Dist: mypy<1.5,>=1.0; extra == "dev"
|
|
225
226
|
Requires-Dist: black<24.0,>=23.0; extra == "dev"
|
|
226
227
|
Requires-Dist: isort<5.13,>=5.12; extra == "dev"
|
|
227
228
|
Requires-Dist: pytest; extra == "dev"
|
|
229
|
+
Requires-Dist: pyee; extra == "dev"
|
|
230
|
+
Requires-Dist: pep249abc; extra == "dev"
|
|
228
231
|
Requires-Dist: pytest-asyncio; extra == "dev"
|
|
229
232
|
Requires-Dist: pytest-sphinx; extra == "dev"
|
|
230
233
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
@@ -255,15 +258,26 @@ Requires-Dist: pre-commit; extra == "dev"
|
|
|
255
258
|
<br/>
|
|
256
259
|
</div>
|
|
257
260
|
|
|
261
|
+
<details>
|
|
262
|
+
<summary> Table of Contents </summary>
|
|
263
|
+
|
|
258
264
|
- [mapepire-python](#mapepire-python)
|
|
259
265
|
- [Overview](#overview)
|
|
260
266
|
- [Setup](#setup)
|
|
261
267
|
- [Install with `pip`](#install-with-pip)
|
|
262
268
|
- [Server Component Setup](#server-component-setup)
|
|
263
|
-
|
|
269
|
+
- [Connection options](#connection-options)
|
|
270
|
+
- [1. Using the `DaemonServer` object](#1-using-the-daemonserver-object)
|
|
271
|
+
- [2. Passing the connection details as a dictionary](#2-passing-the-connection-details-as-a-dictionary)
|
|
272
|
+
- [3. Using a config file (`.ini`) to store the connection details](#3-using-a-config-file-ini-to-store-the-connection-details)
|
|
273
|
+
- [Usage](#usage)
|
|
274
|
+
- [1. Using the `SQLJob` object to run queries synchronously](#1-using-the-sqljob-object-to-run-queries-synchronously)
|
|
264
275
|
- [Query and run](#query-and-run)
|
|
265
|
-
|
|
266
|
-
- [
|
|
276
|
+
- [2. Using the `PoolJob` object to run queries asynchronously](#2-using-the-pooljob-object-to-run-queries-asynchronously)
|
|
277
|
+
- [3. Using the `Pool` object to run queries "concurrently"](#3-using-the-pool-object-to-run-queries-concurrently)
|
|
278
|
+
- [4. Using PEP 249 Implementation](#4-using-pep-249-implementation)
|
|
279
|
+
- [`fetchmany()` and `fetchall()` methods](#fetchmany-and-fetchall-methods)
|
|
280
|
+
- [PEP 249 Asynchronous Implementation](#pep-249-asynchronous-implementation)
|
|
267
281
|
- [Development Setup](#development-setup)
|
|
268
282
|
- [Setup python virtual environment with pip and venv](#setup-python-virtual-environment-with-pip-and-venv)
|
|
269
283
|
- [Create a new virtual environment](#create-a-new-virtual-environment)
|
|
@@ -286,7 +300,7 @@ Requires-Dist: pre-commit; extra == "dev"
|
|
|
286
300
|
- [2. Verify the new environment was installed:](#2-verify-the-new-environment-was-installed)
|
|
287
301
|
- [Run local test suite](#run-local-test-suite)
|
|
288
302
|
|
|
289
|
-
|
|
303
|
+
</details>
|
|
290
304
|
|
|
291
305
|
## Overview
|
|
292
306
|
|
|
@@ -299,7 +313,7 @@ Requires-Dist: pre-commit; extra == "dev"
|
|
|
299
313
|
|
|
300
314
|
## Setup
|
|
301
315
|
|
|
302
|
-
`mapepire-python` requires Python 3.
|
|
316
|
+
`mapepire-python` requires Python 3.10 or later.
|
|
303
317
|
|
|
304
318
|
### Install with `pip`
|
|
305
319
|
|
|
@@ -312,11 +326,75 @@ pip install mapepire-python
|
|
|
312
326
|
### Server Component Setup
|
|
313
327
|
To use mapire-python, you will need to have the Mapepire Server Component running on your IBM i server. Follow these instructions to set up the server component: [Mapepire Server Installation](https://mapepire-ibmi.github.io/guides/sysadmin/)
|
|
314
328
|
|
|
315
|
-
|
|
329
|
+
|
|
330
|
+
# Connection options
|
|
316
331
|
|
|
317
|
-
|
|
332
|
+
There are three ways to configure mapepire server connection details using `mapepire-python`:
|
|
318
333
|
|
|
319
|
-
|
|
334
|
+
1. Using the `DaemonServer` object
|
|
335
|
+
2. Passing the connection details as a dictionary
|
|
336
|
+
3. Using a config file (`.ini`) to store the connection details
|
|
337
|
+
|
|
338
|
+
## 1. Using the `DaemonServer` object
|
|
339
|
+
|
|
340
|
+
to use the `DaemonServer` object, you will need to import the `DaemonServer` class from the `mapepire_python.data_types` module:
|
|
341
|
+
|
|
342
|
+
```python
|
|
343
|
+
from mapepire_python.data_types import DaemonServer
|
|
344
|
+
|
|
345
|
+
creds = DaemonServer(
|
|
346
|
+
host="SERVER",
|
|
347
|
+
port="PORT",
|
|
348
|
+
user="USER",
|
|
349
|
+
password="PASSWORD",
|
|
350
|
+
ignoreUnauthorized=True
|
|
351
|
+
)
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
Once you have created the `DaemonServer` object, you can pass it to the `SQLJob` object to connect to the mapepire server:
|
|
355
|
+
|
|
356
|
+
```python
|
|
357
|
+
from mapepire_python.client.sql_job import SQLJob
|
|
358
|
+
from mapepire_python.data_types import DaemonServer
|
|
359
|
+
|
|
360
|
+
creds = DaemonServer(
|
|
361
|
+
host="SERVER",
|
|
362
|
+
port="PORT",
|
|
363
|
+
user="USER",
|
|
364
|
+
password="PASSWORD",
|
|
365
|
+
ignoreUnauthorized=True
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
job = SQLJob(creds)
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
## 2. Passing the connection details as a dictionary
|
|
372
|
+
|
|
373
|
+
You can also use a dictionary to configure the connection details:
|
|
374
|
+
|
|
375
|
+
```python
|
|
376
|
+
from mapepire_python.client.sql_job import SQLJob
|
|
377
|
+
|
|
378
|
+
creds = {
|
|
379
|
+
"host": "SERVER",
|
|
380
|
+
"port": "port",
|
|
381
|
+
"user": "USER",
|
|
382
|
+
"password": "PASSWORD",
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
job = SQLJob(creds)
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
this is a convenient way to pass the connection details to the mapepire server.
|
|
389
|
+
|
|
390
|
+
## 3. Using a config file (`.ini`) to store the connection details
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
If you use a config file (`.ini`), you can pass the path to the file as an argument:
|
|
394
|
+
|
|
395
|
+
First create a `mapepire.ini` file in the root of your project with the following required fields:
|
|
396
|
+
|
|
397
|
+
```ini title=mapepire.ini
|
|
320
398
|
[mapepire]
|
|
321
399
|
SERVER="SERVER"
|
|
322
400
|
PORT="PORT"
|
|
@@ -324,25 +402,37 @@ USER="USER"
|
|
|
324
402
|
PASSWORD="PASSWORD"
|
|
325
403
|
```
|
|
326
404
|
|
|
327
|
-
|
|
405
|
+
Then you can create a `SQLJob` object by passing the path to the `.ini` file which will handle the connection details
|
|
406
|
+
|
|
328
407
|
|
|
329
408
|
```python
|
|
330
|
-
import configparser
|
|
331
409
|
from mapepire_python.client.sql_job import SQLJob
|
|
332
|
-
from mapepire_python.types import DaemonServer
|
|
333
410
|
|
|
334
|
-
|
|
335
|
-
|
|
411
|
+
job = SQLJob("./mapepire.ini", section="mapepire")
|
|
412
|
+
```
|
|
336
413
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
)
|
|
414
|
+
The `section` argument is optional and allows you to specify a specific section in the `.ini` file where the connection details are stored. This allows you to store multiple connection details to different systems in the same file. If you do not specify a `section`, the first section in the file will be used.
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
# Usage
|
|
418
|
+
|
|
419
|
+
Depending on your setup and use case, you can choose the most convenient way to configure the connection details. The following usage examples are compatible with all three connection options detailed above. For simplicity, we assume there is a `mapepire.ini` file in the root of the project with the connection details.
|
|
344
420
|
|
|
345
|
-
|
|
421
|
+
|
|
422
|
+
There are four main ways to run queries using `mapepire-python`:
|
|
423
|
+
1. Using the `SQLJob` object to run queries synchronously
|
|
424
|
+
2. Using the `PoolJob` object to run queries asynchronously
|
|
425
|
+
3. Using the `Pool` object to run queries "concurrently"
|
|
426
|
+
4. Using PEP 249 Implementation
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
## 1. Using the `SQLJob` object to run queries synchronously
|
|
431
|
+
|
|
432
|
+
```python
|
|
433
|
+
from mapepire_python.client.sql_job import SQLJob
|
|
434
|
+
|
|
435
|
+
with SQLJob("./mapepire.ini") as sql_job:
|
|
346
436
|
with sql_job.query("select * from sample.employee") as query:
|
|
347
437
|
result = query.run(rows_to_fetch=1)
|
|
348
438
|
print(result)
|
|
@@ -484,50 +574,24 @@ In the ouput above, the query was successful and returned one row of data.
|
|
|
484
574
|
To create and run a query in a single step, use the `query_and_run` method:
|
|
485
575
|
|
|
486
576
|
```python
|
|
487
|
-
import configparser
|
|
488
577
|
from mapepire_python.client.sql_job import SQLJob
|
|
489
|
-
from mapepire_python.types import DaemonServer
|
|
490
|
-
|
|
491
|
-
config = configparser.ConfigParser()
|
|
492
|
-
config.read('mapepire.ini')
|
|
493
|
-
|
|
494
|
-
creds = DaemonServer(
|
|
495
|
-
host=config['mapepire']['SERVER'],
|
|
496
|
-
port=config['mapepire']['PORT'],
|
|
497
|
-
user=config['mapepire']['USER'],
|
|
498
|
-
password=config['mapepire']['PASSWORD'],
|
|
499
|
-
ignoreUnauthorized=True
|
|
500
|
-
)
|
|
501
578
|
|
|
502
|
-
with SQLJob(
|
|
579
|
+
with SQLJob("./mapepire.ini") as sql_job:
|
|
503
580
|
# query automatically closed after running
|
|
504
581
|
results = sql_job.query_and_run("select * from sample.employee", rows_to_fetch=1)
|
|
505
582
|
print(result)
|
|
506
583
|
```
|
|
507
584
|
|
|
508
|
-
|
|
585
|
+
## 2. Using the `PoolJob` object to run queries asynchronously
|
|
509
586
|
|
|
510
587
|
The `PoolJob` object can be used to create and run queries asynchronously:
|
|
511
588
|
|
|
512
589
|
```python
|
|
513
590
|
import asyncio
|
|
514
|
-
import configparser
|
|
515
591
|
from mapepire_python.pool.pool_job import PoolJob
|
|
516
|
-
from mapepire_python.types import DaemonServer
|
|
517
|
-
|
|
518
|
-
config = configparser.ConfigParser()
|
|
519
|
-
config.read('mapepire.ini')
|
|
520
|
-
|
|
521
|
-
creds = DaemonServer(
|
|
522
|
-
host=config['mapepire']['SERVER'],
|
|
523
|
-
port=config['mapepire']['PORT'],
|
|
524
|
-
user=config['mapepire']['USER'],
|
|
525
|
-
password=config['mapepire']['PASSWORD'],
|
|
526
|
-
ignoreUnauthorized=True
|
|
527
|
-
)
|
|
528
592
|
|
|
529
593
|
async def main():
|
|
530
|
-
async with PoolJob(
|
|
594
|
+
async with PoolJob("./mapepire.ini") as pool_job:
|
|
531
595
|
async with pool_job.query('select * from sample.employee') as query:
|
|
532
596
|
res = await query.run(rows_to_fetch=1)
|
|
533
597
|
|
|
@@ -540,24 +604,11 @@ To run a create and run a query asynchronously in a single step, use the `query_
|
|
|
540
604
|
|
|
541
605
|
```python
|
|
542
606
|
import asyncio
|
|
543
|
-
import configparser
|
|
544
607
|
from mapepire_python.pool.pool_job import PoolJob
|
|
545
|
-
from mapepire_python.types import DaemonServer
|
|
546
|
-
|
|
547
|
-
config = configparser.ConfigParser()
|
|
548
|
-
config.read('mapepire.ini')
|
|
549
|
-
|
|
550
|
-
creds = DaemonServer(
|
|
551
|
-
host=config['mapepire']['SERVER'],
|
|
552
|
-
port=config['mapepire']['PORT'],
|
|
553
|
-
user=config['mapepire']['USER'],
|
|
554
|
-
password=config['mapepire']['PASSWORD'],
|
|
555
|
-
ignoreUnauthorized=True
|
|
556
|
-
)
|
|
557
608
|
|
|
558
609
|
async def main():
|
|
559
|
-
async with PoolJob(
|
|
560
|
-
res = await pool_job.query_and_run(rows_to_fetch=1)
|
|
610
|
+
async with PoolJob("./mapepire.ini") as pool_job:
|
|
611
|
+
res = await pool_job.query_and_run("select * from sample.employee", rows_to_fetch=1)
|
|
561
612
|
print(res)
|
|
562
613
|
|
|
563
614
|
if __name__ == '__main__':
|
|
@@ -566,32 +617,18 @@ if __name__ == '__main__':
|
|
|
566
617
|
```
|
|
567
618
|
|
|
568
619
|
|
|
569
|
-
##
|
|
620
|
+
## 3. Using the `Pool` object to run queries "concurrently"
|
|
570
621
|
|
|
571
622
|
The `Pool` object can be used to create a pool of `PoolJob` objects to run queries concurrently.
|
|
572
623
|
|
|
573
624
|
```python
|
|
574
625
|
import asyncio
|
|
575
|
-
import configparser
|
|
576
626
|
from mapepire_python.pool.pool_client import Pool, PoolOptions
|
|
577
|
-
from mapepire_python.types import DaemonServer
|
|
578
|
-
|
|
579
|
-
config = configparser.ConfigParser()
|
|
580
|
-
config.read('mapepire.ini')
|
|
581
|
-
|
|
582
|
-
creds = DaemonServer(
|
|
583
|
-
host=config['mapepire']['SERVER'],
|
|
584
|
-
port=config['mapepire']['PORT'],
|
|
585
|
-
user=config['mapepire']['USER'],
|
|
586
|
-
password=config['mapepire']['PASSWORD'],
|
|
587
|
-
ignoreUnauthorized=True
|
|
588
|
-
)
|
|
589
|
-
|
|
590
627
|
|
|
591
628
|
async def main():
|
|
592
629
|
async with Pool(
|
|
593
630
|
options=PoolOptions(
|
|
594
|
-
creds=
|
|
631
|
+
creds="./mapepire.ini",
|
|
595
632
|
opts=None,
|
|
596
633
|
max_size=5,
|
|
597
634
|
starting_size=3
|
|
@@ -610,7 +647,6 @@ async def main():
|
|
|
610
647
|
|
|
611
648
|
if __name__ == '__main__':
|
|
612
649
|
asyncio.run(main())
|
|
613
|
-
|
|
614
650
|
```
|
|
615
651
|
This script will create a pool of 3 `PoolJob` objects and run the query `values (job_name)` concurrently. The results will be printed to the console.
|
|
616
652
|
|
|
@@ -618,6 +654,56 @@ This script will create a pool of 3 `PoolJob` objects and run the query `values
|
|
|
618
654
|
['004460/QUSER/QZDASOINIT', '005096/QUSER/QZDASOINIT', '005319/QUSER/QZDASOINIT']
|
|
619
655
|
```
|
|
620
656
|
|
|
657
|
+
## 4. Using PEP 249 Implementation
|
|
658
|
+
|
|
659
|
+
PEP 249 is the Python Database API Specification v2.0. The `mapepire-python` client provides a PEP 249 implementation that allows you to use the `Connection` and `Cursor` objects to interact with the Mapepire server. Like the examples above, we can pass the `mapepire.ini` file to the `connect` function to create a connection to the server:
|
|
660
|
+
|
|
661
|
+
```python
|
|
662
|
+
from mapepire_python import connect
|
|
663
|
+
|
|
664
|
+
with connect("./mapepire.ini") as conn:
|
|
665
|
+
with conn.execute("select * from sample.employee") as cursor:
|
|
666
|
+
result = cursor.fetchone()
|
|
667
|
+
print(result)
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
### `fetchmany()` and `fetchall()` methods
|
|
671
|
+
|
|
672
|
+
The `Cursor` object provides the `fetchmany()` and `fetchall()` methods to fetch multiple rows from the result set:
|
|
673
|
+
|
|
674
|
+
```python
|
|
675
|
+
with connect("./mapepire.ini") as conn:
|
|
676
|
+
with conn.execute("select * from sample.employee") as cursor:
|
|
677
|
+
results = cursor.fetchmany(size=2)
|
|
678
|
+
print(results)
|
|
679
|
+
```
|
|
680
|
+
---
|
|
681
|
+
|
|
682
|
+
```python
|
|
683
|
+
with connect("./mapepire.ini") as conn:
|
|
684
|
+
with conn.execute("select * from sample.employee") as cursor:
|
|
685
|
+
results = cursor.fetchall()
|
|
686
|
+
print(results)
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
## PEP 249 Asynchronous Implementation
|
|
690
|
+
|
|
691
|
+
The PEP 249 implementation also provides an asynchronous interface for running queries. The `connect` function returns an asynchronous context manager that can be used with the `async with` statement:
|
|
692
|
+
|
|
693
|
+
```python
|
|
694
|
+
import asyncio
|
|
695
|
+
from mapepire_python.asycnio import connect
|
|
696
|
+
|
|
697
|
+
async def main():
|
|
698
|
+
async with connect("./mapepire.ini") as conn:
|
|
699
|
+
async with await conn.execute("select * from sample.employee") as cursor:
|
|
700
|
+
result = await cursor.fetchone()
|
|
701
|
+
print(result)
|
|
702
|
+
|
|
703
|
+
if __name__ == '__main__':
|
|
704
|
+
asyncio.run(main())
|
|
705
|
+
```
|
|
706
|
+
|
|
621
707
|
|
|
622
708
|
# Development Setup
|
|
623
709
|
|
|
@@ -631,7 +717,7 @@ This guide provides instructions for setting up a Python virtual environment usi
|
|
|
631
717
|
|
|
632
718
|
### Create a new virtual environment
|
|
633
719
|
|
|
634
|
-
**Note**: This applies to supported versions of Python 3.
|
|
720
|
+
**Note**: This applies to supported versions of Python 3.10 and higher
|
|
635
721
|
|
|
636
722
|
navigate to the project's directory and run the following command. This will create a new virtual environment in a local folder named `.venv`
|
|
637
723
|
|