I am new to flask and python. I want to implement a Dependency injection container and access the dependencies inside different modules. My first try looks something like:
class AppModule(Module):
def __init__(self, app):
self.app = app
"""Configure the application."""
def configure(self, binder):
client = self.configure_cosmos_client()
binder.bind(CosmosClient, to=client, scope=singleton)
binder.bind(Dao, to=Dao, scope=singleton)
def configure_cosmos_client(self) -> CosmosClient:
return CosmosClient(
url_connection=self.app.config.get('ENDPOINT'),
auth={'masterKey': self.app.config.get('PRIMARYKEY')}
)
app = Flask(__name__)
injector = Injector([AppModule(app)])
FlaskInjector(app=app, injector=injector)
app.run()
and further inside a module, I want to get the CosmosClient dependency something like:
class Dao:
cosmos_client = None
def __init__(self):
self.cosmos_client = DI.get(CosmosClient)
Is there any way to achieve this? Please note "DI.get" is just an example since I could not find how to access these dependencies apart from injecting the dependencies into the route.
Flask-Injector lets you inject dependencies into: views (functions and class-based)
Dependency injection is a technique built on the top of the Inversion of Control. The main idea is to separate the construction and usage of objects. As a software engineer, your objective is to build software so that it is modular and easy to extend.
Although Flask has a built-in web server, as we all know, it's not suitable for production and needs to be put behind a real web server able to communicate with Flask through a WSGI protocol.
As of Flask 1.0, flask server is multi-threaded by default. Each new request is handled in a new thread. This is a simple Flask application using default settings.
Try Dependency Injector. It has with Flask tutorial. Your container will look something like:
from dependency_injector import containers, providers
from dependency_injector.ext import flask
from flask import Flask
from flask_bootstrap import Bootstrap
from github import Github
from . import views, services
class ApplicationContainer(containers.DeclarativeContainer):
"""Application container."""
app = flask.Application(Flask, __name__)
bootstrap = flask.Extension(Bootstrap)
config = providers.Configuration()
github_client = providers.Factory(
Github,
login_or_token=config.github.auth_token,
timeout=config.github.request_timeout,
)
search_service = providers.Factory(
services.SearchService,
github_client=github_client,
)
index_view = flask.View(
views.index,
search_service=search_service,
default_query=config.search.default_query,
default_limit=config.search.default_limit,
)
To run the app you need to:
from .containers import ApplicationContainer
def create_app():
"""Create and return Flask application."""
container = ApplicationContainer()
container.config.from_yaml('config.yml')
container.config.github.auth_token.from_env('GITHUB_TOKEN')
app = container.app()
app.container = container
bootstrap = container.bootstrap()
bootstrap.init_app(app)
app.add_url_rule('/', view_func=container.index_view.as_view())
return app
And testing will look like:
from unittest import mock
import pytest
from github import Github
from flask import url_for
from .application import create_app
@pytest.fixture
def app():
return create_app()
def test_index(client, app):
github_client_mock = mock.Mock(spec=Github)
# Configure mock
with app.container.github_client.override(github_client_mock):
response = client.get(url_for('index'))
assert response.status_code == 200
# Do more asserts
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With