@@ -126,6 +126,95 @@ def add_to_migration_reports(message, category="Other", format="text"):
126126 _logger .warning ("Upgrade report is growing suspiciously long: %s characters so far." , migration_reports_length )
127127
128128
129+ def add_report (
130+ header ,
131+ summary ,
132+ data = None ,
133+ columns = None ,
134+ links = None ,
135+ row_format = None ,
136+ limit = 100 ,
137+ report_format = "html" ,
138+ ):
139+ """Append the upgrade report with a new entry.
140+
141+ The entry consists of a header (title) and a summary (body).
142+ The entry can also display a list of records previously returned by an SQL query. In such case, in addition to the output of
143+ the query passed as "data", parameters "row_format" and "columns" must also be provided.
144+
145+
146+ :param str header: Title of a report entry.
147+ :param str summary: Description of a report entry.
148+ :param List[Tuple] data: Any data in the form of a list of tuples, e.g. the output of cr.fetchall().
149+ :param Tuple[str] columns: Arbitrary names for each column in "data". All columns must be named and
150+ the order of these names must be the same as in "data".
151+ :param Dict[str, Tuple[str, str, str]] links: Optional model/record links, e.g.:
152+ {
153+ "partner_link": ("res.partner", "id", "name"),
154+ "company_link": ("res.company", "company_id", "company_name"),
155+ }
156+ :param str row_format: The way a row in a list is formatted, using named placeholders, e.g.:
157+ "Partner {partner_link} that lives in {city} works at company {company_link}."
158+ :param int limit: The number of records that are going to be displayed in the report.
159+ :param str report_format: Format of the input "summary"; must be one of {"text", "html", "md", "rst"}
160+ """
161+ assert report_format in {"text" , "html" , "md" , "rst" }
162+ if report_format == "md" :
163+ summary = md2html (dedent (summary ))
164+ elif report_format == "rst" :
165+ summary = rst2html (dedent (summary ))
166+
167+ if data :
168+ assert columns is not None
169+ assert row_format is not None
170+ rows = []
171+
172+ for row in data [:limit ]:
173+ row_dict = dict (zip (columns , row ))
174+
175+ if links :
176+ for link_name , (link_model , id_column , name_column ) in links .items ():
177+ row_dict [link_name ] = get_anchor_link_to_record (
178+ link_model ,
179+ row_dict [id_column ],
180+ row_dict [name_column ],
181+ )
182+
183+ row_text = row_format .format (** row_dict )
184+ rows .append ("<li>{}</li>" .format (row_text ))
185+
186+ rows = "<ul>\n " + "\n " .join (rows ) + "\n </ul>"
187+
188+ total = len (data )
189+ disclaimer = "The total number of affected records is {}." .format (total )
190+ if total > limit :
191+ disclaimer += " This list is limited to {} records." .format (limit )
192+
193+ msg = """
194+ <summary>
195+ {}
196+ <details>
197+ <i>{}</i>
198+ {}
199+ </details>
200+ </summary>
201+ """ .format (summary , disclaimer , rows )
202+ else :
203+ msg = """
204+ <summary>
205+ {}
206+ </summary>
207+ """ .format (summary )
208+
209+ raw = False
210+ if report_format != "text" :
211+ if Markup :
212+ msg = Markup (msg )
213+ else :
214+ raw = True
215+ migration_reports .setdefault (header , []).append ((msg , raw ))
216+
217+
129218def announce_release_note (cr ):
130219 filepath = os .path .join (os .path .dirname (__file__ ), "release-note.xml" )
131220 with open (filepath , "rb" ) as fp :
0 commit comments