mimerpy 1.3.0__tar.gz → 1.3.2__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 (61) hide show
  1. {mimerpy-1.3.0 → mimerpy-1.3.2}/PKG-INFO +4 -4
  2. {mimerpy-1.3.0 → mimerpy-1.3.2}/doc/datatypes.rst +59 -8
  3. {mimerpy-1.3.0 → mimerpy-1.3.2}/doc/gettingstarted.rst +1 -1
  4. {mimerpy-1.3.0 → mimerpy-1.3.2}/doc/index.rst +1 -2
  5. {mimerpy-1.3.0 → mimerpy-1.3.2}/doc/installationguide.rst +15 -18
  6. {mimerpy-1.3.0 → mimerpy-1.3.2}/doc/introduction.rst +3 -3
  7. mimerpy-1.3.2/doc/releasenotes.rst +64 -0
  8. {mimerpy-1.3.0 → mimerpy-1.3.2}/doc/userguide.rst +1 -1
  9. {mimerpy-1.3.0 → mimerpy-1.3.2}/pyproject.toml +5 -4
  10. {mimerpy-1.3.0 → mimerpy-1.3.2}/src/mimerpy/__init__.py +10 -24
  11. mimerpy-1.3.2/src/mimerpy/_version.py +4 -0
  12. {mimerpy-1.3.0 → mimerpy-1.3.2}/src/mimerpy/connectionPy.py +3 -3
  13. {mimerpy-1.3.0 → mimerpy-1.3.2}/src/mimerpy/cursorPy.py +119 -5
  14. mimerpy-1.3.0/src/mimerpy/mimPyExceptionHandler.py → mimerpy-1.3.2/src/mimerpy/mimPyErrorCodes.py +19 -36
  15. mimerpy-1.3.2/src/mimerpy/mimPyExceptionHandler.py +58 -0
  16. {mimerpy-1.3.0 → mimerpy-1.3.2}/src/mimerpy/mimPyExceptions.py +3 -0
  17. {mimerpy-1.3.0 → mimerpy-1.3.2}/src/mimerpy/mimerapi.py +117 -26
  18. {mimerpy-1.3.0 → mimerpy-1.3.2}/src/mimerpy/pool.py +2 -3
  19. mimerpy-1.3.2/src/mimerpy/utils.py +99 -0
  20. {mimerpy-1.3.0 → mimerpy-1.3.2}/src/mimerpy.egg-info/PKG-INFO +4 -4
  21. {mimerpy-1.3.0 → mimerpy-1.3.2}/src/mimerpy.egg-info/SOURCES.txt +5 -1
  22. mimerpy-1.3.2/src/mimerpy.egg-info/requires.txt +3 -0
  23. {mimerpy-1.3.0 → mimerpy-1.3.2}/tests/testConnection.py +4 -4
  24. {mimerpy-1.3.0 → mimerpy-1.3.2}/tests/testCursor.py +186 -53
  25. mimerpy-1.3.2/tests/testutils.py +96 -0
  26. mimerpy-1.3.0/doc/releasenotes.rst +0 -31
  27. mimerpy-1.3.0/src/mimerpy/_version.py +0 -34
  28. {mimerpy-1.3.0 → mimerpy-1.3.2}/.gitattributes +0 -0
  29. {mimerpy-1.3.0 → mimerpy-1.3.2}/.gitignore +0 -0
  30. {mimerpy-1.3.0 → mimerpy-1.3.2}/LICENSE.txt +0 -0
  31. {mimerpy-1.3.0 → mimerpy-1.3.2}/MANIFEST.in +0 -0
  32. {mimerpy-1.3.0 → mimerpy-1.3.2}/README.rst +0 -0
  33. {mimerpy-1.3.0 → mimerpy-1.3.2}/dist-requirements.txt +0 -0
  34. {mimerpy-1.3.0 → mimerpy-1.3.2}/doc/.gitignore +0 -0
  35. {mimerpy-1.3.0 → mimerpy-1.3.2}/doc/Makefile +0 -0
  36. {mimerpy-1.3.0 → mimerpy-1.3.2}/doc/README.txt +0 -0
  37. {mimerpy-1.3.0 → mimerpy-1.3.2}/doc/_static/style.css +0 -0
  38. {mimerpy-1.3.0 → mimerpy-1.3.2}/doc/_templates/layout.html +0 -0
  39. {mimerpy-1.3.0 → mimerpy-1.3.2}/doc/codeexamples.rst +0 -0
  40. {mimerpy-1.3.0 → mimerpy-1.3.2}/doc/conf.py +0 -0
  41. {mimerpy-1.3.0 → mimerpy-1.3.2}/doc/dbtest.py +0 -0
  42. {mimerpy-1.3.0 → mimerpy-1.3.2}/doc/exceptions.rst +0 -0
  43. {mimerpy-1.3.0 → mimerpy-1.3.2}/doc/images/mimerhd.png +0 -0
  44. {mimerpy-1.3.0 → mimerpy-1.3.2}/doc/images/mimerhd32x32.ico +0 -0
  45. {mimerpy-1.3.0 → mimerpy-1.3.2}/doc/images/mimerhd32x32.png +0 -0
  46. {mimerpy-1.3.0 → mimerpy-1.3.2}/doc/legalnotice.rst +0 -0
  47. {mimerpy-1.3.0 → mimerpy-1.3.2}/doc/make_for_windows.bat +0 -0
  48. {mimerpy-1.3.0 → mimerpy-1.3.2}/doc/mimerpy.rst +0 -0
  49. {mimerpy-1.3.0 → mimerpy-1.3.2}/scripts/ebuild.sh +0 -0
  50. {mimerpy-1.3.0 → mimerpy-1.3.2}/scripts/ubuntuAutoRelease.sh +0 -0
  51. {mimerpy-1.3.0 → mimerpy-1.3.2}/scripts/windowsAutoRelease.bat +0 -0
  52. {mimerpy-1.3.0 → mimerpy-1.3.2}/setup.cfg +0 -0
  53. {mimerpy-1.3.0 → mimerpy-1.3.2}/src/mimerpy/__main__.py +0 -0
  54. {mimerpy-1.3.0 → mimerpy-1.3.2}/src/mimerpy.egg-info/dependency_links.txt +0 -0
  55. {mimerpy-1.3.0 → mimerpy-1.3.2}/src/mimerpy.egg-info/top_level.txt +0 -0
  56. {mimerpy-1.3.0 → mimerpy-1.3.2}/tests/__init__.py +0 -0
  57. {mimerpy-1.3.0 → mimerpy-1.3.2}/tests/db_config.py +0 -0
  58. {mimerpy-1.3.0 → mimerpy-1.3.2}/tests/dropdb.py +0 -0
  59. {mimerpy-1.3.0 → mimerpy-1.3.2}/tests/testMimerPool.py +0 -0
  60. {mimerpy-1.3.0 → mimerpy-1.3.2}/tests/testMonkey.py +0 -0
  61. {mimerpy-1.3.0 → mimerpy-1.3.2}/tests/testScrollCursor.py +0 -0
