I had a similar recent need, with a bit more on top of it, and solved it with this slightly insane library. (Alas, I haven't figured out a good way to make it act as a true subtype of UnderlyingType yet)
import contextvars from typing import Any, Generic, TypeVar UnderlyingType = TypeVar('UnderlyingType') class DuckTypeContextVar(Generic[UnderlyingType]): """A DuckTypeContextVar takes contextvars.ContextVar to the next level: It duck-type emulates the underlying variable. This means you can do something like sys.stdout = DuckTypeContextVar('stdout', sys.stdout) token = sys.stdout.setLocalValue(myFile) .... sys.stdout.resetLocalValue(token) """ def __init__(self, name: str, value: UnderlyingType) -> None: self._value = contextvars.ContextVar(name, default=value) def getLocalValue(self) -> UnderlyingType: return self._value.get() def setLocalValue(self, value: UnderlyingType) -> contextvars.Token: return self._value.set(value) def resetLocalValue(self, token: contextvars.Token) -> None: self._value.reset(token) def __getattr__(self, attr: str) -> Any: return getattr(self._value, attr) On Wed, Jun 5, 2019 at 6:14 PM Yury Selivanov <yselivanov...@gmail.com> wrote: > On Wed, Jun 5, 2019 at 6:22 PM Christoph Groth <christ...@grothesque.org> > wrote: > [..] > > I'm aware of this possibility, however it is not suitable for the use > > case that I have in mind (configuration variables), because it requires > > too much code for each variable. > > > > Of course one could wrap your example inside a factory function, but > > that's unwieldy as well, since it requires keeping track of one context > > manager for each context variable: > > I suggest you to open an issue on bugs.python.org to implement support > for context manager protocol for contextvars.Token. I'm not opposed > to the idea. Keep in mind that Python 3.8 is already in a feature > freeze mode, so the earliest we can get this is Python 3.9. > > > By the way, contexts being implemented as immutable dictionaries implies > > one copy of a dictionary per call to the set method. That in turn means > > that using hundreds of context variables (a large library could easily > > have that many configuration variables) might not be a good idea. Is > > this correct? > > The contextvars module uses a special dictionary implementation (read > more on that in PEP 567/550) with its ".set()" operation only slightly > slower than updating a standard Python dict. Setting/resetting N > context variables is about 1.5x slower than mutating a Python dict N > times. In short, it's a fast operation by Python standards. > > > > > A final, unrelated comment: I find the use of the word "context" in the > > standard library for both context managers and context variables (and > > related to them "contexts") needlessly confusing. I suggest clearly > > explaining their independence at the top of the documentation of either > > module. > > Pull requests to improve the docs are always welcome! > > Yury > Python-Ideas mailing list -- python-dev(a)python.org > To unsubscribe send an email to python-ideas-leave(a)python.org > https://mail.python.org/mailman3/lists/python-ideas.python.org/ >
Python-Ideas mailing list -- python-dev(a)python.org To unsubscribe send an email to python-ideas-leave(a)python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/