Skip to content

inject.attr: Returned AbstractContextManager is already exited #116

@obs-gh-peterkolloch

Description

@obs-gh-peterkolloch

#96 added special handling for _GeneratorContextManagers to inject.attr.

I think the logic is faulty and/or is not very useful since it "exits" the context manager before even returning it.

The example that the author provided with version 5.3.0 outputs:

enter
exit
20

and thus demonstrates that the context manager returned by inject.attr is already exited before usage.

Looking at the implementation, this is not a surprise:

elif isinstance(inst, contextlib._GeneratorContextManager):
with contextlib.ExitStack() as sync_stack:
inst = sync_stack.enter_context(inst)

A new ExitStack is created, used with with which implicitly class __enter__/__exit__ before returning the new instance. Potentially the author thought that this is about exiting the Python program because of the potentially misleading name?

Anyways, that would also not be a good option since that would hold onto the instance and prevent its garbage collection.

After a quick brainstorming, I could think of the following options:

  1. 🥇 remove the special logic for AbstractContextManager -- the caller of inject.attr must call enter/exit the context appropriately.
  2. Instead of contextlib.ExitStack() use inject.instance(ExitStack). That way one can manage a "global" ExitStack and exit at the appropriate time. I don't like that too much, because again, one would have to close and remove the ExitStack to get rid of the instance.

What do you think? In the meantime, I'll work around this in wrapping the context managers so that they are not recognized as context managers anymore.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions