66
77from ..utils import find_current_section
88from ..utils .ctxproxy import proxy
9- from .renderer import Host , ParseHost
109
1110if TYPE_CHECKING :
1211 from typing import Any , Callable , ClassVar
12+ from sphinx .application import Sphinx
13+ from .renderer import ParseHost
1314
1415
1516from ..utils import Report
1819from .reporter import Reporter
1920
2021
21- class ExtraContxt (ABC ):
22- """Base class for extra context generator in different render phase."""
23-
24- ...
25-
26-
27- class RenderPhaseExtraContext (ExtraContxt ):
22+ class GlobalExtraContxt (ABC ):
2823 @abstractmethod
29- def generate (self , host : Host ) -> Any : ...
24+ def generate (self ) -> Any : ...
3025
3126
32- class ParsePhaseExtraContext (ExtraContxt ):
27+ class ParsePhaseExtraContext (ABC ):
3328 @abstractmethod
3429 def generate (self , host : ParseHost ) -> Any : ...
3530
3631
37- class TransformPhaseExtraContext (ExtraContxt ):
32+ class TransformPhaseExtraContext (ABC ):
3833 @abstractmethod
3934 def generate (self , host : TransformHost ) -> Any : ...
4035
@@ -49,50 +44,47 @@ class ExtraContextRegistry:
4944 parsing : dict [str , ParsePhaseExtraContext ]
5045 parsed : dict [str , ParsePhaseExtraContext ]
5146 post_transform : dict [str , TransformPhaseExtraContext ]
52- render : dict [str , RenderPhaseExtraContext ]
47+ global_ : dict [str , GlobalExtraContxt ]
5348
5449 def __init__ (self ) -> None :
5550 self .names = set ()
5651 self .parsing = {}
5752 self .parsed = {}
5853 self .post_transform = {}
59- self .render = {}
54+ self .global_ = {}
6055
61- self .add_parsing_phase_extra_context ('markup' , _MarkupExtraContext ())
62- self .add_parsing_phase_extra_context ('section' , _SectionExtraContext ())
63- self .add_render_phase_extra_context ('doc' , _DocExtraContext ())
64- self .add_render_phase_extra_context ('env' , _SphinxEnvExtraContext ())
65- self .add_render_phase_extra_context ('config' , _SphinxConfigExtraContext ())
56+ self .add_global_context ('sphinx' , _SphinxExtraContext ())
57+ self .add_parsing_phase_context ('markup' , _MarkupExtraContext ())
58+ self .add_parsing_phase_context ('section' , _SectionExtraContext ())
59+ self .add_parsing_phase_context ('doc' , _DocExtraContext ())
6660
6761 def _name_dedup (self , name : str ) -> None :
6862 # TODO: allow dup
6963 if name in self .names :
7064 raise ValueError (f'Context generator { name } already exists' )
7165 self .names .add (name )
7266
73- def add_parsing_phase_extra_context (
67+ def add_parsing_phase_context (
7468 self , name : str , ctxgen : ParsePhaseExtraContext
7569 ) -> None :
7670 self ._name_dedup (name )
7771 self .parsing ['_' + name ] = ctxgen
7872
79- def add_parsed_phase_extra_context (
73+ def add_parsed_phase_context (
8074 self , name : str , ctxgen : ParsePhaseExtraContext
8175 ) -> None :
8276 self ._name_dedup (name )
8377 self .parsed ['_' + name ] = ctxgen
8478
85- def add_post_transform_phase_extra_context (
79+ def add_post_transform_phase_context (
8680 self , name : str , ctxgen : TransformPhaseExtraContext
8781 ) -> None :
8882 self ._name_dedup (name )
8983 self .post_transform ['_' + name ] = ctxgen
9084
91- def add_render_phase_extra_context (
92- self , name : str , ctxgen : RenderPhaseExtraContext
93- ):
85+ def add_global_context (self , name : str , ctxgen : GlobalExtraContxt ):
9486 self ._name_dedup (name )
95- self .render ['_' + name ] = ctxgen
87+ self .global_ ['_' + name ] = ctxgen
9688
9789
9890# ===================================
@@ -112,9 +104,9 @@ def generate(self, host: ParseHost) -> Any:
112104 }
113105
114106
115- class _DocExtraContext (RenderPhaseExtraContext ):
107+ class _DocExtraContext (ParsePhaseExtraContext ):
116108 @override
117- def generate (self , host : Host ) -> Any :
109+ def generate (self , host : ParseHost ) -> Any :
118110 return proxy (HostWrapper (host ).doctree )
119111
120112
@@ -125,16 +117,12 @@ def generate(self, host: ParseHost) -> Any:
125117 return proxy (find_current_section (parent ))
126118
127119
128- class _SphinxEnvExtraContext (RenderPhaseExtraContext ):
129- @override
130- def generate (self , host : Host ) -> Any :
131- return proxy (host .env )
120+ class _SphinxExtraContext (GlobalExtraContxt ):
121+ app : ClassVar [Sphinx ]
132122
133-
134- class _SphinxConfigExtraContext (RenderPhaseExtraContext ):
135123 @override
136- def generate (self , host : Host ) -> Any :
137- return proxy (host . config )
124+ def generate (self ) -> Any :
125+ return proxy (self . app )
138126
139127
140128# ========================
@@ -150,12 +138,17 @@ class ExtraContextGenerator:
150138
151139 def __init__ (self , node : pending_data ) -> None :
152140 self .node = node
153- self .report = Report ('Extra Context Generation Report' , 'ERROR' )
141+ self .report = Report (
142+ 'Extra Context Generation Report' ,
143+ 'ERROR' ,
144+ source = node .source ,
145+ line = node .line ,
146+ )
154147 Reporter (node ).append (self .report )
155148
156- def on_rendering (self , host : Host ) -> None :
157- for name , ctxgen in self .registry .render .items ():
158- self ._safegen (name , lambda : ctxgen .generate (host ))
149+ def on_anytime (self ) -> None :
150+ for name , ctxgen in self .registry .global_ .items ():
151+ self ._safegen (name , lambda : ctxgen .generate ())
159152
160153 def on_parsing (self , host : ParseHost ) -> None :
161154 for name , ctxgen in self .registry .parsing .items ():
@@ -174,5 +167,9 @@ def _safegen(self, name: str, gen: Callable[[], Any]):
174167 # ctxgen.generate can be user-defined code, exception of any kind are possible.
175168 self .node .extra [name ] = gen ()
176169 except Exception :
177- self .report .text (f'Failed to generate extra context { name } :' )
170+ self .report .text (f'Failed to generate extra context " { name } " :' )
178171 self .report .excption ()
172+
173+
174+ def setup (app : Sphinx ):
175+ _SphinxExtraContext .app = app
0 commit comments