diff --git a/bmds_ui/analysis/api.py b/bmds_ui/analysis/api.py index 1a2c3015..6fcdea08 100644 --- a/bmds_ui/analysis/api.py +++ b/bmds_ui/analysis/api.py @@ -52,7 +52,7 @@ def patch_inputs(self, request, *args, **kwargs): try: validators.validate_input(data, partial=partial) except ValidationError as err: - raise exceptions.ValidationError(err.message) + raise exceptions.ValidationError(err.message) from None instance.reset_execution() instance.inputs = data @@ -207,7 +207,7 @@ def _run_analysis(self, request) -> PolyKAdjustment: try: settings = pydantic_validate(request.data, schema.PolyKInput) except ValidationError as err: - raise exceptions.ValidationError(err.message) + raise exceptions.ValidationError(err.message) from None return settings.calculate() def create(self, request, *args, **kwargs): diff --git a/bmds_ui/analysis/serializers.py b/bmds_ui/analysis/serializers.py index 2b2b01f7..9759c107 100644 --- a/bmds_ui/analysis/serializers.py +++ b/bmds_ui/analysis/serializers.py @@ -65,5 +65,5 @@ def validate_inputs(self, value): try: validators.validate_input(value) except ValueError as err: - raise serializers.ValidationError(err) + raise serializers.ValidationError("Validation failed") from err return value diff --git a/bmds_ui/common/templatetags/bs4.py b/bmds_ui/common/templatetags/bs4.py index 8b12c5bd..6ad26d93 100644 --- a/bmds_ui/common/templatetags/bs4.py +++ b/bmds_ui/common/templatetags/bs4.py @@ -8,8 +8,7 @@ from django import template from django.utils import timezone -from django.utils.html import escapejs -from django.utils.safestring import mark_safe +from django.utils.html import escapejs, format_html from plotly.graph_objs._figure import Figure register = template.Library() @@ -39,7 +38,7 @@ def render(self, context): @register.simple_tag def icon(name: str): - return mark_safe(f'') + return format_html('', name=name) @register.simple_tag() @@ -48,18 +47,18 @@ def plotly(fig: Figure) -> str | None: if fig is None: return "" id = uuid4() - return mark_safe( - dedent( - f""" + return format_html( + dedent("""
Loading...
""" - ) + """), + id=id, + json=escapejs(fig.to_json()), ) diff --git a/bmds_ui/common/validation.py b/bmds_ui/common/validation.py index ee34f8b7..8b044b11 100644 --- a/bmds_ui/common/validation.py +++ b/bmds_ui/common/validation.py @@ -23,4 +23,4 @@ def pydantic_validate(data: Any, model: type[T]) -> T: try: return model.model_validate(data) except PydanticValidationError as err: - raise ValidationError(err.json()) + raise ValidationError(err.json()) from None diff --git a/bmds_ui/common/views.py b/bmds_ui/common/views.py index 7ed1d3b4..c884f544 100644 --- a/bmds_ui/common/views.py +++ b/bmds_ui/common/views.py @@ -214,11 +214,11 @@ def uuid_or_404(value: str) -> UUID: try: return UUID(value) except ValueError: - raise Http404() + raise Http404() from None def int_or_404(value: str) -> int: try: return int(value) except ValueError: - raise Http404() + raise Http404() from None diff --git a/bmds_ui/desktop/components/database_form.py b/bmds_ui/desktop/components/database_form.py index e5f15792..9e5e75b2 100644 --- a/bmds_ui/desktop/components/database_form.py +++ b/bmds_ui/desktop/components/database_form.py @@ -43,14 +43,14 @@ def additional_path_checks(path: Path): try: path.exists() except PermissionError: - raise ValueError(f"Permission denied: {path}") + raise ValueError(f"Permission denied: {path}") from None # create parent path if it doesn't already exist if not path.parent.exists(): try: path.parent.mkdir(parents=True) except Exception: - raise ValueError(f"Cannot create path {path.parent}") + raise ValueError(f"Cannot create path {path.parent}") from None # check path is writable if not path.exists(): @@ -59,7 +59,7 @@ def additional_path_checks(path: Path): f.write("test") f.flush() except Exception: - raise ValueError(f"Cannot write to {path.parent}") + raise ValueError(f"Cannot write to {path.parent}") from None # check existing database is loadable and writeable if path.exists(): @@ -70,7 +70,7 @@ def additional_path_checks(path: Path): conn.commit() conn.close() except (sqlite3.DatabaseError, sqlite3.OperationalError): - raise ValueError(f"Cannot edit database {path}. Is this a sqlite database?") + raise ValueError(f"Cannot edit database {path}. Is this a sqlite database?") from None class NullWidget(Widget): diff --git a/bmds_ui/desktop/config.py b/bmds_ui/desktop/config.py index e2202b2a..fe69e25c 100644 --- a/bmds_ui/desktop/config.py +++ b/bmds_ui/desktop/config.py @@ -159,9 +159,7 @@ def get(cls) -> DesktopConfig: try: cls._config = DesktopConfig.model_validate_json(cls._config_path.read_text()) except ValidationError as err: - raise DesktopException( - f"Cannot parse configuration: {cls._config_path}\n\nSpecific error:{err}" - ) + raise DesktopException(f"Cannot parse configuration: {cls._config_path}") from err return cls._config @classmethod diff --git a/pyproject.toml b/pyproject.toml index 9c728622..ae32a672 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -112,16 +112,12 @@ omit = [ ] [tool.ruff] +exclude = ["scripts"] line-length = 100 -target-version = "py311" - -[tool.ruff.lint] -select = ["F", "E", "W", "I", "UP", "S", "B", "T20", "RUF"] -ignore = ["E501", "B904", "B007", "S308", "S113", "S314"] -unfixable = ["F401", "F841"] - -[tool.ruff.lint.isort] -known-first-party = ["bmds_ui", "pybmds"] +lint.select = ["F", "E", "W", "I", "UP", "S", "B", "T20", "ERA", "NPY", "RUF", "PTH"] +lint.ignore = ["E501"] +lint.unfixable = ["F401", "F841"] +lint.isort.known-first-party = ["bmds_ui", "pybmds"] [tool.ruff.lint.per-file-ignores] "test_*.py" = ["S101", "S106"] diff --git a/tests/analysis/test_executor.py b/tests/analysis/test_executor.py index 5ed921a1..b4d0b05e 100644 --- a/tests/analysis/test_executor.py +++ b/tests/analysis/test_executor.py @@ -72,14 +72,14 @@ def _expected_degree(session, n: int): degrees = set([model.settings.degree for model in session.frequentist.models]) assert degrees == set(list(range(1, n + 1))) - # degree = 1 + # check when degree = 1 data = deepcopy(complete_dichotomous) data["models"] = {"frequentist_restricted": ["Multistage"]} data["dataset_options"][0]["degree"] = 1 session = AnalysisSession.create(data, 0, 0) _expected_degree(session, 1) - # degree = 2 + # check when degree = 2 data = deepcopy(complete_dichotomous) data["models"] = {"frequentist_restricted": ["Multistage"]} data["dataset_options"][0]["degree"] = 2 diff --git a/tests/common/test_api.py b/tests/common/test_api.py index 84e66c6a..913d9919 100644 --- a/tests/common/test_api.py +++ b/tests/common/test_api.py @@ -45,7 +45,7 @@ def test_throttle(self): # success - admin url = reverse("api:healthcheck-throttle") - for i in range(5): + for _ in range(5): resp = admin.get(url) assert resp.status_code == 200 assert "identity" in resp.data diff --git a/tests/common/test_diagnostics.py b/tests/common/test_diagnostics.py index c3c4281e..dcb81208 100644 --- a/tests/common/test_diagnostics.py +++ b/tests/common/test_diagnostics.py @@ -6,7 +6,6 @@ @pytest.fixture -@pytest.mark.django_db def admin_client(): client = Client() client.login(username="admin@bmdsonline.org", password="pw") diff --git a/tests/common/test_worker_health.py b/tests/common/test_worker_health.py index 192cd779..3b3f6762 100644 --- a/tests/common/test_worker_health.py +++ b/tests/common/test_worker_health.py @@ -19,7 +19,7 @@ def test_worker_healthcheck(): # has recent data; should be healthy worker.MAX_SIZE = 5 - for i in range(worker.MAX_SIZE + 2): + for _ in range(worker.MAX_SIZE + 2): worker.push() assert worker.healthy() is True assert worker.series().size == worker.MAX_SIZE diff --git a/tests/desktop/test_config.py b/tests/desktop/test_config.py index d49d9135..fcbbc50f 100644 --- a/tests/desktop/test_config.py +++ b/tests/desktop/test_config.py @@ -14,4 +14,4 @@ def test_get_version_path(): def test_get_app_home(): assert "bmds" in str(config.get_app_home()) - assert Path(".") == config.get_app_home(path_str=".") + assert Path() == config.get_app_home(path_str=".")