diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 82ceaa2..4b49657 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -15,6 +15,10 @@ Unreleased ~~~~~~~~~~ * +[1.0.0] - 2021-01-21 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +* Dropped python3.5 support. + [0.5.4] - 2020-12-10 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Upgrade celery to 5.0.4 diff --git a/celery_utils/__init__.py b/celery_utils/__init__.py index 52eeb67..652cdd8 100644 --- a/celery_utils/__init__.py +++ b/celery_utils/__init__.py @@ -2,6 +2,6 @@ Code to support working with celery. """ -__version__ = '0.5.7' +__version__ = '1.0.0' default_app_config = 'celery_utils.apps.CeleryUtilsConfig' # pylint: disable=invalid-name diff --git a/celery_utils/apps.py b/celery_utils/apps.py index 7db118d..3b50beb 100644 --- a/celery_utils/apps.py +++ b/celery_utils/apps.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ celery_utils Django application initialization. """ diff --git a/celery_utils/management/commands/cleanup_resolved_tasks.py b/celery_utils/management/commands/cleanup_resolved_tasks.py index f5262c6..dea9108 100644 --- a/celery_utils/management/commands/cleanup_resolved_tasks.py +++ b/celery_utils/management/commands/cleanup_resolved_tasks.py @@ -36,13 +36,13 @@ def add_arguments(self, parser): parser.add_argument( '--task-name', '-t', default=None, - help=u"Restrict cleanup to tasks matching the named task.", + help="Restrict cleanup to tasks matching the named task.", ) parser.add_argument( '--age', '-a', type=int, default=30, - help=u"Only delete tasks that have been resolved for at least the specified number of days (default: 30)", + help="Only delete tasks that have been resolved for at least the specified number of days (default: 30)", ) def handle(self, *args, **options): diff --git a/celery_utils/management/commands/tests/test_reapply_tasks.py b/celery_utils/management/commands/tests/test_reapply_tasks.py index ac447f4..d2d64e4 100644 --- a/celery_utils/management/commands/tests/test_reapply_tasks.py +++ b/celery_utils/management/commands/tests/test_reapply_tasks.py @@ -4,8 +4,8 @@ from collections import Counter from datetime import datetime +from unittest import mock -import mock import pytest from django.core.management import call_command @@ -28,24 +28,24 @@ def failed_tasks(): return [ models.FailedTask.objects.create( task_name=tasks.fallible_task.name, - task_id=u'fail_again', + task_id='fail_again', args=[], kwargs={"error_message": "Err, yo!"}, - exc=u'UhOhError().', + exc='UhOhError().', ), models.FailedTask.objects.create( task_name=tasks.fallible_task.name, - task_id=u'will_succeed', + task_id='will_succeed', args=[], kwargs={}, - exc=u'NetworkErrorMaybe?()', + exc='NetworkErrorMaybe?()', ), models.FailedTask.objects.create( task_name=tasks.passing_task.name, - task_id=u'other_task', + task_id='other_task', args=[], kwargs={}, - exc=u'RaceCondition()', + exc='RaceCondition()', ), ] @@ -53,19 +53,19 @@ def failed_tasks(): @pytest.mark.django_db @pytest.mark.usefixtures('failed_tasks') def test_call_command(): - call_command(u'reapply_tasks') - assert_unresolved(models.FailedTask.objects.get(task_id=u'fail_again')) - assert_resolved(models.FailedTask.objects.get(task_id=u'will_succeed')) - assert_resolved(models.FailedTask.objects.get(task_id=u'other_task')) + call_command('reapply_tasks') + assert_unresolved(models.FailedTask.objects.get(task_id='fail_again')) + assert_resolved(models.FailedTask.objects.get(task_id='will_succeed')) + assert_resolved(models.FailedTask.objects.get(task_id='other_task')) @pytest.mark.django_db @pytest.mark.usefixtures('failed_tasks') def test_call_command_with_specified_task(): - call_command(u'reapply_tasks', u'--task-name={}'.format(tasks.fallible_task.name)) - assert_unresolved(models.FailedTask.objects.get(task_id=u'fail_again')) - assert_resolved(models.FailedTask.objects.get(task_id=u'will_succeed')) - assert_unresolved(models.FailedTask.objects.get(task_id=u'other_task')) + call_command('reapply_tasks', f'--task-name={tasks.fallible_task.name}') + assert_unresolved(models.FailedTask.objects.get(task_id='fail_again')) + assert_resolved(models.FailedTask.objects.get(task_id='will_succeed')) + assert_unresolved(models.FailedTask.objects.get(task_id='other_task')) @pytest.mark.django_db @@ -73,19 +73,19 @@ def test_call_command_with_specified_task(): def test_duplicate_tasks(): models.FailedTask.objects.create( task_name=tasks.fallible_task.name, - task_id=u'will_succeed', + task_id='will_succeed', args=[], kwargs={}, - exc=u'AlsoThisOtherError()', + exc='AlsoThisOtherError()', ) # Verify that only one task got run for this task_id. # pylint: disable=no-member - with mock.patch.object(tasks.fallible_task, u'apply_async', wraps=tasks.fallible_task.apply_async) as mock_apply: - call_command(u'reapply_tasks') - task_id_counts = Counter(call[2][u'task_id'] for call in mock_apply.mock_calls) - assert task_id_counts[u'will_succeed'] == 1 + with mock.patch.object(tasks.fallible_task, 'apply_async', wraps=tasks.fallible_task.apply_async) as mock_apply: + call_command('reapply_tasks') + task_id_counts = Counter(call[2]['task_id'] for call in mock_apply.mock_calls) + assert task_id_counts['will_succeed'] == 1 # Verify that both tasks matching that task_id are resolved. - will_succeed_tasks = models.FailedTask.objects.filter(task_id=u'will_succeed').all() + will_succeed_tasks = models.FailedTask.objects.filter(task_id='will_succeed').all() assert len(will_succeed_tasks) == 2 for task_object in will_succeed_tasks: assert_resolved(task_object) diff --git a/celery_utils/migrations/0001_initial.py b/celery_utils/migrations/0001_initial.py index 74bf2c4..5995c97 100644 --- a/celery_utils/migrations/0001_initial.py +++ b/celery_utils/migrations/0001_initial.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Generated by Django 1.10.5 on 2017-01-31 13:50 @@ -33,6 +32,6 @@ class Migration(migrations.Migration): ), migrations.AlterIndexTogether( name='failedtask', - index_together=set([('task_name', 'exc')]), + index_together={('task_name', 'exc')}, ), ] diff --git a/celery_utils/migrations/0002_chordable_django_backend.py b/celery_utils/migrations/0002_chordable_django_backend.py index 3384a97..e3fc27c 100644 --- a/celery_utils/migrations/0002_chordable_django_backend.py +++ b/celery_utils/migrations/0002_chordable_django_backend.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- - - from django.db import migrations diff --git a/celery_utils/models.py b/celery_utils/models.py index 5055d7d..e34ca60 100644 --- a/celery_utils/models.py +++ b/celery_utils/models.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Database models for celery_utils. """ diff --git a/docs/conf.py b/docs/conf.py index 8d4bab1..a1d266b 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # pylint: disable=invalid-name """ edx-celeryutils documentation build configuration file. diff --git a/requirements/base.txt b/requirements/base.txt index 9b037d1..6172942 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -4,7 +4,7 @@ # # make upgrade # -amqp==5.0.2 +amqp==5.0.3 # via kombu billiard==3.6.3.0 # via celery @@ -28,7 +28,7 @@ django-model-utils==4.1.1 # via -r requirements/base.in django==2.2.17 # via - # -c requirements/constraints.txt + # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt # -r requirements/base.in # django-model-utils # jsonfield2 @@ -38,7 +38,7 @@ jsonfield2==4.0.0.post0 # via -r requirements/base.in kombu==5.0.2 # via celery -prompt-toolkit==3.0.9 +prompt-toolkit==3.0.11 # via click-repl pytz==2020.5 # via diff --git a/requirements/celery50.txt b/requirements/celery50.txt index 8a6fbd8..9e9c21d 100644 --- a/requirements/celery50.txt +++ b/requirements/celery50.txt @@ -1,9 +1,9 @@ -amqp==5.0.2 +amqp==5.0.3 billiard==3.6.3.0 celery==5.0.4 click-didyoumean==0.0.3 click-repl==0.1.6 click==7.1.2 kombu==5.0.2 -prompt-toolkit==3.0.9 +prompt-toolkit==3.0.11 vine==5.0.0 diff --git a/requirements/ci.txt b/requirements/ci.txt index 8c29a89..4c5ce8a 100644 --- a/requirements/ci.txt +++ b/requirements/ci.txt @@ -40,11 +40,11 @@ toml==0.10.2 # via tox tox-battery==0.6.1 # via -r requirements/ci.in -tox==3.20.1 +tox==3.21.2 # via # -r requirements/ci.in # tox-battery urllib3==1.26.2 # via requests -virtualenv==20.2.2 +virtualenv==20.4.0 # via tox diff --git a/requirements/constraints.txt b/requirements/constraints.txt index bf04409..f0051a5 100644 --- a/requirements/constraints.txt +++ b/requirements/constraints.txt @@ -8,8 +8,8 @@ # pin when possible. Writing an issue against the offending project and # linking to it here is good. -# Stay on an LTS release -django<2.3 +# This file contains all common constraints for edx-repos +-c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt # pinning it to latest release. celery==5.0.4 diff --git a/requirements/dev.txt b/requirements/dev.txt index 3a06d36..30c3223 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -10,14 +10,14 @@ astroid==2.4.2 # via # pylint # pylint-celery -bleach==3.2.1 +bleach==3.2.2 # via readme-renderer certifi==2020.12.5 # via requests -cffi==1.14.4 - # via cryptography chardet==4.0.0 - # via requests + # via + # diff-cover + # requests click-log==0.3.2 # via edx-lint click==7.1.2 @@ -27,15 +27,13 @@ click==7.1.2 # pip-tools colorama==0.4.4 # via twine -cryptography==3.3.1 - # via secretstorage -diff-cover==4.0.1 +diff-cover==4.2.0 # via -r requirements/dev.in distlib==0.3.1 # via virtualenv django==2.2.17 # via - # -c requirements/constraints.txt + # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt # edx-i18n-tools docutils==0.16 # via readme-renderer @@ -57,10 +55,6 @@ isort==5.7.0 # via # -r requirements/quality.in # pylint -jeepney==0.6.0 - # via - # keyring - # secretstorage jinja2-pluralize==0.3.0 # via diff-cover jinja2==2.11.2 @@ -85,7 +79,7 @@ path==15.0.1 # via path.py pip-tools==5.5.0 # via -r requirements/dev.in -pkginfo==1.6.1 +pkginfo==1.7.0 # via twine pluggy==0.13.1 # via @@ -97,11 +91,9 @@ py==1.10.0 # via tox pycodestyle==2.6.0 # via -r requirements/quality.in -pycparser==2.20 - # via cffi pydocstyle==3.0.0 # via -r requirements/quality.in -pygments==2.7.3 +pygments==2.7.4 # via # diff-cover # readme-renderer @@ -123,7 +115,7 @@ pyparsing==2.4.7 # via packaging pytz==2020.5 # via django -pyyaml==5.3.1 +pyyaml==5.4.1 # via edx-i18n-tools readme-renderer==28.0 # via twine @@ -135,13 +127,10 @@ requests==2.25.1 # twine rfc3986==1.4.0 # via twine -secretstorage==3.3.0 - # via keyring six==1.15.0 # via # astroid # bleach - # cryptography # edx-i18n-tools # edx-lint # pydocstyle @@ -158,17 +147,17 @@ toml==0.10.2 # tox tox-battery==0.6.1 # via -r requirements/dev.in -tox==3.20.1 +tox==3.21.2 # via # -r requirements/dev.in # tox-battery -tqdm==4.55.1 +tqdm==4.56.0 # via twine twine==3.3.0 # via -r requirements/dev.in urllib3==1.26.2 # via requests -virtualenv==20.2.2 +virtualenv==20.4.0 # via tox webencodings==0.5.1 # via bleach diff --git a/requirements/doc.txt b/requirements/doc.txt index 203b085..30102ed 100644 --- a/requirements/doc.txt +++ b/requirements/doc.txt @@ -6,13 +6,13 @@ # alabaster==0.7.12 # via sphinx -amqp==5.0.2 +amqp==5.0.3 # via kombu babel==2.9.0 # via sphinx billiard==3.6.3.0 # via celery -bleach==3.2.1 +bleach==3.2.2 # via readme-renderer celery==5.0.4 # via @@ -40,7 +40,7 @@ django-model-utils==4.1.1 # via -r requirements/base.in django==2.2.17 # via - # -c requirements/constraints.txt + # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt # -r requirements/base.in # django-model-utils # jsonfield2 @@ -52,7 +52,7 @@ docutils==0.16 # readme-renderer # restructuredtext-lint # sphinx -edx-sphinx-theme==1.6.0 +edx-sphinx-theme==1.6.1 # via -r requirements/doc.in future==0.18.2 # via -r requirements/base.in @@ -76,9 +76,9 @@ pbr==5.5.1 # via stevedore pockets==0.9.1 # via sphinxcontrib-napoleon -prompt-toolkit==3.0.9 +prompt-toolkit==3.0.11 # via click-repl -pygments==2.7.3 +pygments==2.7.4 # via # doc8 # readme-renderer @@ -107,7 +107,7 @@ six==1.15.0 # sphinxcontrib-napoleon snowballstemmer==2.0.0 # via sphinx -sphinx==3.4.2 +sphinx==3.4.3 # via # -r requirements/doc.in # edx-sphinx-theme diff --git a/requirements/pip.txt b/requirements/pip.txt index af8270c..884d847 100644 --- a/requirements/pip.txt +++ b/requirements/pip.txt @@ -10,5 +10,5 @@ wheel==0.36.2 # The following packages are considered to be unsafe in a requirements file: pip==20.3.3 # via -r requirements/pip.in -setuptools==51.1.1 +setuptools==51.3.3 # via -r requirements/pip.in diff --git a/requirements/test.txt b/requirements/test.txt index 071b811..5fbf38f 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -30,11 +30,11 @@ ddt==1.4.1 django-model-utils==4.1.1 # via -r requirements/base.in # via - # -c requirements/constraints.txt + # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt # -r requirements/base.in # django-model-utils # jsonfield2 -freezegun==1.0.0 +freezegun==1.1.0 # via -r requirements/test.in future==0.18.2 # via -r requirements/base.in @@ -49,13 +49,13 @@ packaging==20.8 # via pytest pluggy==0.13.1 # via pytest -prompt-toolkit==3.0.9 +prompt-toolkit==3.0.11 # via click-repl py==1.10.0 # via pytest pyparsing==2.4.7 # via packaging -pytest-cov==2.10.1 +pytest-cov==2.11.1 # via -r requirements/test.in pytest-django==4.1.0 # via -r requirements/test.in diff --git a/setup.py b/setup.py old mode 100755 new mode 100644 index de1f7e4..f66ddc4 --- a/setup.py +++ b/setup.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- # pylint: disable=C0111,W6005,W6100 diff --git a/test_settings.py b/test_settings.py index 91ce5c4..52aec82 100644 --- a/test_settings.py +++ b/test_settings.py @@ -76,4 +76,4 @@ def root(*args): CELERY_ALWAYS_EAGER = True results_dir = tempfile.TemporaryDirectory() -CELERY_RESULT_BACKEND = 'file://{}'.format(results_dir.name) +CELERY_RESULT_BACKEND = f'file://{results_dir.name}' diff --git a/tests/test_logged_task.py b/tests/test_logged_task.py index e1595ba..bdd3740 100644 --- a/tests/test_logged_task.py +++ b/tests/test_logged_task.py @@ -9,8 +9,9 @@ """ +from unittest import mock + from billiard.einfo import ExceptionInfo -import mock import pytest from celery_utils.logged_task import LoggedTask diff --git a/tox.ini b/tox.ini index 1eba6da..568717f 100644 --- a/tox.ini +++ b/tox.ini @@ -1,8 +1,7 @@ [tox] -envlist = py38-celery{50}-django{22,30} +envlist = py38-celery{50}-django{22,30,31} [doc8] -; D001 = Line too long. Reason: No hard line-breaks in docs (see OEP-0019). ignore = D001 [pycodestyle] @@ -10,11 +9,6 @@ exclude = .git,.tox,migrations max-line-length = 120 [pydocstyle] -; D101 = Missing docstring in public class -; D105 = Missing docstring in magic method -; D200 = One-line docstring should fit on one line with quotes -; D203 = 1 blank line required before class docstring -; D212 = Multi-line docstring summary should start at the first line ignore = D101,D105,D200,D203,D212 match-dir = (?!migrations) @@ -24,47 +18,49 @@ addopts = --cov celery_utils --cov-report term-missing --cov-report xml norecursedirs = .* docs requirements [testenv] -deps = - django22: Django>=2.2,<2.3 - django30: Django>=3.0,<3.1 - celery50: -r{toxinidir}/requirements/celery50.txt - -r{toxinidir}/requirements/test.txt -commands = - py.test tests/ celery_utils/ {posargs} +deps = + django22: Django>=2.2,<2.3 + django30: Django>=3.0,<3.1 + django31: Django>=3.1,<3.2 + celery50: -r{toxinidir}/requirements/celery50.txt + -r{toxinidir}/requirements/test.txt +commands = + py.test tests/ celery_utils/ {posargs} [testenv:docs] -setenv = - DJANGO_SETTINGS_MODULE = test_settings - PYTHONPATH = {toxinidir} -whitelist_externals = - make - rm -deps = - -r{toxinidir}/requirements/doc.txt -commands = - doc8 --ignore-path docs/_build README.rst docs - rm -f docs/celery_utils.rst - rm -f docs/modules.rst - make -C docs clean - make -C docs html - python setup.py check --restructuredtext --strict +setenv = + DJANGO_SETTINGS_MODULE = test_settings + PYTHONPATH = {toxinidir} +whitelist_externals = + make + rm +deps = + -r{toxinidir}/requirements/doc.txt +commands = + doc8 --ignore-path docs/_build README.rst docs + rm -f docs/celery_utils.rst + rm -f docs/modules.rst + make -C docs clean + make -C docs html + python setup.py check --restructuredtext --strict [testenv:quality] -whitelist_externals = - make - rm - touch -deps = - -r{toxinidir}/requirements/doc.txt - -r{toxinidir}/requirements/quality.txt - -r{toxinidir}/requirements/test.txt -commands = - touch tests/__init__.py - pylint celery_utils - pylint tests - pylint test_utils - rm tests/__init__.py - pycodestyle celery_utils tests - pydocstyle celery_utils tests - isort --check-only tests test_utils celery_utils manage.py setup.py test_settings.py - make help +whitelist_externals = + make + rm + touch +deps = + -r{toxinidir}/requirements/doc.txt + -r{toxinidir}/requirements/quality.txt + -r{toxinidir}/requirements/test.txt +commands = + touch tests/__init__.py + pylint celery_utils + pylint tests + pylint test_utils + rm tests/__init__.py + pycodestyle celery_utils tests + pydocstyle celery_utils tests + isort --check-only tests test_utils celery_utils manage.py setup.py test_settings.py + make help +