[docs]classService(BaseConfigurable):"""A settings base class for service definitions."""model_config=ConfigDict(extra="allow")#: Base type for service definition. This is not usually the base interface that the service implements, and you#: should use the `type` field to override the actually instanciated type.base:Optional[str]=Field(default=None,description="Base type for service definition.")#: Type for service definition. This is the actual type that will be instanciated.type:Optional[str]=Field(default=None,description="Type for service definition.")#: Constructor for service definition. If provided, will be used instead of the default constructor.constructor:Optional[str]=Field(default=None,description="Optional custom constructor for the service.")#: Arguments for the service constructor, by name.arguments:Optional[dict]=Field(default_factory=dict,description="Arguments for the service constructor.")@model_validator(mode="before")@classmethoddef__validate(cls,values):"""Use extra fields as arguments."""arguments=values.get("arguments",{})forkinlist(values.keys()):ifknotincls.model_fields:ifstr.isidentifier(k)andnotiskeyword(k):arguments[k]=values.pop(k)else:raiseValueError(f"Invalid field name: {k} for {cls.__name__}")iflen(arguments):return{**values,"arguments":arguments}returnvalues@model_serializer(mode="wrap")def__serialize(self,wrapped,context):"""Enhance serialization logic to inline arguments, unless they conflict with a model field."""data=wrapped(self,context)arguments=data.pop("arguments",{})inline_arguments={}forkinlist(arguments.keys()):ifknotintype(self).model_fields:inline_arguments[k]=arguments.pop(k)forkin("base","type","constructor"):ifkindataanddata[k]isNone:data.pop(k)return{**data,**({"arguments":arguments}iflen(arguments)else{}),**inline_arguments,}
[docs]defto_service_definition(self,name:str,lifestyle:Optional[Literal["singleton","transient","scoped"]]="singleton")->ServiceDefinition:"""Convert the service settings to a service definition."""returnServiceDefinition(name=name,base=self.base,type=self.type,constructor=self.constructor,arguments=self.arguments,lifestyle=lifestyle,)
[docs]classLazyService(BaseConfigurable):"""A lazy service definition, that will be resolved at runtime."""type:str|list[str]=Field(...,description="Reference to the service to resolve at runtime.")
[docs]defresolve(self,resolver,context):""" Resolve reference value in using the given resolver (callable) and resolution context. """returnresolver(self.type,context)
@model_serializer(mode="wrap")def__serialize(self,wrapped,context):"""Enhance serialization logic to inline arguments, unless they conflict with a model field."""returnwrapped(self,context)