+
Report Engine: Paper Muncher
+
+
+

+
This module integrates Paper
+Muncher as the PDF rendering
+engine for QWeb reports. When the paper-muncher binary is available
+on the system, it replaces wkhtmltopdf as the default engine for PDF
+generation.
+
Main features:
+
+- Automatic detection of the paper-muncher binary in PATH or in
+/opt/paper-muncher/bin/paper-muncher
+- Globally configurable PDF engine via the report.pdf_engine system
+parameter
+- Multi-page header and footer support and report.paperformat
+integration
+- Transparent fallback to wkhtmltopdf when Paper Muncher is not
+installed
+- HTTP-over-pipe communication between Odoo and the Paper Muncher
+subprocess, so report assets are served with Odoo permissions
+
+
This module depends on:
+
+- Odoo modules: base, web
+- Python package: h11
+- System binary: paper-muncher from GitHub
+releases
+
+
Table of contents
+
+
+
+
Install the paper-muncher system binary before enabling this module.
+Example for Ubuntu 22.04 (Jammy):
+
+curl -fsSL -o paper-muncher.deb \
+ "https://github.com/odoo/paper-muncher/releases/download/v0.3.1-1/paper-muncher_v0.3.1-1_jammy_amd64.deb"
+sudo apt install ./paper-muncher.deb
+paper-muncher --help
+
+
If the binary is not installed via the .deb package, add
+/opt/paper-muncher/bin to the PATH of the Odoo process.
+
The Python dependency h11 is declared in the module manifest and
+listed in requirements.txt. Install it in the Odoo Python
+environment if needed:
+
+pip install h11
+
+
Then install the module as any other Odoo addon:
+
+odoo -d <database> -i base_report_paper_muncher --stop-after-init
+
+
Paper Muncher is only supported on Linux and macOS.
+
+
+
+
The system parameter report.pdf_engine controls which PDF engine is
+used:
+
+
+
+
+
+
+| Value |
+Behavior |
+
+
+
+| auto (default) |
+Use Paper Muncher when the binary is available,
+otherwise wkhtmltopdf |
+
+| paper-muncher |
+Force Paper Muncher; raise an error if the
+binary is missing |
+
+| wkhtmltopdf |
+Always use wkhtmltopdf |
+
+
+
+
Change it from code:
+
+env["ir.config_parameter"].sudo().set_param("report.pdf_engine", "auto")
+
+
Or from Settings > Technical > Parameters > System Parameters, key
+report.pdf_engine.
+
Optional environment variables for the Odoo process:
+
+- ODOO_PAPER_MUNCHER_FEATURE=1: pass --feature *=on to the
+binary
+- ODOO_PAPER_MUNCHER_DEBUG=1: pass --debug http-client to the
+binary. This flag is not sent by default in production. It is also
+enabled automatically when the module logger is set to DEBUG.
+
+
+
+
+
Once installed and configured, QWeb PDF reports use Paper Muncher
+automatically when the binary is available and report.pdf_engine is
+set to auto or paper-muncher.
+
Check the engine status:
+
+env["ir.actions.report"].get_wkhtmltopdf_state()
+
+
Returns ok when Paper Muncher is available with auto or
+paper-muncher. Returns install when paper-muncher is forced
+but the binary is missing.
+
When generating PDFs, look for log lines prefixed with PDF engine::
+
+- PDF engine: Paper-Muncher (...): rendering started with Paper
+Muncher
+- PDF engine: Paper-Muncher completed (...): PDF generated
+successfully
+- PDF engine: wkhtmltopdf (...): fallback to wkhtmltopdf
+
+
Low-level HTTP-over-pipe details are logged at DEBUG level only.
+
+
+
+
+- Paper Muncher is only supported on Linux and macOS (not Windows).
+- WebSocket requests are rejected by the HTTP-over-pipe server.
+- Rendering timeout: 15 minutes (SERVE_TIMEOUT).
+- Pipe write timeout: 15 seconds (WRITE_TIMEOUT).
+- The binary must be installed on the system; this module only
+integrates the communication layer.
+
+
+
+
+
Bugs are tracked on GitHub Issues.
+In case of trouble, please check there if your issue has already been reported.
+If you spotted it first, help us to smash it by providing a detailed and welcomed
+feedback.
+
Do not contact contributors directly about support or help with technical issues.
+
+
+
+
+
+
+
This module is maintained by the OCA.
+
+
+
+
OCA, or the Odoo Community Association, is a nonprofit organization whose
+mission is to support the collaborative development of Odoo features and
+promote its widespread use.
+
This module is part of the OCA/server-tools project on GitHub.
+
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
+
+
+
+
+
diff --git a/base_report_paper_muncher/tests/__init__.py b/base_report_paper_muncher/tests/__init__.py
new file mode 100644
index 00000000000..87d081416f6
--- /dev/null
+++ b/base_report_paper_muncher/tests/__init__.py
@@ -0,0 +1,4 @@
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from . import test_paper_muncher_unit
+from . import test_report
diff --git a/base_report_paper_muncher/tests/test_paper_muncher_unit.py b/base_report_paper_muncher/tests/test_paper_muncher_unit.py
new file mode 100644
index 00000000000..074a04524e3
--- /dev/null
+++ b/base_report_paper_muncher/tests/test_paper_muncher_unit.py
@@ -0,0 +1,697 @@
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+import os
+import selectors
+import subprocess
+from unittest.mock import MagicMock, patch
+
+import h11
+
+import odoo.tests
+from odoo.exceptions import UserError
+
+from odoo.addons.base_report_paper_muncher.models.ir_actions_report import (
+ _extract_div_fragments,
+ make_multi_docs_html,
+ partition_on_body,
+)
+from odoo.addons.base_report_paper_muncher.paper_muncher import (
+ FALLBACK_BIN_PATH,
+ PaperMuncherInfo,
+ PaperMuncherServer,
+ _remaining_time,
+ paper_muncher,
+)
+
+
+@odoo.tests.tagged("post_install", "-at_install")
+class TestPaperMuncherHelpers(odoo.tests.TransactionCase):
+ def test_partition_on_body_without_body_tag(self):
+ html = ""
+ self.assertEqual(partition_on_body(html), (html, "", ""))
+
+ def test_partition_on_body_without_closing_tag(self):
+ html = "