Last active
July 1, 2022 12:55
-
-
Save justcallmelarry/7d68467ddbafd960ff8ab13d31d86928 to your computer and use it in GitHub Desktop.
context class with dynamic descriptor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import annotations | |
from contextvars import ContextVar | |
from typing import Callable, Generic, Type, TypeVar, Union | |
_CONTEXT: ContextVar[dict] = ContextVar("custom_context") | |
T = TypeVar("T") | |
class Descriptor(Generic[T]): | |
def __init__(self, *, default: Union[T, Callable[[], T]]) -> None: | |
self._default = default | |
def __set_name__(self, owner: Type[object], name: str) -> None: | |
"""Magic setter that just works""" | |
self._name = name | |
def __get__(self, instance: object, owner: Type[object]) -> T: | |
data = _CONTEXT.get({}) | |
if self._name in data: | |
return data.get(self._name, self._default) | |
if callable(self._default): | |
# run once | |
value = self._default() | |
# set default and context to generated value | |
self._default = value | |
self.__set__(instance, value) | |
return value | |
return self._default | |
def __set__(self, instance: object, value: T) -> None: | |
data = _CONTEXT.get({}) | |
data[self._name] = value | |
_CONTEXT.set(data) | |
class SomeClass: | |
bool_one = Descriptor[bool](default=False) | |
bool_two = Descriptor[bool](default=False) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment