Coverage for tdom/scope.py: 100%

14 statements  

« 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. 

5 

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. 

9 

10Example use: 

11 

12from typing import Literal 

13from contextvars import ContextVar 

14 

15type Theme = Literal["auto", "light", "dark"] 

16theme: ContextVar[Theme] = ContextVar("theme", default="auto") 

17 

18def ThemeProvider(children: Template, value: Theme) -> ScopedTemplate: 

19 retrun ScopedTemplate(children, Scope(theme, value)) 

20""" 

21 

22import typing as t 

23from contextlib import contextmanager 

24from contextvars import ContextVar 

25from dataclasses import dataclass 

26from string.templatelib import Template 

27 

28__all__ = [ 

29 "Scope", 

30 "ScopedTemplate", 

31] 

32 

33 

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 """ 

39 

40 cv: ContextVar[T] 

41 value: T 

42 

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 

48 

49 

50@dataclass(frozen=True, slots=True) 

51class ScopedTemplate: 

52 """ 

53 A `Template` bundled with the `Scope` that should be active while it 

54 renders. 

55 

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 """ 

59 

60 scope: Scope 

61 template: Template