On 25 October 2016 at 03:32, Chris Barker <chris.bar...@noaa.gov> wrote:
> On Sat, Oct 22, 2016 at 8:22 PM, Nick Coghlan <ncogh...@gmail.com> wrote:
>> The big refactoring benefit that this feature would offer over with
>> statements is that it doesn't require a structural change to the code
>> - it's just wrapping an existing expression in a new function call
>> that says "clean this up promptly when the function terminates, even
>> if it's still part of a reference cycle, or we're not using a
>> reference counting GC".
>
> hmm -- that would be simpler in one sense, but wouldn't it require a new
> function to be defined for everything you might want to do this with? rather
> than the same "with" syntax for everything?

Nope, hence the references to contextlib.ExitStack:
https://docs.python.org/3/library/contextlib.html#contextlib.ExitStack

That's a tool for dynamic manipulation of context managers, so even
today you can already write code like this:

  >>> @with_resource_manager
  ... def example(rm, *, msg=None, exc=None):
  ...     rm.enter_context(cm())
  ...     rm.callback(print, "Deferred callback")
  ...     if msg is not None: print(msg)
  ...     if exc is not None: raise exc
  ...
  >>> example(msg="Normal return")
  Enter CM
  Normal return
  Deferred callback
  Exit CM
  >>> example(exc=RuntimeError("Exception thrown"))
  Enter CM
  Deferred callback
  Exit CM
  Traceback (most recent call last):
    ...
  RuntimeError: Exception thrown

The setup code to support it is just a few lines of code:

  >>> import functools
  >>> from contextlib import ExitStack
  >>> def with_resource_manager(f):
  ...     @functools.wraps(f)
  ...     def wrapper(*args, **kwds):
  ...         with ExitStack() as rm:
  ...             return f(rm, *args, **kwds)
  ...     return wrapper
  ...

Plus the example context manager definition:

  >>> from contextlib import contextmanager
  >>> @contextmanager
  ... def cm():
  ...     print("Enter CM")
  ...     try:
  ...         yield
  ...     finally:
  ...         print("Exit CM")
  ...

So the gist of my proposal (from an implementation perspective) is
that if we give frame objects an ExitStack instance (or an operational
equivalent) that can be created on demand and will be cleaned up when
the frame exits (regardless of how that happens), then we can define
an API for adding "at frame termination" callbacks (including making
it easy to dynamically add context managers to that stack) without
needing to define your own scaffolding for that feature - it would
just be a natural part of the way frame objects work.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncogh...@gmail.com   |   Brisbane, Australia
_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to