wired API
- class wired.ServiceContainer(factories, cache=None, context=None)[source]
A service container is used to create service instances.
Create a container via
wired.ServiceRegistry.create_container().A container controls creating services from the registered factories. Services are cached based on their registration constraints and re-used when possible based on the context and requested interface.
- get(iface_or_type=<InterfaceClass zope.interface.Interface>, *, context=<default>, name='', default=<default>)[source]
Find a cached instance or create one from the registered factory.
The instance is found using the following algorithm:
Find an instance matching the criteria in the container. If one is found, return it directly.
Search for a factory, first in the container and second on the service registry. If one is not found, raise a
LookupErroror, if specified, returndefault.Invoking the factory, cache the result in the container for later lookups, and return the result.
- Parameters:
iface_or_type – The registered service interface.
context – A context object. This object will be available as
container.contextin the invoked service factories and will influence which factories are matched. Defaults to the boundcontexton the container.name (str) – The registered name of the service.
default – A service instance to return if lookup fails.
- register_factory(factory, iface_or_type=<InterfaceClass zope.interface.Interface>, *, context=None, name='')[source]
Register a service factory.
This factory will override any lookups defined in the service registry. Otherwise the semantics are identical to
ServiceRegistry.register_factory().
- register_singleton(service, iface_or_type=<InterfaceClass zope.interface.Interface>, *, context=None, name='')[source]
Register a singleton instance.
Functionally, the singleton is wrapped in a factory that always returns the same instance when invoked. See
ServiceRegistry.register_factory()for information on the parameters.
- set(service, iface_or_type=<InterfaceClass zope.interface.Interface>, *, context=<default>, name='')[source]
Add a service instance to the container.
Upon success,
servicewill be returned for matching lookups on the same context.If this service registration would affect a previously-cached lookup then it will raise a
ValueError.- Parameters:
service – A service instance to cache.
iface_or_type – A class or
zope.interface.Interfaceobject defining the interface of the service. Defaults tozope.interface.Interfaceto match any requested interface.context – A context object. The
serviceinstance will be cached for any later lookups using this context. Defaults to the boundcontexton the container.name (str) – An identifier for the service.
- class wired.ServiceRegistry(factory_registry=None)[source]
A service registry contains service factory definitions.
Define the tree of services your application needs once at config-time. Later, per operation, invoke
create_container()to create a new service container which can be used to lazily instantiate service objects on-demand.Using this pattern, your code now depends on the container and your service interfaces. You are now programming to an interface, not to a specific implementation. It is now trivial to register a different factory to mock out, or replace, specific service implementations in tests or for any other purposes.
- create_container(*, context=None)[source]
Create a new
ServiceContainerlinked to the registry.A container will use all the registered service factories, independently of any other containers, in order to find and instantiate service objects.
Practically, a new container should be derived per logical “operation”. An operation is something like a web request, job, transaction, etc.
- Parameters:
context – The container will be bound to a different context object, affecting which factories are selected. By default, the container is bound to the
Nonecontext.
- find_factory(iface_or_type=<InterfaceClass zope.interface.Interface>, *, context=None, name='')[source]
Return the factory registered for the given parameters.
The arguments are the same as those used in
register_factory().- Returns:
The registered factory (or singleton wrapper) or
Noneif a factory cannot be found satisfying the constraints.
- register_factory(factory, iface_or_type=<InterfaceClass zope.interface.Interface>, *, context=None, name='')[source]
Register a service factory.
A factory should accept a single parameter which will be a
ServiceContainerinstance. The factory should not be bound to any particular container and should use the one passed in to find service dependencies.A factory can be registered for a particular type or interface, with more specific factories allowed per type of
contextor bynamestring.It is recommended to register factories using types/interfaces instead of named strings, as they avoid naming clashes between independently defined components/features. Types are always unique and are better at expressing intent and contracts.
An example service factory:
def login_factory(container): dbsession = container.get(name='dbsession') return LoginService(dbsession)
Notice in the above example that the
login_factoryrequires another service nameddbsessionto be registered which triggers a recursive lookup for that service in order to create theLoginServiceinstance.It is not required that the returned service actually implements, or is a subclass, of the defined
iface.- Parameters:
factory – A factory is a callable that accepts a container argument and returns an instance of the service. Specifically,
factory(services: ServiceContainer) -> iface.iface_or_type – A class or
zope.interface.Interfaceobject defining the interface of the service. Defaults tozope.interface.Interfaceto match any requested interface.context – A class or
zope.interface.Interfaceobject defining the type ofcontextrequired in order to use the factory. Defaults toNone.name (str) – An identifier for the service. A factory can be registered for an
iface_or_typeor anameor both, but aniface_or_typeis recommended for most services.
- register_singleton(service, iface_or_type=<InterfaceClass zope.interface.Interface>, *, context=None, name='')[source]
Register a singleton instance.
The singleton is global to all containers created from this registry. Any container created by this registry will receive the same instance.
Functionally, the singleton is wrapped in a factory that always returns the same instance when invoked. See
register_factory()for information on the parameters.
- class wired.service_factory(for_=None, context=None, name: str = '')[source]
Register a factory for a class that can sniff dependencies.
The factory will be registered with a
wired.ServiceRegistrywhen performing a venusian scan.
wired.dataclasses API
- wired.dataclasses.register_dataclass(registry: ServiceRegistry, target, for_=None, context=None, name='')[source]
Register a factory for a dataclass that can sniff dependencies.
from sqlalchemy.orm import Session @dataclass class LoginService: db: Session registry = ServiceRegistry() register_dataclass(registry, LoginService) # ... later container = registry.create_container() svc = container.get(LoginService)
- Parameters:
for – By default,
targetis used as the service type. This can be used to override theiface_or_typeargument inwired.ServiceRegistry.register_factory()to some other type.context – The
contextargument inwired.ServiceRegistry.register_factory().name (str) – The
nameargument inwired.ServiceRegistry.register_factory().
- wired.dataclasses.factory(for_=None, context=None, name: str = '')[source]
Register a factory for a dataclass that can sniff dependencies.
The factory will be registered with a
wired.ServiceRegistrywhen performing a venusian scan.from sqlalchemy.orm import Session @factory @dataclass class LoginService: db: Session # ... later registry = ServiceRegistry() scanner = venusian.Scanner(registry=registry) scanner.scan() # ... later container = registry.create_container() svc = container.get(LoginService)
- wired.dataclasses.singleton(for_=None, context=None, name: str = '')[source]
Register an instance of a dataclass as a singleton.
The singleton will be registered with a
wired.ServiceRegistrywhen performing a venusian scan.@singleton @dataclass class Settings: punctuation: str = ''
- wired.dataclasses.injected(iface_or_type=<InterfaceClass zope.interface.Interface>, *, name='', attr=None, **kwargs) Field[source]
Customize how the field is populated from the generated factory.
If just the field type is insufficient, this descriptor can be used to more explicitly define how the field in the dataclass should be populated from the
wired.ServiceContainer.- Parameters:
iface_or_type – The
iface_or_typeargument inwired.ServiceContainer.get().name (str) – The
nameargument inwired.ServiceContainer.get().attr (str) – An attribute on the returned service object.
All other kwargs are forwarded directly into
dataclasses.field().