@@ -1,10 +1,10 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.2
2
2
  Name: mimerpy
3
- Version: 1.3.0
3
+ Version: 1.3.2
4
4
  Summary: Python database interface for Mimer SQL
5
5
  Author-email: Erik Gunne <mimerpy@mimer.com>, Magdalena Boström <mimerpy@mimer.com>, Mimer Information Technology AB <mimerpy@mimer.com>
6
6
  Maintainer-email: Mimer Information Technology AB <mimerpy@mimer.com>
7
- License-Expression: MIT
7
+ License: MIT
8
8
  Project-URL: Homepage, https://developer.mimer.com/mimerpy
9
9
  Keywords: Mimer,MimerSQL,Database,SQL,PEP249
10
10
  Classifier: Development Status :: 5 - Production/Stable
@@ -21,7 +21,7 @@ Classifier: Programming Language :: Python :: 3.13
21
21
  Requires-Python: >=3.6
22
22
  Description-Content-Type: text/x-rst
23
23
  License-File: LICENSE.txt
24
- Dynamic: license-file
24
+ Requires-Dist: python-dateutil>=2.8.2; python_version < "3.7"
25
25
 
26
26
  MimerPy: Python database interface for Mimer SQL
27
27
  ==================================================
@@ -49,13 +49,19 @@ Overview of Mimer SQL to Python data types:
49
49
  +------------------------+--------------------+
50
50
  | NVARCHAR(n) | Str |
51
51
  +------------------------+--------------------+
52
- | DATE | Str |
52
+ | DATE | date |
53
53
  +------------------------+--------------------+
54
- | TIME(s) | Str |
54
+ | TIME(s) | time |
55
55
  +------------------------+--------------------+
56
- | TIMESTAMP(s) | Str |
56
+ | TIMESTAMP(s) | datetime |
57
57
  +------------------------+--------------------+
58
- | UUID | uuid |
58
+ | BUILTIN.UUID | uuid.UUID |
59
+ +------------------------+--------------------+
60
+ | BUILTIN.GIS_LOCATION | (Float,Float) |
61
+ +------------------------+--------------------+
62
+ | BUILTIN.GIS_LATITUDE | Float |
63
+ +------------------------+--------------------+
64
+ | BUILTIN.GIS_LONGITUDE | Float |
59
65
  +------------------------+--------------------+
60
66
  | INTERVAL | Str |
61
67
  +------------------------+--------------------+
@@ -269,9 +275,12 @@ DATE
269
275
  ----------
270
276
  DATE describes a date using the fields YEAR, MONTH and DAY in the format YYYY-MM-DD. It represents an absolute position on the timeline.
