tina4-python 0.2.121__tar.gz → 0.2.123__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.
- {tina4_python-0.2.121 → tina4_python-0.2.123}/PKG-INFO +1 -1
- {tina4_python-0.2.121 → tina4_python-0.2.123}/pyproject.toml +1 -1
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/Database.py +23 -17
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/ORM.py +27 -5
- {tina4_python-0.2.121 → tina4_python-0.2.123}/.gitignore +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/README.md +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/Auth.py +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/Constant.py +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/DatabaseResult.py +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/DatabaseTypes.py +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/Debug.py +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/Env.py +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/Localization.py +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/Messages.py +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/MiddleWare.py +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/Migration.py +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/Queue.py +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/Request.py +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/Response.py +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/Router.py +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/Session.py +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/ShellColors.py +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/Swagger.py +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/Template.py +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/Webserver.py +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/Websocket.py +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/__init__.py +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/messages.pot +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/public/css/readme.md +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/public/favicon.ico +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/public/images/403.png +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/public/images/404.png +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/public/images/500.png +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/public/images/logo.png +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/public/images/readme.md +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/public/js/readme.md +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/public/js/reconnecting-websocket.js +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/public/js/tina4helper.js +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/public/swagger/index.html +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/public/swagger/oauth2-redirect.html +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/templates/errors/403.twig +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/templates/errors/404.twig +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/templates/errors/500.twig +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/templates/readme.md +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/translations/en/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/translations/en/LC_MESSAGES/messages.po +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/translations/fr/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/translations/fr/LC_MESSAGES/messages.po +0 -0
|
@@ -14,6 +14,7 @@ from tina4_python.Constant import TINA4_LOG_ERROR
|
|
|
14
14
|
from tina4_python.DatabaseResult import DatabaseResult
|
|
15
15
|
from tina4_python.DatabaseTypes import *
|
|
16
16
|
|
|
17
|
+
|
|
17
18
|
class Database:
|
|
18
19
|
|
|
19
20
|
def __init__(self, _connection_string, _username="", _password=""):
|
|
@@ -28,19 +29,19 @@ class Database:
|
|
|
28
29
|
try:
|
|
29
30
|
self.database_module = importlib.import_module(params[0])
|
|
30
31
|
except Exception:
|
|
31
|
-
install_message = "Please implement "+params[0]+" in Database.py and make a pull request!"
|
|
32
|
+
install_message = "Please implement " + params[0] + " in Database.py and make a pull request!"
|
|
32
33
|
if params[0] == SQLITE:
|
|
33
34
|
install_message = "Your python is missing the sqlite3 module, please reinstall or update"
|
|
34
35
|
elif params[0] == MYSQL:
|
|
35
|
-
install_message = "Your python is missing the mysql module, please install with "+MYSQL_INSTALL
|
|
36
|
+
install_message = "Your python is missing the mysql module, please install with " + MYSQL_INSTALL
|
|
36
37
|
elif params[0] == POSTGRES:
|
|
37
|
-
install_message = "Your python is missing the postgres module, please install with "+POSTGRES_INSTALL
|
|
38
|
+
install_message = "Your python is missing the postgres module, please install with " + POSTGRES_INSTALL
|
|
38
39
|
elif params[0] == FIREBIRD:
|
|
39
|
-
install_message = "Your python is missing the firebird module, please install with "+FIREBIRD_INSTALL
|
|
40
|
+
install_message = "Your python is missing the firebird module, please install with " + FIREBIRD_INSTALL
|
|
40
41
|
elif params[0] == MSSQL:
|
|
41
|
-
install_message = "Your python is missing the mssql module, please install with "+MSSQL_INSTALL
|
|
42
|
+
install_message = "Your python is missing the mssql module, please install with " + MSSQL_INSTALL
|
|
42
43
|
|
|
43
|
-
sys.exit("Could not load database driver for "+params[0]+"\n"+install_message)
|
|
44
|
+
sys.exit("Could not load database driver for " + params[0] + "\n" + install_message)
|
|
44
45
|
|
|
45
46
|
self.database_engine = params[0]
|
|
46
47
|
self.database_path = params[1]
|
|
@@ -129,7 +130,7 @@ class Database:
|
|
|
129
130
|
)
|
|
130
131
|
self.dba.autocommit(False)
|
|
131
132
|
else:
|
|
132
|
-
sys.exit("Could not load database driver for "+params[0])
|
|
133
|
+
sys.exit("Could not load database driver for " + params[0])
|
|
133
134
|
|
|
134
135
|
Debug("DATABASE:", self.database_module.__name__, self.host, self.port, self.database_path, self.username,
|
|
135
136
|
Constant.TINA4_LOG_DEBUG)
|
|
@@ -142,25 +143,25 @@ class Database:
|
|
|
142
143
|
"""
|
|
143
144
|
|
|
144
145
|
if self.database_engine == MSSQL:
|
|
145
|
-
sql = "select count(*) as count_table from sys.tables WHERE name = '"+table_name.upper()+"'"
|
|
146
|
+
sql = "select count(*) as count_table from sys.tables WHERE name = '" + table_name.upper() + "'"
|
|
146
147
|
elif self.database_engine == SQLITE:
|
|
147
|
-
sql = "SELECT count(*) as count_table FROM sqlite_master WHERE type='table' AND name='"+table_name+"'"
|
|
148
|
+
sql = "SELECT count(*) as count_table FROM sqlite_master WHERE type='table' AND name='" + table_name + "'"
|
|
148
149
|
elif self.database_engine == MYSQL:
|
|
149
|
-
sql = "SELECT count(*) as count_table FROM information_schema.tables WHERE table_schema = '"+self.database_path+"' AND table_name = '"+table_name+"'"
|
|
150
|
+
sql = "SELECT count(*) as count_table FROM information_schema.tables WHERE table_schema = '" + self.database_path + "' AND table_name = '" + table_name + "'"
|
|
150
151
|
elif self.database_engine == POSTGRES:
|
|
151
152
|
sql = """SELECT count(*) as count_table FROM pg_catalog.pg_class c
|
|
152
153
|
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
|
|
153
|
-
WHERE c.relname = '"""+table_name+"""'
|
|
154
|
+
WHERE c.relname = '""" + table_name + """'
|
|
154
155
|
AND c.relkind = 'r' """
|
|
155
156
|
elif self.database_engine == FIREBIRD:
|
|
156
|
-
sql = "SELECT count(*) as count_table FROM RDB$RELATIONS WHERE RDB$RELATION_NAME = upper('"+table_name+"')"
|
|
157
|
+
sql = "SELECT count(*) as count_table FROM RDB$RELATIONS WHERE RDB$RELATION_NAME = upper('" + table_name + "')"
|
|
157
158
|
else:
|
|
158
159
|
return False
|
|
159
160
|
|
|
160
161
|
try:
|
|
161
162
|
record = self.fetch_one(sql)
|
|
162
163
|
except Exception as e:
|
|
163
|
-
raise Exception
|
|
164
|
+
raise Exception(f"Error checking if table {table_name} exists: " + str(e))
|
|
164
165
|
|
|
165
166
|
if record:
|
|
166
167
|
if record["count_table"] > 0:
|
|
@@ -289,7 +290,7 @@ class Database:
|
|
|
289
290
|
else:
|
|
290
291
|
count_records = 0
|
|
291
292
|
except Exception as e:
|
|
292
|
-
Debug("FETCH ERROR:",
|
|
293
|
+
Debug("FETCH ERROR:", sql_count, str(e), TINA4_LOG_ERROR)
|
|
293
294
|
finally:
|
|
294
295
|
counter_cursor.close()
|
|
295
296
|
|
|
@@ -298,7 +299,7 @@ class Database:
|
|
|
298
299
|
cursor.execute(sql, params)
|
|
299
300
|
return self.get_database_result(cursor, count_records, limit, skip)
|
|
300
301
|
except Exception as e:
|
|
301
|
-
Debug("FETCH ERROR:",
|
|
302
|
+
Debug("FETCH ERROR:", sql, str(e), "params", params, "limit", limit, "skip", skip, Constant.TINA4_LOG_DEBUG)
|
|
302
303
|
return DatabaseResult(None, [], str(e))
|
|
303
304
|
|
|
304
305
|
def fetch_one(self, sql, params=[], skip=0):
|
|
@@ -368,7 +369,6 @@ class Database:
|
|
|
368
369
|
finally:
|
|
369
370
|
cursor.close()
|
|
370
371
|
|
|
371
|
-
|
|
372
372
|
def execute_many(self, sql, params=[]):
|
|
373
373
|
"""
|
|
374
374
|
Execute a query based on a single sql statement with a different number of params
|
|
@@ -407,7 +407,7 @@ class Database:
|
|
|
407
407
|
elif self.database_engine == MSSQL:
|
|
408
408
|
self.dba.execute("BEGIN TRANSACTION")
|
|
409
409
|
elif self.database_engine == POSTGRES:
|
|
410
|
-
self.dba.rollback()
|
|
410
|
+
self.dba.rollback() # start fresh
|
|
411
411
|
else:
|
|
412
412
|
Debug("START TRANSACTION ERROR:", "Database engine unrecognised/not supported",
|
|
413
413
|
Constant.TINA4_LOG_ERROR)
|
|
@@ -491,7 +491,10 @@ class Database:
|
|
|
491
491
|
|
|
492
492
|
records.columns = result.columns
|
|
493
493
|
records.count = len(records.records)
|
|
494
|
+
|
|
494
495
|
return records
|
|
496
|
+
else:
|
|
497
|
+
return False
|
|
495
498
|
|
|
496
499
|
def delete(self, table_name, filter=None):
|
|
497
500
|
"""
|
|
@@ -534,6 +537,8 @@ class Database:
|
|
|
534
537
|
Debug("DELETE ERROR:", sql, result.error, Constant.TINA4_LOG_ERROR)
|
|
535
538
|
return False
|
|
536
539
|
|
|
540
|
+
return False
|
|
541
|
+
|
|
537
542
|
def update(self, table_name, data, primary_key="id"):
|
|
538
543
|
"""
|
|
539
544
|
Update data based on table name and record/primary key provided - single or multiple records
|
|
@@ -589,3 +594,4 @@ class Database:
|
|
|
589
594
|
Debug("UPDATE ERROR:", sql, result.error, Constant.TINA4_LOG_ERROR)
|
|
590
595
|
return False
|
|
591
596
|
|
|
597
|
+
return False
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
# flake8: noqa: E501
|
|
7
7
|
import base64
|
|
8
8
|
from datetime import datetime, date
|
|
9
|
-
import inspect
|
|
10
9
|
import ast
|
|
11
10
|
import json
|
|
12
11
|
import os
|
|
@@ -195,9 +194,26 @@ class BlobField(BaseField):
|
|
|
195
194
|
field_type = "blob"
|
|
196
195
|
if database_type == MSSQL:
|
|
197
196
|
field_type = "varbinary(max)"
|
|
197
|
+
elif database_type == FIREBIRD:
|
|
198
|
+
field_type = "blob sub_type 0"
|
|
198
199
|
return self.column_name.lower() + " " + field_type
|
|
199
200
|
|
|
200
201
|
|
|
202
|
+
class JSONBField(BaseField):
|
|
203
|
+
column_type = dict
|
|
204
|
+
default_value = None
|
|
205
|
+
|
|
206
|
+
def get_definition(self, database_type="generic"):
|
|
207
|
+
field_type = "blob"
|
|
208
|
+
if database_type == POSTGRES:
|
|
209
|
+
field_type = "jsonb"
|
|
210
|
+
elif database_type == MSSQL:
|
|
211
|
+
field_type = "varbinary(max)"
|
|
212
|
+
elif database_type == FIREBIRD:
|
|
213
|
+
field_type = "blob sub_type 0"
|
|
214
|
+
|
|
215
|
+
return self.column_name.lower() + " " + field_type
|
|
216
|
+
|
|
201
217
|
class ForeignKeyField:
|
|
202
218
|
field_type = None
|
|
203
219
|
references_table = None
|
|
@@ -549,7 +565,13 @@ class ORM:
|
|
|
549
565
|
for key, value in record.items():
|
|
550
566
|
if key in self.__field_definitions__:
|
|
551
567
|
field_value = self.__field_definitions__[key]
|
|
552
|
-
|
|
568
|
+
if isinstance(self.__field_definitions__[key], JSONBField):
|
|
569
|
+
try:
|
|
570
|
+
field_value.value = ast.literal_eval(value)
|
|
571
|
+
except Exception as e:
|
|
572
|
+
field_value.value = value
|
|
573
|
+
else:
|
|
574
|
+
field_value.value = value
|
|
553
575
|
|
|
554
576
|
setattr(self, key, field_value)
|
|
555
577
|
return True
|
|
@@ -587,8 +609,8 @@ class ORM:
|
|
|
587
609
|
record = self.__dba__.fetch_one(sql, input_params)
|
|
588
610
|
for key, value in data.items():
|
|
589
611
|
if key in self.__field_definitions__:
|
|
590
|
-
if type(value) ==
|
|
591
|
-
data[key] =
|
|
612
|
+
if type(value) == JSONBField and (isinstance(value, dict) or isinstance(value, list)) or (isinstance(value, str) and value.startswith("{") and value.endswith("}")):
|
|
613
|
+
data[key] = ast.literal_eval(value)
|
|
592
614
|
|
|
593
615
|
if record["count_records"] == 0:
|
|
594
616
|
result = self.__dba__.insert(self.__table_name__, data)
|
|
@@ -634,5 +656,5 @@ class ORM:
|
|
|
634
656
|
else:
|
|
635
657
|
self.__dba__.commit()
|
|
636
658
|
return True
|
|
637
|
-
|
|
659
|
+
|
|
638
660
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/public/js/reconnecting-websocket.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/public/swagger/oauth2-redirect.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/translations/en/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/translations/en/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/translations/fr/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-0.2.121 → tina4_python-0.2.123}/tina4_python/translations/fr/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|