tina4-python 0.2.122__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.
- tina4_python/Auth.py +222 -0
- tina4_python/Constant.py +43 -0
- tina4_python/Database.py +591 -0
- tina4_python/DatabaseResult.py +107 -0
- tina4_python/DatabaseTypes.py +15 -0
- tina4_python/Debug.py +126 -0
- tina4_python/Env.py +37 -0
- tina4_python/Localization.py +42 -0
- tina4_python/Messages.py +30 -0
- tina4_python/MiddleWare.py +90 -0
- tina4_python/Migration.py +107 -0
- tina4_python/ORM.py +639 -0
- tina4_python/Queue.py +615 -0
- tina4_python/Request.py +19 -0
- tina4_python/Response.py +121 -0
- tina4_python/Router.py +423 -0
- tina4_python/Session.py +342 -0
- tina4_python/ShellColors.py +20 -0
- tina4_python/Swagger.py +228 -0
- tina4_python/Template.py +107 -0
- tina4_python/Webserver.py +429 -0
- tina4_python/Websocket.py +49 -0
- tina4_python/__init__.py +392 -0
- tina4_python/messages.pot +83 -0
- tina4_python/public/css/readme.md +0 -0
- tina4_python/public/favicon.ico +0 -0
- tina4_python/public/images/403.png +0 -0
- tina4_python/public/images/404.png +0 -0
- tina4_python/public/images/500.png +0 -0
- tina4_python/public/images/logo.png +0 -0
- tina4_python/public/images/readme.md +0 -0
- tina4_python/public/js/readme.md +0 -0
- tina4_python/public/js/reconnecting-websocket.js +365 -0
- tina4_python/public/js/tina4helper.js +397 -0
- tina4_python/public/swagger/index.html +90 -0
- tina4_python/public/swagger/oauth2-redirect.html +63 -0
- tina4_python/templates/errors/403.twig +10 -0
- tina4_python/templates/errors/404.twig +10 -0
- tina4_python/templates/errors/500.twig +11 -0
- tina4_python/templates/readme.md +1 -0
- tina4_python/translations/en/LC_MESSAGES/messages.mo +0 -0
- tina4_python/translations/en/LC_MESSAGES/messages.po +80 -0
- tina4_python/translations/fr/LC_MESSAGES/messages.mo +0 -0
- tina4_python/translations/fr/LC_MESSAGES/messages.po +84 -0
- tina4_python-0.2.122.dist-info/METADATA +465 -0
- tina4_python-0.2.122.dist-info/RECORD +47 -0
- tina4_python-0.2.122.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Tina4 - This is not a 4ramework.
|
|
3
|
+
# Copy-right 2007 - current Tina4
|
|
4
|
+
# License: MIT https://opensource.org/licenses/MIT
|
|
5
|
+
#
|
|
6
|
+
# flake8: noqa: E501
|
|
7
|
+
SQLITE = "sqlite3"
|
|
8
|
+
FIREBIRD = "firebird.driver"
|
|
9
|
+
FIREBIRD_INSTALL = "pip install firebird-driver or poetry add firebird-driver"
|
|
10
|
+
MYSQL = "mysql.connector"
|
|
11
|
+
MYSQL_INSTALL = "pip install mysql-connector-python or poetry add mysql-connector-python"
|
|
12
|
+
POSTGRES = "psycopg2"
|
|
13
|
+
POSTGRES_INSTALL = "pip install psycopg2-binary or poetry add psycopg2-binary"
|
|
14
|
+
MSSQL = "pymssql"
|
|
15
|
+
MSSQL_INSTALL = "pip install pymssql or poetry add pymssql"
|
tina4_python/Debug.py
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Tina4 - This is not a 4ramework.
|
|
3
|
+
# Copy-right 2007 - current Tina4
|
|
4
|
+
# License: MIT https://opensource.org/licenses/MIT
|
|
5
|
+
#
|
|
6
|
+
# flake8: noqa: E501
|
|
7
|
+
import os
|
|
8
|
+
import sys
|
|
9
|
+
import logging
|
|
10
|
+
import logging.config
|
|
11
|
+
from logging.handlers import RotatingFileHandler
|
|
12
|
+
import tina4_python.Constant as Constant
|
|
13
|
+
from tina4_python.ShellColors import ShellColors
|
|
14
|
+
from datetime import datetime
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
LOGGING_CONFIG = {
|
|
18
|
+
'version': 1,
|
|
19
|
+
'disable_existing_loggers': False,
|
|
20
|
+
'formatters': {
|
|
21
|
+
'default': {
|
|
22
|
+
'format': '%(levelname)s: %(asctime)s: %(message)s',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
'handlers': {
|
|
26
|
+
'stdout': {
|
|
27
|
+
'level': 'DEBUG',
|
|
28
|
+
'class': 'logging.StreamHandler',
|
|
29
|
+
'formatter': 'default',
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
'loggers': {
|
|
33
|
+
'TINA4': {
|
|
34
|
+
'handlers': ['stdout'],
|
|
35
|
+
'level': 'DEBUG',
|
|
36
|
+
'propagate': True,
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
class Debug:
|
|
42
|
+
|
|
43
|
+
@staticmethod
|
|
44
|
+
def info(*args, **kwargs):
|
|
45
|
+
args += (Constant.TINA4_LOG_INFO,)
|
|
46
|
+
Debug(*args, **kwargs)
|
|
47
|
+
|
|
48
|
+
@staticmethod
|
|
49
|
+
def error(*args, **kwargs):
|
|
50
|
+
args += (Constant.TINA4_LOG_ERROR,)
|
|
51
|
+
Debug(*args, **kwargs)
|
|
52
|
+
|
|
53
|
+
@staticmethod
|
|
54
|
+
def debug(*args, **kwargs):
|
|
55
|
+
args += (Constant.TINA4_LOG_DEBUG,)
|
|
56
|
+
Debug(*args, **kwargs)
|
|
57
|
+
|
|
58
|
+
@staticmethod
|
|
59
|
+
def warning(*args, **kwargs):
|
|
60
|
+
args += (Constant.TINA4_LOG_WARNING,)
|
|
61
|
+
Debug(*args, **kwargs)
|
|
62
|
+
|
|
63
|
+
def __init__(self, *args, **kwargs):
|
|
64
|
+
now = datetime.now()
|
|
65
|
+
debug_level = os.getenv("TINA4_DEBUG_LEVEL", Constant.TINA4_LOG_INFO)
|
|
66
|
+
|
|
67
|
+
logging.config.dictConfig(LOGGING_CONFIG)
|
|
68
|
+
if debug_level == Constant.TINA4_LOG_ALL or debug_level == Constant.TINA4_LOG_DEBUG:
|
|
69
|
+
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
|
|
70
|
+
elif debug_level == Constant.TINA4_LOG_INFO:
|
|
71
|
+
logging.basicConfig(stream=sys.stdout, level=logging.INFO)
|
|
72
|
+
elif debug_level == Constant.TINA4_LOG_ERROR:
|
|
73
|
+
logging.basicConfig(stream=sys.stdout, level=logging.ERROR)
|
|
74
|
+
elif debug_level == Constant.TINA4_LOG_WARNING:
|
|
75
|
+
logging.basicConfig(stream=sys.stdout, level=logging.WARNING)
|
|
76
|
+
|
|
77
|
+
params = [now.strftime("%Y-%m-%d %H:%M:%S") + ":"]
|
|
78
|
+
for value in args:
|
|
79
|
+
if value in [Constant.TINA4_LOG_ALL, Constant.TINA4_LOG_DEBUG, Constant.TINA4_LOG_INFO,
|
|
80
|
+
Constant.TINA4_LOG_ERROR, Constant.TINA4_LOG_WARNING]:
|
|
81
|
+
debug_level = value
|
|
82
|
+
else:
|
|
83
|
+
params.append(value)
|
|
84
|
+
|
|
85
|
+
file_name = "debug.log"
|
|
86
|
+
if "file_name" in kwargs:
|
|
87
|
+
file_name = kwargs["file_name"]
|
|
88
|
+
|
|
89
|
+
formatter = logging.Formatter("%(levelname)s: %(asctime)s: %(message)s")
|
|
90
|
+
logger = logging.getLogger('TINA4')
|
|
91
|
+
logger.setLevel(logging.DEBUG)
|
|
92
|
+
|
|
93
|
+
handler = RotatingFileHandler("."+os.sep+"logs"+os.sep+file_name, maxBytes=1024*1024, backupCount=5, encoding="utf-8")
|
|
94
|
+
handler.setFormatter(formatter)
|
|
95
|
+
logger.addHandler(handler)
|
|
96
|
+
|
|
97
|
+
if (os.getenv("TINA4_DEBUG_LEVEL", [Constant.TINA4_LOG_ALL]) == "[TINA4_LOG_ALL]"
|
|
98
|
+
or debug_level in os.getenv("TINA4_DEBUG_LEVEL", [Constant.TINA4_LOG_ALL])):
|
|
99
|
+
|
|
100
|
+
log_level = 0
|
|
101
|
+
# choose the color
|
|
102
|
+
color = ShellColors.bright_blue
|
|
103
|
+
|
|
104
|
+
if debug_level == Constant.TINA4_LOG_INFO:
|
|
105
|
+
color = ShellColors.cyan
|
|
106
|
+
log_level = 20
|
|
107
|
+
|
|
108
|
+
elif debug_level == Constant.TINA4_LOG_DEBUG:
|
|
109
|
+
color = ShellColors.bright_magenta
|
|
110
|
+
log_level = 10
|
|
111
|
+
|
|
112
|
+
elif debug_level == Constant.TINA4_LOG_ERROR:
|
|
113
|
+
color = ShellColors.bright_red
|
|
114
|
+
log_level = 40
|
|
115
|
+
|
|
116
|
+
elif debug_level == Constant.TINA4_LOG_WARNING:
|
|
117
|
+
color = ShellColors.bright_yellow
|
|
118
|
+
log_level = 30
|
|
119
|
+
|
|
120
|
+
end = ShellColors.end
|
|
121
|
+
|
|
122
|
+
logger.log(log_level, f"{color} ".join(str(param) for param in params[1:]).strip()+f"{end} ")
|
|
123
|
+
|
|
124
|
+
handler.flush()
|
|
125
|
+
logger.removeHandler(handler)
|
|
126
|
+
handler.close()
|
tina4_python/Env.py
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Tina4 - This is not a 4ramework.
|
|
3
|
+
# Copy-right 2007 - current Tina4
|
|
4
|
+
# License: MIT https://opensource.org/licenses/MIT
|
|
5
|
+
#
|
|
6
|
+
import os
|
|
7
|
+
import hashlib
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
from dotenv import load_dotenv
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# check .env for information
|
|
13
|
+
def load_env(path: str = '.env'):
|
|
14
|
+
if not os.path.isfile(path):
|
|
15
|
+
current_time = datetime.now()
|
|
16
|
+
result = hashlib.md5(current_time.strftime("%A,%d %B %Y").encode())
|
|
17
|
+
with open(path, 'w') as f:
|
|
18
|
+
f.write("# Project Settings\n")
|
|
19
|
+
f.write("PROJECT_NAME=\"My Project\"\n")
|
|
20
|
+
f.write("VERSION=1.0.0\n")
|
|
21
|
+
f.write("TINA4_LANGUAGE=en\n")
|
|
22
|
+
f.write("API_KEY="+result.hexdigest()+"\n")
|
|
23
|
+
f.write("TINA4_DEBUG_LEVEL=[TINA4_LOG_ALL]\n")
|
|
24
|
+
# Load the .env
|
|
25
|
+
load_dotenv(path)
|
|
26
|
+
# check for defaults we need
|
|
27
|
+
if "TINA4_LANGUAGE" not in os.environ:
|
|
28
|
+
with open(path, 'a') as f:
|
|
29
|
+
f.write("TINA4_LANGUAGE=en\n")
|
|
30
|
+
if "TINA4_DEBUG_LEVEL" not in os.environ:
|
|
31
|
+
with open(path, 'a') as f:
|
|
32
|
+
f.write("TINA4_DEBUG_LEVEL=[\"ALL\"]\n")
|
|
33
|
+
if "API_KEY" not in os.environ:
|
|
34
|
+
current_time = datetime.now()
|
|
35
|
+
result = hashlib.md5(current_time.strftime("%A,%d %B %Y").encode())
|
|
36
|
+
with open(path, 'a') as f:
|
|
37
|
+
f.write("API_KEY="+result.hexdigest()+"\n")
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Tina4 - This is not a 4ramework.
|
|
3
|
+
# Copy-right 2007 - current Tina4
|
|
4
|
+
# License: MIT https://opensource.org/licenses/MIT
|
|
5
|
+
#
|
|
6
|
+
# flake8: noqa: E501
|
|
7
|
+
import gettext
|
|
8
|
+
import os
|
|
9
|
+
import sys
|
|
10
|
+
from tina4_python.Debug import Debug
|
|
11
|
+
from tina4_python import Constant
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# load environment variables from .env file
|
|
15
|
+
# check .env for information
|
|
16
|
+
|
|
17
|
+
def localize():
|
|
18
|
+
translation_path = os.path.join(os.path.dirname(__file__), 'translations')
|
|
19
|
+
available_languages = ['en', 'fr', 'af']
|
|
20
|
+
|
|
21
|
+
# get user language from environment variable
|
|
22
|
+
# default to English
|
|
23
|
+
if "TINA4_LANGUAGE" in os.environ:
|
|
24
|
+
user_language = os.environ.get('TINA4_LANGUAGE', 'en')
|
|
25
|
+
else:
|
|
26
|
+
user_language = "en"
|
|
27
|
+
|
|
28
|
+
# check if an argument is a language
|
|
29
|
+
if len(sys.argv) > 1:
|
|
30
|
+
try:
|
|
31
|
+
int(sys.argv[1])
|
|
32
|
+
except ValueError:
|
|
33
|
+
if sys.argv[1] in available_languages:
|
|
34
|
+
user_language = sys.argv[1]
|
|
35
|
+
|
|
36
|
+
if len(sys.argv) > 2 and sys.argv[2] in available_languages:
|
|
37
|
+
user_language = sys.argv[2]
|
|
38
|
+
|
|
39
|
+
Debug("Language: " + user_language, Constant.TINA4_LOG_INFO)
|
|
40
|
+
# Initialize the translation system
|
|
41
|
+
translation = gettext.translation('messages', translation_path, languages=[user_language])
|
|
42
|
+
translation.install()
|
tina4_python/Messages.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Tina4 - This is not a 4ramework.
|
|
3
|
+
# Copy-right 2007 - current Tina4
|
|
4
|
+
# License: MIT https://opensource.org/licenses/MIT
|
|
5
|
+
#
|
|
6
|
+
# flake8: noqa: E501
|
|
7
|
+
import gettext
|
|
8
|
+
|
|
9
|
+
_ = gettext.gettext
|
|
10
|
+
|
|
11
|
+
MSG_DEBUG = _('Debug: {message}')
|
|
12
|
+
MSG_WARNING = _('Warning: {message}')
|
|
13
|
+
MSG_ERROR = _('Error: {message}')
|
|
14
|
+
MSG_INFO = _('Info: {message}')
|
|
15
|
+
|
|
16
|
+
# Router messages
|
|
17
|
+
MSG_ROUTER_MATCHING = _('Matching: {matching}')
|
|
18
|
+
MSG_ROUTER_VARIABLES = _('Variables: {variables}')
|
|
19
|
+
MSG_ROUTER_ROOT_PATH = _('Root Path {root_path} {url}')
|
|
20
|
+
MSG_ROUTER_STATIC_FILE = _('Attempting to serve static file: {static_file}')
|
|
21
|
+
MSG_ROUTER_CSS_FILE = _('Attempting to serve CSS file: {css_file}')
|
|
22
|
+
MSG_ROUTER_IMAGE_FILE = _('Attempting to serve image file: {image_file}')
|
|
23
|
+
|
|
24
|
+
# Server messages
|
|
25
|
+
MSG_ASSUMING_ROOT_PATH = _('Assuming root path: {root_path}, library path: {library_path}')
|
|
26
|
+
MSG_LOAD_ALL_THINGS = _('Load all things')
|
|
27
|
+
MSG_SERVER_STARTED = _('Server started http://{host_name}:{port}')
|
|
28
|
+
MSG_SERVER_STOPPED = _('Server stopped.')
|
|
29
|
+
MSG_STARTING_WEBSERVER = _('Starting webserver on {port}')
|
|
30
|
+
MSG_ENTRY_POINT_NAME = _('Entry point name ... {name}')
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Tina4 - This is not a 4ramework.
|
|
3
|
+
# Copy-right 2007 - current Tina4
|
|
4
|
+
# License: MIT https://opensource.org/licenses/MIT
|
|
5
|
+
#
|
|
6
|
+
# flake8: noqa: E501
|
|
7
|
+
import asyncio
|
|
8
|
+
|
|
9
|
+
class MiddleWare:
|
|
10
|
+
def __init__(self, middleware_class):
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
:param middleware_class:
|
|
14
|
+
"""
|
|
15
|
+
self.before_methods = []
|
|
16
|
+
self.after_methods = []
|
|
17
|
+
self.any_methods = []
|
|
18
|
+
self.middleware_class = middleware_class
|
|
19
|
+
|
|
20
|
+
self.methods_list = [method for method in vars(middleware_class) if callable(
|
|
21
|
+
getattr(middleware_class, method)) and not method.startswith("__")]
|
|
22
|
+
|
|
23
|
+
for method in self.methods_list:
|
|
24
|
+
if method.startswith("before"):
|
|
25
|
+
self.before_methods.append(method)
|
|
26
|
+
elif method.startswith("after"):
|
|
27
|
+
self.after_methods.append(method)
|
|
28
|
+
else:
|
|
29
|
+
self.any_methods.append(method)
|
|
30
|
+
|
|
31
|
+
async def call_before_methods(self, request, response):
|
|
32
|
+
"""
|
|
33
|
+
Call before methods
|
|
34
|
+
:param request:
|
|
35
|
+
:param response:
|
|
36
|
+
:return:
|
|
37
|
+
"""
|
|
38
|
+
for method in self.before_methods:
|
|
39
|
+
method = getattr(self.middleware_class, method)
|
|
40
|
+
result = method(request, response)
|
|
41
|
+
if asyncio.iscoroutine(result):
|
|
42
|
+
request, response = await result
|
|
43
|
+
else:
|
|
44
|
+
request, response = result
|
|
45
|
+
|
|
46
|
+
return request, response
|
|
47
|
+
|
|
48
|
+
async def call_after_methods(self, request, response):
|
|
49
|
+
"""
|
|
50
|
+
Call after methods
|
|
51
|
+
:param request:
|
|
52
|
+
:param response:
|
|
53
|
+
:return:
|
|
54
|
+
"""
|
|
55
|
+
for method in self.after_methods:
|
|
56
|
+
method = getattr(self.middleware_class, method)
|
|
57
|
+
result = method(request, response)
|
|
58
|
+
if asyncio.iscoroutine(result):
|
|
59
|
+
request, response = await result
|
|
60
|
+
else:
|
|
61
|
+
request, response = result
|
|
62
|
+
return request, response
|
|
63
|
+
|
|
64
|
+
async def call_any_methods(self, request, response):
|
|
65
|
+
"""
|
|
66
|
+
Call any methods
|
|
67
|
+
:param request:
|
|
68
|
+
:param response:
|
|
69
|
+
:return:
|
|
70
|
+
"""
|
|
71
|
+
for method in self.any_methods:
|
|
72
|
+
method = getattr(self.middleware_class, method)
|
|
73
|
+
result = method(request, response)
|
|
74
|
+
if asyncio.iscoroutine(result):
|
|
75
|
+
request, response = await result
|
|
76
|
+
else:
|
|
77
|
+
request, response = result
|
|
78
|
+
return request, response
|
|
79
|
+
|
|
80
|
+
def call_direct_method(self, request, response, method_name):
|
|
81
|
+
"""
|
|
82
|
+
Call direct methods
|
|
83
|
+
:param request:
|
|
84
|
+
:param response:
|
|
85
|
+
:param method_name:
|
|
86
|
+
:return:
|
|
87
|
+
"""
|
|
88
|
+
method = getattr(self.middleware_class, method_name)
|
|
89
|
+
request, response = method(request, response)
|
|
90
|
+
return request, response
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Tina4 - This is not a 4ramework.
|
|
3
|
+
# Copy-right 2007 - current Tina4
|
|
4
|
+
# License: MIT https://opensource.org/licenses/MIT
|
|
5
|
+
#
|
|
6
|
+
# flake8: noqa: E501
|
|
7
|
+
import os
|
|
8
|
+
import sys
|
|
9
|
+
|
|
10
|
+
from tina4_python import ShellColors
|
|
11
|
+
from tina4_python import Constant
|
|
12
|
+
from tina4_python.Debug import Debug
|
|
13
|
+
from tina4_python.Database import MSSQL, POSTGRES, FIREBIRD, MYSQL
|
|
14
|
+
import tina4_python
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def migrate(dba, delimiter=";", migration_folder="migrations"):
|
|
18
|
+
"""
|
|
19
|
+
Migrates the database from the migrate folder
|
|
20
|
+
:param delimiter: SQL delimiter
|
|
21
|
+
:param dba: Database connection
|
|
22
|
+
:param migration_folder: Alternative folder for migrations
|
|
23
|
+
:return:
|
|
24
|
+
"""
|
|
25
|
+
if dba.database_engine == MSSQL:
|
|
26
|
+
if not dba.table_exists("tina4_migration"):
|
|
27
|
+
dba.execute("create table tina4_migration(id integer identity(1,1) not null, description varchar(200) default '', content nvarchar(max), error_message nvarchar(max), passed integer default 0, primary key(id))")
|
|
28
|
+
dba.execute("SET IDENTITY_INSERT tina4_migration ON")
|
|
29
|
+
elif dba.database_engine == POSTGRES:
|
|
30
|
+
dba.execute(
|
|
31
|
+
"create table if not exists tina4_migration(id serial primary key, description varchar(200) default '', content text, error_message text, passed integer default 0)")
|
|
32
|
+
elif dba.database_engine == MYSQL:
|
|
33
|
+
dba.execute(
|
|
34
|
+
"create table if not exists tina4_migration(id integer not null auto_increment, description varchar(200) default '', content text, error_message text, passed integer default 0, primary key(id))")
|
|
35
|
+
elif dba.database_engine == FIREBIRD:
|
|
36
|
+
if not dba.table_exists("tina4_migration"):
|
|
37
|
+
dba.execute(
|
|
38
|
+
"create table tina4_migration(id integer not null, description varchar(200) default '', content blob sub_type text, error_message blob sub_type text, passed integer default 0, primary key(id))")
|
|
39
|
+
else:
|
|
40
|
+
dba.execute(
|
|
41
|
+
"create table if not exists tina4_migration(id integer not null, description varchar(200) default '', content blob, error_message blob, passed integer default 0, primary key(id))")
|
|
42
|
+
|
|
43
|
+
Debug(ShellColors.bright_yellow, "Migration: Found ", tina4_python.root_path + os.sep + migration_folder, ShellColors.end, Constant.TINA4_LOG_INFO)
|
|
44
|
+
dir_list = os.listdir(tina4_python.root_path + os.sep + migration_folder)
|
|
45
|
+
dir_list.sort()
|
|
46
|
+
|
|
47
|
+
for file in dir_list:
|
|
48
|
+
if '.sql' in file:
|
|
49
|
+
Debug(ShellColors.bright_yellow, "Migration: Checking file", file, ShellColors.end, Constant.TINA4_LOG_INFO)
|
|
50
|
+
sql_file = open(tina4_python.root_path + os.sep + migration_folder + os.sep + file)
|
|
51
|
+
file_contents = sql_file.read()
|
|
52
|
+
sql_file.close()
|
|
53
|
+
try:
|
|
54
|
+
dba.execute("delete from tina4_migration where description = ? and passed = ?", [file, 0])
|
|
55
|
+
dba.commit()
|
|
56
|
+
# check if migration exists in the database and has passed - no need to run the scripts below
|
|
57
|
+
|
|
58
|
+
sql_check = "select * from tina4_migration where description = ? and passed = ?"
|
|
59
|
+
record = dba.fetch(sql_check, [file, 1])
|
|
60
|
+
|
|
61
|
+
if record.count == 0:
|
|
62
|
+
Debug(ShellColors.bright_yellow, "Migration: Running migration for", file, ShellColors.end, Constant.TINA4_LOG_INFO)
|
|
63
|
+
# get each migration
|
|
64
|
+
script_content = file_contents.split(";")
|
|
65
|
+
|
|
66
|
+
# all scripts need to pass
|
|
67
|
+
error = False
|
|
68
|
+
error_message = ""
|
|
69
|
+
for script in script_content:
|
|
70
|
+
if script.strip() != "":
|
|
71
|
+
result = dba.execute(script)
|
|
72
|
+
if result.error is not None:
|
|
73
|
+
error = True
|
|
74
|
+
error_message = result.error
|
|
75
|
+
break
|
|
76
|
+
|
|
77
|
+
if not error:
|
|
78
|
+
# passed print(color + f"{debug_level:5}:"+ShellColors.end, "", end="")
|
|
79
|
+
Debug(ShellColors.bright_yellow,"Migration:", ShellColors.end, ShellColors.bright_green+"PASSED running migration for", file, ShellColors.end, Constant.TINA4_LOG_INFO)
|
|
80
|
+
dba.commit()
|
|
81
|
+
next_id = dba.get_next_id("tina4_migration")
|
|
82
|
+
dba.execute("insert into tina4_migration (id, description, content, passed) values (?, ?, ?, 1) ",
|
|
83
|
+
[next_id, file, file_contents])
|
|
84
|
+
dba.commit()
|
|
85
|
+
else:
|
|
86
|
+
# did not pass
|
|
87
|
+
Debug(ShellColors.bright_yellow, "Migration:", ShellColors.end, ShellColors.bright_red+"FAILED running migration for", file, error_message, ShellColors.end, Constant.TINA4_LOG_ERROR)
|
|
88
|
+
dba.rollback()
|
|
89
|
+
next_id = dba.get_next_id("tina4_migration")
|
|
90
|
+
dba.execute(
|
|
91
|
+
"insert into tina4_migration (id, description, content, passed, error_message) values (?, ?, ?, 0, ?) ",
|
|
92
|
+
[next_id, file, file_contents, str(error_message)])
|
|
93
|
+
dba.commit()
|
|
94
|
+
sys.exit(1)
|
|
95
|
+
except Exception as e:
|
|
96
|
+
next_id = dba.get_next_id("tina4_migration")
|
|
97
|
+
dba.execute(
|
|
98
|
+
"insert into tina4_migration (id, description, content, passed, error_message) values (?, ?, ?, 0, ?) ",
|
|
99
|
+
[next_id, file, file_contents, str(e)])
|
|
100
|
+
dba.commit()
|
|
101
|
+
|
|
102
|
+
Debug("Migration: Failed to run", file, e, Constant.TINA4_LOG_ERROR)
|
|
103
|
+
sys.exit(1)
|
|
104
|
+
|
|
105
|
+
if dba.database_engine == MSSQL:
|
|
106
|
+
dba.execute("SET IDENTITY_INSERT tina4_migration OFF")
|
|
107
|
+
|