271
277
 
278
+ DATE values are mapped to Python date objects. When inserting a DATE value, MimerPy also accepts strings in the format 'YYYY-MM-DD'.
272
279
  Example usage of ``DATE``::
273
280
 
274
281
  >>> cursor.execute("create table datetable (c1 DATE)")
282
+ >>> d = date.fromisoformat("2025-01-01")
283
+ >>> cursor.execute("insert INTO datetable VALUES (?)", (d))
275
284
  >>> data = "2020-09-24"
276
285
  >>> cursor.execute("insert INTO datetable VALUES (?)", (data))
277
286
 
@@ -279,24 +288,46 @@ TIME(s)
279
288
  ---------------
280
289
  TIME(s) describes a time in an unspecified day, with seconds precision s, using the fields HOUR, MINUTE and SECOND in the format HH:MM:SS[.sF] where F is the fractional part of the SECOND value. It represents an absolute time of day.
281
290
 
291
+ TIME(s) values are mapped to Python time objects. When inserting a TIME value, MimerPy also accepts strings in the format 'HH:MM:SS[.ffffff]'.
292
+
282
293
  Example usage of ``TIME``::
283
294
 
284
295
  >>> cursor.execute("create table timetable (c1 TIME(0))")
285
- >>> time = "16:04:55"
286
- >>> cursor.execute("insert INTO timetable VALUES (?)", (time))
296
+ >>> t = time.fromisoformat("12:30:20")
297
+ >>> cursor.execute("insert INTO timetable VALUES (?)", (t))
298
+ >>> timestr = "16:04:55"
299
+ >>> cursor.execute("insert INTO timetable VALUES (?)", (timestr))
287
300
 
288
301
  TIMESTAMP(s)
289
302
  ---------------------
290
303
  TIMESTAMP(s) describes both a date and time, with seconds precision s, using the fields YEAR, MONTH, DAY, HOUR, MINUTE and SECOND in the format YYYY-MM-DD HH:MM:SS[.sF]. F is the fractional part of the SECOND value. It represents an absolute position on the timeline.
291
304
 
305
+ TIMESTAMP(s) values are mapped to Python datetime objects. When inserting a TIMESTAMP value, MimerPy also accepts strings in the format 'YYYY-MM-DD HH:MM:SS[.ffffff]'
306
+
292
307
  Example usage of ``TIMESTAMP``::
293
308
 
294
309
  >>> cursor.execute("create table timestamp_table(c1 TIMESTAMP(2))")
295
- >>> cursor.execute("insert into timestamp_table values (:a)", ('2020-09-17 11:21:51.12'))
310
+ >>> dt = datetime.fromisoformat('2020-09-17 11:21:51.12')
311
+ >>> cursor.execute("insert into timestamp_table values (:a)", (dt,))
312
+ >>> cursor.execute("insert into timestamp_table values (:a)", ('2021-01-01 23:12:50.12',))
296
313
 
297
314
  Universally Unique Identifier (UUID)
298
315
  ------------------------------------------
299
- Universally Unique Identifier is currently not implemented.
316
+ The Mimer SQL UUID data type BUILTIN.UUID is handled by the Python built-in uuid module.
317
+ It is also possible to use strings and bytearrays to represent UUID values in MimerPy, but using the uuid module is recommended
318
+
319
+ A BUILTIN.UUID is returned as a uuid.UUID object in Python.
320
+
321
+ Example usage of ``BUILTIN.UUID``::
322
+
323
+ >>> import uuid
324
+ >>> cursor.execute("create table uuidtable (c1 BUILTIN.UUID)")
325
+ >>> uid = uuid.uuid4()
326
+ >>> uuid_byte = uid.bytes
327
+ >>> uuid_str = str(uid)
328
+ >>> cursor.execute("insert into uuidtable values (?)", (uid,))
329
+ >>> cursor.execute("insert into uuidtable values (?)", (uuid_byte,))
330
+ >>> cursor.execute("insert into uuidtable values (?)", (uuid_str,))
300
331
 
301
332
  INTERVAL
302
333
  ------------
@@ -340,6 +371,26 @@ Consider the following example::
340
371
  >>> cursor.execute("create table intervaltable (c1 YEAR(5), c2 INTERVAL YEAR(5) TO MONTH)")
341
372
  >>> cursor.execute("insert into intervaltable values (?)", ("2021", "2021-05"))
342
373
 
