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.
Files changed (35) hide show
  1. {mapepire_python-0.1.5 → mapepire_python-0.1.7}/PKG-INFO +172 -86
  2. {mapepire_python-0.1.5 → mapepire_python-0.1.7}/README.md +166 -83
  3. mapepire_python-0.1.7/mapepire_python/__init__.py +49 -0
  4. mapepire_python-0.1.7/mapepire_python/asyncio/__init__.py +47 -0
  5. mapepire_python-0.1.7/mapepire_python/asyncio/connection.py +82 -0
  6. mapepire_python-0.1.7/mapepire_python/asyncio/cursor.py +99 -0
  7. mapepire_python-0.1.7/mapepire_python/asyncio/utils.py +23 -0
  8. mapepire_python-0.1.7/mapepire_python/base_job.py +78 -0
  9. mapepire_python-0.1.7/mapepire_python/client/__init__.py +3 -0
  10. {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python/client/query.py +43 -4
  11. {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python/client/sql_job.py +16 -7
  12. {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python/client/websocket.py +1 -1
  13. mapepire_python-0.1.7/mapepire_python/core/__init__.py +27 -0
  14. mapepire_python-0.1.7/mapepire_python/core/connection.py +86 -0
  15. mapepire_python-0.1.7/mapepire_python/core/cursor.py +201 -0
  16. mapepire_python-0.1.7/mapepire_python/core/exceptions.py +97 -0
  17. mapepire_python-0.1.7/mapepire_python/core/utils.py +78 -0
  18. {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python/data_types.py +10 -10
  19. mapepire_python-0.1.7/mapepire_python/pool/__init__.py +4 -0
  20. {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python/pool/pool_client.py +6 -2
  21. {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python/pool/pool_job.py +31 -16
  22. {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python/pool/pool_query.py +3 -3
  23. {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python/query_manager.py +5 -6
  24. {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python/version.py +1 -1
  25. {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python.egg-info/PKG-INFO +172 -86
  26. {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python.egg-info/SOURCES.txt +12 -0
  27. {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python.egg-info/requires.txt +3 -0
  28. {mapepire_python-0.1.5 → mapepire_python-0.1.7}/pyproject.toml +7 -3
  29. mapepire_python-0.1.5/mapepire_python/base_job.py +0 -42
  30. {mapepire_python-0.1.5 → mapepire_python-0.1.7}/LICENSE +0 -0
  31. {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python/py.typed +0 -0
  32. {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python/ssl.py +0 -0
  33. {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python.egg-info/dependency_links.txt +0 -0
  34. {mapepire_python-0.1.5 → mapepire_python-0.1.7}/mapepire_python.egg-info/top_level.txt +0 -0
  35. {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.5
4
- Author-email: Allen Institute for Artificial Intelligence <contact@allenai.org>
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.8
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
- - [Example usage](#example-usage)
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
- - [Asynchronous Query Execution](#asynchronous-query-execution)
266
- - [Pooling (beta)](#pooling-beta)
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.9 or later.
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
- ## Example usage
329
+
330
+ # Connection options
316
331
 
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:
332
+ There are three ways to configure mapepire server connection details using `mapepire-python`:
318
333
 
319
- ```ini
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
- 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.
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
- config = configparser.ConfigParser()
335
- config.read('mapepire.ini')
411
+ job = SQLJob("./mapepire.ini", section="mapepire")
412
+ ```
336
413
 
337
- creds = DaemonServer(
338
- host=config['mapepire']['SERVER'],
339
- port=config['mapepire']['PORT'],
340
- user=config['mapepire']['USER'],
341
- password=config['mapepire']['PASSWORD'],
342
- ignoreUnauthorized=True
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
- with SQLJob(creds) as sql_job:
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(creds) as sql_job:
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
- ### Asynchronous Query Execution
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(creds=creds) as pool_job:
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(creds=creds) as pool_job:
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
- ## Pooling (beta)
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=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.8 and higher
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