Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,4 @@ cython_debug/
#.idea/

# PyPI configuration file
.pypirc
.pypirc
38 changes: 9 additions & 29 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ repos:
hooks:
- id: pyproject-fmt
- repo: https://github.com/tox-dev/tox-ini-fmt
rev: 1.4.1
rev: 1.5.0
hooks:
- id: tox-ini-fmt
- repo: https://github.com/rstcheck/rstcheck
Expand All @@ -35,44 +35,24 @@ repos:
rev: v1.0.0
hooks:
- id: sphinx-lint
- repo: https://github.com/asottile/pyupgrade
rev: v3.19.0
hooks:
- id: pyupgrade
args: [--py39-plus]
- repo: https://github.com/adamchainz/django-upgrade
rev: 1.22.2
hooks:
- id: django-upgrade
args: [--target-version, '4.2']
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 24.10.0
hooks:
- id: black
- repo: https://github.com/adamchainz/blacken-docs
rev: 1.19.1
hooks:
- id: blacken-docs
additional_dependencies:
- black==23.1.0
- repo: https://github.com/pycqa/isort
rev: 5.13.2
hooks:
- id: isort
name: isort (python)
- repo: https://github.com/PyCQA/flake8
rev: 7.1.1
hooks:
- id: flake8
additional_dependencies:
- flake8-bugbear
- flake8-comprehensions
- flake8-logging
- flake8-tidy-imports
- repo: https://github.com/adamchainz/djade-pre-commit
rev: 1.3.2
hooks:
- id: djade
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.7
hooks:
# Run the linter.
- id: ruff
# args: [ --fix ]
# Run the formatter.
- id: ruff-format
- repo: local
hooks:
- id: makemigrations
Expand Down
96 changes: 87 additions & 9 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,95 @@ urls.Documentation = "https://github.com/jmitchel3/django-qstash"
urls.Funding = "https://github.com/jmitchel3/django-qstash"
urls.Repository = "https://github.com/jmitchel3/django-qstash"

