On 4/22/06, Nick Coghlan <[EMAIL PROTECTED]> wrote: > Alternatively, I could have a go at clearing it up for next week's alpha2, and > we can ask Anthony to make an explicit request for review of those docs in the > announcement. . .
I've just had a *very* quick scan through the 2.5a1 documentation. I did not look at the PEP, just the official documentation. I've been reading the messages going round on the subject, but I'm getting pretty confused, so I'd still count myself as "unprejudiced"... :-) My immediate reaction was that the docs make reasonable sense: - a context is a thing with enter/exit methods (a block of code is "in" a context) - the with statement delimits the block which is in a context - the with statement asks a context manager for the context in which the block runs - context managers have __context__ methods to produce contexts (they manage the production of explicit context objects) The contextlib.contextmanager decorator starts off looking fine as well: @contextmanager def tag(name): print "<%s>" % name yield print "</%s>" % name Yes, that's a context manager - you pass it to a with statement: >>> with tag("h1"): ... print "foo" ... <h1> foo </h1> But then things go wrong: class Tag: def __init__(self, name): self.name = name @contextmanager def __context__(self): print "<%s>" % self.name yield self print "</%s>" % self.name h1 = Tag("h1") That's bizarre: __context__ isn't the context manager I'm trying to create - those are the instances of Tag. I think this is where the terminology comes unstuck, and it's simply because this is an "abuse" (a bit strong, that - bear with me) of the contextmanager decorator. The thing is, __context__ should be *a function which returns a context*. But we defined it with the decorator as a context manager - an object whose __context__ method produces a context! It works, because context managers produced by the decorator return themselves - that is, they are both context managers and contexts....... No, I just got lost. BUT - the point is that everything was fine until the point where the __context__ method got defined using @contextmanager. Maybe all we need is to have *two* decorators - @context to generate a context (this would be @contextmanager but without the __context__ method) and @contextmanager as now (actually, it only needs the __context__ method - the __enter__ and __exit__ methods are only present to allow the trick of returning self from __context__). Then, the definitions are easy: context manager - has __context__ producing a context context - has __enter__ and __exit__ methods, used by the with statement Things with all 3 methods are just a convenience trick to avoid defining 2 objects - there's no *need* for them (unlike iterators, where "iter(it) is it" is an important defining characteristic of an iterator over an iterable). So my proposal: - use the definitions above - modify contextlib to have 2 decorators - @contextmanager producing a context manager, and @context producing a context. They can be the same under the hood, using an object that defines all 3 methods, but that's just an implementation detail (trick) - amend the documentation of the Tag example in the contextlib docs to use the @context decorator. - tidy up the PEP to reflect this approach Or alternatively, I'm just confused, like the rest of you :-) Paul. _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com