diff --git a/dje/views.py b/dje/views.py index c722e2fd..afc5b50d 100644 --- a/dje/views.py +++ b/dje/views.py @@ -1880,6 +1880,7 @@ class DownloadableMixin: "doc": "application/msword", "html": "text/html", "json": "application/json", + "ods": "application/vnd.oasis.opendocument.spreadsheet", "xls": "application/vnd.ms-excel", "xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "yaml": "application/x-yaml", diff --git a/docs/images/tutorial-6-vuln-report/export-report-to-xlsx.png b/docs/images/tutorial-6-vuln-report/export-report-to-xlsx.png index 83d42593..cb5deed6 100644 Binary files a/docs/images/tutorial-6-vuln-report/export-report-to-xlsx.png and b/docs/images/tutorial-6-vuln-report/export-report-to-xlsx.png differ diff --git a/pyproject.toml b/pyproject.toml index 15622423..90651799 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -154,7 +154,10 @@ dependencies = [ "annotated-types==0.7.0", "semantic-version==2.10.0", # OpenVEX - "msgspec==0.20.0" + "msgspec==0.20.0", + # OpenDocument Format + "odfdo==3.20.2", + "lxml==6.0.2", ] [project.optional-dependencies] diff --git a/reporting/templates/reporting/report_run.html b/reporting/templates/reporting/report_run.html index ddd7db11..a14fea63 100644 --- a/reporting/templates/reporting/report_run.html +++ b/reporting/templates/reporting/report_run.html @@ -52,12 +52,13 @@

diff --git a/reporting/tests/test_views.py b/reporting/tests/test_views.py index 9a4a3847..ae34dcfa 100644 --- a/reporting/tests/test_views.py +++ b/reporting/tests/test_views.py @@ -429,7 +429,7 @@ def test_report_view_get_json_response(self): [0, 1, 2], list(self.column_template.fields.all().values_list("seq", flat=True)) ) - # In case of a change: print repr(response.content) + # In case of a change: print(repr(response.content)) expected = ( "{\n " '"key": "license_126",\n ' @@ -448,10 +448,19 @@ def test_report_view_get_yaml_response(self): ) self.assertEqual(response["Content-Type"], "application/x-yaml") - # In case of a change: >>> print repr(response.content) + # In case of a change: >>> print(repr(response.content)) expected = "- key: license_138\n short_name: license_138\n name: license_138\n" self.assertContains(response, expected) + def test_report_view_get_ods_response(self): + self.client.login(username="test", password="t3st") + url = self.report.get_absolute_url() + "?format=ods" + response = self.client.get(url) + self.assertEqual( + response["Content-Disposition"], 'attachment; filename="license-list-for-analysis.ods"' + ) + self.assertEqual(response["Content-Type"], "application/vnd.oasis.opendocument.spreadsheet") + def test_run_report_view_runtime_parameters_value_fields(self): self.client.login(username="test", password="t3st") diff --git a/reporting/views.py b/reporting/views.py index afa00f2c..86aad47b 100644 --- a/reporting/views.py +++ b/reporting/views.py @@ -24,6 +24,7 @@ from django.views.generic.detail import SingleObjectMixin from django.views.generic.list import MultipleObjectMixin +import odfdo import saneyaml import xlsxwriter @@ -232,6 +233,28 @@ def get_yaml_response(self, **response_kwargs): dump = self.get_dump(saneyaml.dump) return HttpResponse(dump, **response_kwargs) + def get_ods_response(self, **response_kwargs): + """Return the results as ods format.""" + context = self.get_context_data(**self.kwargs) + report_data = [context["headers"]] + context["output"] + + document = odfdo.Document("spreadsheet") + table = odfdo.Table("Report") + + for row_data in report_data: + row = odfdo.Row() + for cell_value in row_data: + row.append(odfdo.Cell(normalize_newlines(cell_value), cell_type="string")) + table.append(row) + + document.body.clear() + document.body.append(table) + + file_output = io.BytesIO() + document.save(file_output) + + return HttpResponse(file_output.getvalue(), **response_kwargs) + def get_xlsx_response(self, **response_kwargs): """Return the results as `xlsx` format.""" context = self.get_context_data(**self.kwargs) diff --git a/thirdparty/dist/lxml-6.0.2-cp314-cp314-macosx_10_13_universal2.whl b/thirdparty/dist/lxml-6.0.2-cp314-cp314-macosx_10_13_universal2.whl new file mode 100644 index 00000000..eb4f4a3f Binary files /dev/null and b/thirdparty/dist/lxml-6.0.2-cp314-cp314-macosx_10_13_universal2.whl differ diff --git a/thirdparty/dist/lxml-6.0.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl b/thirdparty/dist/lxml-6.0.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl new file mode 100644 index 00000000..9da79f6e Binary files /dev/null and b/thirdparty/dist/lxml-6.0.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl differ diff --git a/thirdparty/dist/lxml-6.0.2.tar.gz b/thirdparty/dist/lxml-6.0.2.tar.gz new file mode 100644 index 00000000..c2dcbf42 Binary files /dev/null and b/thirdparty/dist/lxml-6.0.2.tar.gz differ diff --git a/thirdparty/dist/lxml-6.0.2.tar.gz.ABOUT b/thirdparty/dist/lxml-6.0.2.tar.gz.ABOUT new file mode 100644 index 00000000..c56970d2 --- /dev/null +++ b/thirdparty/dist/lxml-6.0.2.tar.gz.ABOUT @@ -0,0 +1,63 @@ +about_resource: lxml-6.0.2.tar.gz +name: lxml +version: 6.0.2 +download_url: https://files.pythonhosted.org/packages/aa/88/262177de60548e5a2bfc46ad28232c9e9cbde697bd94132aeb80364675cb/lxml-6.0.2.tar.gz +description: | + Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API. + lxml is a Pythonic, mature binding for the libxml2 and libxslt libraries. + It provides safe and convenient access to these libraries using the + ElementTree API. + + It extends the ElementTree API significantly to offer support for XPath, + RelaxNG, XML Schema, XSLT, C14N and much more. + + To contact the project, go to the `project home page `_ + or see our bug tracker at https://launchpad.net/lxml + + In case you want to use the current in-development version of lxml, + you can get it from the github repository at + https://github.com/lxml/lxml . Note that this requires Cython to + build the sources, see the build instructions on the project home page. + + + After an official release of a new stable series, bug fixes may become available at + https://github.com/lxml/lxml/tree/lxml-6.0 . + Running ``pip install https://github.com/lxml/lxml/archive/refs/heads/lxml-6.0.tar.gz`` + will install the unreleased branch state as soon as a maintenance branch has been established. + Note that this requires Cython to be installed at an appropriate version for the build. + + 6.0.2 (2025-09-21) + ================== + + Bugs fixed + ---------- + + * LP#2125278: Compilation with libxml2 2.15.0 failed. + Original patch by Xi Ruoyao. + + * Setting ``decompress=True`` in the parser had no effect in libxml2 2.15. + + * Binary wheels on Linux and macOS use the library version libxml2 2.14.6. + See https://gitlab.gnome.org/GNOME/libxml2/-/releases/v2.14.6 + + * Test failures in libxml2 2.15.0 were fixed. + + Other changes + ------------- + + * Binary wheels for Py3.9-3.11 on the ``riscv64`` architecture were added. + + * Error constants were updated to match libxml2 2.15.0. + + * Built using Cython 3.1.4. +homepage_url: https://lxml.de/ +package_url: pkg:pypi/lxml@6.0.2 +license_expression: bsd-new +copyright: Copyright Rick Jelliffe and Academia Sinica Computing Center +attribute: yes +checksum_md5: ac9a945976227fd854d3e9e034e52ca1 +checksum_sha1: 2b37a3d8ad8afe74b7ec616dc695ccc25a73bd97 +licenses: + - key: bsd-new + name: BSD-3-Clause + file: bsd-new.LICENSE diff --git a/thirdparty/dist/odfdo-3.20.2-py3-none-any.whl b/thirdparty/dist/odfdo-3.20.2-py3-none-any.whl new file mode 100644 index 00000000..27ee7a2d Binary files /dev/null and b/thirdparty/dist/odfdo-3.20.2-py3-none-any.whl differ diff --git a/thirdparty/dist/odfdo-3.20.2-py3-none-any.whl.ABOUT b/thirdparty/dist/odfdo-3.20.2-py3-none-any.whl.ABOUT new file mode 100644 index 00000000..5ba8ac74 --- /dev/null +++ b/thirdparty/dist/odfdo-3.20.2-py3-none-any.whl.ABOUT @@ -0,0 +1,15 @@ +about_resource: odfdo-3.20.2-py3-none-any.whl +name: odfdo +version: 3.20.2 +download_url: https://files.pythonhosted.org/packages/8c/7d/b96844125aa731c4624e363708b55afc75f3855f47978a64ed8757bd37a8/odfdo-3.20.2-py3-none-any.whl +package_url: pkg:pypi/odfdo@3.20.2 +license_expression: apache-2.0 +copyright: Copyright odfdo project contributors +attribute: yes +track_changes: yes +checksum_md5: 6686aef9f543d835b262b8c916baa6a2 +checksum_sha1: 31d00a8500c19343b363e6981840b20a0ddd17ff +licenses: + - key: apache-2.0 + name: Apache License 2.0 + file: apache-2.0.LICENSE