Coverage for tdom/scope.py: 100%
14 statements
« prev ^ index » next coverage.py v7.14.3, created at 2026-06-23 04:35 +0000
« prev ^ index » next coverage.py v7.14.3, created at 2026-06-23 04:35 +0000
1"""
2Scope and ScopedTemplate provide a low-level mechanism for tdom components
3to offer context-like functionality, allowing values to flow into nested
4children without requiring prop drilling.
6Under the hood, we build on top of Python's contextvars, because they are
7async and thread safe: valuable for integrations with just about
8any web framework out there.
10Example use:
12from typing import Literal
13from contextvars import ContextVar
15type Theme = Literal["auto", "light", "dark"]
16theme: ContextVar[Theme] = ContextVar("theme", default="auto")
18def ThemeProvider(children: Template, value: Theme) -> ScopedTemplate:
19 retrun ScopedTemplate(children, Scope(theme, value))
20"""
22import typing as t
23from contextlib import contextmanager
24from contextvars import ContextVar
25from dataclasses import dataclass
26from string.templatelib import Template
28__all__ = [
29 "Scope",
30 "ScopedTemplate",
31]
34@dataclass(frozen=True, slots=True)
35class Scope[T]:
36 """
37 A binding of a `ContextVar` to a value, activatable as a context manager.
38 """
40 cv: ContextVar[T]
41 value: T
43 @contextmanager
44 def activate(self) -> t.Generator[None]:
45 """Set `cv` to `value` for the duration of the block, then reset."""
46 with self.cv.set(self.value):
47 yield
50@dataclass(frozen=True, slots=True)
51class ScopedTemplate:
52 """
53 A `Template` bundled with the `Scope` that should be active while it
54 renders.
56 `tdom` components can return this type in place of a regular `Template`
57 to ensure that nested content has access to the appropriate values.
58 """
60 scope: Scope
61 template: Template