Skip to content

Commit f0421f8

Browse files
committed
[18.0][MIG] report_py3o
1 parent 1a1a0f7 commit f0421f8

7 files changed

Lines changed: 50 additions & 50 deletions

File tree

‎report_py3o/__manifest__.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"name": "Py3o Report Engine",
55
"summary": "Reporting engine based on Libreoffice (ODT -> ODT, "
66
"ODT -> PDF, ODT -> DOC, ODT -> DOCX, ODS -> ODS, etc.)",
7-
"version": "16.0.1.0.6",
7+
"version": "18.0.1.0.0",
88
"category": "Reporting",
99
"license": "AGPL-3",
1010
"author": "XCG Consulting, ACSONE SA/NV, Odoo Community Association (OCA)",

‎report_py3o/controllers/main.py‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,18 @@
22
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
33
import json
44
import mimetypes
5+
from urllib.parse import parse_qs
56

67
from werkzeug import exceptions
7-
from werkzeug.urls import url_decode
8+
from werkzeug.datastructures import MultiDict
89

910
from odoo.http import content_disposition, request, route, serialize_exception
1011
from odoo.tools import html_escape
1112

12-
from odoo.addons.web.controllers.report import ReportController
13+
from odoo.addons.web.controllers.report import ReportController as ReportControllerBase
1314

1415

15-
class ReportController(ReportController):
16+
class ReportController(ReportControllerBase):
1617
@route()
1718
def report_routes(self, reportname, docids=None, converter=None, **data):
1819
if converter != "py3o":
@@ -41,7 +42,7 @@ def report_routes(self, reportname, docids=None, converter=None, **data):
4142
if not action_py3o_report:
4243
raise exceptions.HTTPException(
4344
description="Py3o action report not found for report_name "
44-
"%s" % reportname
45+
f"{reportname}"
4546
)
4647
res, filetype = ir_action._render(reportname, docids, data)
4748
filename = action_py3o_report.gen_report_download_filename(docids, data)
@@ -82,7 +83,7 @@ def report_download(self, data, context=None, token=None):
8283
else:
8384
# Particular report:
8485
# decoding the args represented in JSON
85-
data = list(url_decode(url.split("?")[1]).items())
86+
data = list(MultiDict(parse_qs(url.split("?")[1])).items())
8687
response = self.report_routes(
8788
reportname, converter="py3o", **dict(data)
8889
)

‎report_py3o/models/py3o_report.py‎

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@
1010
import warnings
1111
from base64 import b64decode
1212
from contextlib import closing
13+
from importlib.resources import files
1314
from io import BytesIO
1415
from zipfile import ZIP_DEFLATED, ZipFile
1516

16-
import pkg_resources
17-
1817
from odoo import _, api, fields, models, tools
1918
from odoo.exceptions import AccessError
2019
from odoo.tools.safe_eval import safe_eval, time
@@ -129,8 +128,8 @@ def _get_template_from_path(self, tmpl_name):
129128
flbk_filename = None
130129
if report_xml.module:
131130
# if the default is defined
132-
flbk_filename = pkg_resources.resource_filename(
133-
"odoo.addons.%s" % report_xml.module, tmpl_name
131+
flbk_filename = files(f"odoo.addons.{report_xml.module}").joinpath(
132+
tmpl_name
134133
)
135134
elif self._is_valid_template_path(tmpl_name):
136135
flbk_filename = os.path.realpath(tmpl_name)
@@ -271,11 +270,7 @@ def _convert_single_report(self, result_path, model_instance, data):
271270
result_path, result_filename = os.path.split(result_path)
272271
result_path = os.path.join(
273272
result_path,
274-
"%s.%s"
275-
% (
276-
os.path.splitext(result_filename)[0],
277-
self.ir_actions_report_id.py3o_filetype,
278-
),
273+
f"{os.path.splitext(result_filename)[0]}.{self.ir_actions_report_id.py3o_filetype}",
279274
)
280275
return result_path
281276

@@ -299,7 +294,7 @@ def _convert_single_report_cmd(
299294
result_path,
300295
]
301296
if user_installation:
302-
cmd.append("-env:UserInstallation=file:%s" % user_installation)
297+
cmd.append(f"-env:UserInstallation=file:{user_installation}")
303298
return cmd
304299

305300
def _get_or_create_single_report(
@@ -368,7 +363,7 @@ def _cleanup_tempfiles(self, temporary_files):
368363
try:
369364
os.unlink(temporary_file)
370365
except OSError:
371-
logger.error("Error when trying to remove file %s" % temporary_file)
366+
logger.error(f"Error when trying to remove file {temporary_file}")
372367

373368
def create_report(self, res_ids, data):
374369
"""Override this function to handle our py3o report"""

‎report_py3o/static/src/js/py3oactionservice.esm.js‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ registry
1010
let url = `/report/py3o/${action.report_name}`;
1111
const actionContext = action.context || {};
1212
if (
13-
_.isUndefined(action.data) ||
14-
_.isNull(action.data) ||
15-
(_.isObject(action.data) && _.isEmpty(action.data))
13+
action.data === undefined ||
14+
action.data === null ||
15+
(typeof action.data === "object" &&
16+
Object.keys(action.data).length === 0)
1617
) {
1718
// Build a query string with `action.data` (it's the place where reports
1819
// using a wizard to customize the output traditionally put their options)
@@ -33,7 +34,7 @@ registry
3334
url: "/report/download",
3435
data: {
3536
data: JSON.stringify([url, action.report_type]),
36-
context: JSON.stringify(env.services.user.context),
37+
context: JSON.stringify(action.context),
3738
},
3839
});
3940
} finally {

‎report_py3o/tests/test_report_py3o.py‎

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,17 @@
88
import tempfile
99
from base64 import b64decode, b64encode
1010
from contextlib import contextmanager
11+
from importlib.resources import as_file, files
1112
from unittest import mock
1213

13-
import pkg_resources
1414
from PyPDF2 import PdfFileWriter
15-
from PyPDF2.pdf import PageObject
15+
16+
try:
17+
# For PyPDF2 <= 1.26.0
18+
from PyPDF2.pdf import PageObject
19+
except ImportError:
20+
# For PyPDF2 >= 2.0.0
21+
from PyPDF2 import PageObject
1622

1723
from odoo import tools
1824
from odoo.exceptions import ValidationError
@@ -44,12 +50,13 @@ def temporary_copy(path):
4450

4551

4652
class TestReportPy3o(TransactionCase):
47-
def setUp(self):
48-
super(TestReportPy3o, self).setUp()
49-
self.env.user.image_1920 = PNG
50-
self.report = self.env.ref("report_py3o.res_users_report_py3o")
51-
self.py3o_report = self.env["py3o.report"].create(
52-
{"ir_actions_report_id": self.report.id}
53+
@classmethod
54+
def setUpClass(cls):
55+
super().setUpClass()
56+
cls.env.user.image_1920 = PNG
57+
cls.report = cls.env.ref("report_py3o.res_users_report_py3o")
58+
cls.py3o_report = cls.env["py3o.report"].create(
59+
{"ir_actions_report_id": cls.report.id}
5360
)
5461

5562
def test_required_py3_filetype(self):
@@ -146,10 +153,9 @@ def test_report_template_configs(self):
146153
# the demo template is specified with a relative path in in the module
147154
# path
148155
tmpl_name = self.report.py3o_template_fallback
149-
flbk_filename = pkg_resources.resource_filename(
150-
"odoo.addons.%s" % self.report.module, tmpl_name
151-
)
152-
self.assertTrue(os.path.exists(flbk_filename))
156+
with as_file(files(f"odoo.addons.{self.report.module}")) as _asf:
157+
flbk_filename = _asf.joinpath(tmpl_name)
158+
self.assertTrue(flbk_filename.is_file())
153159
res = self.report._render(self.report.id, self.env.user.ids)
154160
self.assertTrue(res)
155161
# The generation fails if the template is not found
@@ -190,9 +196,8 @@ def test_report_template_configs(self):
190196
@tools.misc.mute_logger("odoo.addons.report_py3o.models.py3o_report")
191197
def test_report_template_fallback_validity(self):
192198
tmpl_name = self.report.py3o_template_fallback
193-
flbk_filename = pkg_resources.resource_filename(
194-
"odoo.addons.%s" % self.report.module, tmpl_name
195-
)
199+
with as_file(files(f"odoo.addons.{self.report.module}")) as _asf:
200+
flbk_filename = _asf.joinpath(tmpl_name)
196201
# an exising file in a native format is a valid template if it's
197202
self.assertTrue(self.py3o_report._get_template_from_path(tmpl_name))
198203
self.report.module = None
@@ -208,7 +213,7 @@ def test_report_template_fallback_validity(self):
208213
self.assertTrue(self.py3o_report._get_template_from_path(tmp_filename))
209214
# check security
210215
self.assertFalse(
211-
self.py3o_report._get_template_from_path("rm -rf . & %s" % flbk_filename)
216+
self.py3o_report._get_template_from_path(f"rm -rf . & {flbk_filename}")
212217
)
213218
# a file in a non native LibreOffice format is not a valid template
214219
with tempfile.NamedTemporaryFile(suffix=".toto") as f:

‎report_py3o/views/ir_actions_report.xml‎

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,20 @@
66
<field name="model">ir.actions.report</field>
77
<field name="inherit_id" ref="base.act_report_xml_view" />
88
<field name="arch" type="xml">
9-
<xpath expr="/form/field[1]" position="before">
9+
<xpath expr="//sheet" position="before">
1010
<field name="is_py3o_report_not_available" invisible="1" />
11-
<div
12-
class="alert alert-danger"
13-
role="alert"
14-
style="margin-bottom:0px;"
15-
attrs="{'invisible': [('is_py3o_report_not_available','=',False)]}"
16-
>
17-
<field name="msg_py3o_report_not_available" />
11+
<div class="alert alert-danger" role="alert" style="margin-bottom:0px;">
12+
<field
13+
name="msg_py3o_report_not_available"
14+
invisible="not is_py3o_report_not_available"
15+
/>
1816
</div>
1917
</xpath>
2018
<xpath expr="//page[@name='security']" position="before">
2119
<page
2220
string="LibreOffice Template"
2321
name="py3o_tab"
24-
attrs="{'invisible': [('report_type', '!=', 'py3o')]}"
22+
invisible="report_type != 'py3o'"
2523
>
2624
<group name="py3o_params">
2725
<field name="lo_bin_path" />

‎report_py3o/views/py3o_template.xml‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,19 @@
3131
</field>
3232
</record>
3333
<record id="py3o_template_configuration_tree_view" model="ir.ui.view">
34-
<field name="name">py3o.template.configuration.tree.view</field>
34+
<field name="name">py3o.template.configuration.list.view</field>
3535
<field name="model">py3o.template</field>
3636
<field name="arch" type="xml">
37-
<tree>
37+
<list>
3838
<field name="name" />
3939
<field name="filetype" />
40-
</tree>
40+
</list>
4141
</field>
4242
</record>
4343
<record id="py3o_template_configuration_action" model="ir.actions.act_window">
4444
<field name="name">Py3o Templates</field>
4545
<field name="res_model">py3o.template</field>
46-
<field name="view_mode">tree,form</field>
46+
<field name="view_mode">list,form</field>
4747
</record>
4848
<menuitem
4949
id="py3o_template_configuration_menu"

0 commit comments

Comments
 (0)