On Wed, Jan 17, 2018 at 8:53 PM, Yury Selivanov <yselivanov...@gmail.com> wrote: > On Wed, Jan 17, 2018 at 2:24 PM, Guido van Rossum <gvanros...@gmail.com> > wrote: >> Perhaps you can update the PEP with a summary of the rejected ideas from >> this thread? > > The Rejected Ideas section of the PEP is now updated with the below:
I've added two more subsections to Rejected Ideas: Make Context a MutableMapping ----------------------------- Making the ``Context`` class implement the ``abc.MutableMapping`` interface would mean that it is possible to set and unset variables using ``Context[var] = value`` and ``del Context[var]`` operations. This proposal was deferred to Python 3.8+ because of the following: 1. If in Python 3.8 it is decided that generators should support context variables (see :pep:`550` and :pep:`568`), then ``Context`` would be transformed into a chain-map of context variables mappings (as every generator would have its own mapping). That would make mutation operations like ``Context.__delitem__`` confusing, as they would operate only on the topmost mapping of the chain. 2. Having a single way of mutating the context (``ContextVar.set()`` and ``ContextVar.reset()`` methods) makes the API more straightforward. For example, it would be non-obvious why the below code fragment does not work as expected:: var = ContextVar('var') ctx = copy_context() ctx[var] = 'value' print(ctx[var]) # Prints 'value' print(var.get()) # Raises a LookupError While the following code would work:: ctx = copy_context() def func(): ctx[var] = 'value' # Contrary to the previous example, this would work # because 'func()' is running within 'ctx'. print(ctx[var]) print(var.get()) ctx.run(func) Have initial values for ContextVars ----------------------------------- Nathaniel Smith proposed to have a required ``initial_value`` keyword-only argument for the ``ContextVar`` constructor. The main argument against this proposal is that for some types there is simply no sensible "initial value" except ``None``. E.g. consider a web framework that stores the current HTTP request object in a context variable. With the current semantics it is possible to create a context variable without a default value:: # Framework: current_request: ContextVar[Request] = \ ContextVar('current_request') # Later, while handling an HTTP request: request: Request = current_request.get() # Work with the 'request' object: return request.method Note that in the above example there is no need to check if ``request`` is ``None``. It is simply expected that the framework always sets the ``current_request`` variable, or it is a bug (in which case ``current_request.get()`` would raise a ``LookupError``). If, however, we had a required initial value, we would have to guard against ``None`` values explicitly:: # Framework: current_request: ContextVar[Optional[Request]] = \ ContextVar('current_request', initial_value=None) # Later, while handling an HTTP request: request: Optional[Request] = current_request.get() # Check if the current request object was set: if request is None: raise RuntimeError # Work with the 'request' object: return request.method Moreover, we can loosely compare context variables to regular Python variables and to ``threading.local()`` objects. Both of them raise errors on failed lookups (``NameError`` and ``AttributeError`` respectively). Yury _______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com