1010from .template import TemplateRenderer
1111from ..data import RawData , PendingData , ParsedData
1212from ..utils import (
13- Unpicklable ,
1413 Report ,
1514 Reporter ,
1615 find_nearest_block_element ,
2423class Base (nodes .Element ): ...
2524
2625
27- class pending_node (Base , Unpicklable ):
26+ class pending_node (Base ):
2827 # The data to be rendered by Jinja template.
2928 data : PendingData | ParsedData | dict [str , Any ]
3029 # The extra context for Jina template.
@@ -35,6 +34,8 @@ class pending_node(Base, Unpicklable):
3534 inline : bool
3635 #: Whether the rendering pipeline is finished (failed is also finished).
3736 rendered : bool
37+ #: The report of render pipepine.
38+ report : Report
3839
3940 def __init__ (
4041 self ,
@@ -51,18 +52,58 @@ def __init__(
5152 self .template = tmpl
5253 self .inline = inline
5354 self .rendered = False
55+ self .report = Report (
56+ 'Render Report' , 'DEBUG' , source = self .source , line = self .line
57+ )
5458
5559 # Init hook lists.
5660 self ._raw_data_hooks = []
5761 self ._parsed_data_hooks = []
5862 self ._markup_text_hooks = []
5963 self ._rendered_nodes_hooks = []
6064
65+ def get_error_report (self ) -> Report :
66+ if self .template .debug :
67+ # Reuse the render report as possible.
68+ self .report ['type' ] = 'ERROR'
69+ return self .report
70+ return Report ('Render Report' , 'ERROR' , source = self .source , line = self .line )
71+
72+ def ensure_data_parsed (self ) -> ParsedData | dict [str , Any ] | None :
73+ """
74+ Ensure self.data is parsed (instance of ParsedData | dict[str, Any]).
75+ if no, parse it.
76+ """
77+ if not isinstance (self .data , PendingData ):
78+ return self .data
79+
80+ self .report .text ('Raw data:' )
81+ self .report .code (pformat (self .data .raw ), lang = 'python' )
82+ self .report .text ('Schema:' )
83+ self .report .code (pformat (self .data .schema ), lang = 'python' )
84+
85+ for hook in self ._raw_data_hooks :
86+ hook (self , self .data .raw )
87+
88+ try :
89+ data = self .data = self .data .parse ()
90+ except ValueError as e :
91+ report = self .get_error_report ()
92+ report .text ('Failed to parse raw data:' )
93+ report .exception (e )
94+ self += report
95+ return None
96+
97+ for hook in self ._parsed_data_hooks :
98+ hook (self , data )
99+
100+ return data
101+
61102 def render (self , host : Host ) -> None :
62103 """
63104 The core function for rendering data to docutils nodes.
64105
65- 1. Schema.parse(RawData) -> ParsedData
106+ 1. Schema.parse(RawData) -> ParsedData (self.parse_data)
66107 2. TemplateRenderer.render(ParsedData) -> Markup Text (``str``)
67108 3. MarkupRenderer.render(Markup Text) -> doctree Nodes (list[nodes.Node])
68109 """
@@ -74,51 +115,22 @@ def render(self, host: Host) -> None:
74115 # Clear empty reports.
75116 Reporter (self ).clear_empty ()
76117
77- dbg = Report ('Render Report' , 'DEBUG' , source = self .source , line = self .line )
78-
79- def get_error_report () -> Report :
80- if self .template .debug :
81- # Reuse the debug report as possible.
82- dbg ['type' ] = 'ERROR'
83- return dbg
84- return Report ('Render Report' , 'ERROR' , source = self .source , line = self .line )
85-
86118 # 1. Prepare context for Jinja template.
87- if isinstance (self .data , PendingData ):
88- dbg .text ('Raw data:' )
89- dbg .code (pformat (self .data .raw ), lang = 'python' )
90- dbg .text ('Schema:' )
91- dbg .code (pformat (self .data .schema ), lang = 'python' )
92-
93- for hook in self ._raw_data_hooks :
94- hook (self , self .data .raw )
95-
96- try :
97- data = self .data = self .data .parse ()
98- except ValueError as e :
99- report = get_error_report ()
100- report .text ('Failed to parse raw data:' )
101- report .exception (e )
102- self += report
103- return
104- else :
105- data = self .data
119+ if (data := self .ensure_data_parsed ()) is None :
120+ return # parse failure
106121
107- for hook in self ._parsed_data_hooks :
108- hook (self , data )
109-
110- dbg .text (f'Parsed data (type: { type (data )} ):' )
111- dbg .code (pformat (data ), lang = 'python' )
112- dbg .text ('Extra context (only keys):' )
113- dbg .code (pformat (list (self .extra .keys ())), lang = 'python' )
114- dbg .text (f'Template (phase: { self .template .phase } ):' )
115- dbg .code (self .template .text , lang = 'jinja' )
122+ self .report .text (f'Parsed data (type: { type (data )} ):' )
123+ self .report .code (pformat (data ), lang = 'python' )
124+ self .report .text ('Extra context (only keys):' )
125+ self .report .code (pformat (list (self .extra .keys ())), lang = 'python' )
126+ self .report .text (f'Template (phase: { self .template .phase } ):' )
127+ self .report .code (self .template .text , lang = 'jinja' )
116128
117129 # 2. Render the template and data to markup text.
118130 try :
119131 markup = TemplateRenderer (self .template .text ).render (data , extra = self .extra )
120132 except Exception as e :
121- report = get_error_report ()
133+ report = self . get_error_report ()
122134 report .text ('Failed to render Jinja template:' )
123135 report .exception (e )
124136 self += report
@@ -127,14 +139,14 @@ def get_error_report() -> Report:
127139 for hook in self ._markup_text_hooks :
128140 markup = hook (self , markup )
129141
130- dbg .text ('Rendered markup text:' )
131- dbg .code (markup , lang = 'rst' )
142+ self . report .text ('Rendered markup text:' )
143+ self . report .code (markup , lang = 'rst' )
132144
133145 # 3. Render the markup text to doctree nodes.
134146 try :
135147 ns , msgs = MarkupRenderer (host ).render (markup , inline = self .inline )
136148 except Exception as e :
137- report = get_error_report ()
149+ report = self . get_error_report ()
138150 report .text (
139151 'Failed to render markup text '
140152 f'to { "inline " if self .inline else "" } nodes:'
@@ -143,20 +155,21 @@ def get_error_report() -> Report:
143155 self += report
144156 return
145157
146- dbg .text (f'Rendered nodes (inline: { self .inline } ):' )
147- dbg .code ('\n \n ' .join ([n .pformat () for n in ns ]), lang = 'xml' )
158+ self . report .text (f'Rendered nodes (inline: { self .inline } ):' )
159+ self . report .code ('\n \n ' .join ([n .pformat () for n in ns ]), lang = 'xml' )
148160 if msgs :
149- dbg .text ('Systemd messages:' )
150- [dbg .node (msg ) for msg in msgs ]
161+ self . report .text ('Systemd messages:' )
162+ [self . report .node (msg ) for msg in msgs ]
151163
152164 # 4. Add rendered nodes to container.
153165 for hook in self ._rendered_nodes_hooks :
154166 hook (self , ns )
167+
155168 # TODO: set_source_info?
156169 self += ns
157170
158171 if self .template .debug :
159- self += dbg
172+ self += self . report
160173
161174 return
162175
0 commit comments