|
3 | 3 | import html |
4 | 4 | import logging |
5 | 5 | import re |
| 6 | +from multiprocessing import Process, Queue |
6 | 7 |
|
7 | 8 | import babel |
8 | 9 | import lxml |
@@ -544,32 +545,42 @@ def verify_upgraded_jinja_fields(cr): |
544 | 545 |
|
545 | 546 |
|
546 | 547 | def is_converted_template_valid(env, template_before, template_after, model_name, record_id, engine="inline_template"): |
547 | | - render_before = None |
548 | | - with contextlib.suppress(Exception): |
549 | | - render_before = _render_template_jinja(env, template_before, model_name, record_id) |
550 | | - |
551 | | - render_after = None |
552 | | - if render_before is not None: |
553 | | - try: |
554 | | - with mute_logger("odoo.addons.mail.models.mail_render_mixin"): |
555 | | - render_after = env["mail.render.mixin"]._render_template( |
556 | | - template_after, model_name, [record_id], engine=engine |
557 | | - )[record_id] |
558 | | - except Exception: |
559 | | - pass |
560 | | - |
561 | | - # post process qweb render to remove comments from the rendered jinja in |
562 | | - # order to avoid false negative because qweb never render comments. |
563 | | - if render_before and render_after and engine == "qweb": |
564 | | - element_before = lxml.html.fragment_fromstring(render_before, create_parent="div") |
565 | | - for comment_element in element_before.xpath("//comment()"): |
566 | | - comment_element.getparent().remove(comment_element) |
567 | | - render_before = lxml.html.tostring(element_before, encoding="unicode") |
568 | | - render_after = lxml.html.tostring( |
569 | | - lxml.html.fragment_fromstring(render_after, create_parent="div"), encoding="unicode" |
570 | | - ) |
| 548 | + def callback(q): |
| 549 | + render_before = None |
| 550 | + with contextlib.suppress(Exception): |
| 551 | + render_before = _render_template_jinja(env, template_before, model_name, record_id) |
| 552 | + |
| 553 | + render_after = None |
| 554 | + if render_before is not None: |
| 555 | + try: |
| 556 | + with mute_logger("odoo.addons.mail.models.mail_render_mixin"): |
| 557 | + render_after = env["mail.render.mixin"]._render_template( |
| 558 | + template_after, model_name, [record_id], engine=engine |
| 559 | + )[record_id] |
| 560 | + except Exception: |
| 561 | + pass |
| 562 | + |
| 563 | + # post process qweb render to remove comments from the rendered jinja in |
| 564 | + # order to avoid false negative because qweb never render comments. |
| 565 | + if render_before and render_after and engine == "qweb": |
| 566 | + element_before = lxml.html.fragment_fromstring(render_before, create_parent="div") |
| 567 | + for comment_element in element_before.xpath("//comment()"): |
| 568 | + comment_element.getparent().remove(comment_element) |
| 569 | + render_before = lxml.html.tostring(element_before, encoding="unicode") |
| 570 | + render_after = lxml.html.tostring( |
| 571 | + lxml.html.fragment_fromstring(render_after, create_parent="div"), encoding="unicode" |
| 572 | + ) |
| 573 | + |
| 574 | + q.put(render_before is not None and render_before == render_after) |
571 | 575 |
|
572 | | - return render_before is not None and render_before == render_after |
| 576 | + # to avoid memory leaks in external C libraries (lxml/libxml2), process in a forked child |
| 577 | + queue = Queue() |
| 578 | + proc = Process(target=callback, args=[queue]) |
| 579 | + proc.start() |
| 580 | + res = queue.get(timeout=60) |
| 581 | + if proc.is_alive(): |
| 582 | + proc.kill() |
| 583 | + return res |
573 | 584 |
|
574 | 585 |
|
575 | 586 | # jinja render |
|
0 commit comments