[Python-Dev] Why are contexts also managers? (was r45544 - peps/trunk/pep-0343.txt)

Nick Coghlan ncoghlan at gmail.com
Fri Apr 21 11:31:35 CEST 2006


Guido van Rossum wrote:
> Sorry Nick, but you've still got it backwards. The name of the
> decorator shouldn't indicate the type of the return value (of calling
> the decorated generator) -- it should indicate how we think about the
> function. Compare @staticmethod and @classmethod -- the return type
> doesn't enter into it. I think of the function/generator itself as the
> context manager; it returns a context.

Let me have another go. . .

One of the proposals when Raymond raised the issue of naming the PEP 343 
protocol was to call objects with "__enter__"/"__exit__" methods "contexts". 
This was rejected because there were too many things (like decimal.Context) 
that already used that name but couldn't easily be made to fit the new 
definition. So we settled on calling them "context managers" instead.

This wasn't changed by the later discussion that introduced the __context__ 
method. Instead, the new term "manageable context" (or simply "context") was 
introduced to mean "anything with a __context__ method". This was OK, because 
existing context objects like decimal.Context could easily add a context 
method to return an appropriate context manager.

Notice that in *both* approved versions of PEP 343 (before and after the 
inclusion of the __context__ method) the name of the decorator matched the 
name of the kind of object returned by the decorated generator function.

*THIS ALL CHANGED AT PYCON* (at least, I assume that's where it happened - it 
sure didn't happen on this list, and the timing is about right).

During implementation, the meanings of "context" and "context manager" were 
swapped from the meanings in the approved PEP, leading to the current 
situation where decimal.Context is actually not, in fact, a context. These 
meanings were then the ones included in the checked in documentation for 
contextlib, and in PJE's recent update to PEP 343 itself.

However, *despite* the meanings of the two terms being swapped, the decorator 
kept the same name. This means that when using a generator to create a 
"context manager" like decimal.Context under the revised terminology, you are 
forced to claim that the __context__ method is itself a context manager:

   class Context(object):
      # Actually a context manager, despite the class name

      @contextlib.contextmanager
      def __context__(self):
          # Actually a context, despite the decorator name
          newctx = self.copy()
          oldctx = decimal.getcontext()
          decimal.setcontext(newctx)
          try:
              yield newctx
          finally:
              decimal.setcontext(oldctx)

I also note that the decimal module in 2.5a1 actually uses the originally 
approved PEP 343 terminology, calling the object returned from __context__ a 
ContextManager.

And all of this is why I believe we need to either fix the documentation to 
use the terminology used in the PEP at the time of approval, or else finish 
the job of swapping the two terms and change the name of the decorator. Having 
remembered why we picked "context manager" over "context" in the first place, 
my preference is strongly for reverting to the original terminology.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
---------------------------------------------------------------
             http://www.boredomandlaziness.org


More information about the Python-Dev mailing list