From 96609dad1826fdf8c30acd85ff281f61a848b50f Mon Sep 17 00:00:00 2001 From: Bruno Alla Date: Wed, 16 Oct 2024 19:04:53 +0100 Subject: [PATCH 1/8] Enable more Ruff rules --- pyproject.toml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 9128594..7448832 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -63,3 +63,13 @@ DJANGO_SETTINGS_MODULE = "tests.settings" [tool.coverage.run] plugins = ["django_coverage_plugin"] include = ["drf_excel/*"] + +[tool.ruff] +target-version = "py39" + +[tool.ruff.lint] +extend-select = [ + "B", # flake8-bugbear + "UP", # pyupgrade + "I", # isort +] From af7b49ed51001682107a716c758fd42cdf5d5e8c Mon Sep 17 00:00:00 2001 From: Bruno Alla Date: Wed, 16 Oct 2024 19:06:04 +0100 Subject: [PATCH 2/8] Allow Ruff to auto-fix issues --- .pre-commit-config.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9093aac..b939e3b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,5 +15,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.6.8 hooks: - - id: ruff-format - id: ruff + args: [--fix, --exit-non-zero-on-fix] + - id: ruff-format From c447108f9c5c289bb178a49397fb4dd490100e19 Mon Sep 17 00:00:00 2001 From: Bruno Alla Date: Wed, 16 Oct 2024 19:06:25 +0100 Subject: [PATCH 3/8] Update Ruff --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b939e3b..0ab43b5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,7 +13,7 @@ repos: - id: trailing-whitespace - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.6.8 + rev: v0.6.9 hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix] From 74fd14f132aec6a8f43a6e4465f32e0cd3868d25 Mon Sep 17 00:00:00 2001 From: Bruno Alla Date: Wed, 16 Oct 2024 19:07:02 +0100 Subject: [PATCH 4/8] Autofix issues with Ruff --- drf_excel/fields.py | 5 +++-- drf_excel/mixins.py | 6 +++--- drf_excel/renderers.py | 2 +- drf_excel/utilities.py | 2 +- tests/conftest.py | 2 +- tests/test_fields.py | 20 ++++++++++---------- tests/test_utilities.py | 7 +++---- tests/test_viewset_mixin.py | 2 +- tests/testapp/serializers.py | 2 +- tests/testapp/views.py | 5 +++-- tests/urls.py | 2 +- 11 files changed, 28 insertions(+), 27 deletions(-) diff --git a/drf_excel/fields.py b/drf_excel/fields.py index 62f0fb3..f6ad915 100644 --- a/drf_excel/fields.py +++ b/drf_excel/fields.py @@ -1,8 +1,9 @@ import contextlib import datetime import json +from collections.abc import Iterable from decimal import Decimal -from typing import Any, Callable, Iterable, Union +from typing import Any, Callable, Union from django.utils.dateparse import parse_date, parse_datetime, parse_time from openpyxl.cell import Cell @@ -29,7 +30,7 @@ from drf_excel.utilities import XLSXStyle, get_setting, sanitize_value, set_cell_style -class XLSXField(object): +class XLSXField: sanitize = True def __init__( diff --git a/drf_excel/mixins.py b/drf_excel/mixins.py index 8877a6d..edd2d90 100644 --- a/drf_excel/mixins.py +++ b/drf_excel/mixins.py @@ -2,7 +2,7 @@ from rest_framework.response import Response -class XLSXFileMixin(object): +class XLSXFileMixin: """ Mixin which allows the override of the filename being passed back to the user when the spreadsheet is downloaded. @@ -26,7 +26,7 @@ def finalize_response(self, request, response, *args, **kwargs): isinstance(response, Response) and response.accepted_renderer.format == "xlsx" ): - response["content-disposition"] = "attachment; filename={}".format( - escape_uri_path(self.get_filename(request=request, *args, **kwargs)), + response["content-disposition"] = ( + f"attachment; filename={escape_uri_path(self.get_filename(request=request, *args, **kwargs))}" ) return response diff --git a/drf_excel/renderers.py b/drf_excel/renderers.py index 5aa0e9e..fd33182 100644 --- a/drf_excel/renderers.py +++ b/drf_excel/renderers.py @@ -57,7 +57,7 @@ def render(self, data, accepted_media_type=None, renderer_context=None): Render `data` into XLSX workbook, returning a workbook. """ if data is None: - return bytes() + return b"" if not self._check_validation_data(data): return json.dumps(data) diff --git a/drf_excel/utilities.py b/drf_excel/utilities.py index b46492c..309001a 100644 --- a/drf_excel/utilities.py +++ b/drf_excel/utilities.py @@ -5,7 +5,7 @@ ESCAPE_CHARS = ("=", "-", "+", "@", "\t", "\r", "\n") -class XLSXStyle(object): +class XLSXStyle: # Class that holds all parts of a style, but without being an actual NamedStyle def __init__(self, style_dict=None): diff --git a/tests/conftest.py b/tests/conftest.py index 79cb2f9..d92a6ec 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,5 +1,5 @@ import io -from typing import Union, Callable +from typing import Callable, Union import pytest from openpyxl.reader.excel import load_workbook diff --git a/tests/test_fields.py b/tests/test_fields.py index 112e09c..bc582b0 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -1,28 +1,28 @@ -from decimal import Decimal import datetime as dt +from decimal import Decimal from types import SimpleNamespace import pytest from openpyxl.cell import Cell from openpyxl.worksheet.worksheet import Worksheet from rest_framework.fields import ( + BooleanField, CharField, - IntegerField, - FloatField, - DecimalField, - DateTimeField, DateField, - TimeField, + DateTimeField, + DecimalField, + FloatField, + IntegerField, ListField, - BooleanField, + TimeField, ) from drf_excel.fields import ( - XLSXField, - XLSXNumberField, + XLSXBooleanField, XLSXDateField, + XLSXField, XLSXListField, - XLSXBooleanField, + XLSXNumberField, ) from drf_excel.utilities import XLSXStyle diff --git a/tests/test_utilities.py b/tests/test_utilities.py index 6cc2f94..2c39dc6 100644 --- a/tests/test_utilities.py +++ b/tests/test_utilities.py @@ -1,16 +1,15 @@ +import datetime as dt from types import SimpleNamespace import pytest -import datetime as dt - from openpyxl.cell import Cell -from openpyxl.styles import Font, PatternFill, Alignment, Border, Color, Side +from openpyxl.styles import Alignment, Border, Color, Font, PatternFill, Side from openpyxl.worksheet.worksheet import Worksheet from drf_excel.utilities import ( - get_setting, XLSXStyle, get_attribute, + get_setting, sanitize_value, set_cell_style, ) diff --git a/tests/test_viewset_mixin.py b/tests/test_viewset_mixin.py index de8801a..eb0395c 100644 --- a/tests/test_viewset_mixin.py +++ b/tests/test_viewset_mixin.py @@ -4,7 +4,7 @@ from rest_framework.test import APIClient from time_machine import TimeMachineFixture -from tests.testapp.models import ExampleModel, AllFieldsModel, Tag +from tests.testapp.models import AllFieldsModel, ExampleModel, Tag pytestmark = pytest.mark.django_db diff --git a/tests/testapp/serializers.py b/tests/testapp/serializers.py index a138c7e..e788d2f 100644 --- a/tests/testapp/serializers.py +++ b/tests/testapp/serializers.py @@ -1,6 +1,6 @@ from rest_framework import serializers -from .models import ExampleModel, AllFieldsModel +from .models import AllFieldsModel, ExampleModel class ExampleSerializer(serializers.ModelSerializer): diff --git a/tests/testapp/views.py b/tests/testapp/views.py index 33f5fc7..f435cd4 100644 --- a/tests/testapp/views.py +++ b/tests/testapp/views.py @@ -1,9 +1,10 @@ from rest_framework.viewsets import ReadOnlyModelViewSet + from drf_excel.mixins import XLSXFileMixin from drf_excel.renderers import XLSXRenderer -from .models import ExampleModel, AllFieldsModel -from .serializers import ExampleSerializer, AllFieldsSerializer +from .models import AllFieldsModel, ExampleModel +from .serializers import AllFieldsSerializer, ExampleSerializer class ExampleViewSet(XLSXFileMixin, ReadOnlyModelViewSet): diff --git a/tests/urls.py b/tests/urls.py index d2a8ebb..30a06d5 100644 --- a/tests/urls.py +++ b/tests/urls.py @@ -1,6 +1,6 @@ from rest_framework import routers -from .testapp.views import ExampleViewSet, AllFieldsViewSet +from .testapp.views import AllFieldsViewSet, ExampleViewSet router = routers.SimpleRouter() router.register(r"examples", ExampleViewSet) From 4996655a20a9d87c7c70fe306b100bc472cc0118 Mon Sep 17 00:00:00 2001 From: Bruno Alla Date: Wed, 16 Oct 2024 19:09:08 +0100 Subject: [PATCH 5/8] Manual fix issue flagged by Ruff --- drf_excel/renderers.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drf_excel/renderers.py b/drf_excel/renderers.py index fd33182..56727e9 100644 --- a/drf_excel/renderers.py +++ b/drf_excel/renderers.py @@ -1,7 +1,6 @@ import json from collections.abc import Iterable, MutableMapping from tempfile import TemporaryFile -from typing import Dict from django.utils.functional import Promise from openpyxl import Workbook @@ -315,7 +314,7 @@ def _get_label(parent_label, label_sep, obj): return _header_dict - def _flatten_data(self, data, parent_key="", key_sep=".") -> Dict[str, XLSXField]: + def _flatten_data(self, data, parent_key="", key_sep=".") -> dict[str, XLSXField]: items = [] for k, v in data.items(): new_key = f"{parent_key}{key_sep}{k}" if parent_key else k From 3c7b8e1259a0fd8bf1c076f8f73487e458cabbc0 Mon Sep 17 00:00:00 2001 From: Bruno Alla Date: Wed, 16 Oct 2024 19:09:29 +0100 Subject: [PATCH 6/8] Ignore issue raised by flake8-bugbear --- drf_excel/mixins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drf_excel/mixins.py b/drf_excel/mixins.py index edd2d90..a3623c2 100644 --- a/drf_excel/mixins.py +++ b/drf_excel/mixins.py @@ -27,6 +27,6 @@ def finalize_response(self, request, response, *args, **kwargs): and response.accepted_renderer.format == "xlsx" ): response["content-disposition"] = ( - f"attachment; filename={escape_uri_path(self.get_filename(request=request, *args, **kwargs))}" + f"attachment; filename={escape_uri_path(self.get_filename(request=request, *args, **kwargs))}" # noqa: B026 ) return response From fb61e33475d779fea349f29f167e67456fbb9473 Mon Sep 17 00:00:00 2001 From: Bruno Alla Date: Wed, 16 Oct 2024 19:11:27 +0100 Subject: [PATCH 7/8] Split long statement over 2 lines --- drf_excel/mixins.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drf_excel/mixins.py b/drf_excel/mixins.py index a3623c2..f857166 100644 --- a/drf_excel/mixins.py +++ b/drf_excel/mixins.py @@ -26,7 +26,8 @@ def finalize_response(self, request, response, *args, **kwargs): isinstance(response, Response) and response.accepted_renderer.format == "xlsx" ): + filename = self.get_filename(request=request, *args, **kwargs) # noqa: B026 response["content-disposition"] = ( - f"attachment; filename={escape_uri_path(self.get_filename(request=request, *args, **kwargs))}" # noqa: B026 + f"attachment; filename={escape_uri_path(filename)}" ) return response From c9ca309d6c718a11b35505e5fd2a4a34bcc9a850 Mon Sep 17 00:00:00 2001 From: Bruno Alla Date: Wed, 16 Oct 2024 19:21:56 +0100 Subject: [PATCH 8/8] Fix B026 warning --- drf_excel/mixins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drf_excel/mixins.py b/drf_excel/mixins.py index f857166..709a044 100644 --- a/drf_excel/mixins.py +++ b/drf_excel/mixins.py @@ -26,7 +26,7 @@ def finalize_response(self, request, response, *args, **kwargs): isinstance(response, Response) and response.accepted_renderer.format == "xlsx" ): - filename = self.get_filename(request=request, *args, **kwargs) # noqa: B026 + filename = self.get_filename(request, *args, **kwargs) response["content-disposition"] = ( f"attachment; filename={escape_uri_path(filename)}" )