Skip to content

Commit

Permalink
Merge branch 'main' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
cclauss authored Feb 18, 2024
2 parents a4a39c0 + ee3b500 commit f723a74
Show file tree
Hide file tree
Showing 22 changed files with 161 additions and 69 deletions.
10 changes: 10 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "daily"
8 changes: 4 additions & 4 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
Expand All @@ -51,7 +51,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
uses: github/codeql-action/autobuild@v3

# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
Expand All @@ -65,4 +65,4 @@ jobs:
# make release

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3
22 changes: 17 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,18 @@ jobs:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', 'pypy-3.9']
matrix: # https://docs.djangoproject.com/en/stable/faq/install/#what-python-version-can-i-use-with-django
django-version: ["3.2", "4.2", "5.0"]
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', 'pypy-3.10']
exclude:
- django-version: "3.2"
python-version: "3.11"
- django-version: "3.2"
python-version: "3.12"
- django-version: "5.0"
python-version: "3.8"
- django-version: "5.0"
python-version: "3.9"

services:
rabbitmq:
Expand All @@ -21,14 +31,16 @@ jobs:
- "5672:5672"

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install tox tox-gh-actions
- name: Test with tox
run: tox -vv
run: tox
env:
DJANGO: ${{ matrix.django-version }}
14 changes: 10 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ exclude: "migrations"

repos:
- repo: https://github.com/asottile/pyupgrade
rev: v3.8.0
rev: v3.15.0
hooks:
- id: pyupgrade
args: ["--py37-plus"]

- repo: https://github.com/PyCQA/flake8
rev: 6.0.0
rev: 7.0.0
hooks:
- id: flake8

Expand All @@ -19,14 +19,20 @@ repos:
- id: yesqa

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
rev: v4.5.0
hooks:
- id: check-merge-conflict
- id: check-toml
- id: check-yaml
- id: mixed-line-ending

- repo: https://github.com/pycqa/isort
rev: 5.12.0
rev: 5.13.2
hooks:
- id: isort

- repo: https://github.com/adamchainz/django-upgrade
rev: 1.16.0
hooks:
- id: django-upgrade
args: [--target-version, "3.2"]
24 changes: 24 additions & 0 deletions Changelog
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,30 @@
Change history
================

Next
====


2.6.0
=====
:release-date: !!! FIX_ME !!!
:release-by: !!! FIX_ME !!!

