Skip to content

Exception information isn't passed through to context.with_resource managed resources #2447

@brianm78

Description

@brianm78

When writing a simple tool with a bunch of commands updating a database, I was using a context manager in each command that would begin a transaction, and then commit it on success, or rollback on error.

Initially, I thought I'd be able to avoid some boilerplate on every subcommand by adding the session as a managed resource via ctx.with_resource(context_manager). However, while this works in the success case, it will also commit the transaction if an unexpected exception occurs, since the exception information doesn't seem to be being passed through to the context manager.

Eg. given the below context manager:

class TestContextManager:
    def __enter__(self):
        print("ENTER")

    def __exit__(self, exc_type, exc_val, traceback):
        print("EXIT", exc_type, exc_val, traceback)

Using it in a regular context manager via:

with TestContextManager():
    raise Exception()

will correctly print the exc_type, exc_val and traceback parameters when an exception occurs. But using it via:

@click.group()
@click.pass_context
def cli(ctx):
    ctx.obj = ctx.with_resource(TestContextManager())

These will always be None, and so any context manager that needs to act differently on the occurrence of an exception vs success will always treat this as success. (And likewise, try/except blocks will never trigger in function-style ones using the @contextmanager decorator.)

Would it be possible for the exception information to be passed through to managed resources so that context managers that treat success/failure cases differently operate correctly?

Environment:

  • Python version: 3.10.9
  • Click version: 8.1.3

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions