diff --git a/README.rst b/README.rst index 2617825d..0bb2f8db 100644 --- a/README.rst +++ b/README.rst @@ -52,10 +52,25 @@ What is ``Dependency Injector``? ``Dependency Injector`` is a dependency injection framework for Python. -Why do I need it? -================= +It stands on two principles: -``Dependency Injector`` helps you understand and change the structure of the application. +- Explicit is better than implicit (PEP20). +- Do no magic to your code. + +How does it different from the other frameworks? + +- **No autowiring.** The framework does NOT do any autowiring / autoresolving of the dependencies. You need to specify everything explicitly. Because *"Explicit is better than implicit" (PEP20)*. +- **Does not pollute your code.** Your application does NOT know and does NOT depend on the framework. No ``@inject`` decorators, annotations, patching or any other magic tricks. + +``Dependency Injector`` makes a simple contract with you: + +- You tell the framework how to build you code +- The framework does it for you + +The power of the ``Dependency Injector`` is in its simplicity and straightforwardness. It is a simple tool for the powerful concept. + +Example +======= With the ``Dependency Injector`` you keep **application structure in one place**. This place is called **the container**. You use the container to manage all the components of the @@ -67,133 +82,145 @@ the application structure. It is **easy to understand and change** it. *The container is like a map of your application. You always know what depends on what.* -``Flask`` + ``Dependency Injector`` example application container: +Example application container: .. code-block:: python - 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 + import logging + import sys - from . import views, services + from dependency_injector import containers, providers + + from . import http, monitors, dispatcher - class ApplicationContainer(containers.DeclarativeContainer): - """Application container.""" + class ApplicationContainer(containers.DeclarativeContainer): - app = flask.Application(Flask, __name__) + config = providers.Configuration() - bootstrap = flask.Extension(Bootstrap) + configure_logging = providers.Callable( + logging.basicConfig, + stream=sys.stdout, + level=config.log.level, + format=config.log.format, + ) - config = providers.Configuration() + http_client = providers.Factory(http.HttpClient) - github_client = providers.Factory( - Github, - login_or_token=config.github.auth_token, - timeout=config.github.request_timeout, - ) + example_monitor = providers.Factory( + monitors.HttpMonitor, + http_client=http_client, + options=config.monitors.example, + ) - search_service = providers.Factory( - services.SearchService, - github_client=github_client, - ) + httpbin_monitor = providers.Factory( + monitors.HttpMonitor, + http_client=http_client, + options=config.monitors.httpbin, + ) - index_view = flask.View( - views.index, - search_service=search_service, - default_query=config.search.default_query, - default_limit=config.search.default_limit, - ) + dispatcher = providers.Factory( + dispatcher.Dispatcher, + monitors=providers.List( + example_monitor, + httpbin_monitor, + ), + ) -Running such container looks like this: +Example of running of such application: .. code-block:: python - from .containers import ApplicationContainer + 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') + def main() -> None: + container = ApplicationContainer() - app = container.app() - app.container = container + container.config.from_yaml('config.yml') + container.configure_logging() - bootstrap = container.bootstrap() - bootstrap.init_app(app) - - app.add_url_rule('/', view_func=container.index_view.as_view()) - - return app - -And testing looks like: - -.. code-block:: python - - from unittest import mock - - import pytest - from github import Github - from flask import url_for - - from .application import create_app + dispatcher = container.dispatcher() + dispatcher.run() - @pytest.fixture - def app(): - return create_app() + if __name__ == '__main__': + main() +Tutorials +========= - def test_index(client, app): - github_client_mock = mock.Mock(spec=Github) - # Configure mock +Tutorial is a good point to start. - with app.container.github_client.override(github_client_mock): - response = client.get(url_for('index')) +Choose one of the following: - assert response.status_code == 200 - # Do more asserts +- `Flask web application tutorial `_ +- `Aiohttp REST API tutorial `_ +- `Asyncio monitoring daemon tutorial `_ -See complete example here - `Flask + Dependency Injector Example `_ - -How to install? ---------------- +Installation +============ - The package is available on the `PyPi`_:: pip install dependency-injector -Where is the docs? ------------------- +Documentation +============= - The documentation is available on the `Read The Docs `_ -Have a question? ----------------- +Frequently asked questions +========================== -- Open a `Github Issue `_ +What is the dependency injection? + - dependency injection is a principle that decreases coupling and increases cohesion + +Why should I do the dependency injection? + - your code becomes more flexible, testable and clear + - you have no problems when you need to understand how it works or change it 😎 + +How do I start doing the dependency injection? + - you start writing the code following the dependency injection principle + - you register all of your application components and their dependencies in the container + - when you need a component, you get it from the container + +Why do I need a framework for this? + - you need the framework for this to not create it by your own + - this framework gives you the container and the providers + - the container is like a dictionary with the batteries 🔋 + - the providers manage the lifetime of your components, you will need factories, singletons, smart config object etc + +What price do I pay and what do I get? + - you need to explicitly specify the dependencies in the container + - it will be extra work in the beginning + - it will payoff when project grows or in two weeks 😊 (when you forget what project was about) + +What features does the framework have? + - building objects graph + - smart configuration object + - providers: factory, singleton, thread locals registers, etc + - positional and keyword context injections + - overriding of the objects in any part of the graph + +What features the framework does NOT have? + - autowiring / autoresolving of the dependencies + - the annotations and ``@inject``-like decorators + +Have a question? + - Open a `Github Issue `_ Found a bug? ------------- - -- Open a `Github Issue `_ + - Open a `Github Issue `_ Want to help? -------------- - -- |star| Star the ``Dependency Injector`` on the `Github `_ -- |new| Start a new project with the ``Dependency Injector`` -- |tell| Tell your friend about the ``Dependency Injector`` + - |star| Star the ``Dependency Injector`` on the `Github `_ + - |new| Start a new project with the ``Dependency Injector`` + - |tell| Tell your friend about the ``Dependency Injector`` Want to contribute? -------------------- - -- |fork| Fork the project -- |pull| Open a pull request to the ``develop`` branch + - |fork| Fork the project + - |pull| Open a pull request to the ``develop`` branch .. _PyPi: https://pypi.org/project/dependency-injector/ diff --git a/docs/index.rst b/docs/index.rst index 8ce60902..a4f77569 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -64,7 +64,22 @@ Dependency Injector --- Dependency injection framework for Python ``Dependency Injector`` is a dependency injection framework for Python. -It helps you understand and change the structure of the application. +It stands on two principles: + +- Explicit is better than implicit (PEP20). +- Do no magic to your code. + +How does it different from the other frameworks? + +- **No autowiring.** The framework does NOT do any autowiring / autoresolving of the dependencies. You need to specify everything explicitly. Because *"Explicit is better than implicit" (PEP20)*. +- **Does not pollute your code.** Your application does NOT know and does NOT depend on the framework. No ``@inject`` decorators, annotations, patching or any other magic tricks. + +``Dependency Injector`` makes a simple contract with you: + +- You tell the framework how to build you code +- The framework does it for you + +The power of the ``Dependency Injector`` is in its simplicity and straightforwardness. It is a simple tool for the powerful concept. With the ``Dependency Injector`` you keep **application structure in one place**. This place is called **the container**. You use the container to manage all the components of the diff --git a/docs/introduction/key_features.rst b/docs/introduction/key_features.rst index 9ed30269..c2a1756f 100644 --- a/docs/introduction/key_features.rst +++ b/docs/introduction/key_features.rst @@ -13,6 +13,23 @@ It was designed to be a unified and developer-friendly tool that helps implement a dependency injection design pattern in a formal, pretty, and Pythonic way. +It stands on two principles: + +- Explicit is better than implicit (PEP20). +- Do no magic to your code. + +How does it different from the other frameworks? + +- **No autowiring.** The framework does NOT do any autowiring / autoresolving of the dependencies. You need to specify everything explicitly. Because *"Explicit is better than implicit" (PEP20)*. +- **Does not pollute your code.** Your application does NOT know and does NOT depend on the framework. No ``@inject`` decorators, annotations, patching or any other magic tricks. + +``Dependency Injector`` makes a simple contract with you: + +- You tell the framework how to build you code +- The framework does it for you + +The power of the ``Dependency Injector`` is in its simplicity and straightforwardness. It is a simple tool for the powerful concept. + The key features of the ``Dependency Injector`` framework are: + Easy, smart, and Pythonic style. diff --git a/docs/main/changelog.rst b/docs/main/changelog.rst index c86f3a1a..01cde170 100644 --- a/docs/main/changelog.rst +++ b/docs/main/changelog.rst @@ -7,6 +7,14 @@ that were made in every particular version. From version 0.7.6 *Dependency Injector* framework strictly follows `Semantic versioning`_ +3.29.0 +------ +- Update README with the more direct message on what is ``Dependency Injector`` and how is it + different from the other frameworks. +- Change the example code in the README. +- Add FAQ to the README. +- Update documentation key features and index pages. + 3.28.1 ------ - Fix typos in the ``asyncio`` + ``Dependency Injector`` monitoring daemon tutorial. diff --git a/src/dependency_injector/__init__.py b/src/dependency_injector/__init__.py index 32f64c27..be2daa3e 100644 --- a/src/dependency_injector/__init__.py +++ b/src/dependency_injector/__init__.py @@ -1,6 +1,6 @@ """Dependency injector top-level package.""" -__version__ = '3.28.1' +__version__ = '3.29.0' """Version number that follows semantic versioning. :type: str