一个小的依赖注入容器,从php的pimple移植过来
scute的Python项目详细描述
浮渣
scute是python 3.6+的一个小型依赖注入容器,从php的Pimple移植而来,它包括 只有一个文件和一个类(大约100行代码)。
测试套件,甚至这个自述文件,基本上都是Pimple的拷贝粘贴,只对Python进行了轻微的修改 还有一些像injections management through decorators这样的python加法。
所以所有的荣誉都归于Fabien Potencier和粉刺贡献者!
从pypi安装:
$ pip install scute
然后将其导入到您的代码中,您就可以开始了:
fromscuteimportContainer
创建容器就是设置Container
类:
container=Container()
与许多其他依赖注入容器一样,scute能够管理两个 不同类型的数据:services和parameters。
(请注意,快速查看the test suite也可以很好地概述此模块的功能)
定义参数
定义参数就像使用scute实例作为数组一样简单:
# define some parameterscontainer['cookie_name']='SESSION_ID'container['session_storage_class']='SessionStorage'
定义服务
服务是作为更大系统的一部分执行某些操作的对象。 服务示例:数据库连接、模板引擎、mailer。几乎 任何对象都可以是服务。
服务由返回 对象:
#define some servicesdefsession_storage(c:Container):session_storage_class_ref=getattr(importlib.import_module('app'),c['session_storage_class'])returnsession_storage_class_ref(c['cookie_name'])container['session_storage']=session_storagecontainer['session']=labmdac:newSession(c['session_storage'])
注意,该函数可以访问当前容器 实例,允许引用其他服务或参数。
由于只有在获得对象时才创建对象,因此定义的顺序 不要紧,也没有表演惩罚。
使用定义的服务也非常简单:
# get the session objectsession=container['session']# the above call is roughly equivalent to the following code:# storage = app.SessionStorage('SESSION_ID')# session = Session(storage)
定义工厂服务
默认情况下,每次获得服务时,scute都返回它的相同实例。
如果要为所有调用返回不同的实例,请使用factory()
方法包装您的可调用实例:
container['session']=container.factory(lambdac:newSession(c['session_storage'])
现在,对container['session']
的每个调用都返回会话的一个新实例。
保护参数
因为scute将可调用项视为服务定义,所以您需要
用protect()
方法包装匿名函数,将其存储为
参数:
container['random']=container.protect(lambda:randrange(10000))
创建后修改服务
在某些情况下,您可能希望在服务定义
定义。您可以使用extend()
方法来定义
在服务创建后立即运行:
container['mail']=lambdac:MailjetApi(user=c['email.user'],password=['email.password'])defextended_email(mail,c:Container):mail.set_from(c['mail.default_from'])returnmailcontainer.extend('mail',extended_email)
第一个参数是对象的名称,第二个参数是 获取对对象实例和容器的访问权限。返回值为 服务定义,因此需要在容器上重新分配它。
获取服务创建函数
当你访问一个对象时,scute会自动调用callable(函数,lambda,callable类…)
您定义的,它为您创建服务对象。如果你想得到
原始访问此函数,可以使用raw()
方法:
session_function=container.raw('session')
使用装饰器管理注射
还可以使用decorator管理可调用的依赖项,方法是bind_callable()
并设置依赖项以通过依赖项id的元组注入:
@container.bind_callable(('mailer','signal'))# 'mailer' and 'signal' are injections defined somewhere else on this Containerdefsend_email(mailer:Mailer,email_sent_signal:Signal):mailer.send_email(config)email_sent_signal.send()
但是,如果您添加injection_id
参数,这个可调用的也将是服务本身!
@container.bind_callable(('config','mailer','signal'),injection_id='app_mailer')defapp_mailer(config:tuple,mailer:Mailer,signal:Signal):mailer.add_config(config)mailer.set_signal(signal)returnmailer# your container now has a new 'app_mailer' service, that can be injected into other services :-)