Добре, поки мене не було я не лише серіали дивився, я також встиг написати ще одну DI бібліотеку для Python 😎.
Навіщо то взагалі у Пайтоні? Ну сама концепція DI це дуже крута штука, яку можна використовувати будь де без усіляких фреймворків. Але у такому разі треба самому бутстрапити залежності при старті апки і думати як оверайдити залежності у тестах. До того ж скоріш за все це все скатиться у
service locator та нескінченні if my_service is None: my_service = get_my_service().
Раніше я користувався
dependency-injector. Це чудова ліба, але вона завжди здавалась мені дуже навороченою для моїх цілей. І якщо на робочих проєктах її використання ще якось було виправдано, то для маленьких pet-проєктів це точно оверкіл - я завжди починаю з перечитування документації перш ніж засетапити новий проєкт із цією лібою. До того ж вона вже 2 роки не розвивається, тому я почав шукати альтернативи.
Мені подобається концепція DI у FastAPI - залежності це звичайні функції, ніяких контейнерів чи цілої пачки різних типів провайдерів - якщо хочеш щоб твоя залежність була кешованою - просто оберни її у lru_cache.
Із того що я знайшов цікавого у pypi:
-
FastDepends - типу як у FastAPI, але із якимись лівими функціями, інколи скаржиться на аргументи які не мають інжектитись через тайп анотації, не має ресурс менеджменту і не може ніяк засунути async залежність у sync функцію, навіть якщо ми вже у async контексті, а ще не дуже дружить із FastAPI 🤯
-
picobox - дуже крута концепція, але функціонал в основному зусереджений на Scopes (щоб залежності кешувались як сінглтон, у треді, у асінк тасці, реквестах, тощо), не має ресурс менеджменту і не дуже дружить із тайп анотаціями
-
injector - стара ліба, мабуть непогана, але мені ніколи не подобався її API
-
di та
rodi - це більше схоже на ресолвери залежностей, над якими ще треба побудувати свій зручний API, хоча я може і помиляюсь
Тобто нічого із того що я знайшов мені не підходить. А мені усього то потрібно:
1. Власне інжекція залежностей у аргументи функцій, було б гарно якби як у FastAPI
2. Менеджмент ресурсів - щоб можна було зробити залежність яка має teardown і кешує свій результат впродовж життя апки - зручно для конекшенів у БД
3. Можливість оверайдити залежності для тестів
4. Зручний API і без зайвих можливостей
Тож я написав
picodi (спочатку це мало бути nanodi, але pypi сказав що імʼя дуже схоже на вже існуючу лібу і не дав створити із такою назвою)- по суті це декоратор котрий резолвить (просто викликає функцію) залежності і сує їх у декоровану функцію, усе. Із додаткових можливостей - ресурс менеджмент, оверайдинг залежностей, працює із FastAPI і бонус - можливість резолвити асинхронну залежність-ресурс у синхронну функцію і ніякого вайрінгу (і ніякого детекту циклічних залежностей також 😁). Можливо імплементація трохи наївна, але поки мені подобається - я вже замінив dependency-injector на декількох своїх pet-проєктах без якихось проблем.
Тож якщо у когось з вас є схожі вимоги до DI фреймворку - можете спробувати, та не соромтесь робити issues та PR's 😊.
https://github.com/yakimka/picodi