mimerpy 1.3.0__py3-none-any.whl

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.
mimerpy/__init__.py ADDED
@@ -0,0 +1,155 @@
1
+ # Copyright (c) 2017 Mimer Information Technology
2
+
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+ #
21
+ # See license for more details.
22
+
23
+ try:
24
+ from ._version import version as __version__
25
+ except ImportError:
26
+ __version__ = "0.0.0" # fallback if not built
27
+
28
+
29
+ #
30
+ # Set globals in mimerpy module and version in mimerapi module
31
+ #
32
+ from mimerpy import mimerapi
33
+ import re
34
+
35
+ apilevel = '2.0'
36
+ threadsafety = '1'
37
+ 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
58
+ else:
59
+ # String access to DECIMAL(p,s) and FLOAT(p). Map to Python decimal
60
+ mimerapi._level = 2
61
+
62
+
63
+ from mimerpy.connectionPy import Connection
64
+
65
+ def connect(dsn='', user='', password='',
66
+ autocommit=False, errorhandler=None):
67
+ """
68
+ Create a database connection.
69
+
70
+ dsn Data source name.
71
+ If empty, the environment variable MIMER_DATABASE is consulted.
72
+ If that variable is unavailable, the default database as
73
+ specified in /etc/sqlhosts (UNIX) or in the Mimer Administrator
74
+ (Windows) is used.
75
+
76
+ user Name of the ident to use.
77
+ If empty, the database server will perform an OS_USER login
78
+ using the OS-level username. This does not work if the database
79
+ server is remote.
80
+
81
+ password Password to chosen ident.
82
+ Leave this empty if performing an OS_USER login.
83
+
84
+ autocommit Autocommit mode.
85
+ The default behaviour according to PEP-0249 is False, meaning
86
+ that all transactions have to be explicitly committed.
87
+ If autocommit is enabled, each statement is committed
88
+ automatically when executed.
89
+
90
+ errorhandler A handler for errors according to the Optional Error Handling
91
+ Extension described in PEP-0249.
92
+ """
93
+ return Connection(dsn, user, password, autocommit, errorhandler)
94
+
95
+ #
96
+ # Tracing and logging
97
+ #
98
+ import functools
99
+ import logging
100
+ from mimerpy.cursorPy import _define_funcs
101
+
102
+ def _tracefunc(func, prefix, logger):
103
+ @functools.wraps(func)
104
+ def tracer(*args, **kwargs):
105
+ r_args = [repr(a) for a in args]
106
+ r_kwargs = ["%s=%s" % (k, repr(v)) for k, v in kwargs.items()]
107
+ signature = ", ".join(r_args + r_kwargs)
108
+ logger.info("%sCall %s(%s)"
109
+ % (prefix, func.__name__, signature))
110
+ try:
111
+ value = func(*args, **kwargs)
112
+ logger.info("%sRet: %s" % (prefix, repr(value)))
113
+ return value
114
+ except Exception as e:
115
+ logger.info("EXCEPTION: %s" % repr(e))
116
+ raise e
117
+ return tracer
118
+
119
+ def _alterfuncs(d, prefix, logger):
120
+ for fn in dir(d):
121
+ f = d.__getattribute__(fn)
122
+ if fn[0] != '_' and fn[0] >= 'a' and callable(f):
123
+ setattr(d, fn, _tracefunc(f, prefix, logger))
124
+
125
+ def _apitrace(prefix=''):
126
+ logger = logging.getLogger("MimerAPI")
127
+ logger.setLevel(logging.INFO)
128
+ _alterfuncs(mimerapi, prefix, logger)
129
+ _define_funcs()
130
+
131
+ def _altermeths(d, prefix, logger):
132
+ for fn in dir(d):
133
+ if fn[0] != '_' and fn[0] >= 'a':
134
+ try:
135
+ f = d.__getattribute__(d, fn)
136
+ if callable(f):
137
+ setattr(d, fn, _tracefunc(f, prefix, logger))
138
+ except AttributeError:
139
+ pass
140
+
141
+ def _pytrace(prefix=''):
142
+ logger = logging.getLogger("MimerPy")
143
+ logger.setLevel(logging.INFO)
144
+ _alterfuncs(mimerpy, prefix, logger)
145
+ _altermeths(mimerpy.connectionPy.Connection, prefix, logger)
146
+ _altermeths(mimerpy.cursorPy.Cursor, prefix, logger)
147
+ _altermeths(mimerpy.cursorPy.ScrollCursor, prefix, logger)
148
+
149
+ def _trace(things=255, prefix='', setLogLevel=True):
150
+ if setLogLevel:
151
+ logging.basicConfig(level=logging.INFO)
152
+ if things & 1:
153
+ _pytrace(prefix)
154
+ if things & 2:
155
+ _apitrace(prefix)
mimerpy/__main__.py ADDED
@@ -0,0 +1,81 @@
1
+ # Copyright (c) 2017 Mimer Information Technology
2
+
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+ #
21
+ # See license for more details.
22
+
23
+ import mimerpy
24
+ from mimerpy import mimerapi
25
+ import argparse
26
+
27
+ if __name__ == '__main__':
28
+ parser = argparse.ArgumentParser(prog = "mimerpy", description="""
29
+ A simple command line program for the MimerPy library. It can
30
+ display the version number of the MimerPy library (-v switch) or
31
+ connect to a Mimer SQL database server and execute a singe SQL
32
+ statement (provide database, user, and password arguments and a
33
+ SQL statement).
34
+ """)
35
+ parser.add_argument("-d", "--database",
36
+ help="Database to connect to")
37
+ parser.add_argument("-u", "--user",
38
+ help="User name to use in connection")
39
+ parser.add_argument("-p", "--password",
40
+ help="Password for the user")
41
+ parser.add_argument("-v", "--version",
42
+ help="Display MimerPy and MimerAPI version numbers",
43
+ action="store_true")
44
+ parser.add_argument("-t", "--tag",
45
+ help=argparse.SUPPRESS, action="store_true")
46
+ parser.add_argument("--trace",
47
+ help=argparse.SUPPRESS, action="store_true")
48
+ parser.add_argument("sql", default=None, nargs='?',
49
+ help="A SQL command to execute")
50
+ args = parser.parse_args()
51
+
52
+ something = False
53
+
54
+ if args.tag:
55
+ something = True
56
+ print(mimerpy.version)
57
+
58
+ if args.version:
59
+ something = True
60
+ print("MimerPy version %s" % mimerpy.__version__)
61
+ print("Mimer API version %s" % mimerapi.__version__)
62
+
63
+ if args.sql:
64
+ something = True
65
+ try:
66
+ if args.trace:
67
+ mimerpy._trace()
68
+ with mimerpy.connect(dsn = args.database,
69
+ user = args.user,
70
+ password = args.password,
71
+ autocommit = True) as con:
72
+ with con.cursor() as cur:
73
+ cur.execute(args.sql)
74
+ if cur.description is not None:
75
+ for r in cur:
76
+ print(r)
77
+ except Exception as e:
78
+ print(e)
79
+
80
+ if not something:
81
+ print("Use option -h to get help")
mimerpy/_version.py ADDED
@@ -0,0 +1,34 @@
1
+ # file generated by setuptools-scm
2
+ # don't change, don't track in version control
3
+
4
+ __all__ = [
5
+ "__version__",
6
+ "__version_tuple__",
7
+ "version",
8
+ "version_tuple",
9
+ "__commit_id__",
10
+ "commit_id",
11
+ ]
12
+
13
+ TYPE_CHECKING = False
14
+ if TYPE_CHECKING:
15
+ from typing import Tuple
16
+ from typing import Union
17
+
18
+ VERSION_TUPLE = Tuple[Union[int, str], ...]
19
+ COMMIT_ID = Union[str, None]
20
+ else:
21
+ VERSION_TUPLE = object
22
+ COMMIT_ID = object
23
+
24
+ version: str
25
+ __version__: str
26
+ __version_tuple__: VERSION_TUPLE
27
+ version_tuple: VERSION_TUPLE
28
+ commit_id: COMMIT_ID
29
+ __commit_id__: COMMIT_ID
30
+
31
+ __version__ = version = '1.3.0'
32
+ __version_tuple__ = version_tuple = (1, 3, 0)
33
+
34
+ __commit_id__ = commit_id = None
@@ -0,0 +1,273 @@
1
+ # Copyright (c) 2017 Mimer Information Technology
2
+
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+ #
21
+ # See license for more details.
22
+
23
+ from mimerpy import mimerapi
24
+ import weakref
25
+ from mimerpy.cursorPy import *
26
+ from mimerpy.mimPyExceptionHandler import *
27
+ import sys
28
+
29
+ def defaulterrorhandler(connection, cursor, errorclass, errorvalue):
30
+ """
31
+ If cursor is not None, (errorclass, errorvalue) is appended to
32
+ cursor.messages; otherwise it is appended to
33
+ connection.messages. Then errorclass is raised with errorvalue as
34
+ the value.
35
+ You can override this with your own error handler by assigning it
36
+ to the instance.
37
+ """
38
+ # sys.tracebacklimit = 1
39
+ error = errorclass, errorvalue
40
+ if cursor:
41
+ cursor.messages.append(error)
42
+ else:
43
+ connection.messages.append(error)
44
+
45
+ raise errorclass(errorvalue)
46
+
47
+
48
+ class Connection:
49
+
50
+ """
51
+
52
+ MimerSQL database connection
53
+
54
+ The class Connection is used to establish
55
+ a connection with a Mimer database.
56
+
57
+ """
58
+
59
+ def __init__(self, dsn='', user='', password='',
60
+ autocommit=False, errorhandler=None):
61
+ """
62
+ Creates a database connection.
63
+
64
+ Use the mimerpy.connect() function to create a connection rather than
65
+ calling this function.
66
+ """
67
+ self.autocommitmode = autocommit
68
+ self.errorhandler = (errorhandler if errorhandler
69
+ else defaulterrorhandler)
70
+ self.messages = []
71
+ self._session = None
72
+ self.__cursors = weakref.WeakSet()
73
+ self._transaction = False
74
+
75
+ dsn = dsn if dsn else ""
76
+ user = user if user else ""
77
+ password = password if password else ""
78
+
79
+ (self._session, rc) = mimerapi.mimerBeginSession8(dsn, user, password)
80
+ if rc:
81
+ if rc == 90:
82
+ rc = -25031 # Login failure
83
+ (ec, ev) = get_mimerapi_exception(rc, self._session)
84
+ mimerapi.mimerEndSession(self._session)
85
+ self._session = None
86
+ self.errorhandler(self, None, ec, ev)
87
+
88
+
89
+ def __enter__(self):
90
+ return self
91
+
92
+ def __exit__(self,type, value, traceback):
93
+ self.__check_if_open()
94
+ self.close()
95
+
96
+ def __del__(self):
97
+ if (not self._session == None):
98
+ self.close()
99
+
100
+ def close(self):
101
+ """
102
+
103
+ Closes the database connection.
104
+
105
+ Method is used for closing a connection.
106
+ When using close() all cursors that are
107
+ using the connection are also closed.
108
+
109
+ If the auto-commit feature is turned off
110
+ and a connection is closed before committing
111
+ any changes, an implicit rollback is executed.
112
+ Thus, before evoking close(), commit() should
113
+ be used to prevent any changes being lost. However,
114
+ if auto-commit is turned on, an implicit rollback
115
+ is not performed.
116
+
117
+ When a connection has been closed using close(),
118
+ it is unusable and a ProgrammingError() is raised
119
+ if any operations are attempted on the connection.
120
+
121
+ """
122
+ if (not self._session == None):
123
+ for cur in self.__cursors:
124
+ cur.close()
125
+
126
+ if (self._transaction):
127
+ rc_value = mimerapi.mimerEndTransaction(self._session, 1)
128
+ if (rc_value != -24101):
129
+ self.__check_mimerapi_error(rc_value, self._session)
130
+ self._transaction = False
131
+ rc_value = mimerapi.mimerEndSession(self._session)
132
+ self.__check_mimerapi_error(rc_value, self._session)
133
+ self._session = None
134
+
135
+ def rollback(self):
136
+ """
137
+
138
+ Rolls back any pending transaction. Causes the database
139
+ to roll back to the start of any pending transaction.
140
+ If a connection is closed without committing any changes
141
+ made during the transaction, a rollback is implicitly performed.
142
+
143
+ """
144
+ self.__check_if_open()
145
+ if (self._transaction):
146
+ rc_value = mimerapi.mimerEndTransaction(self._session, 1)
147
+ self.__check_mimerapi_error(rc_value, self._session)
148
+ self._transaction = False
149
+
150
+ def commit(self):
151
+ """Commits any pending transaction."""
152
+ self.__check_if_open()
153
+ if (self._transaction):
154
+ rc_value = mimerapi.mimerEndTransaction(self._session, 0)
155
+ self.__check_mimerapi_error(rc_value, self._session)
156
+ self._transaction = False
157
+
158
+ def cursor(self, **kwargs):
159
+ """
160
+
161
+ Returns a new Cursor Object using the connection.
162
+ If scrollable is unspecified, the default cursor class
163
+ will be returned. If scrollable = True a scrollable
164
+ cursor will be returned.
165
+
166
+ """
167
+ self.__check_if_open()
168
+ kwargs2 = kwargs.copy()
169
+ mode = kwargs2.pop('scrollable', False)
170
+ if (mode):
171
+ curs = ScrollCursor(self, self._session)
172
+ else:
173
+ curs = Cursor(self, self._session)
174
+
175
+ self.__cursors.add(curs)
176
+ return curs
177
+
178
+ def execute(self, *arg):
179
+ """
180
+ Creates a cursor and executes a database operation.
181
+
182
+ arg
183
+ query to execute
184
+
185
+ Returns a new Cursor object using the connection and executes
186
+ a database operation.
187
+
188
+ """
189
+ self.__check_if_open()
190
+ curs = Cursor(self, self._session)
191
+ self.__cursors.add(curs)
192
+ curs.execute(*arg)
193
+ return curs
194
+
195
+ def executemany(self, *arg):
196
+ """
197
+ Creates a cursor and executes a database operation.
198
+
199
+ arg
200
+ query to execute and parameter sequences.
201
+
202
+ Returns a new Cursor object using the connection and executes
203
+ a database operation against all parameter sequences or mappings
204
+ found in args.
205
+
206
+ """
207
+ self.__check_if_open()
208
+ curs = Cursor(self, self._session)
209
+ self.__cursors.add(curs)
210
+ curs.executemany(*arg)
211
+ return curs
212
+
213
+ def autocommit(self, mode):
214
+ """
215
+
216
+ Turns autocommit mode on or off. Defualt is false.
217
+ By using this method, from this point onward changes are autocommitted.
218
+
219
+ arg
220
+ Boolean
221
+
222
+ """
223
+ if (mode):
224
+ self.autocommitmode = True
225
+ if (self._transaction):
226
+ self.rollback()
227
+ else:
228
+ self.autocommitmode = False
229
+
230
+ def reset(self):
231
+ """
232
+ Reset the connection. Close all cursors and do rollback if a transaction
233
+ is running. Reset auto commit to default.
234
+ """
235
+ if self.__cursors:
236
+ for cur in self.__cursors:
237
+ cur.close()
238
+
239
+ if self._transaction:
240
+ self.rollback()
241
+
242
+ self.autocommit(False)
243
+
244
+ def __raise_exception(self, rc):
245
+ self.errorhandler(self, None, get_error_class(rc),
246
+ (rc, mimerpy_error[rc]))
247
+
248
+ def __check_if_open(self):
249
+ if (self._session == None):
250
+ self.__raise_exception(-25010)
251
+
252
+ def __check_mimerapi_error(self, rc, handle):
253
+ if rc < 0:
254
+ (ec, ev) = get_mimerapi_exception(rc, handle)
255
+ self.errorhandler(self, None, ec, ev)
256
+
257
+ def xid(self):
258
+ self.__raise_exception(-25001)
259
+
260
+ def tpc_begin(self):
261
+ self.__raise_exception(-25001)
262
+
263
+ def tpc_prepare(self):
264
+ self.__raise_exception(-25001)
265
+
266
+ def tpc_commit(self):
267
+ self.__raise_exception(-25001)
268
+
269
+ def tpc_rollback(self):
270
+ self.__raise_exception(-25001)
271
+
272
+ def tpc_recover(self):
273
+ self.__raise_exception(-25001)