Skip to content

Instantly share code, notes, and snippets.

@justcallmelarry
Last active July 1, 2022 12:55
Show Gist options
  • Save justcallmelarry/7d68467ddbafd960ff8ab13d31d86928 to your computer and use it in GitHub Desktop.
Save justcallmelarry/7d68467ddbafd960ff8ab13d31d86928 to your computer and use it in GitHub Desktop.
context class with dynamic descriptor
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