Skip to content

Lazy Provider #203

@xelandernt

Description

@xelandernt

Discussed in #201

Originally posted by JCHacking October 10, 2025
I have the following use case:

# ip.py
from that_depends import BaseContainer, ContextScopes, fetch_context_item, providers

from project import IpReader, IpDelete, FirewallContainer

class IpContainer(BaseContainer):
    reader: providers.Singleton[IpReader] = providers.Singleton(IpReader)
    
    delete: providers.Singleton[IpDelete] = providers.Singleton(IpDelete, reader=reader.cast, firewall_reader=FirewallContainer.reader.cast)
# firewall.py
from that_depends import BaseContainer, ContextScopes, fetch_context_item, providers

from project import FirewallReader, FirewallDelete, IpContainer

class FirewallContainer(BaseContainer):
    reader: providers.Singleton[FirewallReader] = providers.Singleton(FirewallReader)
    
    delete: providers.Singleton[FirewallDelete] = providers.Singleton(FirewallDelete, reader=reader.cast, ip_reader=IpContainer.reader.cast)

This generates a circular import, but if instead of doing it directly I do something like this:

# ip.py
from that_depends import BaseContainer, ContextScopes, fetch_context_item, providers

from project import IpReader, IpDelete, FirewallReader

async def _firewall_reader() -> FirewallReader:
    from project import FirewallContainer
    return await FirewallContainer.reader()


class IpContainer(BaseContainer):
    reader: providers.Singleton[IpReader] = providers.Singleton(IpReader)
    
    firewall_reader: providers.Singleton[FirewallReader] = providers.Singleton(_firewall_reader)
    
    delete: providers.Singleton[IpDelete] = providers.Singleton(IpDelete, reader=reader.cast, firewall_reader=firewall_reader.cast)

The other file a similar change

Could something like a lazy provider be created to do this?

For example, specifying it like this:

delete: providers.Singleton[IpDelete] = providers.Singleton(IpDelete, reader=reader.cast, firewall_reader=LazyProvider(“project.FirewallContainer.firewall_reader”).cast)

It would be good to have a way to avoid always importing containers for cases like these, where both depend on each other due to system requirements.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestv3Relevant to version 3.*

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions