Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate 'escape html' #1618

Merged
7 changes: 3 additions & 4 deletions .github/workflows/django-import-export-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ jobs:
fail-fast: true
matrix:
python-version:
- '3.7'
- '3.8'
- '3.9'
- '3.10'
Expand All @@ -45,8 +44,8 @@ jobs:
- name: Set up MySQL
run: >
sudo /etc/init.d/mysql start
mysql -e 'CREATE DATABASE ${{ env.DB_NAME }};'

mysql -e 'CREATE DATABASE ${{ env.DB_NAME }};'
-u${{ env.IMPORT_EXPORT_MYSQL_USER }}
-p${{ env.IMPORT_EXPORT_MYSQL_PASSWORD }}
- name: Check out repository code
Expand All @@ -57,7 +56,7 @@ jobs:
python-version: ${{ matrix.python-version }}
- name: Install Dependencies
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade pip
pip install tox coverage coveralls
- name: Run tox targets for ${{ matrix.python-version }} (sqlite)
run: tox run -f py$(echo ${{ matrix.python-version }} | tr -d .)
Expand Down
9 changes: 8 additions & 1 deletion docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,16 @@ Changelog
- Added support for Django 4.2 (#1570)
- Refactoring and fix to support filtering exports (#1579)
- Store ``instance`` and ``original`` object in :class:`~import_export.results.RowResult` (#1584)
- Removed reference to tablib dev from tox build (#1603)
- Add customizable blocks in import.html (#1598)
- Removed reference to tablib dev from tox build (#1603)
- Updated ru translation (#1604)
- Remove 'escape output' deprecation (#1618)

- Removal of deprecated :ref:`IMPORT_EXPORT_ESCAPE_OUTPUT_ON_EXPORT`.

- Deprecation of :ref:`IMPORT_EXPORT_ESCAPE_HTML_ON_EXPORT`. Refer to :ref:`installation`.

- Removed support for python3.7 and django4.0 (past EOL) (#1618)
- removed duplicate admin integration tests (#1616)
- Fix for cache entries not removed (#1621)
- Fixed badly formatted translation string (#1622)
Expand Down
12 changes: 3 additions & 9 deletions docs/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -120,20 +120,14 @@ Note that if you disable transaction support via configuration (or if your datab
does not support transactions), then validation errors will still be presented to the user
but valid rows will have imported.

``IMPORT_EXPORT_ESCAPE_OUTPUT_ON_EXPORT``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If set to ``True``, export output will be sanitized. By default this is set to ``False``.

Note: currently this only works for ``HTML`` output, and only for exports done via the admin UI.

This setting is deprecated and will be replaced by ``IMPORT_EXPORT_ESCAPE_HTML_ON_EXPORT``.

``IMPORT_EXPORT_ESCAPE_HTML_ON_EXPORT``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If set to ``True``, strings will be HTML escaped. By default this is ``False``.

This is deprecated and will be removed in a future release. Future releases will
escape strings by default.

``IMPORT_EXPORT_ESCAPE_FORMULAE_ON_EXPORT``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Expand Down
1 change: 0 additions & 1 deletion import_export/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -753,7 +753,6 @@ def get_export_data(self, file_format, queryset, *args, **kwargs):
data = self.get_data_for_export(request, queryset, *args, **kwargs)
export_data = file_format.export_data(
data,
escape_output=self.should_escape_output,
escape_html=self.should_escape_html,
escape_formulae=self.should_escape_formulae,
)
Expand Down
14 changes: 2 additions & 12 deletions import_export/formats/base_formats.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import html
import warnings

import tablib
from tablib.formats import registry
Expand All @@ -15,7 +14,7 @@ def create_dataset(self, in_stream):
"""
raise NotImplementedError()

def export_data(self, dataset, escape_output=False, **kwargs):
def export_data(self, dataset, **kwargs):
"""
Returns format representation for given dataset.
"""
Expand Down Expand Up @@ -86,8 +85,6 @@ def create_dataset(self, in_stream, **kwargs):
return tablib.import_set(in_stream, format=self.get_title(), **kwargs)

def export_data(self, dataset, **kwargs):
# remove the deprecated `escape_output` param if present
kwargs.pop("escape_output", None)
if kwargs.pop("escape_html", None):
self._escape_html(dataset)
if kwargs.pop("escape_formulae", None):
Expand Down Expand Up @@ -168,14 +165,7 @@ class HTML(TextFormat):
TABLIB_MODULE = "tablib.formats._html"
CONTENT_TYPE = "text/html"

def export_data(self, dataset, escape_output=False, **kwargs):
if escape_output:
warnings.warn(
"escape_output flag now deprecated - "
"this will be removed in a future release",
DeprecationWarning,
)
super()._escape_html(dataset)
def export_data(self, dataset, **kwargs):
return super().export_data(dataset, **kwargs)


Expand Down
19 changes: 5 additions & 14 deletions import_export/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,20 +113,13 @@ class BaseExportMixin(BaseImportExportMixin):
escape_formulae = False

@property
def should_escape_output(self):
if hasattr(settings, "IMPORT_EXPORT_ESCAPE_OUTPUT_ON_EXPORT"):
def should_escape_html(self):
if hasattr(settings, "IMPORT_EXPORT_ESCAPE_HTML_ON_EXPORT"):
warnings.warn(
"IMPORT_EXPORT_ESCAPE_OUTPUT_ON_EXPORT will be deprecated "
"in a future release. "
"Refer to docs for new attributes.",
"IMPORT_EXPORT_ESCAPE_HTML_ON_EXPORT is deprecated and "
"will be removed in a future release.",
DeprecationWarning,
)
return getattr(
settings, "IMPORT_EXPORT_ESCAPE_OUTPUT_ON_EXPORT", self.escape_exported_data
)

@property
def should_escape_html(self):
v = getattr(settings, "IMPORT_EXPORT_ESCAPE_HTML_ON_EXPORT", self.escape_html)
if v is True:
logger.debug("IMPORT_EXPORT_ESCAPE_HTML_ON_EXPORT is enabled")
Expand Down Expand Up @@ -198,9 +191,7 @@ def get_export_data(self, file_format, queryset, *args, **kwargs):
Returns file_format representation for given queryset.
"""
data = self.get_data_for_export(self.request, queryset, *args, **kwargs)
export_data = file_format.export_data(
data, escape_output=self.should_escape_output
)
export_data = file_format.export_data(data)
return export_data

def get_context_data(self, **kwargs):
Expand Down
3 changes: 2 additions & 1 deletion requirements/base.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
Django>=3.2
tablib[html,ods,xls,xlsx,yaml]>=3.4.0
# tablib temporarily pinned to 3.5.0 - see issue #1602
tablib[html,ods,xls,xlsx,yaml]==3.5.0
diff-match-patch
7 changes: 3 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@
CLASSIFIERS = [
"Framework :: Django",
"Framework :: Django :: 3.2",
"Framework :: Django :: 4.0",
"Framework :: Django :: 4.1",
"Framework :: Django :: 4.2",
"Intended Audience :: Developers",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
Expand All @@ -24,10 +22,11 @@
"Topic :: Software Development",
]

# tablib temporarily pinned to 3.5.0 - see issue #1602
install_requires = [
"diff-match-patch",
"Django>=3.2",
"tablib[html,ods,xls,xlsx,yaml]>=3.4.0",
"tablib[html,ods,xls,xlsx,yaml]==3.5.0",
]


Expand Down Expand Up @@ -55,7 +54,7 @@
packages=find_packages(exclude=["tests"]),
include_package_data=True,
install_requires=install_requires,
python_requires=">=3.7",
python_requires=">=3.8",
classifiers=CLASSIFIERS,
zip_safe=False,
)
30 changes: 4 additions & 26 deletions tests/core/tests/test_admin_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -712,27 +712,6 @@ def test_returns_xlsx_export(self):
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
)

@override_settings(IMPORT_EXPORT_ESCAPE_HTML_ON_EXPORT=True)
@patch("import_export.mixins.logger")
def test_export_escape_html(self, mock_logger):
Book.objects.create(id=1, name="=SUM(1+1)")
Book.objects.create(id=2, name="<script>alert(1)</script>")
response = self.client.get("/admin/core/book/export/")
self.assertEqual(response.status_code, 200)

xlsx_index = self._get_input_format_index("xlsx")
data = {"file_format": str(xlsx_index)}
response = self.client.post("/admin/core/book/export/", data)
self.assertEqual(response.status_code, 200)
content = response.content
wb = load_workbook(filename=BytesIO(content))
self.assertEqual("&lt;script&gt;alert(1)&lt;/script&gt;", wb.active["B2"].value)
self.assertEqual("=SUM(1+1)", wb.active["B3"].value)

mock_logger.debug.assert_called_once_with(
"IMPORT_EXPORT_ESCAPE_HTML_ON_EXPORT is enabled"
)

@override_settings(IMPORT_EXPORT_ESCAPE_FORMULAE_ON_EXPORT=True)
@patch("import_export.mixins.logger")
def test_export_escape_formulae(self, mock_logger):
Expand All @@ -754,18 +733,17 @@ def test_export_escape_formulae(self, mock_logger):
"IMPORT_EXPORT_ESCAPE_FORMULAE_ON_EXPORT is enabled"
)

@override_settings(IMPORT_EXPORT_ESCAPE_OUTPUT_ON_EXPORT=True)
def test_export_escape_deprecation_warning(self):
@override_settings(IMPORT_EXPORT_ESCAPE_HTML_ON_EXPORT=True)
def test_export_escape_html_deprecation_warning(self):
response = self.client.get("/admin/core/book/export/")
self.assertEqual(response.status_code, 200)

xlsx_index = self._get_input_format_index("xlsx")
data = {"file_format": str(xlsx_index)}
with self.assertWarnsRegex(
DeprecationWarning,
r"IMPORT_EXPORT_ESCAPE_OUTPUT_ON_EXPORT will be "
"deprecated in a future release. "
r"Refer to docs for new attributes.",
r"IMPORT_EXPORT_ESCAPE_HTML_ON_EXPORT is deprecated "
"and will be removed in a future release.",
):
self.client.post("/admin/core/book/export/", data)

Expand Down
23 changes: 0 additions & 23 deletions tests/core/tests/test_base_formats.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,29 +210,6 @@ def setUp(self):
)
)

def test_export_data_escape(self):
# deprecated
# this test can be removed in a future release because the param
# is replaced by `escape_html`
with self.assertWarnsRegex(
DeprecationWarning,
"escape_output flag now deprecated - "
"this will be removed in a future release",
):
res = self.format.export_data(self.dataset, escape_output=True)
self.assertIn(
(
"<tr><td>1</td>\n"
"<td>good_user</td>\n"
"<td>John Doe</td></tr>\n"
"<tr><td>2</td>\n"
"<td>evil_user</td>\n"
"<td>&lt;script&gt;alert(&quot;I want to steal your credit card "
"data&quot;)&lt;/script&gt;</td></tr>\n"
),
res,
)

def test_export_html_escape(self):
res = self.format.export_data(self.dataset, escape_html=True)
self.assertIn(
Expand Down
7 changes: 3 additions & 4 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
[tox]
min_version = 4.0
envlist =
{py37,py38,py39,py310}-{django32}
{py38,py39,py310}-{django40}
{py38,py39,py310}-{django32}
{py310,py311}-{django41,django42,djangomain}
# tablib dev temporarily removed - see issue #1602
# py311-djangomain-tablibdev

[gh-actions]
python =
3.7: py37
3.8: py38
3.9: py39
3.10: py310
Expand All @@ -19,7 +19,6 @@ commands = python ./runtests.py
deps =
tablibdev: -egit+https://github.com/jazzband/tablib.git@master\#egg=tablib
django32: Django>=3.2,<4.0
django40: Django>=4.0,<4.1
django41: Django>=4.1,<4.2
django42: Django>=4.2,<4.3
djangomain: https://github.com/django/django/archive/main.tar.gz
Expand Down