Skip to content

Commit cde7ba9

Browse files
committed
refactor: Replace extra context loader with closure
1 parent 95a7362 commit cde7ba9

4 files changed

Lines changed: 55 additions & 35 deletions

File tree

src/sphinxnotes/render/ctxnodes.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
UnresolvedContext,
1313
ResolvedContext,
1414
)
15-
from .extractx import ExtraContextLoader
15+
from .extractx import ExtraContextRequest, build_load_extra, extra_context_names
1616
from .markup import MarkupRenderer
1717
from .jinja import TemplateRenderer
1818
from .utils import (
@@ -132,15 +132,15 @@ def err_report() -> Report:
132132
report.text(f'Template (phase: {self.template.phase}):')
133133
report.code(self.template.text, lang='jinja')
134134

135-
extras = ExtraContextLoader(self, host)
135+
extra_request = ExtraContextRequest(self.template.phase, self, host.env, host)
136136
report.text('Available extra context names:')
137-
report.code(pformat(sorted(extras.names())), lang='python')
137+
report.code(pformat(sorted(extra_context_names())), lang='python')
138138

139139
# 2. Render the template and context to markup text.
140140
try:
141141
markup = TemplateRenderer(self.template.text).render(
142142
ctx,
143-
globals_={'load_extra': extras.load},
143+
globals={'load_extra': build_load_extra(extra_request)},
144144
debug=self.template.debug,
145145
)
146146
except Exception as e:

src/sphinxnotes/render/extractx.py

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,13 @@
1515

1616
@dataclass(frozen=True)
1717
class ExtraContextRequest:
18+
#: The render phase of the current template.
1819
phase: Phase
20+
#: The pending node being rendered.
1921
node: pending_node
22+
#: The current Sphinx build environment.
2023
env: BuildEnvironment
24+
#: The current render host.
2125
host: SphinxDirective | SphinxRole | SphinxTransform
2226

2327

@@ -68,39 +72,19 @@ def decorator(cls):
6872
return decorator
6973

7074

71-
# ========================
72-
# Extra Context Generation
73-
# ========================
75+
def extra_context_names() -> set[str]:
76+
return _REGISTRY.get_names()
7477

7578

76-
class ExtraContextLoader:
77-
node: pending_node
78-
request: ExtraContextRequest
79-
cache: dict[str, Any]
80-
81-
def __init__(
82-
self,
83-
node: pending_node,
84-
host: SphinxDirective | SphinxRole | SphinxTransform,
85-
) -> None:
86-
self.node = node
87-
self.request = ExtraContextRequest(node.template.phase, node, host.env, host)
88-
self.cache = {}
89-
90-
def names(self) -> set[str]:
91-
return _REGISTRY.get_names()
92-
93-
def load(self, name: str) -> Any:
94-
if name in self.cache:
95-
return self.cache[name]
96-
79+
def build_load_extra(request: ExtraContextRequest):
80+
def load_extra(name: str) -> Any:
9781
ctx = _REGISTRY.get(name)
9882
if ctx is None:
9983
raise ValueError(
10084
f'Extra context "{name}" is not registered. '
101-
f'Available: {sorted(self.names())}'
85+
f'Available: {sorted(extra_context_names())}'
10286
)
10387

104-
value = ctx.generate(self.request)
105-
self.cache[name] = value
106-
return value
88+
return ctx.generate(request)
89+
90+
return load_extra

src/sphinxnotes/render/jinja.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class TemplateRenderer:
3333
def render(
3434
self,
3535
data: ResolvedContext,
36-
globals_: dict[str, Any] | None = None,
36+
globals: dict[str, Any] | None = None,
3737
debug: bool = False,
3838
) -> str:
3939
# Convert data to context dict.
@@ -43,8 +43,8 @@ def render(
4343
ctx = data.copy()
4444

4545
# Inject globals.
46-
if globals_:
47-
ctx.update(globals_)
46+
if globals:
47+
ctx.update(globals)
4848

4949
return self._render(ctx, debug=debug)
5050

tests/test_extractx.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from types import SimpleNamespace
2+
3+
from sphinxnotes.render.extractx import (
4+
ExtraContext,
5+
ExtraContextRequest,
6+
_REGISTRY,
7+
build_load_extra,
8+
)
9+
from sphinxnotes.render.template import Template
10+
from sphinxnotes.render.ctxnodes import pending_node
11+
12+
13+
class CountingExtraContext(ExtraContext):
14+
def __init__(self) -> None:
15+
self.calls = 0
16+
17+
def generate(self, request):
18+
self.calls += 1
19+
return self.calls
20+
21+
22+
def test_extra_context_loader_does_not_cache_values():
23+
name = 'test_no_cache'
24+
ctx = CountingExtraContext()
25+
_REGISTRY.register(name, ctx)
26+
27+
try:
28+
node = pending_node({}, Template(''))
29+
host = SimpleNamespace(env=SimpleNamespace())
30+
request = ExtraContextRequest(Template('').phase, node, host.env, host)
31+
load_extra = build_load_extra(request)
32+
33+
assert load_extra(name) == 1
34+
assert load_extra(name) == 2
35+
finally:
36+
_REGISTRY.ctxs.pop(name, None)

0 commit comments

Comments
 (0)