11
11
from psycopg2 .extensions import quote_ident
12
12
from psycopg2 .extras import Json
13
13
14
+ from .const import NEARLYWARN
14
15
from .exceptions import MigrationError
15
16
from .helpers import table_of_model
16
17
from .misc import import_script , log_progress
@@ -157,7 +158,7 @@ def html_converter(transform_callback, selector=None):
157
158
:param str selector: targets the elements to loop on
158
159
:return: object HTMLConverter with callback
159
160
"""
160
- return HTMLConverter (transform_callback , selector )
161
+ return HTMLConverter (make_pickleable_callback ( transform_callback ) , selector )
161
162
162
163
163
164
def make_pickleable_callback (callback ):
@@ -182,10 +183,16 @@ def make_pickleable_callback(callback):
182
183
raise MigrationError (error_msg ) from None
183
184
184
185
185
- class HTMLConverter :
186
+ class BaseConverter :
186
187
def __init__ (self , callback , selector = None ):
188
+ self .callback = callback
187
189
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 )
189
196
190
197
def has_changed (self , els ):
191
198
if self .selector :
@@ -201,18 +208,39 @@ def __call__(self, content):
201
208
# Wrap in <wrap> node before parsing to preserve external comments and multi-root nodes,
202
209
# except for when this looks like a full html doc, because in this case the wrap tag breaks the logic in
203
210
# 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>" )
208
212
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
214
214
return (has_changed , new_content )
215
215
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
+
216
244
217
245
class Convertor :
218
246
def __init__ (self , converters , callback ):
@@ -320,14 +348,26 @@ def convert_html_content(
320
348
- "~* '\yabc.*xyz\y'"
321
349
:param dict kwargs: extra keyword arguments to pass to :func:`convert_html_column`
322
350
"""
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
+
323
366
convert_html_columns (
324
367
cr ,
325
368
"ir_ui_view" ,
326
369
["arch_db" ],
327
- converter_callback ,
370
+ qweb_converter ,
328
371
where_column = where_column ,
329
372
** dict (kwargs , extra_where = "type = 'qweb'" ),
330
373
)
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