mapepire-python 0.1.3__tar.gz → 0.1.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.
Files changed (23) hide show
  1. {mapepire_python-0.1.3 → mapepire_python-0.1.5}/PKG-INFO +205 -27
  2. {mapepire_python-0.1.3 → mapepire_python-0.1.5}/README.md +201 -26
  3. mapepire_python-0.1.5/mapepire_python/base_job.py +42 -0
  4. {mapepire_python-0.1.3 → mapepire_python-0.1.5}/mapepire_python/client/query.py +31 -17
  5. {mapepire_python-0.1.3 → mapepire_python-0.1.5}/mapepire_python/client/sql_job.py +80 -30
  6. mapepire_python-0.1.5/mapepire_python/client/websocket.py +37 -0
  7. mapepire_python-0.1.3/mapepire_python/types.py → mapepire_python-0.1.5/mapepire_python/data_types.py +8 -2
  8. mapepire_python-0.1.5/mapepire_python/pool/pool_client.py +141 -0
  9. mapepire_python-0.1.5/mapepire_python/pool/pool_job.py +303 -0
  10. mapepire_python-0.1.5/mapepire_python/pool/pool_query.py +136 -0
  11. mapepire_python-0.1.5/mapepire_python/query_manager.py +68 -0
  12. {mapepire_python-0.1.3 → mapepire_python-0.1.5}/mapepire_python/ssl.py +1 -1
  13. {mapepire_python-0.1.3 → mapepire_python-0.1.5}/mapepire_python/version.py +1 -1
  14. {mapepire_python-0.1.3 → mapepire_python-0.1.5}/mapepire_python.egg-info/PKG-INFO +205 -27
  15. {mapepire_python-0.1.3 → mapepire_python-0.1.5}/mapepire_python.egg-info/SOURCES.txt +8 -3
  16. {mapepire_python-0.1.3 → mapepire_python-0.1.5}/mapepire_python.egg-info/requires.txt +3 -0
  17. {mapepire_python-0.1.3 → mapepire_python-0.1.5}/pyproject.toml +3 -0
  18. mapepire_python-0.1.3/mapepire_python/pool.py +0 -29
  19. {mapepire_python-0.1.3 → mapepire_python-0.1.5}/LICENSE +0 -0
  20. {mapepire_python-0.1.3 → mapepire_python-0.1.5}/mapepire_python/py.typed +0 -0
  21. {mapepire_python-0.1.3 → mapepire_python-0.1.5}/mapepire_python.egg-info/dependency_links.txt +0 -0
  22. {mapepire_python-0.1.3 → mapepire_python-0.1.5}/mapepire_python.egg-info/top_level.txt +0 -0
  23. {mapepire_python-0.1.3 → mapepire_python-0.1.5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mapepire-python
3
- Version: 0.1.3
3
+ Version: 0.1.5
4
4
  Author-email: Allen Institute for Artificial Intelligence <contact@allenai.org>
5
5
  License: Apache License
6
6
  Version 2.0, January 2004
@@ -217,12 +217,15 @@ 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
+ Requires-Dist: websockets
221
+ Requires-Dist: pyee
220
222
  Provides-Extra: dev
221
223
  Requires-Dist: ruff; extra == "dev"
222
224
  Requires-Dist: mypy<1.5,>=1.0; extra == "dev"
223
225
  Requires-Dist: black<24.0,>=23.0; extra == "dev"
224
226
  Requires-Dist: isort<5.13,>=5.12; extra == "dev"
225
227
  Requires-Dist: pytest; extra == "dev"
228
+ Requires-Dist: pytest-asyncio; extra == "dev"
226
229
  Requires-Dist: pytest-sphinx; extra == "dev"
227
230
  Requires-Dist: pytest-cov; extra == "dev"
228
231
  Requires-Dist: twine>=1.11.0; extra == "dev"
@@ -243,8 +246,8 @@ Requires-Dist: pre-commit; extra == "dev"
243
246
  <a href="https://github.com/Mapepire-IBMi/mapepire-python/actions">
244
247
  <img alt="CI" src="https://img.shields.io/github/actions/workflow/status/Mapepire-IBMi/mapepire-python/main.yml">
245
248
  </a>
246
- <a href="https://pypi.org/project/python-wsdb/">
247
- <img alt="PyPI" src="https://img.shields.io/pypi/v/python-wsdb">
249
+ <a href="https://pypi.org/project/mapepire-python/">
250
+ <img alt="PyPI" src="https://img.shields.io/pypi/v/mapepire-python">
248
251
  </a>
249
252
  <a href="https://github.com/Mapepire-IBMi/mapepire-python/blob/main/LICENSE">
250
253
  <img alt="License" src="https://img.shields.io/github/license/allenai/tango.svg?color=blue&cachedrop">
@@ -252,35 +255,47 @@ Requires-Dist: pre-commit; extra == "dev"
252
255
  <br/>
253
256
  </div>
254
257
 
255
- - [Overview](#overview)
256
- - [Setup](#setup)
257
- - [Install with `pip`](#install-with-pip)
258
- - [Server Component Setup (Forthcoming)](#server-component-setup-forthcoming)
259
- - [Example usage](#example-usage)
258
+ - [mapepire-python](#mapepire-python)
259
+ - [Overview](#overview)
260
+ - [Setup](#setup)
261
+ - [Install with `pip`](#install-with-pip)
262
+ - [Server Component Setup](#server-component-setup)
263
+ - [Example usage](#example-usage)
264
+ - [Query and run](#query-and-run)
265
+ - [Asynchronous Query Execution](#asynchronous-query-execution)
266
+ - [Pooling (beta)](#pooling-beta)
260
267
  - [Development Setup](#development-setup)
261
268
  - [Setup python virtual environment with pip and venv](#setup-python-virtual-environment-with-pip-and-venv)
262
269
  - [Create a new virtual environment](#create-a-new-virtual-environment)
263
270
  - [Unix/macOS](#unixmacos)
264
271
  - [Windows](#windows)
265
272
  - [Activate the virtual environment:](#activate-the-virtual-environment)
273
+ - [Unix.macOS](#unixmacos-1)
274
+ - [Windows](#windows-1)
275
+ - [Unix/macOS](#unixmacos-2)
276
+ - [Windows](#windows-2)
266
277
  - [Prepare pip](#prepare-pip)
278
+ - [Unix/macOS](#unixmacos-3)
279
+ - [Windows](#windows-3)
267
280
  - [Install Dependencies using `requirements-dev.txt`](#install-dependencies-using-requirements-devtxt)
281
+ - [Unix/macOS](#unixmacos-4)
282
+ - [Windows](#windows-4)
268
283
  - [Setup Python virtual environment with Conda](#setup-python-virtual-environment-with-conda)
269
284
  - [Create an environment from an environment-dev.yml file](#create-an-environment-from-an-environment-devyml-file)
270
285
  - [1. Activate the new environment:](#1-activate-the-new-environment)
271
286
  - [2. Verify the new environment was installed:](#2-verify-the-new-environment-was-installed)
272
- - [Run local test suite](#run-local-test-suite)
287
+ - [Run local test suite](#run-local-test-suite)
273
288
 
274
289
 
275
290
 
291
+ ## Overview
276
292
 
277
- #### ⚠️ (WIP!) This Project is for demo purposes only
293
+ <img src="images/mapepire-logo.png" alt="logo" width="200"/>
278
294
 
279
- ## Overview
295
+ ---
280
296
 
281
- ![alt text](images/image-1.png)
282
297
 
283
- `mapepire-python` is a Python client implementation that leverages the [CodeFori Server Component](https://github.com/ThePrez/CodeForIBMiServer).
298
+ `mapepire-python` is a Python client implementation for [Mapepire](https://github.com/Mapepire-IBMi) that provides a simple interface for connecting to an IBM i server and running SQL queries. The client is designed to work with the [Mapepire Server Component](https://github.com/Mapepire-IBMi/mapepire-server)
284
299
 
285
300
  ## Setup
286
301
 
@@ -288,36 +303,49 @@ Requires-Dist: pre-commit; extra == "dev"
288
303
 
289
304
  ### Install with `pip`
290
305
 
291
- `mapepire-python` is available on [PyPi](https://pypi.org/project/python-wsdb/). Just Run
306
+ `mapepire-python` is available on [PyPi](https://pypi.org/project/mapepire-python/). Just Run
292
307
 
293
308
  ```bash
294
- pip install python-wsdb
309
+ pip install mapepire-python
295
310
  ```
296
311
 
297
- ### Server Component Setup (Forthcoming)
312
+ ### Server Component Setup
313
+ 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/)
298
314
 
299
315
  ## Example usage
300
316
 
301
- The following script sets up a `DaemonServer` object that will be used to connect with the Server Component. Then a single `SQLJob` is created to facilitate the connection from the client side.
317
+ Setup the server credentials used to connect to the server. One way to do this is to create a `mapepire.ini` file in the root of your project with the following content:
318
+
319
+ ```ini
320
+ [mapepire]
321
+ SERVER="SERVER"
322
+ PORT="PORT"
323
+ USER="USER"
324
+ PASSWORD="PASSWORD"
325
+ ```
326
+
327
+ The following script sets up a `DaemonServer` object that will be used to connect with the Server Component. Then a single `SQLJob` is created to facilitate the connection from the client side.
302
328
 
303
329
  ```python
330
+ import configparser
304
331
  from mapepire_python.client.sql_job import SQLJob
305
332
  from mapepire_python.types import DaemonServer
306
333
 
334
+ config = configparser.ConfigParser()
335
+ config.read('mapepire.ini')
336
+
307
337
  creds = DaemonServer(
308
- host="localhost",
309
- port=8085,
310
- user="USER",
311
- password="PASSWORD",
338
+ host=config['mapepire']['SERVER'],
339
+ port=config['mapepire']['PORT'],
340
+ user=config['mapepire']['USER'],
341
+ password=config['mapepire']['PASSWORD'],
312
342
  ignoreUnauthorized=True
313
343
  )
314
344
 
315
-
316
- job = SQLJob()
317
- res = job.connect(creds)
318
- query = job.query("select * from sample.employee")
319
- result = query.run(rows_to_fetch=3)
320
- print(result)
345
+ with SQLJob(creds) as sql_job:
346
+ with sql_job.query("select * from sample.employee") as query:
347
+ result = query.run(rows_to_fetch=1)
348
+ print(result)
321
349
  ```
322
350
 
323
351
  Here is the output from the script above:
@@ -440,6 +468,156 @@ Here is the output from the script above:
440
468
  }
441
469
 
442
470
  ```
471
+ The results object is a JSON object that contains the metadata and data from the query. Here are the different fields returned:
472
+ - `id` field contains the query ID
473
+ - `has_results` field indicates whether the query returned any results
474
+ - `update_count` field indicates the number of rows updated by the query (-1 if the query did not update any rows)
475
+ - `metadata` field contains information about the columns returned by the query
476
+ - `data` field contains the results of the query
477
+ - `is_done` field indicates whether the query has finished executing
478
+ - `success` field indicates whether the query was successful.
479
+
480
+ In the ouput above, the query was successful and returned one row of data.
481
+
482
+ ### Query and run
483
+
484
+ To create and run a query in a single step, use the `query_and_run` method:
485
+
486
+ ```python
487
+ import configparser
488
+ 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
+
502
+ with SQLJob(creds) as sql_job:
503
+ # query automatically closed after running
504
+ results = sql_job.query_and_run("select * from sample.employee", rows_to_fetch=1)
505
+ print(result)
506
+ ```
507
+
508
+ ### Asynchronous Query Execution
509
+
510
+ The `PoolJob` object can be used to create and run queries asynchronously:
511
+
512
+ ```python
513
+ import asyncio
514
+ import configparser
515
+ 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
+
529
+ async def main():
530
+ async with PoolJob(creds=creds) as pool_job:
531
+ async with pool_job.query('select * from sample.employee') as query:
532
+ res = await query.run(rows_to_fetch=1)
533
+
534
+ if __name__ == '__main__':
535
+ asyncio.run(main())
536
+
537
+ ```
538
+
539
+ To run a create and run a query asynchronously in a single step, use the `query_and_run` method:
540
+
541
+ ```python
542
+ import asyncio
543
+ import configparser
544
+ 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
+
558
+ async def main():
559
+ async with PoolJob(creds=creds) as pool_job:
560
+ res = await pool_job.query_and_run(rows_to_fetch=1)
561
+ print(res)
562
+
563
+ if __name__ == '__main__':
564
+ asyncio.run(main())
565
+
566
+ ```
567
+
568
+
569
+ ## Pooling (beta)
570
+
571
+ The `Pool` object can be used to create a pool of `PoolJob` objects to run queries concurrently.
572
+
573
+ ```python
574
+ import asyncio
575
+ import configparser
576
+ 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
+
591
+ async def main():
592
+ async with Pool(
593
+ options=PoolOptions(
594
+ creds=creds,
595
+ opts=None,
596
+ max_size=5,
597
+ starting_size=3
598
+ )
599
+ ) as pool:
600
+ job_names = []
601
+ resultsA = await asyncio.gather(
602
+ pool.execute('values (job_name)'),
603
+ pool.execute('values (job_name)'),
604
+ pool.execute('values (job_name)')
605
+ )
606
+ job_names = [res['data'][0]['00001'] for res in resultsA]
607
+
608
+ print(job_names)
609
+
610
+
611
+ if __name__ == '__main__':
612
+ asyncio.run(main())
613
+
614
+ ```
615
+ 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
+
617
+ ```bash
618
+ ['004460/QUSER/QZDASOINIT', '005096/QUSER/QZDASOINIT', '005319/QUSER/QZDASOINIT']
619
+ ```
620
+
443
621
 
444
622
  # Development Setup
445
623
 
@@ -3,8 +3,8 @@
3
3
  <a href="https://github.com/Mapepire-IBMi/mapepire-python/actions">
4
4
  <img alt="CI" src="https://img.shields.io/github/actions/workflow/status/Mapepire-IBMi/mapepire-python/main.yml">
5
5
  </a>
6
- <a href="https://pypi.org/project/python-wsdb/">
7
- <img alt="PyPI" src="https://img.shields.io/pypi/v/python-wsdb">
6
+ <a href="https://pypi.org/project/mapepire-python/">
7
+ <img alt="PyPI" src="https://img.shields.io/pypi/v/mapepire-python">
8
8
  </a>
9
9
  <a href="https://github.com/Mapepire-IBMi/mapepire-python/blob/main/LICENSE">
10
10
  <img alt="License" src="https://img.shields.io/github/license/allenai/tango.svg?color=blue&cachedrop">
@@ -12,35 +12,47 @@
12
12
  <br/>
13
13
  </div>
14
14
 
15
- - [Overview](#overview)
16
- - [Setup](#setup)
17
- - [Install with `pip`](#install-with-pip)
18
- - [Server Component Setup (Forthcoming)](#server-component-setup-forthcoming)
19
- - [Example usage](#example-usage)
15
+ - [mapepire-python](#mapepire-python)
16
+ - [Overview](#overview)
17
+ - [Setup](#setup)
18
+ - [Install with `pip`](#install-with-pip)
19
+ - [Server Component Setup](#server-component-setup)
20
+ - [Example usage](#example-usage)
21
+ - [Query and run](#query-and-run)
22
+ - [Asynchronous Query Execution](#asynchronous-query-execution)
23
+ - [Pooling (beta)](#pooling-beta)
20
24
  - [Development Setup](#development-setup)
21
25
  - [Setup python virtual environment with pip and venv](#setup-python-virtual-environment-with-pip-and-venv)
22
26
  - [Create a new virtual environment](#create-a-new-virtual-environment)
23
27
  - [Unix/macOS](#unixmacos)
24
28
  - [Windows](#windows)
25
29
  - [Activate the virtual environment:](#activate-the-virtual-environment)
30
+ - [Unix.macOS](#unixmacos-1)
31
+ - [Windows](#windows-1)
32
+ - [Unix/macOS](#unixmacos-2)
33
+ - [Windows](#windows-2)
26
34
  - [Prepare pip](#prepare-pip)
35
+ - [Unix/macOS](#unixmacos-3)
36
+ - [Windows](#windows-3)
27
37
  - [Install Dependencies using `requirements-dev.txt`](#install-dependencies-using-requirements-devtxt)
38
+ - [Unix/macOS](#unixmacos-4)
39
+ - [Windows](#windows-4)
28
40
  - [Setup Python virtual environment with Conda](#setup-python-virtual-environment-with-conda)
29
41
  - [Create an environment from an environment-dev.yml file](#create-an-environment-from-an-environment-devyml-file)
30
42
  - [1. Activate the new environment:](#1-activate-the-new-environment)
31
43
  - [2. Verify the new environment was installed:](#2-verify-the-new-environment-was-installed)
32
- - [Run local test suite](#run-local-test-suite)
44
+ - [Run local test suite](#run-local-test-suite)
33
45
 
34
46
 
35
47
 
48
+ ## Overview
36
49
 
37
- #### ⚠️ (WIP!) This Project is for demo purposes only
50
+ <img src="images/mapepire-logo.png" alt="logo" width="200"/>
38
51
 
39
- ## Overview
52
+ ---
40
53
 
41
- ![alt text](images/image-1.png)
42
54
 
43
- `mapepire-python` is a Python client implementation that leverages the [CodeFori Server Component](https://github.com/ThePrez/CodeForIBMiServer).
55
+ `mapepire-python` is a Python client implementation for [Mapepire](https://github.com/Mapepire-IBMi) that provides a simple interface for connecting to an IBM i server and running SQL queries. The client is designed to work with the [Mapepire Server Component](https://github.com/Mapepire-IBMi/mapepire-server)
44
56
 
45
57
  ## Setup
46
58
 
@@ -48,36 +60,49 @@
48
60
 
49
61
  ### Install with `pip`
50
62
 
51
- `mapepire-python` is available on [PyPi](https://pypi.org/project/python-wsdb/). Just Run
63
+ `mapepire-python` is available on [PyPi](https://pypi.org/project/mapepire-python/). Just Run
52
64
 
53
65
  ```bash
54
- pip install python-wsdb
66
+ pip install mapepire-python
55
67
  ```
56
68
 
57
- ### Server Component Setup (Forthcoming)
69
+ ### Server Component Setup
70
+ 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/)
58
71
 
59
72
  ## Example usage
60
73
 
61
- The following script sets up a `DaemonServer` object that will be used to connect with the Server Component. Then a single `SQLJob` is created to facilitate the connection from the client side.
74
+ Setup the server credentials used to connect to the server. One way to do this is to create a `mapepire.ini` file in the root of your project with the following content:
75
+
76
+ ```ini
77
+ [mapepire]
78
+ SERVER="SERVER"
79
+ PORT="PORT"
80
+ USER="USER"
81
+ PASSWORD="PASSWORD"
82
+ ```
83
+
84
+ The following script sets up a `DaemonServer` object that will be used to connect with the Server Component. Then a single `SQLJob` is created to facilitate the connection from the client side.
62
85
 
63
86
  ```python
87
+ import configparser
64
88
  from mapepire_python.client.sql_job import SQLJob
65
89
  from mapepire_python.types import DaemonServer
66
90
 
91
+ config = configparser.ConfigParser()
92
+ config.read('mapepire.ini')
93
+
67
94
  creds = DaemonServer(
68
- host="localhost",
69
- port=8085,
70
- user="USER",
71
- password="PASSWORD",
95
+ host=config['mapepire']['SERVER'],
96
+ port=config['mapepire']['PORT'],
97
+ user=config['mapepire']['USER'],
98
+ password=config['mapepire']['PASSWORD'],
72
99
  ignoreUnauthorized=True
73
100
  )
74
101
 
75
-
76
- job = SQLJob()
77
- res = job.connect(creds)
78
- query = job.query("select * from sample.employee")
79
- result = query.run(rows_to_fetch=3)
80
- print(result)
102
+ with SQLJob(creds) as sql_job:
103
+ with sql_job.query("select * from sample.employee") as query:
104
+ result = query.run(rows_to_fetch=1)
105
+ print(result)
81
106
  ```
82
107
 
83
108
  Here is the output from the script above:
@@ -200,6 +225,156 @@ Here is the output from the script above:
200
225
  }
201
226
 
202
227
  ```
228
+ The results object is a JSON object that contains the metadata and data from the query. Here are the different fields returned:
229
+ - `id` field contains the query ID
230
+ - `has_results` field indicates whether the query returned any results
231
+ - `update_count` field indicates the number of rows updated by the query (-1 if the query did not update any rows)
232
+ - `metadata` field contains information about the columns returned by the query
233
+ - `data` field contains the results of the query
234
+ - `is_done` field indicates whether the query has finished executing
235
+ - `success` field indicates whether the query was successful.
236
+
237
+ In the ouput above, the query was successful and returned one row of data.
238
+
239
+ ### Query and run
240
+
241
+ To create and run a query in a single step, use the `query_and_run` method:
242
+
243
+ ```python
244
+ import configparser
245
+ from mapepire_python.client.sql_job import SQLJob
246
+ from mapepire_python.types import DaemonServer
247
+
248
+ config = configparser.ConfigParser()
249
+ config.read('mapepire.ini')
250
+
251
+ creds = DaemonServer(
252
+ host=config['mapepire']['SERVER'],
253
+ port=config['mapepire']['PORT'],
254
+ user=config['mapepire']['USER'],
255
+ password=config['mapepire']['PASSWORD'],
256
+ ignoreUnauthorized=True
257
+ )
258
+
259
+ with SQLJob(creds) as sql_job:
260
+ # query automatically closed after running
261
+ results = sql_job.query_and_run("select * from sample.employee", rows_to_fetch=1)
262
+ print(result)
263
+ ```
264
+
265
+ ### Asynchronous Query Execution
266
+
267
+ The `PoolJob` object can be used to create and run queries asynchronously:
268
+
269
+ ```python
270
+ import asyncio
271
+ import configparser
272
+ from mapepire_python.pool.pool_job import PoolJob
273
+ from mapepire_python.types import DaemonServer
274
+
275
+ config = configparser.ConfigParser()
276
+ config.read('mapepire.ini')
277
+
278
+ creds = DaemonServer(
279
+ host=config['mapepire']['SERVER'],
280
+ port=config['mapepire']['PORT'],
281
+ user=config['mapepire']['USER'],
282
+ password=config['mapepire']['PASSWORD'],
283
+ ignoreUnauthorized=True
284
+ )
285
+
286
+ async def main():
287
+ async with PoolJob(creds=creds) as pool_job:
288
+ async with pool_job.query('select * from sample.employee') as query:
289
+ res = await query.run(rows_to_fetch=1)
290
+
291
+ if __name__ == '__main__':
292
+ asyncio.run(main())
293
+
294
+ ```
295
+
296
+ To run a create and run a query asynchronously in a single step, use the `query_and_run` method:
297
+
298
+ ```python
299
+ import asyncio
300
+ import configparser
301
+ from mapepire_python.pool.pool_job import PoolJob
302
+ from mapepire_python.types import DaemonServer
303
+
304
+ config = configparser.ConfigParser()
305
+ config.read('mapepire.ini')
306
+
307
+ creds = DaemonServer(
308
+ host=config['mapepire']['SERVER'],
309
+ port=config['mapepire']['PORT'],
310
+ user=config['mapepire']['USER'],
311
+ password=config['mapepire']['PASSWORD'],
312
+ ignoreUnauthorized=True
313
+ )
314
+
315
+ async def main():
316
+ async with PoolJob(creds=creds) as pool_job:
317
+ res = await pool_job.query_and_run(rows_to_fetch=1)
318
+ print(res)
319
+
320
+ if __name__ == '__main__':
321
+ asyncio.run(main())
322
+
323
+ ```
324
+
325
+
326
+ ## Pooling (beta)
327
+
328
+ The `Pool` object can be used to create a pool of `PoolJob` objects to run queries concurrently.
329
+
330
+ ```python
331
+ import asyncio
332
+ import configparser
333
+ from mapepire_python.pool.pool_client import Pool, PoolOptions
334
+ from mapepire_python.types import DaemonServer
335
+
336
+ config = configparser.ConfigParser()
337
+ config.read('mapepire.ini')
338
+
339
+ creds = DaemonServer(
340
+ host=config['mapepire']['SERVER'],
341
+ port=config['mapepire']['PORT'],
342
+ user=config['mapepire']['USER'],
343
+ password=config['mapepire']['PASSWORD'],
344
+ ignoreUnauthorized=True
345
+ )
346
+
347
+
348
+ async def main():
349
+ async with Pool(
350
+ options=PoolOptions(
351
+ creds=creds,
352
+ opts=None,
353
+ max_size=5,
354
+ starting_size=3
355
+ )
356
+ ) as pool:
357
+ job_names = []
358
+ resultsA = await asyncio.gather(
359
+ pool.execute('values (job_name)'),
360
+ pool.execute('values (job_name)'),
361
+ pool.execute('values (job_name)')
362
+ )
363
+ job_names = [res['data'][0]['00001'] for res in resultsA]
364
+
365
+ print(job_names)
366
+
367
+
368
+ if __name__ == '__main__':
369
+ asyncio.run(main())
370
+
371
+ ```
372
+ 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.
373
+
374
+ ```bash
375
+ ['004460/QUSER/QZDASOINIT', '005096/QUSER/QZDASOINIT', '005319/QUSER/QZDASOINIT']
376
+ ```
377
+
203
378
 
204
379
  # Development Setup
205
380
 
@@ -0,0 +1,42 @@
1
+ from typing import Any, Dict, Optional, Union
2
+
3
+ from .data_types import DaemonServer, JobStatus, QueryOptions
4
+
5
+
6
+ class BaseJob:
7
+ def __init__(self, creds: DaemonServer = None, options: Dict[Any, Any] = {}) -> None:
8
+ self.creds = creds
9
+ self.options = options
10
+
11
+ def connect(self, db2_server: Union[DaemonServer, Dict[str, Any]]) -> Dict[str, Any]:
12
+ raise NotImplementedError()
13
+
14
+ def close(self) -> None:
15
+ raise NotImplementedError()
16
+
17
+ def get_status(self) -> JobStatus:
18
+ raise NotImplementedError()
19
+
20
+ def query(
21
+ self,
22
+ sql: str,
23
+ opts: Optional[Union[Dict[str, Any], QueryOptions]] = None,
24
+ ):
25
+ raise NotImplementedError()
26
+
27
+ def query_and_run(
28
+ self, sql: str, opts: Optional[Dict[str, Any]] = None, **kwargs
29
+ ) -> Dict[str, Any]:
30
+ raise NotImplementedError()
31
+
32
+ def __enter__(self):
33
+ raise NotImplementedError()
34
+
35
+ def __exit__(self, *args, **kwargs):
36
+ raise NotImplementedError()
37
+
38
+ async def __aenter__(self):
39
+ raise NotImplementedError()
40
+
41
+ async def __aexit__(self, *args, **kwargs):
42
+ raise NotImplementedError()