374
+
375
+ GIS_LOCATION, GIS_LATITUDE, and GIS_LONGITUDE
376
+ ------------------------------------------------------------------------
377
+ BUILTIN.GIS_LOCATION is used to store a geographic location as a pair of latitude and longitude coordinates.
378
+
379
+ BUILTIN.GIS_LATITUDE is used to store the latitude coordinate and BUILTIN.GIS_LONGITUDE is used
380
+ to store the longitude coordinate of a geographic location.
381
+
382
+ To work with BUILTIN.GIS_LOCATION in MimerPy, use a tuple with two float values representing latitude and longitude.
383
+ BUILTIN.GIS_LATITUDE and BUILTIN.GIS_LONGITUDE are represented as float values in Python.
384
+ MimerPy returns BUILTIN.GIS_LOCATION as a tuple of two float values, and BUILTIN.GIS_LATITUDE and BUILTIN.GIS_LONGITUDE as float values.
385
+
386
+ Example usage of ``BUILTIN.GIS_LOCATION``, ``BUILTIN.GIS_LATITUDE``, and ``BUILTIN.GIS_LONGITUDE``::
387
+
388
+ >>> cursor.execute("create table gistable (loc BUILTIN.GIS_LOCATION, lat BUILTIN.GIS_LATITUDE, lon BUILTIN.GIS_LONGITUDE)")
389
+ >>> lat = 23.21
390
+ >>> lon = -45.67
391
+ >>> loc = (37.21, -51.62)
392
+ >>> cursor.execute("insert INTO gistable VALUES (?, ?, ?)", (loc, lat, lon))
393
+
343
394
  NULL
344
395
  ------------
345
396
  The Python data type ``None`` is mapped to ``NULL`` in
@@ -9,7 +9,7 @@ running, please visit the `Mimer documentation`_.
9
9
 
10
10
  .. _Mimer documentation: https://developer.mimer.com/products/documentation/
11
11
 
12
- .. note:: MimerPy requires Python 3.5 or later. On Windows the command to run python3 varies between `python` and `python3` depending on what versions you have installed. On Linux the command normally is `python3`. In this guide we use `python3` as command, but you might have to adjust for your environment.
12
+ .. note:: MimerPy requires Python 3.6 or later. On Windows the command to run python3 varies between `python` and `python3` depending on what versions you have installed. On Linux the command normally is `python3`. In this guide we use `python3` as command, but you might have to adjust for your environment.
13
13
 
14
14
  Checking the MimerPy installation
15
15
  ---------------------------------
@@ -9,8 +9,7 @@ MimerPy -- Python database interface for Mimer SQL
9
9
  MimerPy is an adapter for Mimer SQL in Python_ which implements the `PEP 249`_
10
10
  specification.
11
11
  It allows the user to connect to Mimer SQL through Python, gaining access of the exceptional performance and powerful features provided by a Mimer SQL database.
12
- MimerPy is implemented as a CPython wrapper of the `Mimer SQL C API`_
13
- also known as Mimer API.
12
+ MimerPy uses the `Mimer SQL C API`_ also known as Mimer API using `ctypes`.
14
13
 
15
14
  The following documentation covers the full interface of MimerPy,
16
15
  demonstrating how to
@@ -7,24 +7,11 @@ The following section covers how to install MimerPy.
7
7
  Requirements
8
8
  ------------------------
9
9
 
10
- MimerPy can currently run with Python3.5 or later, keep in mind
10
+ MimerPy can currently run with Python3.6 or later, keep in mind
11
11
  to use the correct versions if you have multiple versions installed.
12
12
 
13
- If you are running on Ubuntu or Linux, some Python header files are needed for the installation. To install all the
14
- required files use the command:
15
-
16
- .. code-block:: console
17
-
18
- $ sudo apt-get install python3-dev
19
-
20
- Alternatively you can download the Python-dev package in any preferable way.
21
-
22
- .. note:: The error “Python.h: No such file or directory”, is solved by downloading the -dev package.
23
-
24
13
  You need to install the Mimer SQL C API and have a Mimer SQL database server of version 11 or newer.
25
14
 
26
- .. note:: The error “mimerapi.h: No such file or directory”, is caused by Mimer SQL not being installed or a Mimer SQL version older than 11.
27
-
28
15
  .. _sec-SQL-api:
29
16
 
30
17
  Mimer SQL C API
@@ -63,14 +50,24 @@ To build MimerPy's source use the command:
63
50
 
64
51
  .. code-block:: console
65
52
 
66
- $ python3 setup.py build
67
- $ python3 setup.py install
53
+ $ python3 -m build
54
+ $ python3 -m pip install -e .
68
55
 
69
- If you wish to install the built distribution, you can download it from `PyPI`_ and then use pip to install:
56
+ If you wish to install the release distribution manually, you can download it from `PyPI`_ and then use pip to install:
57
+
58
+ To use the source distribution, use the command:
70
59
 
71
60
  .. code-block:: console
72
61
 
73
- $ python3 -m pip install mimerpy-current.version.tar.gz
62
+ $ python3 -m pip install mimerpy-<version>.tar.gz
63
+
64
+ You can also use the pre-built wheel file using the command:
65
+
66
+ .. code-block:: console
67
+
68
+ $ python3 -m pip install mimerpy-<version>-py3-none-any.whl
69
+
70
+
74
71
 