- Formally support Python 3.12. (#690)
- Avoid crash when can not get human readable description (#648)
- Update codeql-analysis.yml (#653)
- Celery Beat scheduled tasks may be executed repeatedly (#660)
- Drop Django 4.0 from CI to avoid security issues (#662)
- Change assert self.app.timezone.zone to assert self.app.timezone.key (#664)
- README.rst: Use git instead of zipfile for installing from Github (#670)
- Update supported Python & Django version in setup.py (#672)
- Update runtime.txt to include Django 5.0 (#681)
- README.rst: Crontab effect description (#689)
- Replace case.patching fixture with mockeypatch + MagicMock (#692)
- Upgrade GitHub Actions and PyPy 3.10 and Django 5.0 (#699, #705)
- Django v5.0: django.utils.timezone.utc alias --> datetime.timezone.utc (#703)


.. _version-2.5.0:

2.5.0
Expand Down
6 changes: 3 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ Example creating crontab-based periodic task

A crontab schedule has the fields: ``minute``, ``hour``, ``day_of_week``,
``day_of_month`` and ``month_of_year``, so if you want the equivalent
of a ``30 * * * *`` (execute every 30 minutes) crontab entry you specify:
of a ``30 * * * *`` (execute 30 minutes past every hour) crontab entry you specify:

.. code-block:: Python
Expand Down Expand Up @@ -298,12 +298,12 @@ Using the development version
With pip
~~~~~~~~

You can install the latest snapshot of django-celery-beat using the following
You can install the latest main version of django-celery-beat using the following
pip command:

.. code-block:: bash
$ pip install https://github.com/celery/django-celery-beat/zipball/master#egg=django-celery-beat
$ pip install git+https://github.com/celery/django-celery-beat#egg=django-celery-beat
Developing django-celery-beat
Expand Down
5 changes: 0 additions & 5 deletions django_celery_beat/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
import re
from collections import namedtuple

import django

__version__ = '2.5.0'
__author__ = 'Asif Saif Uddin, Ask Solem'
__contact__ = 'auvipy@gmail.com, ask@celeryproject.org'
Expand All @@ -29,6 +27,3 @@
del re

__all__ = []

if django.VERSION < (3, 2):
default_app_config = 'django_celery_beat.apps.BeatConfig'
24 changes: 17 additions & 7 deletions django_celery_beat/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ def clean_kwargs(self):
return self._clean_json('kwargs')


@admin.register(PeriodicTask)
class PeriodicTaskAdmin(admin.ModelAdmin):
"""Admin-interface for periodic tasks."""

Expand Down Expand Up @@ -184,30 +185,39 @@ def _message_user_about_update(self, request, rows_updated, verb):
),
)

@admin.action(
description=_('Enable selected tasks')
)
def enable_tasks(self, request, queryset):
rows_updated = queryset.update(enabled=True)
PeriodicTasks.update_changed()
self._message_user_about_update(request, rows_updated, 'enabled')
enable_tasks.short_description = _('Enable selected tasks')

@admin.action(
description=_('Disable selected tasks')
)
def disable_tasks(self, request, queryset):
rows_updated = queryset.update(enabled=False, last_run_at=None)
PeriodicTasks.update_changed()
self._message_user_about_update(request, rows_updated, 'disabled')
disable_tasks.short_description = _('Disable selected tasks')

def _toggle_tasks_activity(self, queryset):
return queryset.update(enabled=Case(
When(enabled=True, then=Value(False)),
default=Value(True),
))

@admin.action(
description=_('Toggle activity of selected tasks')
)
def toggle_tasks(self, request, queryset):
rows_updated = self._toggle_tasks_activity(queryset)
PeriodicTasks.update_changed()
self._message_user_about_update(request, rows_updated, 'toggled')
toggle_tasks.short_description = _('Toggle activity of selected tasks')

@admin.action(
description=_('Run selected tasks')
)
def run_tasks(self, request, queryset):
self.celery_app.loader.import_default_modules()
tasks = [(self.celery_app.tasks.get(task.task),
Expand Down Expand Up @@ -249,9 +259,9 @@ def run_tasks(self, request, queryset):
pluralize(tasks_run, _('was,were')),
),
)
run_tasks.short_description = _('Run selected tasks')


@admin.register(ClockedSchedule)
class ClockedScheduleAdmin(admin.ModelAdmin):
"""Admin-interface for clocked schedules."""

Expand All @@ -263,12 +273,12 @@ class ClockedScheduleAdmin(admin.ModelAdmin):
)


@admin.register(CrontabSchedule)
class CrontabScheduleAdmin(admin.ModelAdmin):
"""Admin class for CrontabSchedule."""

list_display = ('__str__', 'human_readable')


admin.site.register(IntervalSchedule)
admin.site.register(CrontabSchedule, CrontabScheduleAdmin)
admin.site.register(SolarSchedule)
admin.site.register(ClockedSchedule, ClockedScheduleAdmin)
admin.site.register(PeriodicTask, PeriodicTaskAdmin)
16 changes: 8 additions & 8 deletions django_celery_beat/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,14 +274,6 @@ class CrontabSchedule(models.Model):
'Cron Hours to Run. Use "*" for "all". (Example: "8,20")'),
validators=[validators.hour_validator],
)
day_of_week = models.CharField(
max_length=64, default='*',
verbose_name=_('Day(s) Of The Week'),
help_text=_(
'Cron Days Of The Week to Run. Use "*" for "all", Sunday '
'is 0 or 7, Monday is 1. (Example: "0,5")'),
validators=[validators.day_of_week_validator],
)
day_of_month = models.CharField(
max_length=31 * 4, default='*',
verbose_name=_('Day(s) Of The Month'),
Expand All @@ -298,6 +290,14 @@ class CrontabSchedule(models.Model):
'(Example: "1,12")'),
validators=[validators.month_of_year_validator],
)
day_of_week = models.CharField(
max_length=64, default='*',
verbose_name=_('Day(s) Of The Week'),
help_text=_(
'Cron Days Of The Week to Run. Use "*" for "all", Sunday '
'is 0 or 7, Monday is 1. (Example: "0,5")'),
validators=[validators.day_of_week_validator],
)

timezone = timezone_field.TimeZoneField(
default=crontab_schedule_celery_timezone,
Expand Down
4 changes: 2 additions & 2 deletions django_celery_beat/schedulers.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,9 +300,9 @@ def sync(self):
while self._dirty:
name = self._dirty.pop()
try:
self.schedule[name].save()
self._schedule[name].save()
_tried.add(name)
except (KeyError, ObjectDoesNotExist):
except (KeyError, TypeError, ObjectDoesNotExist):
_failed.add(name)
except DatabaseError as exc:
logger.exception('Database error while sync: %r', exc)
Expand Down
3 changes: 2 additions & 1 deletion django_celery_beat/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# -- XXX This module must not use translation as that causes
# -- a recursive loader import!
import time
from datetime import timezone as datetime_timezone

from django.conf import settings
from django.utils import timezone
Expand All @@ -19,7 +20,7 @@ def make_aware(value):
if getattr(settings, 'USE_TZ', False):
# naive datetimes are assumed to be in UTC.
if timezone.is_naive(value):
value = timezone.make_aware(value, timezone.utc)
value = timezone.make_aware(value, datetime_timezone.utc)
# then convert to the Django configured timezone.
default_tz = timezone.get_default_timezone()
value = timezone.localtime(value, default_tz)
Expand Down
5 changes: 5 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,8 @@
),
},
))

intersphinx_mapping = globals().get('intersphinx_mapping', {})
intersphinx_mapping['celery'] = (
'https://celery.readthedocs.io/en/main/', None)
globals().update({'intersphinx_mapping': intersphinx_mapping})
2 changes: 1 addition & 1 deletion requirements/runtime.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Django>=2.2,<5.0
Django>=2.2,<5.1
1 change: 0 additions & 1 deletion requirements/test-django32.txt

This file was deleted.

1 change: 0 additions & 1 deletion requirements/test-django40.txt

This file was deleted.

1 change: 0 additions & 1 deletion requirements/test-django41.txt

This file was deleted.

1 change: 0 additions & 1 deletion requirements/test-django42.txt

This file was deleted.

3 changes: 1 addition & 2 deletions requirements/test.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
case>=1.3.1
pytest-django>=4.5.2,<5.0
pytest>=6.2.5,<8.0
pytest>=6.2.5,<9.0
pytest-timeout
ephem
10 changes: 5 additions & 5 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ def _pyimp():
E_UNSUPPORTED_PYTHON = f'{NAME} 1.0 requires %s %s or later!'

PYIMP = _pyimp()
PY37_OR_LESS = sys.version_info < (3, 7)
PY38_OR_LESS = sys.version_info < (3, 8)
PYPY_VERSION = getattr(sys, 'pypy_version_info', None)
PYPY24_ATLEAST = PYPY_VERSION and PYPY_VERSION >= (2, 4)

if PY37_OR_LESS and not PYPY24_ATLEAST:
raise Exception(E_UNSUPPORTED_PYTHON % (PYIMP, '3.7'))
if PY38_OR_LESS and not PYPY24_ATLEAST:
raise Exception(E_UNSUPPORTED_PYTHON % (PYIMP, '3.8'))

# -*- Classifiers -*-

Expand All @@ -35,18 +35,18 @@ def _pyimp():
License :: OSI Approved :: BSD License
Programming Language :: Python
Programming Language :: Python :: 3
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: 3.12
Programming Language :: Python :: Implementation :: CPython
Programming Language :: Python :: Implementation :: PyPy
Framework :: Django
Framework :: Django :: 3.2
Framework :: Django :: 4.0
Framework :: Django :: 4.1
Framework :: Django :: 4.2
Framework :: Django :: 5.0
Operating System :: OS Independent
Topic :: Communications
Topic :: System :: Distributed Computing
Expand Down
Loading

0 comments on commit f723a74

Please sign in to comment.