diff --git a/Mirador_backend/app.py b/Mirador_backend/app.py index 9ac4c9337c118174b9e3443e9829bf4235386cad..f8e1395dda723cbb842f2f9e49cc18c3f3844f69 100644 --- a/Mirador_backend/app.py +++ b/Mirador_backend/app.py @@ -4,25 +4,34 @@ from flask_restful_swagger import swagger from flask_apispec.extension import FlaskApiSpec from Mirador_backend.routes import v1 -from Mirador_backend.utils.config import ConfigFactory +from Mirador_backend.utils.containers import Container from Mirador_backend.utils.database import db -from Mirador_backend.utils.app import setApp +from Mirador_backend.utils.config import Config +from dependency_injector import providers +from dependency_injector.wiring import Provide, inject -app = Flask(__name__) -setApp(app) -api = Api(app) -docs = FlaskApiSpec(app) -app.config.from_object(ConfigFactory()) -app.db = db(app.config['DB'], app.config['DEBUG']) +@inject +def shutdown_session(db: db = Provide[Container.db], exception=None): + db.close() -v1.register_routes(api, docs) +@inject +def do_create_app(config: Config = Provide[Container.config]) -> Flask: + app = Flask(__name__) + app.container = Container() + app.config = config + app.teardown_appcontext(shutdown_session) + api = Api(app) + docs = FlaskApiSpec(app) + v1.register_routes(api, docs) + return app -@app.teardown_appcontext -def shutdown_session(exception=None): - app.db.close() + +# Just for flask resolver +def create_app(): + return do_create_app() if __name__ == '__main__': - app.run() + create_app().run() diff --git a/Mirador_backend/models.py b/Mirador_backend/models.py index e6e15a9c64e07f3ecf7e17309fac7dee326b03f2..260868d1e31692b8aa9ceb49b1d529ffdd100d39 100644 --- a/Mirador_backend/models.py +++ b/Mirador_backend/models.py @@ -4,8 +4,10 @@ from sqlalchemy.orm import mapped_column from sqlalchemy import Integer, JSON from sqlalchemy import select from sqlalchemy.exc import NoResultFound +from Mirador_backend.utils.containers import Container +from Mirador_backend.utils.database import db +from dependency_injector.wiring import Provide, inject import json -from Mirador_backend.utils.app import getApp class NotFound(NoResultFound): @@ -16,10 +18,10 @@ class BaseModel(DeclarativeBase): """A generic model class """ - session = getApp().db.session + session = None """Access the db session""" - engine = getApp().db.engine + engine = None """Access the db session""" fillable = ['id'] @@ -33,13 +35,21 @@ class BaseModel(DeclarativeBase): } """Actual data fields""" - def create_all(): + @inject + def __init__(self, db: db = Provide[Container.db]): + super().__init__() + if db is None: + raise Exception('DB must be set') + self.session = db.session + self.engine = db.engine + + def create_all(self): """Creates all tables for all models""" - BaseModel.metadata.create_all(getApp().db.engine) + BaseModel.metadata.create_all(self.engine) def drop_all(): """drop all tables for all models""" - BaseModel.metadata.drop_all(getApp().db.engine) + BaseModel.metadata.drop_all(self.engine) @classmethod def query(cls, stmt): diff --git a/Mirador_backend/resources/base.py b/Mirador_backend/resources/base.py index e264ec229954b9ebb6ee29d06042912c10696dc6..945ceae68b684b5ecebebf75e57c2b5296c41b0b 100644 --- a/Mirador_backend/resources/base.py +++ b/Mirador_backend/resources/base.py @@ -10,9 +10,6 @@ from flask_apispec import doc from flask_restful import marshal, fields from Mirador_backend.models import BaseModel, NotFound -from Mirador_backend.utils.app import getApp - -logger = getApp().logger class ResourceGroup(MethodResource, Resource): diff --git a/Mirador_backend/tests/tester.py b/Mirador_backend/tests/tester.py index f2f6882b1c3e08cdf8e51d7bfef6a0d7da001298..2a1d61a16b0540340001cb4b5bc3bf4200e1ae85 100644 --- a/Mirador_backend/tests/tester.py +++ b/Mirador_backend/tests/tester.py @@ -3,14 +3,15 @@ import json from os.path import dirname, abspath from flask_fixtures import FixturesMixin -from Mirador_backend.app import app +from Mirador_backend.app import create_app from Mirador_backend.models import BaseModel class TestCase(unittest.TestCase, FixturesMixin): fixtures = ['test.json'] - app = app - db = BaseModel + + app = create_app() + db = BaseModel() def setUp(self): self.base = 'v1/mirador_resource' diff --git a/Mirador_backend/utils/app.py b/Mirador_backend/utils/app.py deleted file mode 100644 index 71f6b56ec5782e1acf0afb0376b8cb088d70f74b..0000000000000000000000000000000000000000 --- a/Mirador_backend/utils/app.py +++ /dev/null @@ -1,9 +0,0 @@ -def getApp(): - return getApp.app - - -getApp.app = None - - -def setApp(app): - getApp.app = app diff --git a/Mirador_backend/utils/config.py b/Mirador_backend/utils/config.py index 002af568656fde59a17a71b24f981e74ee97f8fe..23e4297359b202ca3e339cc6833433c2dc98662f 100644 --- a/Mirador_backend/utils/config.py +++ b/Mirador_backend/utils/config.py @@ -23,13 +23,9 @@ class Config(object): 'BASE': getenv('MYSQL_DATABASE', 'base'), } - -class TestingConfig(Config): - TESTING = True - DEBUG = True - DB = None - FIXTURES_DIRS = ['tests/fixtures'] - - -def ConfigFactory(): - return TestingConfig if getenv('ENV', 'dev') == 'test' else Config + def __init__(): + if getenv('ENV', 'dev') == 'test': + self.TESTING = True + self.DEBUG = True + self.DB = None + self.FIXTURES_DIRS = ['tests/fixtures'] diff --git a/Mirador_backend/utils/containers.py b/Mirador_backend/utils/containers.py new file mode 100644 index 0000000000000000000000000000000000000000..624b4218456ef424dd40814237b17c46663fce02 --- /dev/null +++ b/Mirador_backend/utils/containers.py @@ -0,0 +1,14 @@ +from dependency_injector import containers, providers +from Mirador_backend.utils.config import Config +from Mirador_backend.utils.database import db + + +class Container(containers.DeclarativeContainer): + wiring_config = containers.WiringConfiguration(modules=[ + "Mirador_backend.app", + "Mirador_backend.models", + "Mirador_backend.resources.base", + "Mirador_backend.tests.tester" + ]) + config = providers.Factory(Config) + db = providers.Factory(db, config=config) diff --git a/Mirador_backend/utils/database.py b/Mirador_backend/utils/database.py index 8d35a0d9336999665dea11abc82a34d1e10736dc..5f7c4ee8c44405860e4425affad25b904c429f4d 100644 --- a/Mirador_backend/utils/database.py +++ b/Mirador_backend/utils/database.py @@ -9,9 +9,9 @@ class db(): return 'sqlite://' return f'{params["TYPE"]}://{params["USER"]}:{params["PASSWORD"]}@{params["HOST"]}/{params["BASE"]}' - def __init__(self, config, debug): - self.config = config - self.engine = create_engine(self.__getDBUri(), echo=debug) + def __init__(self, config): + self.config = config['DB'] + self.engine = create_engine(self.__getDBUri(), echo=config['DEBUG']) self.session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=self.engine)) diff --git a/setup.py b/setup.py index 5cfd0c114c7824e806643ad1a615e1db4f3384cb..c9398281940281515420f9ef0e28d68291bb22e1 100644 --- a/setup.py +++ b/setup.py @@ -39,6 +39,7 @@ setup( # 1.1.x is incompatible with mariadb connector already in python:3.10 docker image "mariadb>=1.0.11,<1.1.0", "python-dotenv", + "dependency-injector", ], extras_require={