Русский
Русский
English
Статистика
Реклама

Dependency Injector 4.0 упрощенная интеграция с другими Python фреймворками



Привет,

Я выпустил новую мажорную версию Dependency Injector.

Основная фича этой версии связывание (wiring). Она позволяет делать инъекции в функции и методы без затягивания их в контейнер.

from dependency_injector import containers, providersfrom dependency_injector.wiring import Provideclass Container(containers.DeclarativeContainer):    config = providers.Configuration()    api_client = providers.Singleton(        ApiClient,        api_key=config.api_key,        timeout=config.timeout.as_int(),    )    service = providers.Factory(        Service,        api_client=api_client,    )def main(service: Service = Provide[Container.service]):    ...if __name__ == '__main__':    container = Container()    container.config.api_key.from_env('API_KEY')    container.config.timeout.from_env('TIMEOUT')    container.wire(modules=[sys.modules[__name__]])    main()  # <-- зависимость внедряется автоматически    with container.api_client.override(mock.Mock()):        main()  # <-- переопределенная зависимость внедряется автоматически

Когда вызывается функция main() зависимость Service собирается и передается автоматически.

При тестировании вызывается container.api_client.override() чтобы заменить API клиент на мок. При вызове main() зависимость Service будет собираться с моком.

Новая фича упрощает использование Dependency Injectorа с другими Python фреймворками.

Как связывание помогает интеграции с другими фреймворками?


Связывание дает возможность делать точные инъекции независимо от структуры приложения. В отличии от 3-ей версии для внедрения зависимости не нужно затягивать функцию или класс в контейнер.

Пример с Flask:

import sysfrom dependency_injector import containers, providersfrom dependency_injector.wiring import Providefrom flask import Flask, jsonclass Service:    ...class Container(containers.DeclarativeContainer):    service = providers.Factory(Service)def index_view(service: Service = Provide[Container.service]) -> str:    return json.dumps({'service_id': id(service)})if __name__ == '__main__':    container = Container()    container.wire(modules=[sys.modules[__name__]])    app = Flask(__name__)    app.add_url_rule('/', 'index', index_view)    app.run()

Другие примеры:


Как работает связывание?


Для того чтобы применять связывание нужно:

  • Разместить маркеры в коде. Маркер вида Provide[Container.bar] указывается как дефолтное значение аргумента функции или метода. Маркеры нужны чтобы указать что и куда внедрять.
  • Связать контейнер с маркерами в коде. Для этого нужно вызвать метод container.wire(modules=[...], packages=[...]) и указать модули или пакеты, в которых есть маркеры.
  • Использовать функции и методы как обычно. Фреймворк подготовит и внедрит нужные зависимости автоматически.

Связывание работает на базе интроспекции. При вызове container.wire(modules=[...], packages=[...]) фреймворк пройдется по всем функциям и методам в этих пакетах и модулях и изучит их дефолтные параметры. Если дефолтным параметром будет маркер, то такая функция или метод будут пропатчены декоратором внедрения зависимостей. Этот декоратор при вызове подготавливает и внедряет зависимости вместо маркеров в оригинальную функцию.

def foo(bar: Bar = Provide[Container.bar]):    ...container = Container()container.wire(modules=[sys.modules[__name__]])foo()  # <--- Аргумент "bar" будет внедрен# То же что и:foo(bar=container.bar())

Больше про связывание можно узнать тут.

Совместимость?


Версия 4.0 совместима с версиями 3.х.

Интеграционные модули ext.flask и ext.aiohttp задеприкечены в пользу связывания.
При использовании фреймворк будет выводить предупреждение и рекомендовать перейти на связывание.

Полный список изменений можно найти тут.

Что дальше?


Источник: habr.com
К списку статей
Опубликовано: 12.10.2020 02:06:31
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Python

Dependency injection

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru