Halo, Habr! Saya telah merilis versi utama baru dari Dependency Injector .
Fitur utama dari versi ini adalah kabel. Ini memungkinkan Anda memasukkan fungsi dan metode tanpa menyeretnya ke dalam wadah.
from dependency_injector import containers, providers
from dependency_injector.wiring import Provide
class 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() # <--
Saat fungsi dipanggil,
main()ketergantungan Servicedikumpulkan dan diteruskan secara otomatis.
Selama pengujian, itu dipanggil
container.api_client.override()untuk mengganti klien API dengan tiruan. Saat dipanggil, main()dependensi Serviceakan mengumpulkan tiruan.
Fitur baru ini mempermudah penggunaan Dependency Injector dengan framework Python lainnya.
Bagaimana menghubungkan membantu berintegrasi dengan kerangka kerja lain?
Binding memungkinkan injeksi yang presisi terlepas dari struktur aplikasinya. Tidak seperti versi 3, injeksi ketergantungan tidak perlu menarik fungsi atau kelas ke dalam penampung.
Contoh dengan Flask:
import sys
from dependency_injector import containers, providers
from dependency_injector.wiring import Provide
from flask import Flask, json
class 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()
Contoh lain:
Bagaimana cara kerja penjilidan?
Untuk menerapkan penjilidan Anda perlu:
- .
Provide[Container.bar]. . - . container.wire(modules=[...], packages=[...]) , .
- . .
Pengikatan bekerja atas dasar introspeksi. Saat dipanggil,
container.wire(modules=[...], packages=[...])framework akan memeriksa semua fungsi dan metode dalam paket dan modul ini dan memeriksa parameter defaultnya. Jika parameter default adalah marker, maka fungsi atau metode seperti itu akan ditambal oleh dekorator injeksi ketergantungan. Dekorator ini, ketika dipanggil, menyiapkan dan menyuntikkan dependensi alih-alih penanda ke dalam fungsi aslinya.
def foo(bar: Bar = Provide[Container.bar]):
...
container = Container()
container.wire(modules=[sys.modules[__name__]])
foo() # <--- "bar"
# :
foo(bar=container.bar())
Pelajari lebih lanjut tentang menautkan di sini .
Kesesuaian?
Versi 4.0 kompatibel dengan versi 3.x.
Modul integrasi
ext.flaskdan ext.aiohttpdisematkan untuk mendukung bundling.
Saat digunakan, kerangka kerja akan menampilkan peringatan dan merekomendasikan beralih ke penautan.
Daftar lengkap perubahan dapat ditemukan di sini .
Apa berikutnya?
- Lihat Github proyek
- Lihat dokumentasinya