1111from psycopg2 .extensions import quote_ident
1212from psycopg2 .extras import Json
1313
14+ from .const import NEARLYWARN
1415from .exceptions import MigrationError
1516from .helpers import table_of_model
1617from .misc import import_script , log_progress
@@ -157,7 +158,7 @@ def html_converter(transform_callback, selector=None):
157158 :param str selector: targets the elements to loop on
158159 :return: object HTMLConverter with callback
159160 """
160- return HTMLConverter (transform_callback , selector )
161+ return HTMLConverter (make_pickleable_callback ( transform_callback ) , selector )
161162
162163
163164def make_pickleable_callback (callback ):
@@ -182,10 +183,16 @@ def make_pickleable_callback(callback):
182183 raise MigrationError (error_msg ) from None
183184
184185
185- class HTMLConverter :
186+ class BaseConverter :
186187 def __init__ (self , callback , selector = None ):
188+ self .callback = callback
187189 self .selector = selector
188- self .callback = make_pickleable_callback (callback )
190+
191+ def for_html (self ):
192+ return HTMLConverter (self .callback , self .selector )
193+
194+ def for_qweb (self ):
195+ return QWebConverter (self .callback , self .selector )
189196
190197 def has_changed (self , els ):
191198 if self .selector :
@@ -201,18 +208,39 @@ def __call__(self, content):
201208 # Wrap in <wrap> node before parsing to preserve external comments and multi-root nodes,
202209 # except for when this looks like a full html doc, because in this case the wrap tag breaks the logic in
203210 # https://github.com/lxml/lxml/blob/2ac88908ffd6df380615c0af35f2134325e4bf30/src/lxml/html/html5parser.py#L184
204- els = html .fromstring (
205- content if content .strip ()[:5 ].lower () == "<html" else f"<wrap>{ content } </wrap>" ,
206- parser = utf8_parser ,
207- )
211+ els = self ._loads (content if content .strip ()[:5 ].lower () == "<html" else f"<wrap>{ content } </wrap>" )
208212 has_changed = self .has_changed (els )
209- new_content = (
210- re .sub (r"(^<wrap>|</wrap>$|^<wrap/>$)" , "" , etree .tostring (els , encoding = "unicode" ).strip ())
211- if has_changed
212- else content
213- )
213+ new_content = re .sub (r"(^<wrap>|</wrap>$|^<wrap/>$)" , "" , self ._dumps (els ).strip ()) if has_changed else content
214214 return (has_changed , new_content )
215215
216+ def _loads (self , string ):
217+ raise NotImplementedError
218+
219+ def _dumps (self , node ):
220+ raise NotImplementedError
221+
222+
223+ class HTMLConverter (BaseConverter ):
224+ def for_html (self ):
225+ return self
226+
227+ def _loads (self , string ):
228+ return html .fromstring (string , parser = utf8_parser )
229+
230+ def _dumps (self , node ):
231+ return html .tostring (node , encoding = "unicode" )
232+
233+
234+ class QWebConverter (BaseConverter ):
235+ def for_qweb (self ):
236+ return self
237+
238+ def _loads (self , string ):
239+ return html .fromstring (string , parser = html .XHTMLParser (encoding = "utf-8" ))
240+
241+ def _dumps (self , node ):
242+ return etree .tostring (node , encoding = "unicode" )
243+
216244
217245class Convertor :
218246 def __init__ (self , converters , callback ):
@@ -320,14 +348,26 @@ def convert_html_content(
320348 - "~* '\yabc.*xyz\y'"
321349 :param dict kwargs: extra keyword arguments to pass to :func:`convert_html_column`
322350 """
351+ if hasattr (converter_callback , "for_html" ): # noqa: SIM108
352+ html_converter = converter_callback .for_html ()
353+ else :
354+ # trust the given converter to handle HTML
355+ html_converter = converter_callback
356+
357+ for table , columns in html_fields (cr ):
358+ convert_html_columns (cr , table , columns , html_converter , where_column = where_column , ** kwargs )
359+
360+ if hasattr (converter_callback , "for_qweb" ):
361+ qweb_converter = converter_callback .for_qweb ()
362+ else :
363+ _logger .log (NEARLYWARN , "Cannot adapt converter callback %r for qweb; using it directly" , converter_callback )
364+ qweb_converter = converter_callback
365+
323366 convert_html_columns (
324367 cr ,
325368 "ir_ui_view" ,
326369 ["arch_db" ],
327- converter_callback ,
370+ qweb_converter ,
328371 where_column = where_column ,
329372 ** dict (kwargs , extra_where = "type = 'qweb'" ),
330373 )
331-
332- for table , columns in html_fields (cr ):
333- convert_html_columns (cr , table , columns , converter_callback , where_column = where_column , ** kwargs )
0 commit comments