Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ RUN --mount=type=cache,target=/root/.cache/uv,sharing=locked \
-r /tmp/openspp-requirements.txt

# Download and install Odoo (cache the tarball to avoid re-downloading)
# --no-deps: Odoo's runtime dependencies are already installed above from its
# requirements.txt, which carries the correct per-Python-version pins. Odoo's
# setup.py additionally declares an unpinned PyPDF2; resolving it installs
# legacy PyPDF2 3.x, which odoo.tools.pdf then selects over pypdf and which
# crashes multi-record PDF printing (OP#1168).
RUN --mount=type=cache,target=/root/.cache/uv,sharing=locked \
--mount=type=cache,target=/tmp/downloads,sharing=locked \
set -eux; \
Expand All @@ -91,7 +96,7 @@ RUN --mount=type=cache,target=/root/.cache/uv,sharing=locked \
mv /opt/odoo /opt/odoo-src; \
mkdir -p /opt/odoo; \
mv /opt/odoo-src /opt/odoo/odoo; \
uv pip install -e /opt/odoo/odoo
uv pip install --no-deps -e /opt/odoo/odoo

# Download OCA dependencies in builder (cache tarballs to avoid re-downloading)
RUN --mount=type=cache,target=/tmp/downloads,sharing=locked \
Expand Down
11 changes: 11 additions & 0 deletions spp_base_common/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,17 @@ Dependencies
Changelog
=========

19.0.2.0.2
~~~~~~~~~~

- test: add a regression test guarding the PDF backend selected by
``odoo.tools.pdf``. The Docker image accidentally shipped legacy
PyPDF2 3.x next to pypdf; Odoo prefers PyPDF2 when importable, and its
removed 1.x API (``numPages``/``getPage``) crashes multi-record PDF
printing with a ``DeprecationError`` (OP#1168). The fix is in
``docker/Dockerfile`` (``--no-deps`` on the Odoo editable install);
this test fails on any image that regresses.

19.0.2.0.1
~~~~~~~~~~

Expand Down
2 changes: 1 addition & 1 deletion spp_base_common/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
{
"name": "OpenSPP Base (Common)",
"category": "OpenSPP/Core",
"version": "19.0.2.0.1",
"version": "19.0.2.0.2",
"sequence": 1,
"author": "OpenSPP.org",
"website": "https://github.com/OpenSPP/OpenSPP2",
Expand Down
4 changes: 4 additions & 0 deletions spp_base_common/readme/HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
### 19.0.2.0.2

- test: add a regression test guarding the PDF backend selected by `odoo.tools.pdf`. The Docker image accidentally shipped legacy PyPDF2 3.x next to pypdf; Odoo prefers PyPDF2 when importable, and its removed 1.x API (`numPages`/`getPage`) crashes multi-record PDF printing with a `DeprecationError` (OP#1168). The fix is in `docker/Dockerfile` (`--no-deps` on the Odoo editable install); this test fails on any image that regresses.

### 19.0.2.0.1

- fix(security): add `groups="base.group_system"` to the existing `<menuitem id="base.menu_management" />` override in `views/main_view.xml`. Out of the box the Apps top-level menu has no group restriction and is visible to every logged-in user, violating the OP#951 audit's `Apps: no` rows. The override here is the single authoritative declaration for this menu's attributes in the OpenSPP install (sequence, custom OpenSPP icon, and now group_ids); doing the gating anywhere upstream (e.g. a `post_init_hook` in `spp_security`) is unreliable because this `<menuitem>` reload re-writes the record without a `groups` attribute and resets `group_ids` to empty.
Expand Down
14 changes: 13 additions & 1 deletion spp_base_common/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,18 @@ <h2><a class="toc-backref" href="#toc-entry-1">Changelog</a></h2>
</div>
</div>
<div class="section" id="section-1">
<h1>19.0.2.0.2</h1>
<ul class="simple">
<li>test: add a regression test guarding the PDF backend selected by
<tt class="docutils literal">odoo.tools.pdf</tt>. The Docker image accidentally shipped legacy
PyPDF2 3.x next to pypdf; Odoo prefers PyPDF2 when importable, and its
removed 1.x API (<tt class="docutils literal">numPages</tt>/<tt class="docutils literal">getPage</tt>) crashes multi-record PDF
printing with a <tt class="docutils literal">DeprecationError</tt> (OP#1168). The fix is in
<tt class="docutils literal">docker/Dockerfile</tt> (<tt class="docutils literal"><span class="pre">--no-deps</span></tt> on the Odoo editable install);
this test fails on any image that regresses.</li>
</ul>
</div>
<div class="section" id="section-2">
<h1>19.0.2.0.1</h1>
<ul class="simple">
<li>fix(security): add <tt class="docutils literal"><span class="pre">groups=&quot;base.group_system&quot;</span></tt> to the existing
Expand All @@ -510,7 +522,7 @@ <h1>19.0.2.0.1</h1>
<tt class="docutils literal">group_ids</tt> to empty.</li>
</ul>
</div>
<div class="section" id="section-2">
<div class="section" id="section-3">
<h1>19.0.2.0.0</h1>
<ul class="simple">
<li>Initial migration to OpenSPP2</li>
Expand Down
1 change: 1 addition & 0 deletions spp_base_common/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from . import test_ir_module_module
from . import test_pdf_backend
from . import test_phone_number_validation
40 changes: 40 additions & 0 deletions spp_base_common/tests/test_pdf_backend.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import io

from odoo.tests import TransactionCase
from odoo.tools.pdf import PdfFileReader, PdfFileWriter


class TestPdfBackend(TransactionCase):
"""Guard the PDF backend selected by odoo.tools.pdf.

Printing a report for multiple records splits the combined document in
ir.actions.report._render_qweb_pdf_prepare_streams using the legacy
PyPDF2 1.x API (numPages, getPage, addPage). If the image ships legacy
PyPDF2 3.x, odoo.tools.pdf selects it over pypdf and that API raises
DeprecationError, so multi-record printing crashes while single-record
printing still works (OP#1168).
"""

def _make_two_page_pdf(self):
from reportlab.pdfgen import canvas

buffer = io.BytesIO()
pdf_canvas = canvas.Canvas(buffer)
pdf_canvas.drawString(100, 750, "page 1")
pdf_canvas.showPage()
pdf_canvas.drawString(100, 750, "page 2")
pdf_canvas.showPage()
pdf_canvas.save()
buffer.seek(0)
return buffer

def test_01_multi_record_split_legacy_api(self):
# Mirrors the multi-record path of _render_qweb_pdf_prepare_streams
reader = PdfFileReader(self._make_two_page_pdf())
self.assertEqual(reader.numPages, 2)
for page_index in range(reader.numPages):
writer = PdfFileWriter()
writer.addPage(reader.getPage(page_index))
stream = io.BytesIO()
writer.write(stream)
self.assertTrue(stream.getvalue().startswith(b"%PDF"))
Loading