75
72
  .. _GitHub: https://github.com/mimersql/MimerPy
76
73
  .. _PyPI: https://pypi.org/
@@ -6,10 +6,10 @@ MimerPy is an adapter for Mimer SQL in Python_ which implements the
6
6
  Python Database API specfication `PEP 249`_.
7
7
 
8
8
  The adapter allows the user to access the powerful tools and
9
- advantages of Mimer SQL through Python. MimerPy is implemented as a
10
- CPython wrapper of the `Mimer SQL C API`_.
9
+ advantages of Mimer SQL through Python. MimerPy uses `ctypes` to do
10
+ dynamic binding to the `Mimer SQL C API`_.
11
11
 
12
- To use MimerPy, there is a minimum requirement of Python 3.5 or newer and
12
+ To use MimerPy, there is a minimum requirement of Python 3.6 or newer and
13
13
  it is dependent on the `Mimer SQL C API`_.
14
14
 
15
15
  The Mimer SQL C API is a discrete C API that comes with Mimer SQL. The
@@ -0,0 +1,64 @@
1
+ ***************
2
+ Release Notes
3
+ ***************
4
+
5
+ .. _sec-release-notes:
6
+
7
+ MimerPy Version 1.1
8
+ -------------------
9
+ MimerPy version 1.1 is the first public version.
10
+
11
+ Known problems:
12
+
13
+ * DDL and DML statments can not be mixed in one transaction.
14
+ DDL statements are always committed
15
+
16
+ * DDL statements in a transaction can not be rolled back.
17
+
18
+ * The methods :meth:`setinputsizes` and :meth:`setoutputsize` are not
19
+ implemented for cursors.
20
+
21
+ * Accessing values with the type builtin.uuid in Mimer SQL requires a
22
+ MimerAPI of version 11.0.5B or later.
23
+
24
+ * Accessing values with the type FLOAT(p) in Mimer SQL requires a
25
+ MimerAPI of version 11.0.5B or later.
26
+
27
+ * Accessing integer values larger than 2**63 with the type INTEGER(p)
28
+ in Mimer SQL requires a MimerAPI of version 11.0.5B or later.
29
+
30
+ * Using method :meth:`callproc` to call a Stored Procedure is not yet
31
+ supported.
32
+
33
+
34
+ MimerPy Version 1.3.0
35
+ ---------------------
36
+ MimerPy version 1.3.0 is a major release that uses `ctypes` and dynamic bindings
37
+ to the Mimer SQL C API.
38
+
39
+ Major changes:
40
+
41
+ * MimerPy is now implemented using `ctypes` to access the Mimer SQL C API.
42
+ This removes the need for a C compiler on all platforms.
43
+ * MimerPy now requires Python 3.6 or later.
44
+
45
+ MimerPy Version 1.3.1
46
+ ---------------------
47
+ MimerPy version 1.3.1 adds support for UUID and GIS datatypes in Mimer SQL and handles date, time, and timestamp correctly.
48
+
49
+ Major changes:
50
+
51
+ * Support for the UUID datatype BUILTIN.UUID added.
52
+ * Support for GIS datatypes added. This include BUILTIN.GIS_LOCATION, BUILTIN.GIS_LATITUDE, and BUILTIN.GIS_LONGITUDE. This requires Mimer SQL version 11.0.8E or later.
53
+ * Date are mapped to Python date objects. Strings in the format 'YYYY-MM-DD' are also accepted when inserting DATE values.
54
+ * Time are mapped to Python time objects. Strings in the format 'HH:MM:SS[.ffffff]' are also accepted when inserting TIME values.
55
+ * Timestamp are mapped to Python datetime objects. Strings in the format 'YYYY-MM-DD HH:MM:SS[.ffffff]' are also accepted when inserting TIMESTAMP values.
56
+
57
+ MimerPy Version 1.3.2
58
+ ---------------------
59
+ MimerPy version 1.3.2 is a minor buggfix release that fix a problem with datetime in Python version 3.9 and older
60
+
61
+ Major changes:
62
+
63
+ * Use a safe datetime and time parser
64
+ * On Python 3.6, use dateutil module to parse ISO 8601 date strings
@@ -5,7 +5,7 @@ User guide
5
5
  .. _mimer-syntax:
6
6
 
7
7
  This chapter of the documentation covers the relationship between
8
- MimerPy, Mimer SQL and the Mimer SQL C API.
8
+ MimerPy and Mimer SQL.
9
9
 
10
10
  Connection parameters
11
11
  ---------------------
@@ -1,5 +1,5 @@
1
1
  [build-system]
2
- requires = ["setuptools>=77", "setuptools-scm>=8", "wheel", "tomli; python_version<'3.11'"]
2
+ requires = [ "setuptools>=68,<77", "setuptools-scm<8", "wheel"]
3
3
  build-backend = "setuptools.build_meta"
