mapepire-python 0.1.4__tar.gz → 0.1.6__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.4 → mapepire_python-0.1.6}/PKG-INFO +283 -20
- mapepire_python-0.1.6/README.md +655 -0
- mapepire_python-0.1.6/mapepire_python/__init__.py +49 -0
- mapepire_python-0.1.6/mapepire_python/asyncio/__init__.py +47 -0
- mapepire_python-0.1.6/mapepire_python/asyncio/connection.py +82 -0
- mapepire_python-0.1.6/mapepire_python/asyncio/cursor.py +99 -0
- mapepire_python-0.1.6/mapepire_python/asyncio/utils.py +23 -0
- mapepire_python-0.1.6/mapepire_python/base_job.py +78 -0
- mapepire_python-0.1.6/mapepire_python/client/__init__.py +3 -0
- mapepire_python-0.1.6/mapepire_python/client/query.py +185 -0
- {mapepire_python-0.1.4 → mapepire_python-0.1.6}/mapepire_python/client/sql_job.py +89 -30
- mapepire_python-0.1.6/mapepire_python/client/websocket.py +37 -0
- mapepire_python-0.1.6/mapepire_python/core/__init__.py +27 -0
- mapepire_python-0.1.6/mapepire_python/core/connection.py +86 -0
- mapepire_python-0.1.6/mapepire_python/core/cursor.py +201 -0
- mapepire_python-0.1.6/mapepire_python/core/exceptions.py +97 -0
- mapepire_python-0.1.6/mapepire_python/core/utils.py +78 -0
- mapepire_python-0.1.4/mapepire_python/types.py → mapepire_python-0.1.6/mapepire_python/data_types.py +18 -12
- mapepire_python-0.1.6/mapepire_python/pool/__init__.py +4 -0
- mapepire_python-0.1.6/mapepire_python/pool/pool_client.py +145 -0
- mapepire_python-0.1.6/mapepire_python/pool/pool_job.py +318 -0
- mapepire_python-0.1.4/mapepire_python/client/query.py → mapepire_python-0.1.6/mapepire_python/pool/pool_query.py +38 -34
- mapepire_python-0.1.6/mapepire_python/query_manager.py +67 -0
- {mapepire_python-0.1.4 → mapepire_python-0.1.6}/mapepire_python/ssl.py +1 -1
- {mapepire_python-0.1.4 → mapepire_python-0.1.6}/mapepire_python/version.py +1 -1
- {mapepire_python-0.1.4 → mapepire_python-0.1.6}/mapepire_python.egg-info/PKG-INFO +283 -20
- mapepire_python-0.1.6/mapepire_python.egg-info/SOURCES.txt +32 -0
- {mapepire_python-0.1.4 → mapepire_python-0.1.6}/mapepire_python.egg-info/requires.txt +6 -0
- {mapepire_python-0.1.4 → mapepire_python-0.1.6}/pyproject.toml +6 -0
- mapepire_python-0.1.4/README.md +0 -398
- mapepire_python-0.1.4/mapepire_python/pool.py +0 -29
- mapepire_python-0.1.4/mapepire_python.egg-info/SOURCES.txt +0 -15
- {mapepire_python-0.1.4 → mapepire_python-0.1.6}/LICENSE +0 -0
- {mapepire_python-0.1.4 → mapepire_python-0.1.6}/mapepire_python/py.typed +0 -0
- {mapepire_python-0.1.4 → mapepire_python-0.1.6}/mapepire_python.egg-info/dependency_links.txt +0 -0
- {mapepire_python-0.1.4 → mapepire_python-0.1.6}/mapepire_python.egg-info/top_level.txt +0 -0
- {mapepire_python-0.1.4 → mapepire_python-0.1.6}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: mapepire-python
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.6
|
|
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,18 @@ 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
|
|
222
|
+
Requires-Dist: pep249abc
|
|
220
223
|
Provides-Extra: dev
|
|
221
224
|
Requires-Dist: ruff; extra == "dev"
|
|
222
225
|
Requires-Dist: mypy<1.5,>=1.0; extra == "dev"
|
|
223
226
|
Requires-Dist: black<24.0,>=23.0; extra == "dev"
|
|
224
227
|
Requires-Dist: isort<5.13,>=5.12; extra == "dev"
|
|
225
228
|
Requires-Dist: pytest; extra == "dev"
|
|
229
|
+
Requires-Dist: pyee; extra == "dev"
|
|
230
|
+
Requires-Dist: pep249abc; extra == "dev"
|
|
231
|
+
Requires-Dist: pytest-asyncio; extra == "dev"
|
|
226
232
|
Requires-Dist: pytest-sphinx; extra == "dev"
|
|
227
233
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
228
234
|
Requires-Dist: twine>=1.11.0; extra == "dev"
|
|
@@ -252,26 +258,49 @@ Requires-Dist: pre-commit; extra == "dev"
|
|
|
252
258
|
<br/>
|
|
253
259
|
</div>
|
|
254
260
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
- [
|
|
261
|
+
<details>
|
|
262
|
+
<summary> Table of Contents </summary>
|
|
263
|
+
|
|
264
|
+
- [mapepire-python](#mapepire-python)
|
|
265
|
+
- [Overview](#overview)
|
|
266
|
+
- [Setup](#setup)
|
|
267
|
+
- [Install with `pip`](#install-with-pip)
|
|
268
|
+
- [Server Component Setup](#server-component-setup)
|
|
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)
|
|
275
|
+
- [Query and run](#query-and-run)
|
|
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)
|
|
260
281
|
- [Development Setup](#development-setup)
|
|
261
282
|
- [Setup python virtual environment with pip and venv](#setup-python-virtual-environment-with-pip-and-venv)
|
|
262
283
|
- [Create a new virtual environment](#create-a-new-virtual-environment)
|
|
263
284
|
- [Unix/macOS](#unixmacos)
|
|
264
285
|
- [Windows](#windows)
|
|
265
286
|
- [Activate the virtual environment:](#activate-the-virtual-environment)
|
|
287
|
+
- [Unix.macOS](#unixmacos-1)
|
|
288
|
+
- [Windows](#windows-1)
|
|
289
|
+
- [Unix/macOS](#unixmacos-2)
|
|
290
|
+
- [Windows](#windows-2)
|
|
266
291
|
- [Prepare pip](#prepare-pip)
|
|
292
|
+
- [Unix/macOS](#unixmacos-3)
|
|
293
|
+
- [Windows](#windows-3)
|
|
267
294
|
- [Install Dependencies using `requirements-dev.txt`](#install-dependencies-using-requirements-devtxt)
|
|
295
|
+
- [Unix/macOS](#unixmacos-4)
|
|
296
|
+
- [Windows](#windows-4)
|
|
268
297
|
- [Setup Python virtual environment with Conda](#setup-python-virtual-environment-with-conda)
|
|
269
298
|
- [Create an environment from an environment-dev.yml file](#create-an-environment-from-an-environment-devyml-file)
|
|
270
299
|
- [1. Activate the new environment:](#1-activate-the-new-environment)
|
|
271
300
|
- [2. Verify the new environment was installed:](#2-verify-the-new-environment-was-installed)
|
|
272
|
-
- [Run local test suite](#run-local-test-suite)
|
|
273
|
-
|
|
301
|
+
- [Run local test suite](#run-local-test-suite)
|
|
274
302
|
|
|
303
|
+
</details>
|
|
275
304
|
|
|
276
305
|
## Overview
|
|
277
306
|
|
|
@@ -284,7 +313,7 @@ Requires-Dist: pre-commit; extra == "dev"
|
|
|
284
313
|
|
|
285
314
|
## Setup
|
|
286
315
|
|
|
287
|
-
`mapepire-python` requires Python 3.
|
|
316
|
+
`mapepire-python` requires Python 3.10 or later.
|
|
288
317
|
|
|
289
318
|
### Install with `pip`
|
|
290
319
|
|
|
@@ -297,28 +326,116 @@ pip install mapepire-python
|
|
|
297
326
|
### Server Component Setup
|
|
298
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/)
|
|
299
328
|
|
|
300
|
-
|
|
329
|
+
|
|
330
|
+
# Connection options
|
|
331
|
+
|
|
332
|
+
There are three ways to configure mapepire server connection details using `mapepire-python`:
|
|
333
|
+
|
|
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
|
+
```
|
|
301
353
|
|
|
302
|
-
|
|
354
|
+
Once you have created the `DaemonServer` object, you can pass it to the `SQLJob` object to connect to the mapepire server:
|
|
303
355
|
|
|
304
356
|
```python
|
|
305
357
|
from mapepire_python.client.sql_job import SQLJob
|
|
306
|
-
from mapepire_python.
|
|
358
|
+
from mapepire_python.data_types import DaemonServer
|
|
307
359
|
|
|
308
360
|
creds = DaemonServer(
|
|
309
|
-
host="
|
|
310
|
-
port=
|
|
361
|
+
host="SERVER",
|
|
362
|
+
port="PORT",
|
|
311
363
|
user="USER",
|
|
312
364
|
password="PASSWORD",
|
|
313
365
|
ignoreUnauthorized=True
|
|
314
366
|
)
|
|
315
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
|
|
316
391
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
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
|
|
398
|
+
[mapepire]
|
|
399
|
+
SERVER="SERVER"
|
|
400
|
+
PORT="PORT"
|
|
401
|
+
USER="USER"
|
|
402
|
+
PASSWORD="PASSWORD"
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
Then you can create a `SQLJob` object by passing the path to the `.ini` file which will handle the connection details
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
```python
|
|
409
|
+
from mapepire_python.client.sql_job import SQLJob
|
|
410
|
+
|
|
411
|
+
job = SQLJob("./mapepire.ini", section="mapepire")
|
|
412
|
+
```
|
|
413
|
+
|
|
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.
|
|
420
|
+
|
|
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:
|
|
436
|
+
with sql_job.query("select * from sample.employee") as query:
|
|
437
|
+
result = query.run(rows_to_fetch=1)
|
|
438
|
+
print(result)
|
|
322
439
|
```
|
|
323
440
|
|
|
324
441
|
Here is the output from the script above:
|
|
@@ -441,6 +558,152 @@ Here is the output from the script above:
|
|
|
441
558
|
}
|
|
442
559
|
|
|
443
560
|
```
|
|
561
|
+
The results object is a JSON object that contains the metadata and data from the query. Here are the different fields returned:
|
|
562
|
+
- `id` field contains the query ID
|
|
563
|
+
- `has_results` field indicates whether the query returned any results
|
|
564
|
+
- `update_count` field indicates the number of rows updated by the query (-1 if the query did not update any rows)
|
|
565
|
+
- `metadata` field contains information about the columns returned by the query
|
|
566
|
+
- `data` field contains the results of the query
|
|
567
|
+
- `is_done` field indicates whether the query has finished executing
|
|
568
|
+
- `success` field indicates whether the query was successful.
|
|
569
|
+
|
|
570
|
+
In the ouput above, the query was successful and returned one row of data.
|
|
571
|
+
|
|
572
|
+
### Query and run
|
|
573
|
+
|
|
574
|
+
To create and run a query in a single step, use the `query_and_run` method:
|
|
575
|
+
|
|
576
|
+
```python
|
|
577
|
+
from mapepire_python.client.sql_job import SQLJob
|
|
578
|
+
|
|
579
|
+
with SQLJob("./mapepire.ini") as sql_job:
|
|
580
|
+
# query automatically closed after running
|
|
581
|
+
results = sql_job.query_and_run("select * from sample.employee", rows_to_fetch=1)
|
|
582
|
+
print(result)
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
## 2. Using the `PoolJob` object to run queries asynchronously
|
|
586
|
+
|
|
587
|
+
The `PoolJob` object can be used to create and run queries asynchronously:
|
|
588
|
+
|
|
589
|
+
```python
|
|
590
|
+
import asyncio
|
|
591
|
+
from mapepire_python.pool.pool_job import PoolJob
|
|
592
|
+
|
|
593
|
+
async def main():
|
|
594
|
+
async with PoolJob("./mapepire.ini") as pool_job:
|
|
595
|
+
async with pool_job.query('select * from sample.employee') as query:
|
|
596
|
+
res = await query.run(rows_to_fetch=1)
|
|
597
|
+
|
|
598
|
+
if __name__ == '__main__':
|
|
599
|
+
asyncio.run(main())
|
|
600
|
+
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
To run a create and run a query asynchronously in a single step, use the `query_and_run` method:
|
|
604
|
+
|
|
605
|
+
```python
|
|
606
|
+
import asyncio
|
|
607
|
+
from mapepire_python.pool.pool_job import PoolJob
|
|
608
|
+
|
|
609
|
+
async def main():
|
|
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)
|
|
612
|
+
print(res)
|
|
613
|
+
|
|
614
|
+
if __name__ == '__main__':
|
|
615
|
+
asyncio.run(main())
|
|
616
|
+
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
## 3. Using the `Pool` object to run queries "concurrently"
|
|
621
|
+
|
|
622
|
+
The `Pool` object can be used to create a pool of `PoolJob` objects to run queries concurrently.
|
|
623
|
+
|
|
624
|
+
```python
|
|
625
|
+
import asyncio
|
|
626
|
+
from mapepire_python.pool.pool_client import Pool, PoolOptions
|
|
627
|
+
|
|
628
|
+
async def main():
|
|
629
|
+
async with Pool(
|
|
630
|
+
options=PoolOptions(
|
|
631
|
+
creds="./mapepire.ini",
|
|
632
|
+
opts=None,
|
|
633
|
+
max_size=5,
|
|
634
|
+
starting_size=3
|
|
635
|
+
)
|
|
636
|
+
) as pool:
|
|
637
|
+
job_names = []
|
|
638
|
+
resultsA = await asyncio.gather(
|
|
639
|
+
pool.execute('values (job_name)'),
|
|
640
|
+
pool.execute('values (job_name)'),
|
|
641
|
+
pool.execute('values (job_name)')
|
|
642
|
+
)
|
|
643
|
+
job_names = [res['data'][0]['00001'] for res in resultsA]
|
|
644
|
+
|
|
645
|
+
print(job_names)
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
if __name__ == '__main__':
|
|
649
|
+
asyncio.run(main())
|
|
650
|
+
```
|
|
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.
|
|
652
|
+
|
|
653
|
+
```bash
|
|
654
|
+
['004460/QUSER/QZDASOINIT', '005096/QUSER/QZDASOINIT', '005319/QUSER/QZDASOINIT']
|
|
655
|
+
```
|
|
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
|
+
|
|
444
707
|
|
|
445
708
|
# Development Setup
|
|
446
709
|
|
|
@@ -454,7 +717,7 @@ This guide provides instructions for setting up a Python virtual environment usi
|
|
|
454
717
|
|
|
455
718
|
### Create a new virtual environment
|
|
456
719
|
|
|
457
|
-
**Note**: This applies to supported versions of Python 3.
|
|
720
|
+
**Note**: This applies to supported versions of Python 3.10 and higher
|
|
458
721
|
|
|
459
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`
|
|
460
723
|
|