This repository was archived by the owner on Dec 15, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathapp.py
More file actions
192 lines (140 loc) · 5.35 KB
/
app.py
File metadata and controls
192 lines (140 loc) · 5.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
import os.path
import sqlite3
import sqlalchemy
import sqlalchemy.orm
import sqlalchemy.event
from flask import Flask, Blueprint
from flask_injector import FlaskInjector
from traces_api.api.restplus import api
from traces_api.database.tools import create_database, recreate_database
from traces_api.config import Config
from traces_api.modules.unit.controller import ns as dataset_namespace
from traces_api.modules.annotated_unit.controller import ns as annotated_unit_namespace
from traces_api.modules.mix.controller import ns as mix_namespace
from traces_api.trace_tools import TraceAnalyzer, TraceNormalizer, TraceMixing
from traces_api.compression import Compression
APP_DIR = os.path.dirname(os.path.realpath(__file__))
def _fk_pragma_on_connect(dbapi_con, con_record):
# Enable Foreign key support on SQLite db
if isinstance(dbapi_con, sqlite3.Connection):
dbapi_con.execute('pragma foreign_keys=ON')
def create_engine(url, **params):
"""
Create sqlalchemy engine
:param url: database connection url
:param params: additional parameters
:return: created engine
"""
engine = sqlalchemy.create_engine(url, **params)
sqlalchemy.event.listen(engine, 'connect', _fk_pragma_on_connect)
return engine
def setup_database(engine):
"""
Setup database session using session maker
:param engine:
:return:
"""
session = sqlalchemy.orm.sessionmaker(bind=engine)
session = sqlalchemy.orm.scoped_session(session)
return session
def prepare_database(url, recreate=False):
"""
Prepare database session
:param url: database connection url
:param recreate: set True if database should be recreated, False otherwise
:return: sqlalchemy session_maker
"""
engine = create_engine(url)
session_maker = setup_database(engine)
if recreate:
recreate_database(engine)
else:
create_database(engine)
return engine, session_maker
class FlaskApp:
"""
Configure Flask Application
"""
def __init__(self, session_maker, engine, config):
"""
:param session_maker: SqlAlchemy session maker
:param engine: SqlAlchemy engine
:param config: config
"""
self._session_maker = session_maker
self._engine = engine
self._config = config
def init_app(self, flask_app):
"""
Initialize appliaction
:param flask_app:
"""
@flask_app.teardown_request
def teardown_request(exception):
# Always rollback and cleanup transaction
# All data should be already saved
self._session_maker().rollback()
blueprint = Blueprint('api', __name__)
api.init_app(blueprint)
api.add_namespace(dataset_namespace)
api.add_namespace(annotated_unit_namespace)
api.add_namespace(mix_namespace)
flask_app.register_blueprint(blueprint)
@staticmethod
def _abs_storage_path(config_value):
"""
Use absolute storage path
:param config_value:
:return: absolute path to folder
"""
if config_value.startswith("/"):
return config_value
return "{}/{}".format(APP_DIR, config_value)
def configure(self, binder):
"""
Configure application, setup binder
:param binder:
"""
from traces_api.modules.unit.service import UnitService
from traces_api.modules.annotated_unit.service import AnnotatedUnitService
from traces_api.modules.mix.service import MixService
from traces_api.storage import FileStorage
annotated_unit_storage = FileStorage(self._abs_storage_path(self._config.get("storage", "ann_units_dir")), compression=Compression())
annotated_unit_service = AnnotatedUnitService(self._session_maker, annotated_unit_storage, TraceAnalyzer(), TraceNormalizer())
unit_storage = FileStorage(self._abs_storage_path(self._config.get("storage", "units_dir")), compression=Compression(), subdirectories=False)
unit_service = UnitService(self._session_maker, annotated_unit_service, unit_storage, TraceAnalyzer())
mix_storage = FileStorage(self._abs_storage_path(self._config.get("storage", "mixes_dir")), compression=Compression())
mix_service = MixService(self._session_maker, self._engine, annotated_unit_service, mix_storage, TraceNormalizer(), TraceMixing())
binder.bind(UnitService, to=unit_service)
binder.bind(AnnotatedUnitService, to=annotated_unit_service)
binder.bind(MixService, to=mix_service)
def create_app(self):
"""
Create Flask application
:return: flask application
"""
app = Flask(__name__)
self.init_app(app)
FlaskInjector(app=app, modules=[self.configure])
return app
def get_config():
"""
Get config
:return: Config
"""
return Config("config.ini")
def get_flask_application():
"""
Rum application
"""
config = get_config()
engine, session = prepare_database(config.get("database", "connection_string"), config.get("database", "recreate"))
engine.dispose()
app = FlaskApp(session, engine, config).create_app()
return app
def run():
config = get_config()
app = get_flask_application()
app.run(debug=True, port=int(config.get("app", "port")))
if __name__ == "__main__":
run()