4
4
 
5
5
 
@@ -9,9 +9,10 @@ dynamic = ["version"]
9
9
  description = "Python database interface for Mimer SQL"
10
10
  readme = "README.rst"
11
11
  requires-python = ">=3.6"
12
-
13
- license = "MIT"
14
- license-files = ["LICENSE.txt"]
12
+ dependencies = [
13
+ "python-dateutil>=2.8.2; python_version<'3.7'",
14
+ ]
15
+ license = { text = "MIT" }
15
16
  authors = [
16
17
  { name = "Erik Gunne", email = "mimerpy@mimer.com" },
17
18
  { name = "Magdalena Boström", email = "mimerpy@mimer.com" },
@@ -27,39 +27,25 @@ except ImportError:
27
27
 
28
28
 
29
29
  #
30
- # Set globals in mimerpy module and version in mimerapi module
30
+ # Set globals in mimerpy module
31
31
  #
32
- from mimerpy import mimerapi
33
32
  import re
34
33
 
35
34
  apilevel = '2.0'
36
35
  threadsafety = '1'
37
36
  paramstyle = 'qmark'
38
- _v = re.findall(r'^\d+\.\d+\.\d+$', __version__)
39
- version = _v[0] if len(_v) else ''
40
- version_info = tuple([int(x) for x in version.split(".")]) if len(version) else ()
41
- mimerapi.__version__ = mimerapi.mimerAPIVersion().rstrip()
42
-
43
-
44
- #
45
- # Check MimerAPI required version and set function level
46
- #
47
- from mimerpy.mimPyExceptions import *
48
- from mimerpy.mimPyExceptionHandler import mimerpy_error
49
-
50
- (_a, _b, _c, _d) = re.findall(r'^(\d+)\.(\d+)\.(\d)+(.)',
51
- mimerapi.__version__)[0]
52
- mimerapi._version_tuple = (int(_a), int(_b), int(_c), _d)
53
- if mimerapi._version_tuple < (11, 0, 5, 'A'):
54
- raise NotSupportedError((-25101, mimerpy_error[-25101]))
55
- elif mimerapi._version_tuple < (11, 0, 5, 'B'):
56
- # First supported version
57
- mimerapi._level = 1
37
+ # Accept both release and dev versions, e.g. 1.3.1.dev1+geb9c067d3.d20251016
38
+ m = re.match(r'^(\d+\.\d+\.\d+)', __version__)
39
+ if m:
40
+ version = m.group(1)
41
+ version_info = tuple(int(x) for x in version.split("."))
58
42
  else:
59
- # String access to DECIMAL(p,s) and FLOAT(p). Map to Python decimal
60
- mimerapi._level = 2
43
+ version = __version__
44
+ version_info = ()
61
45
 
62
46
 
47
+ from mimerpy.mimPyExceptions import *
48
+ from mimerpy.mimPyErrorCodes import mimerpy_error
63
49
  from mimerpy.connectionPy import Connection
64
50
 
65
51
  def connect(dsn='', user='', password='',
@@ -0,0 +1,4 @@
1
+ # file generated by setuptools_scm
2
+ # don't change, don't track in version control
3
+ __version__ = version = '1.3.2'
4
+ __version_tuple__ = version_tuple = (1, 3, 2)
@@ -20,10 +20,10 @@
20
20
  #
21
21
  # See license for more details.
22
22
 
23
- from mimerpy import mimerapi
23
+ from . import mimerapi
24
24
  import weakref
25
- from mimerpy.cursorPy import *
26
- from mimerpy.mimPyExceptionHandler import *
25
+ from .cursorPy import *
26
+ from .mimPyExceptionHandler import *
27
27
  import sys
28
28
 
29
29
  def defaulterrorhandler(connection, cursor, errorclass, errorvalue):
@@ -20,12 +20,15 @@
20
20
  #
21
21
  # See license for more details.
22
22
 
23
- from mimerpy.mimPyExceptionHandler import *
24
- from mimerpy import mimerapi
23
+ from .mimPyExceptionHandler import *
24
+ from . import mimerapi
25
25
  import collections, decimal, uuid
26
26
  from types import GeneratorType
27
-
28
-
27
+ import uuid
28
+ import string
29
+ from datetime import date, time, datetime
30
+ from mimerpy.utils import tolerant_fromiso_datetime, tolerant_fromiso_time
31
+
29
32
  def _pythonSetDecimal(statement, cur_column, parameter):
30
33
  if parameter is None:
31
34
  rc = mimerapi.mimerSetString8(statement, cur_column, parameter)
@@ -69,7 +72,106 @@ def _pythonGetUUID(statement, col):
69
72
  return (rc, None)
70
73
 
71
74
  def _pythonSetUUID(statement, col, val):
72
- return mimerapi.mimerSetUUID(statement, col, val.bytes)
75
+ if val is None:
76
+ return mimerapi.mimerSetUUID(statement, col, None)
77
+
78
+ if isinstance(val, uuid.UUID):
79
+ v = val.bytes
80
+ elif isinstance(val, (bytes, bytearray, memoryview)):
81
+ # allow raw 16-byte input
82
+ v = bytes(val)
83
+ elif isinstance(val, str):
84
+ # accepts both hyphenated and hex-only UUID strings
85
+ try:
86
+ v = uuid.UUID(val).bytes
87
+ except ValueError:
88
+ # invalid string representation
89
+ return mimerapi.MIMERPY_DATA_CONVERSION_ERROR
90
+ else:
91
+ # unsupported type
92
+ return mimerapi.MIMERPY_DATA_CONVERSION_ERROR
93
+
94
+ return mimerapi.mimerSetUUID(statement, col, v)
95
+
96
+ def _pythonGetTimestamp(statement, col):
97
+ rc, val = mimerapi.mimerGetString8(statement, col)
98
+ if rc >= 0 and val is not None:
99
+ return (rc, tolerant_fromiso_datetime(val))
100
+ return (rc, None)
101
+
102
+ def _pythonSetTimestamp(statement, col, val):
103
+ if val is None:
104
+ return mimerapi.mimerSetNull(statement, col)
105
+ if isinstance(val, datetime):
106
+ v = val.isoformat(sep=' ', timespec='microseconds')
107
+ elif isinstance(val, str):
108
+ try:
109
+ #Parse to ensure valid format but use orginal for higher precision
110
+ val = val.strip()
111
+ tolerant_fromiso_datetime(val)
112
+ v = val
113
+ except ValueError:
114
+ # invalid string representation
115
+ return mimerapi.MIMERPY_DATA_CONVERSION_ERROR
116
+ else:
117
+ # unsupported type
118
+ return mimerapi.MIMERPY_DATA_CONVERSION_ERROR
119
+
120
+ return mimerapi.mimerSetString8(statement, col, v)
121
+
122
+
123
+ def _pythonGetTime(statement, col):
124
+ rc, val = mimerapi.mimerGetString8(statement, col)
125
+ if rc >= 0 and val is not None:
126
+ return (rc, tolerant_fromiso_time(val))
127
+ return (rc, None)
128
+
129
+ def _pythonSetTime(statement, col, val):
130
+ if val is None:
131
+ return mimerapi.mimerSetNull(statement, col)
132
+ if isinstance(val, time):
133
+ v = val.isoformat(timespec='microseconds')
134
+ elif isinstance(val, str):
135
+ try:
136
+ #Parse to ensure valid format but use orginal for higher precision
137
+ val = val.strip()
138
+ tolerant_fromiso_time(val)
139
+ v = val
140
+ except ValueError:
141
+ # invalid string representation
142
+ return mimerapi.MIMERPY_DATA_CONVERSION_ERROR
143
+ else:
144
+ # unsupported type
145
+ return mimerapi.MIMERPY_DATA_CONVERSION_ERROR
146
+
147
+ return mimerapi.mimerSetString8(statement, col, v)
148
+
149
+ def _pythonGetDate(statement, col):
150
+ rc, val = mimerapi.mimerGetString8(statement, col)
151
+ if rc >= 0 and val is not None:
152
+ return (rc, date.fromisoformat(val))
153
+ return (rc, None)
154
+
155
+ def _pythonSetDate(statement, col, val):
156
+ if val is None:
157
+ return mimerapi.mimerSetNull(statement, col)
158
+ if isinstance(val, date):
159
+ v = val.isoformat()
160
+ elif isinstance(val, str):
161
+ try:
162
+ #Parse to ensure valid format
163
+ val = val.strip()
164
+ date.fromisoformat(val)
165
+ v = val
166
+ except ValueError:
167
+ # invalid string representation
168
+ return mimerapi.MIMERPY_DATA_CONVERSION_ERROR
169
+ else:
170
+ # unsupported type
171
+ return mimerapi.MIMERPY_DATA_CONVERSION_ERROR
172
+
173
+ return mimerapi.mimerSetString8(statement, col, v)
174
+
73
175
 
74
176
  def _define_funcs():
75
177
  global get_funcs
@@ -116,6 +218,12 @@ def _define_funcs():
116
218
  58: mimerapi.mimerGetNclobData8,
117
219
  59: mimerapi.mimerGetNclobData8,
118
220
  8104: _pythonGetUUID,
221
+ mimerapi.MIMER_TYPE_LOCATION: mimerapi.mimerGetGisLocation,
222
+ mimerapi.MIMER_TYPE_LATITUDE: mimerapi.mimerGetGisLatitude,
223
+ mimerapi.MIMER_TYPE_LONGITUDE: mimerapi.mimerGetGisLongitude,
224
+ mimerapi.MIMER_TYPE_TIMESTAMP: _pythonGetTimestamp,
225
+ mimerapi.MIMER_TYPE_TIME: _pythonGetTime,
226
+ mimerapi.MIMER_TYPE_DATE: _pythonGetDate,
119
227
  }
120
228
 
121
229
  set_funcs = {1: mimerapi.mimerSetString8,
@@ -158,6 +266,12 @@ def _define_funcs():
158
266
  59: mimerapi.mimerSetNclobData8,
159
267
  501: mimerapi.mimerSetNull,
160
268
  8104: _pythonSetUUID,
269
+ mimerapi.MIMER_TYPE_LOCATION: mimerapi.mimerSetGisLocation,
270
+ mimerapi.MIMER_TYPE_LATITUDE: mimerapi.mimerSetGisLatitude,
271
+ mimerapi.MIMER_TYPE_LONGITUDE: mimerapi.mimerSetGisLongitude,
272
+ mimerapi.MIMER_TYPE_TIMESTAMP: _pythonSetTimestamp,
273
+ mimerapi.MIMER_TYPE_TIME: _pythonSetTime,
274
+ mimerapi.MIMER_TYPE_DATE: _pythonSetDate,
161
275
  }
162
276
 
163
277
  _define_funcs()
@@ -19,17 +19,27 @@
19
19
  # SOFTWARE.
20
20
  #
21
21
  # See license for more details.
22
-
23
- from mimerpy.mimPyExceptions import *
24
- from mimerpy import mimerapi
25
-
22
+ """
23
+ Contains all MimerPy error code tables and mappings used by the exception system.
24
+ Separated from mimPyExceptions and mimPyExceptionHandler to avoid circular imports.
25
+ """
26
+ from .mimPyExceptions import (
27
+ DatabaseError, DataError, IntegrityError, InternalError,
28
+ InterfaceError, NotSupportedError, OperationalError,
29
+ ProgrammingError, TransactionAbortError
30
+ )
31
+ def _api_version_string():
32
+ try:
33
+ from mimerpy import mimerapi
34
+ return mimerapi.__version__
35
+ except Exception:
36
+ return "unknown"
37
+
26
38
  # When adding new MimerAPI error codes:
27
39
  # - Use the range -25xxx
28
40
  # - Check the dictionaries below so that the right exception is thrown
29
41
  # - Update env/gblsym/message.sym in the Mimer trunk
30
42
  # - Update dbl/sdb/syscat.ddi in the Mimer trunk
31
- # - Tell Jarl
32
-
33
43
  mimerpy_error = {
34
44
  -25000:"Unsupported method",
35
45
  -25001:"TPC is unsupported",
@@ -43,8 +53,8 @@ mimerpy_error = {
43
53
  -25020:"Data conversion error",
44
54
  -25030:"Out of memory",
45
55
  -25031:"Login failure",
46
- -25101:("The operation requires Mimer API version 11.0.5A or newer. You have %s." % mimerapi.__version__),
47
- -25102:("The operation requires Mimer API version 11.0.5B or newer. You have %s." % mimerapi.__version__),
56
+ -25101:("The operation requires Mimer API version 11.0.5A or newer. You have %s." % _api_version_string()),
57
+ -25102:("The operation requires Mimer API version 11.0.5B or newer. You have %s." % _api_version_string()),
48
58
  }
49
59
 
50
60
  py_error_nnnnn = {10001:TransactionAbortError,10003:TransactionAbortError,24010:DataError,24011:DataError
@@ -64,31 +74,4 @@ py_error_nnxxx = {10:DataError, 11:OperationalError, 12:ProgrammingError,
64
74
  25:ProgrammingError, 26:InterfaceError,
65
75
  27:DataError, 28: NotSupportedError}
66
76
 
67
- py_error_xxxxx = InternalError
68
-
69
- def get_error_class(rc):
70
- """
71
- Return a suitable error class from an error number.
72
- """
73
- rc = -rc;
74
- if rc in py_error_nnnnn:
75
- return py_error_nnnnn[rc]
76
- rc = rc // 10
77
- if rc in py_error_nnnnx:
78
- return py_error_nnnnx[rc]
79
- rc = rc // 100
80
- if rc in py_error_nnxxx:
81
- return py_error_nnxxx[rc]
82
- return py_error_xxxxx
83
-
84
-
85
- def get_mimerapi_exception(rc, mimerapi_handle):
86
- """
87
- Return (errorclass, errorvalue) from a failed MimerAPI call.
88
- """
89
- if -25999 <= rc <= -25000:
90
- return (get_error_class(rc), (rc, mimerpy_error[rc]))
91
- (rc0, _, msg) = mimerapi.mimerGetError8(mimerapi_handle)
92
- if rc0:
93
- msg = "Unknown error %d" % rc
94
- return (get_error_class(rc), (rc, msg))
77
+ py_error_xxxxx = InternalError