question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Make Closing marker working with providers that contains a resource as argument

See original GitHub issue

Hi!

Is it possible to make the Closing marker work with all types providers that contain a resource inside? For example, in the following code, the Closing marker does not work:

# handlers
@inject
async def create_project(
    request: web.Request,
    project_repository: ProjectRepository = Closing[Provide[Container.project_repository]],
) -> web.Response:
    ....
# di
class Container(containers.DeclarativeContainer):
    db_session = providers.Resource(get_session, database=db)
    project_repository = providers.Factory(
        ProjectRepository,
        session=db_session
    )

At this moment it will work if we add a separate resource argument to handler:

@inject
async def create_project(
    request: web.Request,
    project_repository: Session = Closing[Provide[Container.db_session]],
    project_repository: ProjectRepository = Closing[Provide[Container.project_repository]],
) -> web.Response:
    ....

Issue Analytics

  • State:closed
  • Created a year ago
  • Reactions:1
  • Comments:6 (4 by maintainers)

github_iconTop GitHub Comments

3reactions
StummeJcommented, Nov 15, 2022

@kiriharu until it’s merged, it can be monkey patched with the following code

from typing import Any, Callable
from dependency_injector import providers, wiring
from dependency_injector.wiring import ProvidersMap, _patched_registry, Provide, Provider

# This backports/monkeypatches the dependency injector to allow `Closing` on dependent resources.
# It is extremely important that it is imported BEFORE dependency_injector is used. This can be
# removed once https://github.com/ets-labs/python-dependency-injector/pull/636 is merged and released.

def _locate_dependent_closing_args(provider: providers.Provider) -> dict[str, providers.Provider]:
    if not hasattr(provider, "args"):
        return {}

    closing_deps = {}
    for arg in provider.args:
        if not isinstance(arg, providers.Provider) or not hasattr(arg, "args"):
            continue

        if not arg.args and isinstance(arg, providers.Resource):
            return {str(id(arg)): arg}
        else:
            closing_deps += _locate_dependent_closing_args(arg)
    return closing_deps


def _bind_injections(fn: Callable[..., Any], providers_map: ProvidersMap) -> None:
    patched_callable = _patched_registry.get_callable(fn)
    if patched_callable is None:
        return

    for injection, marker in patched_callable.reference_injections.items():
        provider = providers_map.resolve_provider(marker.provider, marker.modifier)

        if provider is None:
            continue

        if isinstance(marker, Provide):
            patched_callable.add_injection(injection, provider)
        elif isinstance(marker, Provider):
            if isinstance(provider, providers.Delegate):
                patched_callable.add_injection(injection, provider)
            else:
                patched_callable.add_injection(injection, provider.provider)

        if injection in patched_callable.reference_closing:
            patched_callable.add_closing(injection, provider)
            deps = _locate_dependent_closing_args(provider)
            for key, dep in deps.items():
                patched_callable.add_closing(key, dep)

wiring._bind_injections = _bind_injections
2reactions
rmk135commented, Dec 19, 2022

Amazing feature! Thanks to everybody involved and special thanks to @StummeJ for the PR!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Resource provider - Dependency Injector
Resource provider provides a component with initialization and shutdown. It works well for configuring logging, event loop, thread or process pool, etc.
Read more >
Resource leak: 'in' is never closed - java - Stack Overflow
above line will invoke Constructor of Scanner class with argument System.in, and will return a reference to newly constructed object. It is connected...
Read more >
The Resource provider Meta-Argument - HashiCorp Developer
The provider meta-argument specifies the provider configuration Terraform should use for a resource, overriding Terraform's default behavior.
Read more >
Marker | Maps JavaScript API - Google Developers
Creates a marker with the options specified. If a map is specified, the marker is added to the map upon construction. Note that...
Read more >
6. Resources - Spring
The Resource abstraction is used extensively in Spring itself, as an argument type in many method signatures when a resource is needed.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found