[tool.isort]
add_imports = [
"from __future__ import annotations",
[tool.ruff]
# line-length = 226
lint.select = [
"AIR", # Airflow
"ASYNC", # flake8-async
"B", # flake8-bugbear
"C4", # flake8-comprehensions
"C90", # McCabe cyclomatic complexity
"DJ", # flake8-django
"DTZ", # flake8-datetimez
"E", # pycodestyle
"EXE", # flake8-executable
"F", # Pyflakes
"FA", # flake8-future-annotations
"FAST", # FastAPI
"FIX", # flake8-fixme
"FLY", # flynt
"FURB", # refurb
"G", # flake8-logging-format
"I", # isort
"ICN", # flake8-import-conventions
"INP", # flake8-no-pep420
"INT", # flake8-gettext
"ISC", # flake8-implicit-str-concat
"LOG", # flake8-logging
"N", # pep8-naming
"NPY", # NumPy-specific rules
"PD", # pandas-vet
"PERF", # Perflint
"PGH", # pygrep-hooks
"PIE", # flake8-pie
"PL", # Pylint
"PT", # flake8-pytest-style
"PTH", # flake8-use-pathlib
"PYI", # flake8-pyi
"RSE", # flake8-raise
"S", # flake8-bandit
"SIM", # flake8-simplify
"SLF", # flake8-self
"SLOT", # flake8-slots
"T10", # flake8-debugger
"TD", # flake8-todos
"TID", # flake8-tidy-imports
"UP", # pyupgrade
"W", # pycodestyle
"YTT", # flake8-2020
# "A", # flake8-builtins
# "ANN", # flake8-annotations
# "ARG", # flake8-unused-arguments
# "BLE", # flake8-blind-except
# "COM", # flake8-commas
# "CPY", # flake8-copyright
# "D", # pydocstyle
# "DOC", # pydoclint
# "EM", # flake8-errmsg
# "ERA", # eradicate
# "FBT", # flake8-boolean-trap
# "Q", # flake8-quotes
# "RET", # flake8-return
# "RUF", # Ruff-specific rules
# "T20", # flake8-print
# "TC", # flake8-type-checking
# "TRY", # tryceratops
]
force_single_line = true
profile = "black"
src_paths = [
".",
"example",
"src",
lint.ignore = [
"B904", # raise-without-from-inside-except
"DJ001", # django-nullable-model-string-field
"DJ008", # django-model-without-dunder-str
"E501", # line-too-long
"PT006", # pytest-parametrize-names-wrong-type
"PT009", # pytest-unittest-assertion
"PT011", # pytest-raises-too-broad
"PT017", # pytest-assert-in-except
]
lint.per-file-ignores."__init__.py" = [ "E402" ]
lint.per-file-ignores."sample_project/*" = [ "F401" ]
lint.per-file-ignores."sample_project/cfehome/tasks.py" = [ "PTH123" ]
lint.per-file-ignores."src/django_qstash/discovery/utils.py" = [ "PERF203" ]
lint.per-file-ignores."src/django_qstash/management/commands/task_schedules.py" = [ "N806", "PERF203" ]
lint.per-file-ignores."src/django_qstash/results/tasks.py" = [ "N806" ]
lint.per-file-ignores."src/django_qstash/schedules/validators.py" = [ "S308" ]
lint.per-file-ignores."tests/*" = [ "S101" ]
lint.per-file-ignores."tests/settings.py" = [ "S105" ]
lint.per-file-ignores."tests/test_settings.py" = [ "S106", "SIM117" ]
lint.isort.force-single-line = true
lint.mccabe.max-complexity = 13 # default is 10
lint.pylint.allow-magic-value-types = [ "int", "str" ]
lint.pylint.max-args = 9 # default is 5
lint.pylint.max-branches = 15 # default is 12

[tool.pyproject-fmt]
max_supported_python = "3.13"
Expand Down
2 changes: 1 addition & 1 deletion sample_project/cfehome/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
<div class="container">
<h1>Hello, <span class="gradient-text">Django QStash!</span></h1>
<p>Experience the power of background tasks with QStash - a modern, serverless task queue for Django applications.</p>

<a href="{% url 'register_user' %}" class="try-button">Try Notifications App →</a>

<div class="features">
Expand Down
2 changes: 1 addition & 1 deletion sample_project/cfehome/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
urlpatterns = [
path("", views.index),
path("admin/", admin.site.urls),
path('', include('notifications.urls')),
path("", include("notifications.urls")),
path("qstash/webhook/", include("django_qstash.urls")),
]

Expand Down
2 changes: 1 addition & 1 deletion sample_project/cfehome/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@


def index(request):
return render(request, 'index.html')
return render(request, "index.html")
1 change: 1 addition & 0 deletions sample_project/manage.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""

from __future__ import annotations

import os
Expand Down
4 changes: 2 additions & 2 deletions sample_project/notifications/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@


class NotificationsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'notifications'
default_auto_field = "django.db.models.BigAutoField"
name = "notifications"
63 changes: 35 additions & 28 deletions sample_project/notifications/tasks.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
from django_qstash import shared_task
import json
from django.core.mail import send_mail

from django.conf import settings
from django.core.mail import send_mail

from django_qstash import shared_task


@shared_task
def send_welcome_notification(user_email):
Expand All @@ -16,20 +19,20 @@ def send_welcome_notification(user_email):
# [user_email],
# fail_silently=False,
# )

return json.dumps({
"status": "success",
"email": user_email,
"type": "welcome",
"message": "Welcome email sent successfully"
})

return json.dumps(
{
"status": "success",
"email": user_email,
"type": "welcome",
"message": "Welcome email sent successfully",
}
)
except Exception as e:
return json.dumps({
"status": "error",
"email": user_email,
"type": "welcome",
"error": str(e)
})
return json.dumps(
{"status": "error", "email": user_email, "type": "welcome", "error": str(e)}
)


@shared_task
def send_reminder_notification(user_email):
Expand All @@ -44,17 +47,21 @@ def send_reminder_notification(user_email):
# [user_email],
# fail_silently=False,
# )

return json.dumps({
"status": "success",
"email": user_email,
"type": "reminder",
"message": "Reminder sent successfully"
})

return json.dumps(
{
"status": "success",
"email": user_email,
"type": "reminder",
"message": "Reminder sent successfully",
}
)
except Exception as e:
return json.dumps({
"status": "error",
"email": user_email,
"type": "reminder",
"error": str(e)
})
return json.dumps(
{
"status": "error",
"email": user_email,
"type": "reminder",
"error": str(e),
}
)
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,15 @@ <h1 class="success-title">Registration Successful!</h1>

<div class="task-info">
<h2 class="task-title">Task Information</h2>

<div class="task-label">Welcome Email Task ID:</div>
<div class="task-id">{{ welcome_task_id }}</div>

<div class="task-label">Reminder Email Task ID:</div>
<div class="task-id">{{ reminder_task_id }}</div>

<p class="info-text">✉️ A welcome email has been sent immediately, and a reminder will be sent in 24 hours.</p>

<a href="{% url 'task_dashboard' %}" class="view-dashboard">View Task Dashboard →</a>
</div>
</div>
Expand Down
5 changes: 3 additions & 2 deletions sample_project/notifications/urls.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from django.urls import path

from . import views

urlpatterns = [
path('register/', views.register_user, name='register_user'),
path('dashboard/', views.task_dashboard, name='task_dashboard'),
path("register/", views.register_user, name="register_user"),
path("dashboard/", views.task_dashboard, name="task_dashboard"),
]
2 changes: 1 addition & 1 deletion src/django_qstash/app/base.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from __future__ import annotations

import functools
from collections.abc import Callable
from typing import Any
from typing import Callable

from django.core.exceptions import ImproperlyConfigured

Expand Down
2 changes: 1 addition & 1 deletion src/django_qstash/app/decorators.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

from collections.abc import Callable
from typing import Any
from typing import Callable

from django_qstash.app.base import QStashTask

Expand Down
16 changes: 8 additions & 8 deletions src/django_qstash/discovery/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import logging
import os
import warnings
from functools import lru_cache
from functools import cache
from importlib import import_module

from django.apps import apps
Expand All @@ -18,7 +18,7 @@
)


@lru_cache(maxsize=None)
@cache
def discover_tasks(locations_only: bool = False) -> list[str] | list[dict]:
"""
Automatically discover tasks in Django apps and return them as a list of tuples.
Expand All @@ -35,12 +35,12 @@ def discover_tasks(locations_only: bool = False) -> list[str] | list[dict]:
from django_qstash.app import QStashTask

discovered_tasks = []
packages = []

# Add Django apps that contain tasks.py
for app_config in apps.get_app_configs():
if module_has_submodule(app_config.module, "tasks"):
packages.append(app_config.name)
# Django apps that contain tasks.py
packages = [
app_config.name
for app_config in apps.get_app_configs()
if module_has_submodule(app_config.module, "tasks")
]

# Add the directory containing settings.py if it has a tasks.py module
if DJANGO_QSTASH_DISCOVER_INCLUDE_SETTINGS_DIR:
Expand Down
Loading