diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..fa26e52 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,43 @@ +# run test suites + +name: Tests +on: + - pull_request + - push + - release + - workflow_dispatch + +# cancel the current workflow if another commit was pushed on the same PR or reference +# uses the GitHub workflow name to avoid collision with other workflows running on the same PR/reference +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + tests: + runs-on: ${{ matrix.platform }} + strategy: + matrix: + platform: [ ubuntu-latest, windows-latest ] + python-version: [ '3.7', '3.8', '3.9', '3.10', '3.11', '3.12' ] + steps: + - uses: actions/checkout@v1 + - name: Cache .tox directory + uses: actions/cache@v2 + with: + path: '.tox' + # -X at the end can be bumped to force by-pass of a cache in case it's broken + # as GitHub actions does not support deletion of caches... + key: ${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('*requirements*.txt') }}-X + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install tox tox-gh-actions + - name: Test with tox + run: tox + env: + PLATFORM: ${{ matrix.platform }} diff --git a/.gitignore b/.gitignore index 852263c..28e8d5d 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,7 @@ docs/_build coverage.xml junit.xml *celerybeat-schedule* + +# IDE +.idea +.vscode diff --git a/CHANGES.txt b/CHANGES.txt index 3e49b93..a2259a9 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,8 @@ +5.0.0a +================ +- Add support of Python 3.12 +- Add support `celery_config_module` option for alternate location of `celeryconfig.py` + 4.0.0 ================ - Drop support for celery 3.0 diff --git a/README.rst b/README.rst index a48b5b8..e2232c5 100644 --- a/README.rst +++ b/README.rst @@ -64,6 +64,10 @@ If you want to use the standard **celeryconfig** python file you can set the [celery] use_celeryconfig = True + celery_config_module = my.custom.celeryconfig + +You may also suppress the **celery_config_module** directive to use the default +`"celeryconfig"` You can get more information for celeryconfig.py here: diff --git a/pyramid_celery/__init__.py b/pyramid_celery/__init__.py index bdc6ee3..583cca9 100644 --- a/pyramid_celery/__init__.py +++ b/pyramid_celery/__init__.py @@ -70,7 +70,7 @@ def setup_app(app, root, request, registry, closer, ini_location): ) if asbool(celery_config.get('use_celeryconfig', False)) is True: - config_path = 'celeryconfig' + config_path = celery_config.get('celery_config_module', 'celeryconfig') celery_app.config_from_object(config_path) else: hijack_key = 'worker_hijack_root_logger' diff --git a/pyramid_celery/loaders.py b/pyramid_celery/loaders.py index 199a8d6..ffe81a5 100644 --- a/pyramid_celery/loaders.py +++ b/pyramid_celery/loaders.py @@ -92,7 +92,7 @@ def get_route_config(parser, section): class INILoader(celery.loaders.base.BaseLoader): - ConfigParser = configparser.SafeConfigParser + ConfigParser = configparser.ConfigParser def __init__(self, app, **kwargs): self.celery_conf = kwargs.pop('ini_file') diff --git a/requirements.txt b/requirements.txt index 687e0c0..145d899 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ pyramid celery +importlib-metadata<5; python_version <= "3.7" diff --git a/setup.cfg b/setup.cfg index 1ddb900..39f541f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -9,7 +9,7 @@ norecursedirs = addopts = -rxEfs - --strict + --strict-markers --doctest-modules --doctest-glob=\*.rst --tb=short diff --git a/setup.py b/setup.py index 38dc01a..64f8ec6 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,4 @@ import os -import sys from setuptools import setup, find_packages here = os.path.abspath(os.path.dirname(__file__)) @@ -8,36 +7,41 @@ requires = ['pyramid', 'celery'] -setup(name='pyramid_celery', - version='4.0.0', - description='Celery integration with pyramid', - long_description=README + "\n" + CHANGES, - classifiers=[ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Developers", - "License :: OSI Approved :: MIT License", - "Operating System :: Unix", - "Operating System :: POSIX", - "Operating System :: Microsoft :: Windows", - "Programming Language :: Python", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: Implementation :: CPython", - "Programming Language :: Python :: Implementation :: PyPy", - ], - author='John Anderson', - author_email='sontek@gmail.com', - url='https://github.com/sontek/pyramid_celery', - keywords='paste pyramid celery message queue amqp job task distributed', - license='MIT', - packages=find_packages(), - include_package_data=True, - zip_safe=False, - install_requires=requires, - tests_require=requires + ['pytest'], - python_requires='>=3.6', - test_suite="pyramid_celery", +setup( + name='pyramid_celery', + version='5.0.0a', + description='Celery integration with pyramid', + long_description=README + "\n" + CHANGES, + classifiers=[ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Operating System :: Unix", + "Operating System :: POSIX", + "Operating System :: Microsoft :: Windows", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.6", + "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", + ], + author='John Anderson', + author_email='sontek@gmail.com', + url='https://github.com/sontek/pyramid_celery', + keywords='paste pyramid celery message queue amqp job task distributed', + license='MIT', + packages=find_packages(), + include_package_data=True, + zip_safe=False, + install_requires=requires, + tests_require=requires + ['pytest'], + python_requires='>=3.6', + test_suite="pyramid_celery", ) diff --git a/tests/configs/custom_useceleryconfig.ini b/tests/configs/custom_useceleryconfig.ini new file mode 100644 index 0000000..3b50d30 --- /dev/null +++ b/tests/configs/custom_useceleryconfig.ini @@ -0,0 +1,3 @@ +[celery] +use_celeryconfig = true +celery_config_module = custom_celeryconfig.config diff --git a/tests/custom_celeryconfig/__init__.py b/tests/custom_celeryconfig/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/custom_celeryconfig/config.py b/tests/custom_celeryconfig/config.py new file mode 100644 index 0000000..942f10e --- /dev/null +++ b/tests/custom_celeryconfig/config.py @@ -0,0 +1 @@ +BROKER_URL = "redis://localhost:1337/1" diff --git a/tests/test_celery.py b/tests/test_celery.py index 954da2e..d9c2cde 100644 --- a/tests/test_celery.py +++ b/tests/test_celery.py @@ -52,6 +52,22 @@ def test_includeme_use_celeryconfig(): assert celery_app.conf['broker_url'] == 'redis://localhost:1337/0' +@pytest.mark.unit +def test_includeme_use_custom_celeryconfig(): + from pyramid_celery import includeme + from pyramid_celery import celery_app + from pyramid import testing + from pyramid.registry import Registry + config = testing.setUp() + config.registry = Registry() + config.registry.settings = {} + + includeme(config) + config.configure_celery('tests/configs/custom_useceleryconfig.ini') + + assert celery_app.conf['broker_url'] == 'redis://localhost:1337/1' + + @pytest.mark.unit def test_preload_no_ini(): from pyramid_celery import on_preload_parsed @@ -74,7 +90,7 @@ def test_preload_ini(): with mock.patch('pyramid_celery.bootstrap') as boot: on_preload_parsed(options) - assert boot.called_with('dev.ini') + boot.assert_called_with(options['ini']) @pytest.mark.unit @@ -105,8 +121,8 @@ def test_preload_with_ini_vars(): with mock.patch('pyramid_celery.bootstrap') as boot: on_preload_parsed(options) - expected_vars = {'database': 'foo', 'password': 'bar'} - assert boot.called_with('dev.ini', expected_vars) + expected_vars = {'database': 'foo', 'password': 'bar'} + boot.assert_called_with(options['ini'], options=expected_vars) @pytest.mark.unit @@ -127,7 +143,7 @@ def test_ini_logging(): format='', colorize=False, ) - assert setup_logging.called_with('tests/configs/dev.ini') + setup_logging.assert_called_with('tests/configs/dev.ini') @pytest.mark.unit diff --git a/tox.ini b/tox.ini index 22ae5ae..5d5a452 100644 --- a/tox.ini +++ b/tox.ini @@ -1,10 +1,10 @@ [tox] skipsdist = True -envlist = py36, py37, py38, py39, pypy3, flake8, celery4, celery5 +envlist = py{36,37,38,39,310,py3}-{celery4,celery5}, py{311,312}-celery5, flake8 [base] commands = - {envpython} -m pip install -e . -r test-requirements.txt + {envpython} -m pip install -e . -r requirements.txt -r test-requirements.txt [testenv] pip_pre=False @@ -33,3 +33,19 @@ commands = {[base]commands} {envpython} -m pip install -U 'celery>3,<5' {envpython} -m pytest {posargs} + +[gh-actions] +python = + 3.6: py36-{celery4,celery5} + 3.7: py37-{celery4,celery5} + 3.8: py38-{celery4,celery5} + 3.9: py39-{celery4,celery5} + 3.10: py310-{celery4,celery5}, flake8 + 3.11: py311-celery5 + 3.12: py312-celery5 + +[gh-actions:env] +PLATFORM = + ubuntu-latest: linux + macos-latest: macos + windows-latest: windows