From 2de5902af1f39e5789540822742fd2d2a396f026 Mon Sep 17 00:00:00 2001 From: Jake Howard Date: Mon, 3 Feb 2025 23:10:36 +0000 Subject: [PATCH] Revert "Drop support for Python 3.8" It's needed to maintain support for older Django versions. This reverts commit 8073900aaa2a8c83c227df4cd01ce788d68fcdce and f970f5b4fe4b16f977153f4941c311a0f28bd16a. --- .github/workflows/ci.yml | 8 +++++++- django_tasks/backends/base.py | 3 +-- django_tasks/backends/database/admin.py | 4 ++-- django_tasks/backends/database/backend.py | 3 +-- .../backends/database/management/commands/db_worker.py | 4 ++-- django_tasks/backends/database/utils.py | 3 +-- django_tasks/backends/dummy.py | 4 ++-- django_tasks/checks.py | 3 +-- django_tasks/signal_handlers.py | 5 +++-- django_tasks/task.py | 10 ++++++---- pyproject.toml | 3 ++- tests/tests/test_immediate_backend.py | 7 +++---- 12 files changed, 31 insertions(+), 26 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed15fd6..d03540b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,13 +15,19 @@ jobs: fail-fast: false matrix: os: [windows-latest, macos-latest, ubuntu-latest] - python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] django-version: ["4.2", "5.0", "5.1"] exclude: + - django-version: "5.0" + python-version: "3.8" - django-version: "5.0" python-version: "3.9" + - django-version: "5.1" + python-version: "3.8" - django-version: "5.1" python-version: "3.9" + - os: windows-latest # JSON1 is only built-in on 3.9+ + python-version: 3.8 steps: - uses: actions/checkout@v4 diff --git a/django_tasks/backends/base.py b/django_tasks/backends/base.py index 144af8c..3ca8036 100644 --- a/django_tasks/backends/base.py +++ b/django_tasks/backends/base.py @@ -1,7 +1,6 @@ from abc import ABCMeta, abstractmethod -from collections.abc import Iterable from inspect import iscoroutinefunction -from typing import Any, TypeVar +from typing import Any, Iterable, TypeVar from asgiref.sync import sync_to_async from django.core.checks import messages diff --git a/django_tasks/backends/database/admin.py b/django_tasks/backends/database/admin.py index 0e05414..cacbcd6 100644 --- a/django_tasks/backends/database/admin.py +++ b/django_tasks/backends/database/admin.py @@ -1,4 +1,4 @@ -from typing import Optional +from typing import List, Optional from django.contrib import admin from django.http import HttpRequest @@ -38,5 +38,5 @@ def has_change_permission( def get_readonly_fields( self, request: HttpRequest, obj: Optional[DBTaskResult] = None - ) -> list[str]: + ) -> List[str]: return [f.name for f in self.model._meta.fields] diff --git a/django_tasks/backends/database/backend.py b/django_tasks/backends/database/backend.py index 62000fc..788b651 100644 --- a/django_tasks/backends/database/backend.py +++ b/django_tasks/backends/database/backend.py @@ -1,6 +1,5 @@ -from collections.abc import Iterable from dataclasses import dataclass -from typing import TYPE_CHECKING, Any, TypeVar +from typing import TYPE_CHECKING, Any, Iterable, TypeVar import django from django.apps import apps diff --git a/django_tasks/backends/database/management/commands/db_worker.py b/django_tasks/backends/database/management/commands/db_worker.py index bc11587..b5bc132 100644 --- a/django_tasks/backends/database/management/commands/db_worker.py +++ b/django_tasks/backends/database/management/commands/db_worker.py @@ -6,7 +6,7 @@ import time from argparse import ArgumentParser, ArgumentTypeError from types import FrameType -from typing import Optional +from typing import List, Optional from django.core.exceptions import SuspiciousOperation from django.core.management.base import BaseCommand @@ -29,7 +29,7 @@ class Worker: def __init__( self, *, - queue_names: list[str], + queue_names: List[str], interval: float, batch: bool, backend_name: str, diff --git a/django_tasks/backends/database/utils.py b/django_tasks/backends/database/utils.py index 9574729..93cf039 100644 --- a/django_tasks/backends/database/utils.py +++ b/django_tasks/backends/database/utils.py @@ -1,6 +1,5 @@ -from collections.abc import Generator from contextlib import contextmanager -from typing import Any, Optional, Union +from typing import Any, Generator, Optional, Union from uuid import UUID import django diff --git a/django_tasks/backends/dummy.py b/django_tasks/backends/dummy.py index c44cb39..a66b001 100644 --- a/django_tasks/backends/dummy.py +++ b/django_tasks/backends/dummy.py @@ -1,6 +1,6 @@ from copy import deepcopy from functools import partial -from typing import TypeVar +from typing import List, TypeVar from django.db import transaction from django.utils import timezone @@ -20,7 +20,7 @@ class DummyBackend(BaseTaskBackend): supports_defer = True supports_async_task = True - results: list[TaskResult] + results: List[TaskResult] def __init__(self, alias: str, params: dict) -> None: super().__init__(alias, params) diff --git a/django_tasks/checks.py b/django_tasks/checks.py index 45ba238..afd9dc4 100644 --- a/django_tasks/checks.py +++ b/django_tasks/checks.py @@ -1,5 +1,4 @@ -from collections.abc import Iterable, Sequence -from typing import Any +from typing import Any, Iterable, Sequence from django.apps.config import AppConfig from django.core.checks.messages import CheckMessage diff --git a/django_tasks/signal_handlers.py b/django_tasks/signal_handlers.py index eb4aa8a..1a7f6a2 100644 --- a/django_tasks/signal_handlers.py +++ b/django_tasks/signal_handlers.py @@ -1,4 +1,5 @@ import logging +from typing import Type from asgiref.local import Local from django.core.signals import setting_changed @@ -25,7 +26,7 @@ def clear_tasks_handlers(*, setting: str, **kwargs: dict) -> None: @receiver(task_enqueued) def log_task_enqueued( - sender: type[BaseTaskBackend], task_result: TaskResult, **kwargs: dict + sender: Type[BaseTaskBackend], task_result: TaskResult, **kwargs: dict ) -> None: logger.debug( "Task id=%s path=%s enqueued backend=%s", @@ -37,7 +38,7 @@ def log_task_enqueued( @receiver(task_finished) def log_task_finished( - sender: type[BaseTaskBackend], task_result: TaskResult, **kwargs: dict + sender: Type[BaseTaskBackend], task_result: TaskResult, **kwargs: dict ) -> None: if task_result.status == ResultStatus.FAILED: # Use `.exception` to integrate with error monitoring tools (eg Sentry) diff --git a/django_tasks/task.py b/django_tasks/task.py index f24cda8..1274e8f 100644 --- a/django_tasks/task.py +++ b/django_tasks/task.py @@ -5,8 +5,10 @@ TYPE_CHECKING, Any, Callable, + Dict, Generic, Optional, + Type, TypeVar, Union, cast, @@ -100,7 +102,7 @@ def using( Create a new task with modified defaults """ - changes: dict[str, Any] = {} + changes: Dict[str, Any] = {} if priority is not None: changes["priority"] = priority @@ -243,13 +245,13 @@ class TaskResult(Generic[T]): args: list """The arguments to pass to the task function""" - kwargs: dict[str, Any] + kwargs: Dict[str, Any] """The keyword arguments to pass to the task function""" backend: str """The name of the backend the task will run on""" - _exception_class: Optional[type[BaseException]] = field(init=False, default=None) + _exception_class: Optional[Type[BaseException]] = field(init=False, default=None) _traceback: Optional[str] = field(init=False, default=None) _return_value: Optional[T] = field(init=False, default=None) @@ -270,7 +272,7 @@ def return_value(self) -> Optional[T]: raise ValueError("Task has not finished yet") @property - def exception_class(self) -> Optional[type[BaseException]]: + def exception_class(self) -> Optional[Type[BaseException]]: """The exception raised by the task function""" if not self.is_finished: raise ValueError("Task has not finished yet") diff --git a/pyproject.toml b/pyproject.toml index 670c854..44e2650 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,6 +17,7 @@ classifiers = [ "Development Status :: 3 - Alpha", "License :: OSI Approved :: BSD License", "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", @@ -35,7 +36,7 @@ classifiers = [ "Topic :: Internet :: WWW/HTTP", "Typing :: Typed" ] -requires-python = ">=3.9" +requires-python = ">=3.8" dependencies = [ "Django>=4.2", "typing_extensions", diff --git a/tests/tests/test_immediate_backend.py b/tests/tests/test_immediate_backend.py index 5afcaea..9c55777 100644 --- a/tests/tests/test_immediate_backend.py +++ b/tests/tests/test_immediate_backend.py @@ -71,10 +71,9 @@ def test_catches_exception(self) -> None: ), ] for task, exception, message in test_data: - with ( - self.subTest(task), - self.assertLogs("django_tasks", level="ERROR") as captured_logs, - ): + with self.subTest(task), self.assertLogs( + "django_tasks", level="ERROR" + ) as captured_logs: result = task.enqueue() # assert logging