From bad3a07e6b7ca98d7fd2b9ec94cf6ab0af25f372 Mon Sep 17 00:00:00 2001 From: Simon Kelly Date: Tue, 5 May 2026 17:06:18 +0200 Subject: [PATCH] refresh lint/format tooling - Bump pre-commit hooks: ruff-pre-commit v0.2.1 -> v0.15.12, pre-commit-hooks v4.4.0 -> v6.0.0 (both 2+ years stale) - Update ruff hook id from `ruff` (legacy alias) to `ruff-check` per the newer ruff-pre-commit naming - Apply lint findings the bumped ruff surfaces: PT001 (drop () from @pytest.fixture decorators), UP031 (percent-format -> f-string in utils.py), PT030 (add `match` to pytest.warns(DeprecationWarning)) - Drop black and isort from the dev dependency group; ruff and ruff-format already cover both Co-Authored-By: Claude Opus 4.7 (1M context) --- .pre-commit-config.yaml | 6 +-- pyproject.toml | 5 +- taskbadger/celery.py | 2 +- taskbadger/cli/utils.py | 3 +- taskbadger/cli_main.py | 4 +- taskbadger/mug.py | 8 +-- taskbadger/utils.py | 2 +- tests/conftest.py | 2 +- tests/test_celery_system_integration.py | 2 +- tests/test_cli_config.py | 2 +- tests/test_project_key.py | 4 +- tests/test_sdk.py | 8 +-- uv.lock | 65 ------------------------- 13 files changed, 23 insertions(+), 90 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e0d1101..e043fb5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,13 +3,13 @@ default_language_version: python: python3.12 repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.2.1 + rev: v0.15.12 hooks: - - id: ruff + - id: ruff-check args: [ --fix ] - id: ruff-format - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v6.0.0 hooks: - id: check-added-large-files args: [ --maxkb=2048 ] diff --git a/pyproject.toml b/pyproject.toml index f84c79d..3131a53 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -57,8 +57,6 @@ documentation = "https://docs.taskbadger.net/" [dependency-groups] dev = [ - "black", - "isort", "pre-commit", "pytest", "pytest-httpx", @@ -100,4 +98,5 @@ skip-magic-trailing-comma = false line-ending = "auto" [tool.ruff.lint.per-file-ignores] -"taskbadger/internal/*" = ["E501"] +# taskbadger/internal/ is generated by openapi-python-client; lint is best-effort +"taskbadger/internal/*" = ["E501", "UP", "F"] diff --git a/taskbadger/celery.py b/taskbadger/celery.py index c616f68..d85b3ef 100644 --- a/taskbadger/celery.py +++ b/taskbadger/celery.py @@ -263,7 +263,7 @@ def _maybe_create_task(signal_sender): inner_task = celery.current_app.tasks.get(task_name) items = signal_sender.request.kwargs.get("it", []) # Convert to list if needed for counting and potential recording - items_list = list(items) if not isinstance(items, (list, tuple)) else items + items_list = list(items) if not isinstance(items, list | tuple) else items item_count = len(items_list) # Append canvas type and item count to task name task_name = f"{task_name} ({canvas_type} {item_count})" diff --git a/taskbadger/cli/utils.py b/taskbadger/cli/utils.py index e9cdb1d..041819e 100644 --- a/taskbadger/cli/utils.py +++ b/taskbadger/cli/utils.py @@ -1,6 +1,5 @@ import json from enum import Enum -from typing import Optional import typer from rich import print @@ -29,7 +28,7 @@ def get_actions(action_def: tuple[str, str, str]) -> list[Action]: return [] -def merge_kv_json(metadata_kv: Optional[list[str]], metadata_json: str) -> dict: +def merge_kv_json(metadata_kv: list[str] | None, metadata_json: str) -> dict: metadata = {} for kv in metadata_kv or []: k, v = kv.strip().split("=", 1) diff --git a/taskbadger/cli_main.py b/taskbadger/cli_main.py index 00115f1..1f1aaf5 100644 --- a/taskbadger/cli_main.py +++ b/taskbadger/cli_main.py @@ -72,7 +72,7 @@ def info(ctx: typer.Context): @app.callback() def main( ctx: typer.Context, - org: Optional[str] = typer.Option( + org: str | None = typer.Option( None, "--org", "-o", @@ -80,7 +80,7 @@ def main( show_default=False, help="Organization Slug. This will override values from the config file and environment variables.", ), - project: Optional[str] = typer.Option( + project: str | None = typer.Option( None, "--project", "-p", diff --git a/taskbadger/mug.py b/taskbadger/mug.py index 7193099..c027c61 100644 --- a/taskbadger/mug.py +++ b/taskbadger/mug.py @@ -1,8 +1,8 @@ import dataclasses +from collections.abc import Callable from contextlib import ContextDecorator from contextvars import ContextVar from copy import deepcopy -from typing import Callable, Optional, Union from taskbadger.internal import AuthenticatedClient from taskbadger.systems import System @@ -10,7 +10,7 @@ _local = ContextVar("taskbadger_client") -Callback = Union[str, Callable[[dict], Optional[dict]]] +Callback = str | Callable[[dict], dict | None] @dataclasses.dataclass @@ -47,7 +47,7 @@ class Session(ContextDecorator): def __init__(self): self._session = None - def __enter__(self) -> Union[AuthenticatedClient, None]: + def __enter__(self) -> AuthenticatedClient | None: if Badger.is_configured(): self._session = Badger.current.session() return self._session.__enter__() @@ -144,7 +144,7 @@ def client(self) -> AuthenticatedClient: def scope(self) -> Scope: return self._scope - def call_before_create(self, task: dict) -> Optional[dict]: + def call_before_create(self, task: dict) -> dict | None: if self.settings and self.settings.before_create: return self.settings.before_create(task) return task diff --git a/taskbadger/utils.py b/taskbadger/utils.py index 9dfd89c..ac9d049 100644 --- a/taskbadger/utils.py +++ b/taskbadger/utils.py @@ -5,7 +5,7 @@ def import_string(dotted_path): try: module_path, class_name = dotted_path.rsplit(".", 1) except ValueError as err: - raise ImportError("%s doesn't look like a module path" % dotted_path) from err + raise ImportError(f"{dotted_path} doesn't look like a module path") from err module = import_module(module_path) diff --git a/tests/conftest.py b/tests/conftest.py index 5619737..eaa77b5 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,7 +3,7 @@ from taskbadger.mug import Badger, Settings -@pytest.fixture() +@pytest.fixture def _bind_settings(): Badger.current.bind(Settings("https://taskbadger.net", "token", "org", "proj")) yield diff --git a/tests/test_celery_system_integration.py b/tests/test_celery_system_integration.py index d7d7c7d..84fc851 100644 --- a/tests/test_celery_system_integration.py +++ b/tests/test_celery_system_integration.py @@ -39,7 +39,7 @@ def _wait_for_mock_calls(mock_obj, expected_count, timeout=5): time.sleep(0.05) -@pytest.fixture() +@pytest.fixture def _bind_settings_with_system(): systems = [CelerySystemIntegration()] Badger.current.bind( diff --git a/tests/test_cli_config.py b/tests/test_cli_config.py index 180af10..7d533e4 100644 --- a/tests/test_cli_config.py +++ b/tests/test_cli_config.py @@ -21,7 +21,7 @@ def mock_config_location(): os.remove(config_path) -@pytest.fixture() +@pytest.fixture def _mock_config(mock_config_location): config = Config( organization_slug="test_org", diff --git a/tests/test_project_key.py b/tests/test_project_key.py index aed27ce..0e28544 100644 --- a/tests/test_project_key.py +++ b/tests/test_project_key.py @@ -102,7 +102,7 @@ def test_init_legacy_key_emits_deprecation_warning(self): init("org", "project", "legacy-token") def test_init_legacy_key_still_works(self): - with pytest.warns(DeprecationWarning): + with pytest.warns(DeprecationWarning, match="Legacy API keys are deprecated"): init("org", "project", "legacy-token") settings = Badger.current.settings assert settings.organization_slug == "org" @@ -152,7 +152,7 @@ def test_project_key_is_valid(self): runner = CliRunner() -@pytest.fixture() +@pytest.fixture def mock_config_location(): config_path = Path(__file__).parent / "_mock_config_project_key" with mock.patch("taskbadger.config._get_config_path", return_value=config_path): diff --git a/tests/test_sdk.py b/tests/test_sdk.py index d45264c..728a55c 100644 --- a/tests/test_sdk.py +++ b/tests/test_sdk.py @@ -24,24 +24,24 @@ def _init_skd(): init("org", "project", "token") -@pytest.fixture() +@pytest.fixture def settings(): return Badger.current.settings -@pytest.fixture() +@pytest.fixture def patched_get(): with mock.patch("taskbadger.sdk.task_get.sync") as get: yield get -@pytest.fixture() +@pytest.fixture def patched_create(): with mock.patch("taskbadger.sdk.task_create.sync_detailed") as create: yield create -@pytest.fixture() +@pytest.fixture def patched_update(): with mock.patch("taskbadger.sdk.task_partial_update.sync_detailed") as update: yield update diff --git a/uv.lock b/uv.lock index 25ab5ca..1ccb006 100644 --- a/uv.lock +++ b/uv.lock @@ -65,40 +65,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/30/da/43b15f28fe5f9e027b41c539abc5469052e9d48fd75f8ff094ba2a0ae767/billiard-4.2.1-py3-none-any.whl", hash = "sha256:40b59a4ac8806ba2c2369ea98d876bc6108b051c227baffd928c644d15d8f3cb", size = 86766, upload-time = "2024-09-21T13:40:20.188Z" }, ] -[[package]] -name = "black" -version = "25.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "click" }, - { name = "mypy-extensions" }, - { name = "packaging" }, - { name = "pathspec" }, - { name = "platformdirs" }, - { name = "tomli", marker = "python_full_version < '3.11'" }, - { name = "typing-extensions", marker = "python_full_version < '3.11'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/94/49/26a7b0f3f35da4b5a65f081943b7bcd22d7002f5f0fb8098ec1ff21cb6ef/black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666", size = 649449, upload-time = "2025-01-29T04:15:40.373Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/3b/4ba3f93ac8d90410423fdd31d7541ada9bcee1df32fb90d26de41ed40e1d/black-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32", size = 1629419, upload-time = "2025-01-29T05:37:06.642Z" }, - { url = "https://files.pythonhosted.org/packages/b4/02/0bde0485146a8a5e694daed47561785e8b77a0466ccc1f3e485d5ef2925e/black-25.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da", size = 1461080, upload-time = "2025-01-29T05:37:09.321Z" }, - { url = "https://files.pythonhosted.org/packages/52/0e/abdf75183c830eaca7589144ff96d49bce73d7ec6ad12ef62185cc0f79a2/black-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:055e59b198df7ac0b7efca5ad7ff2516bca343276c466be72eb04a3bcc1f82d7", size = 1766886, upload-time = "2025-01-29T04:18:24.432Z" }, - { url = "https://files.pythonhosted.org/packages/dc/a6/97d8bb65b1d8a41f8a6736222ba0a334db7b7b77b8023ab4568288f23973/black-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:db8ea9917d6f8fc62abd90d944920d95e73c83a5ee3383493e35d271aca872e9", size = 1419404, upload-time = "2025-01-29T04:19:04.296Z" }, - { url = "https://files.pythonhosted.org/packages/7e/4f/87f596aca05c3ce5b94b8663dbfe242a12843caaa82dd3f85f1ffdc3f177/black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0", size = 1614372, upload-time = "2025-01-29T05:37:11.71Z" }, - { url = "https://files.pythonhosted.org/packages/e7/d0/2c34c36190b741c59c901e56ab7f6e54dad8df05a6272a9747ecef7c6036/black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299", size = 1442865, upload-time = "2025-01-29T05:37:14.309Z" }, - { url = "https://files.pythonhosted.org/packages/21/d4/7518c72262468430ead45cf22bd86c883a6448b9eb43672765d69a8f1248/black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096", size = 1749699, upload-time = "2025-01-29T04:18:17.688Z" }, - { url = "https://files.pythonhosted.org/packages/58/db/4f5beb989b547f79096e035c4981ceb36ac2b552d0ac5f2620e941501c99/black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2", size = 1428028, upload-time = "2025-01-29T04:18:51.711Z" }, - { url = "https://files.pythonhosted.org/packages/83/71/3fe4741df7adf015ad8dfa082dd36c94ca86bb21f25608eb247b4afb15b2/black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b", size = 1650988, upload-time = "2025-01-29T05:37:16.707Z" }, - { url = "https://files.pythonhosted.org/packages/13/f3/89aac8a83d73937ccd39bbe8fc6ac8860c11cfa0af5b1c96d081facac844/black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc", size = 1453985, upload-time = "2025-01-29T05:37:18.273Z" }, - { url = "https://files.pythonhosted.org/packages/6f/22/b99efca33f1f3a1d2552c714b1e1b5ae92efac6c43e790ad539a163d1754/black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f", size = 1783816, upload-time = "2025-01-29T04:18:33.823Z" }, - { url = "https://files.pythonhosted.org/packages/18/7e/a27c3ad3822b6f2e0e00d63d58ff6299a99a5b3aee69fa77cd4b0076b261/black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba", size = 1440860, upload-time = "2025-01-29T04:19:12.944Z" }, - { url = "https://files.pythonhosted.org/packages/98/87/0edf98916640efa5d0696e1abb0a8357b52e69e82322628f25bf14d263d1/black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f", size = 1650673, upload-time = "2025-01-29T05:37:20.574Z" }, - { url = "https://files.pythonhosted.org/packages/52/e5/f7bf17207cf87fa6e9b676576749c6b6ed0d70f179a3d812c997870291c3/black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3", size = 1453190, upload-time = "2025-01-29T05:37:22.106Z" }, - { url = "https://files.pythonhosted.org/packages/e3/ee/adda3d46d4a9120772fae6de454c8495603c37c4c3b9c60f25b1ab6401fe/black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171", size = 1782926, upload-time = "2025-01-29T04:18:58.564Z" }, - { url = "https://files.pythonhosted.org/packages/cc/64/94eb5f45dcb997d2082f097a3944cfc7fe87e071907f677e80788a2d7b7a/black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18", size = 1442613, upload-time = "2025-01-29T04:19:27.63Z" }, - { url = "https://files.pythonhosted.org/packages/09/71/54e999902aed72baf26bca0d50781b01838251a462612966e9fc4891eadd/black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717", size = 207646, upload-time = "2025-01-29T04:15:38.082Z" }, -] - [[package]] name = "celery" version = "5.4.0" @@ -395,15 +361,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0a/66/7f8c48009c72d73bc6bbe6eb87ac838d6a526146f7dab14af671121eb379/invoke-2.2.0-py3-none-any.whl", hash = "sha256:6ea924cc53d4f78e3d98bc436b08069a03077e6f85ad1ddaa8a116d7dad15820", size = 160274, upload-time = "2023-07-12T18:05:16.294Z" }, ] -[[package]] -name = "isort" -version = "6.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1c/28/b382d1656ac0ee4cef4bf579b13f9c6c813bff8a5cb5996669592c8c75fa/isort-6.0.0.tar.gz", hash = "sha256:75d9d8a1438a9432a7d7b54f2d3b45cad9a4a0fdba43617d9873379704a8bdf1", size = 828356, upload-time = "2025-01-27T22:01:45.69Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/76/c7/d6017f09ae5b1206fbe531f7af3b6dac1f67aedcbd2e79f3b386c27955d6/isort-6.0.0-py3-none-any.whl", hash = "sha256:567954102bb47bb12e0fae62606570faacddd441e45683968c8d1734fb1af892", size = 94053, upload-time = "2025-01-27T22:01:43.609Z" }, -] - [[package]] name = "jinja2" version = "3.1.5" @@ -509,15 +466,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, ] -[[package]] -name = "mypy-extensions" -version = "1.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/98/a4/1ab47638b92648243faf97a5aeb6ea83059cc3624972ab6b8d2316078d3f/mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782", size = 4433, upload-time = "2023-02-04T12:11:27.157Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", size = 4695, upload-time = "2023-02-04T12:11:25.002Z" }, -] - [[package]] name = "nodeenv" version = "1.9.1" @@ -558,15 +506,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451, upload-time = "2024-11-08T09:47:44.722Z" }, ] -[[package]] -name = "pathspec" -version = "0.12.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, -] - [[package]] name = "platformdirs" version = "4.3.6" @@ -1086,9 +1025,7 @@ cli = [ [package.dev-dependencies] dev = [ - { name = "black" }, { name = "invoke" }, - { name = "isort" }, { name = "openapi-python-client" }, { name = "pre-commit" }, { name = "pytest" }, @@ -1112,9 +1049,7 @@ provides-extras = ["celery", "cli"] [package.metadata.requires-dev] dev = [ - { name = "black" }, { name = "invoke" }, - { name = "isort" }, { name = "openapi-python-client" }, { name = "pre-commit" }, { name = "pytest" },