Hagen Fürstenau wrote:
I'm proposing to add an iterator version of "nested" to contextlib (possibly called "inested"), which takes an iterable of context managers instead of a variable number of parameters. The implementation could be taken over from the present "nested", only changing "def nested(*managers)" to "def inested(managers)".
This has the advantage that an iterator can be passed to "inested", so that each context managers is created in the context of all previous ones, which was one of the reasons for introducing the multi-with statement in the first place. "contextlib.inested" would therefore be the generalization of the multi-with statement to a variable number of managers (and "contextlib.nested" would stay deprecated).
The semantic change actually needed to make nested() more equivalent to the multi-with statement is for it to accept zero-argument callables that create context managers as arguments rather than pre-created context managers. Rather than changing the name of the function, this could be done by inspecting the first argument for an "__enter__" method. If it has one, use the old semantics (and issue a DeprecationWarning as in 3.1). Otherwise, use the proposed new semantics. However, the semantic equivalence still won't be complete as nested() currently has no way of matching the multi-with behaviour of allowing outer context managers to suppress exceptions raised by the constructors or __enter__ methods of inner context managers. Attempting to do so will result in a RuntimeError as the contextlib.contextmanager wrapper complains that the generator implementing nested() didn't yield. The further enhancement needed to address that would be to tweak nested() to raise a custom exception in that case (e.g. ContextSkipped) and provide an "allowskip" context manager that just catches and suppresses that specific exception: i.e. @contextmanager def allowskip(): try: yield except ContextSkipped: pass with allowskip(), nested(*cm_factories): # Do something I suggest putting an RFE on the tracker for this. Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia ---------------------------------------------------------------