diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 89cdba0c..949098a2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,10 +2,10 @@ name: Python CI on: push: - branches: [ main ] + branches: [main] pull_request: branches: - - '**' + - '**' jobs: @@ -15,30 +15,30 @@ jobs: strategy: matrix: os: [ubuntu-20.04] - python-version: ['3.8'] - toxenv: ["quality", "docs", "django32", "django42"] + python-version: ['3.8', '3.11'] + toxenv: ["django42", "quality", "docs"] steps: - - uses: actions/checkout@v4 - - name: setup python - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - - - name: Install pip - run: pip install -r requirements/pip.txt - - - name: Install Dependencies - run: pip install -r requirements/ci.txt - - - name: Run Tests - env: - TOXENV: ${{ matrix.toxenv }} - run: tox - - - name: Run coverage - if: matrix.python-version == '3.8' && matrix.toxenv == 'django42' - uses: codecov/codecov-action@v3 - with: - flags: unittests - fail_ci_if_error: true + - uses: actions/checkout@v4 + - name: Setup python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + + - name: Install pip + run: pip install -r requirements/pip.txt + + - name: Install Dependencies + run: pip install -r requirements/ci.txt + + - name: Run Tests + env: + TOXENV: ${{ matrix.toxenv }} + run: tox + + - name: Run coverage + if: matrix.python-version == '3.8' && matrix.toxenv == 'django42' + uses: codecov/codecov-action@v3 + with: + flags: unittests + fail_ci_if_error: false diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 5ad7aad6..a1762b32 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -13,6 +13,13 @@ Change Log Unreleased ---------- + +[9.8.0] - 2024-04-11 + +Added +~~~~~ +* Added support for Python 3.11 + [9.7.0] - 2024-04-04 -------------------- Added diff --git a/openedx_events/__init__.py b/openedx_events/__init__.py index 9d5edda1..1b77b947 100644 --- a/openedx_events/__init__.py +++ b/openedx_events/__init__.py @@ -5,4 +5,4 @@ more information about the project. """ -__version__ = "9.7.0" +__version__ = "9.8.0" diff --git a/openedx_events/content_authoring/data.py b/openedx_events/content_authoring/data.py index e76559bf..1483ddbc 100644 --- a/openedx_events/content_authoring/data.py +++ b/openedx_events/content_authoring/data.py @@ -185,7 +185,7 @@ class LibraryBlockData: @attr.s(frozen=True) class ContentObjectData: """ - Data about changed content object + Data about changed content object. Arguments: object_id (str): identifier of the Content object. This represents the id of the course or library block diff --git a/openedx_events/event_bus/tests/test_loader.py b/openedx_events/event_bus/tests/test_loader.py index 720f3d7c..417b89c0 100644 --- a/openedx_events/event_bus/tests/test_loader.py +++ b/openedx_events/event_bus/tests/test_loader.py @@ -3,10 +3,12 @@ """ import copy +import sys import warnings from contextlib import contextmanager from unittest import TestCase +import pytest from django.test import override_settings from openedx_events.data import EventsMetadata @@ -83,6 +85,7 @@ def test_missing_attribute(self): ) assert loaded == {'def': 'ault'} + @pytest.mark.skipif(sys.version_info > (3, 9), reason="Python 3.8.x required") # Temporary until 3.8 is dropped @override_settings(EB_LOAD_PATH='builtins.dict') def test_bad_args_for_callable(self): with assert_warnings([ @@ -96,6 +99,20 @@ def test_bad_args_for_callable(self): ) assert loaded == {'def': 'ault'} + @pytest.mark.skipif(sys.version_info < (3, 9), reason="Python 3.11.x required") # Temporary until 3.8 is dropped + @override_settings(EB_LOAD_PATH='builtins.dict') + def test_bad_args_for_callable(self): + with assert_warnings([ + "Failed to load from setting EB_LOAD_PATH: " + "TypeError('dict() argument after * must be an iterable, not int'); " + "component will be inactive" + ]): + loaded = _try_load( + setting_name="EB_LOAD_PATH", args=(1), kwargs={'2': 3}, + expected_class=dict, default={'def': 'ault'}, + ) + assert loaded == {'def': 'ault'} + class TestProducer(TestCase): diff --git a/openedx_events/tests/test_producer_config.py b/openedx_events/tests/test_producer_config.py index 1b89e07e..51bb5358 100644 --- a/openedx_events/tests/test_producer_config.py +++ b/openedx_events/tests/test_producer_config.py @@ -42,18 +42,16 @@ def test_enabled_disabled_events(self, mock_producer): XBLOCK_PUBLISHED.send_event(xblock_info=self.xblock_info) mock_send.send.assert_called() mock_send.send.call_count = 2 + expected_call_args = [ + {'topic': 'enabled_topic_a', 'event_key_field': 'xblock_info.usage_key'}, + {'topic': 'enabled_topic_b', 'event_key_field': 'xblock_info.usage_key'} + ] # check that call_args_list only consists of enabled topics. call_args = mock_send.send.call_args_list[0][1] - self.assertDictContainsSubset( - {'topic': 'enabled_topic_a', 'event_key_field': 'xblock_info.usage_key'}, - call_args - ) + self.assertEqual(call_args, {**call_args, **expected_call_args[0]}) call_args = mock_send.send.call_args_list[1][1] - self.assertDictContainsSubset( - {'topic': 'enabled_topic_b', 'event_key_field': 'xblock_info.usage_key'}, - call_args - ) + self.assertEqual(call_args, {**call_args, **expected_call_args[1]}) @patch("openedx_events.apps.logger") @patch('openedx_events.apps.get_producer') diff --git a/openedx_events/tests/test_tooling.py b/openedx_events/tests/test_tooling.py index da480d3d..626cdb9e 100644 --- a/openedx_events/tests/test_tooling.py +++ b/openedx_events/tests/test_tooling.py @@ -111,8 +111,9 @@ def test_generate_signal_metadata(self, datetime_mock, socket_mock, events_packa } metadata = self.public_signal.generate_signal_metadata() + metadata_as_dict = attr.asdict(metadata) - self.assertDictContainsSubset(expected_metadata, attr.asdict(metadata)) + self.assertEqual(metadata_as_dict, {**expected_metadata, **metadata_as_dict}) self.assertIsInstance(metadata.id, UUID) @override_settings(SERVICE_VARIANT="lms") @@ -138,8 +139,9 @@ def test_generate_signal_metadata_with_valid_time(self, socket_mock, events_pack } metadata = self.public_signal.generate_signal_metadata(time=expected_time) + metadata_as_dict = attr.asdict(metadata) - self.assertDictContainsSubset(expected_metadata, attr.asdict(metadata)) + self.assertEqual(metadata_as_dict, {**expected_metadata, **metadata_as_dict}) self.assertIsInstance(metadata.id, UUID) @ddt.data( diff --git a/requirements/base.txt b/requirements/base.txt index c9b7abfe..6e35e604 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -8,8 +8,10 @@ asgiref==3.8.1 # via django attrs==23.2.0 # via -r requirements/base.in -backports-zoneinfo==0.2.1 - # via django +backports-zoneinfo==0.2.1 ; python_version < "3.9" + # via + # -c requirements/constraints.txt + # django cffi==1.16.0 # via pynacl click==8.1.7 @@ -25,19 +27,19 @@ django-crum==0.7.9 # via edx-django-utils django-waffle==4.1.0 # via edx-django-utils -edx-django-utils==5.11.0 +edx-django-utils==5.12.0 # via -r requirements/base.in edx-opaque-keys[django]==2.5.1 # via -r requirements/base.in fastavro==1.9.4 # via -r requirements/base.in -newrelic==9.7.1 +newrelic==9.8.0 # via edx-django-utils pbr==6.0.0 # via stevedore psutil==5.9.8 # via edx-django-utils -pycparser==2.21 +pycparser==2.22 # via cffi pymongo==3.13.0 # via edx-opaque-keys @@ -49,7 +51,7 @@ stevedore==5.2.0 # via # edx-django-utils # edx-opaque-keys -typing-extensions==4.10.0 +typing-extensions==4.11.0 # via # asgiref # edx-opaque-keys diff --git a/requirements/ci.txt b/requirements/ci.txt index c9dd7491..641296fb 100644 --- a/requirements/ci.txt +++ b/requirements/ci.txt @@ -12,7 +12,7 @@ colorama==0.4.6 # via tox distlib==0.3.8 # via virtualenv -filelock==3.13.1 +filelock==3.13.4 # via # tox # virtualenv diff --git a/requirements/constraints.txt b/requirements/constraints.txt index 09c2c45e..7bcb44c8 100644 --- a/requirements/constraints.txt +++ b/requirements/constraints.txt @@ -15,3 +15,6 @@ # This should be removed once the issue is fixed with a new astroid release or with a test_generate_avro_schemas.py # module refactor. astroid<3.0.0 + +# Temporary to Support the python 3.11 Upgrade +backports.zoneinfo;python_version<"3.9" # Newer versions have zoneinfo available in the standard library diff --git a/requirements/dev.txt b/requirements/dev.txt index c5f8b544..50519892 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -16,11 +16,16 @@ astroid==2.15.8 # pylint-celery attrs==23.2.0 # via -r requirements/quality.txt -backports-zoneinfo==0.2.1 +backports-tarfile==1.0.0 # via # -r requirements/quality.txt + # jaraco-context +backports-zoneinfo==0.2.1 ; python_version < "3.9" + # via + # -c requirements/constraints.txt + # -r requirements/quality.txt # django -build==1.1.1 +build==1.2.1 # via # -r requirements/pip-tools.txt # pip-tools @@ -106,7 +111,7 @@ docutils==0.20.1 # via # -r requirements/quality.txt # readme-renderer -edx-django-utils==5.11.0 +edx-django-utils==5.12.0 # via -r requirements/quality.txt edx-lint==5.3.6 # via -r requirements/quality.txt @@ -118,7 +123,7 @@ exceptiongroup==1.2.0 # pytest fastavro==1.9.4 # via -r requirements/quality.txt -filelock==3.13.1 +filelock==3.13.4 # via # -r requirements/ci.txt # tox @@ -147,11 +152,11 @@ isort==5.13.2 # via # -r requirements/quality.txt # pylint -jaraco-classes==3.3.1 +jaraco-classes==3.4.0 # via # -r requirements/quality.txt # keyring -jaraco-context==4.3.0 +jaraco-context==5.3.0 # via # -r requirements/quality.txt # keyring @@ -169,7 +174,7 @@ jinja2==3.1.3 # -r requirements/quality.txt # code-annotations # diff-cover -keyring==25.0.0 +keyring==25.1.0 # via # -r requirements/quality.txt # twine @@ -198,11 +203,11 @@ more-itertools==10.2.0 # -r requirements/quality.txt # jaraco-classes # jaraco-functools -newrelic==9.7.1 +newrelic==9.8.0 # via # -r requirements/quality.txt # edx-django-utils -nh3==0.2.15 +nh3==0.2.17 # via # -r requirements/quality.txt # readme-renderer @@ -245,7 +250,7 @@ psutil==5.9.8 # edx-django-utils pycodestyle==2.11.1 # via -r requirements/quality.txt -pycparser==2.21 +pycparser==2.22 # via # -r requirements/quality.txt # cffi @@ -379,7 +384,7 @@ tox==4.14.2 # via -r requirements/ci.txt twine==5.0.0 # via -r requirements/quality.txt -typing-extensions==4.10.0 +typing-extensions==4.11.0 # via # -r requirements/quality.txt # asgiref diff --git a/requirements/doc.txt b/requirements/doc.txt index d442b3c6..06a3a454 100644 --- a/requirements/doc.txt +++ b/requirements/doc.txt @@ -18,13 +18,16 @@ babel==2.14.0 # via # pydata-sphinx-theme # sphinx -backports-zoneinfo==0.2.1 +backports-tarfile==1.0.0 + # via jaraco-context +backports-zoneinfo==0.2.1 ; python_version < "3.9" # via + # -c requirements/constraints.txt # -r requirements/test.txt # django beautifulsoup4==4.12.3 # via pydata-sphinx-theme -build==1.1.1 +build==1.2.1 # via -r requirements/doc.in certifi==2024.2.2 # via requests @@ -76,7 +79,7 @@ docutils==0.19 # readme-renderer # restructuredtext-lint # sphinx -edx-django-utils==5.11.0 +edx-django-utils==5.12.0 # via -r requirements/test.txt edx-opaque-keys[django]==2.5.1 # via -r requirements/test.txt @@ -103,9 +106,9 @@ iniconfig==2.0.0 # via # -r requirements/test.txt # pytest -jaraco-classes==3.3.1 +jaraco-classes==3.4.0 # via keyring -jaraco-context==4.3.0 +jaraco-context==5.3.0 # via keyring jaraco-functools==4.0.0 # via keyring @@ -118,7 +121,7 @@ jinja2==3.1.3 # -r requirements/test.txt # code-annotations # sphinx -keyring==25.0.0 +keyring==25.1.0 # via twine livereload==2.6.3 # via sphinx-autobuild @@ -134,11 +137,11 @@ more-itertools==10.2.0 # via # jaraco-classes # jaraco-functools -newrelic==9.7.1 +newrelic==9.8.0 # via # -r requirements/test.txt # edx-django-utils -nh3==0.2.15 +nh3==0.2.17 # via readme-renderer packaging==24.0 # via @@ -161,7 +164,7 @@ psutil==5.9.8 # via # -r requirements/test.txt # edx-django-utils -pycparser==2.21 +pycparser==2.22 # via # -r requirements/test.txt # cffi @@ -284,7 +287,7 @@ tornado==6.4 # via livereload twine==5.0.0 # via -r requirements/doc.in -typing-extensions==4.10.0 +typing-extensions==4.11.0 # via # -r requirements/test.txt # asgiref diff --git a/requirements/pip-tools.txt b/requirements/pip-tools.txt index 50451b3c..8ea29a86 100644 --- a/requirements/pip-tools.txt +++ b/requirements/pip-tools.txt @@ -4,7 +4,7 @@ # # make upgrade # -build==1.1.1 +build==1.2.1 # via pip-tools click==8.1.7 # via pip-tools diff --git a/requirements/quality.txt b/requirements/quality.txt index 6e3a3f9d..3080054f 100644 --- a/requirements/quality.txt +++ b/requirements/quality.txt @@ -15,8 +15,11 @@ astroid==2.15.8 # pylint-celery attrs==23.2.0 # via -r requirements/test.txt -backports-zoneinfo==0.2.1 +backports-tarfile==1.0.0 + # via jaraco-context +backports-zoneinfo==0.2.1 ; python_version < "3.9" # via + # -c requirements/constraints.txt # -r requirements/test.txt # django certifi==2024.2.2 @@ -68,7 +71,7 @@ django-waffle==4.1.0 # edx-django-utils docutils==0.20.1 # via readme-renderer -edx-django-utils==5.11.0 +edx-django-utils==5.12.0 # via -r requirements/test.txt edx-lint==5.3.6 # via -r requirements/quality.in @@ -97,9 +100,9 @@ isort==5.13.2 # via # -r requirements/quality.in # pylint -jaraco-classes==3.3.1 +jaraco-classes==3.4.0 # via keyring -jaraco-context==4.3.0 +jaraco-context==5.3.0 # via keyring jaraco-functools==4.0.0 # via keyring @@ -111,7 +114,7 @@ jinja2==3.1.3 # via # -r requirements/test.txt # code-annotations -keyring==25.0.0 +keyring==25.1.0 # via twine lazy-object-proxy==1.10.0 # via astroid @@ -129,11 +132,11 @@ more-itertools==10.2.0 # via # jaraco-classes # jaraco-functools -newrelic==9.7.1 +newrelic==9.8.0 # via # -r requirements/test.txt # edx-django-utils -nh3==0.2.15 +nh3==0.2.17 # via readme-renderer packaging==24.0 # via @@ -157,7 +160,7 @@ psutil==5.9.8 # edx-django-utils pycodestyle==2.11.1 # via -r requirements/quality.in -pycparser==2.21 +pycparser==2.22 # via # -r requirements/test.txt # cffi @@ -248,7 +251,7 @@ tomlkit==0.12.4 # via pylint twine==5.0.0 # via -r requirements/quality.in -typing-extensions==4.10.0 +typing-extensions==4.11.0 # via # -r requirements/test.txt # asgiref diff --git a/requirements/test.txt b/requirements/test.txt index b9352b31..52f4b9bc 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -10,8 +10,9 @@ asgiref==3.8.1 # django attrs==23.2.0 # via -r requirements/base.txt -backports-zoneinfo==0.2.1 +backports-zoneinfo==0.2.1 ; python_version < "3.9" # via + # -c requirements/constraints.txt # -r requirements/base.txt # django cffi==1.16.0 @@ -43,7 +44,7 @@ django-waffle==4.1.0 # via # -r requirements/base.txt # edx-django-utils -edx-django-utils==5.11.0 +edx-django-utils==5.12.0 # via -r requirements/base.txt edx-opaque-keys[django]==2.5.1 # via -r requirements/base.txt @@ -57,7 +58,7 @@ jinja2==3.1.3 # via code-annotations markupsafe==2.1.5 # via jinja2 -newrelic==9.7.1 +newrelic==9.8.0 # via # -r requirements/base.txt # edx-django-utils @@ -73,7 +74,7 @@ psutil==5.9.8 # via # -r requirements/base.txt # edx-django-utils -pycparser==2.21 +pycparser==2.22 # via # -r requirements/base.txt # cffi @@ -113,7 +114,7 @@ tomli==2.0.1 # via # coverage # pytest -typing-extensions==4.10.0 +typing-extensions==4.11.0 # via # -r requirements/base.txt # asgiref diff --git a/tests/test_openedx_events.py b/tests/test_openedx_events.py deleted file mode 100644 index 414734f3..00000000 --- a/tests/test_openedx_events.py +++ /dev/null @@ -1,12 +0,0 @@ -""" -Tests for openedx_events.py. -""" - - -class TestEvents: - """ - Tests of openedx events. - """ - - def test_something(self): - """TODO: Write real test cases.""" diff --git a/tox.ini b/tox.ini index c21befde..6fb74812 100644 --- a/tox.ini +++ b/tox.ini @@ -1,8 +1,7 @@ [tox] -envlist = py{38}-django{32, 42}, quality, docs, pii_check +envlist = py{38, 311}-django{42}, quality, docs [doc8] -; D001 = Line too long ignore = D001 [pycodestyle] @@ -28,16 +27,14 @@ max-doc-length = 120 ; D413 = Missing blank line after last section (numpy style) ; D414 = Section has no content (numpy style) ignore = D101,D200,D203,D212,D215,D404,D405,D406,D407,D408,D409,D410,D411,D412,D413,D414 -match-dir = (?!migrations) [pytest] DJANGO_SETTINGS_MODULE = test_utils.test_settings -addopts = --cov openedx_events --cov tests --cov-report term-missing --cov-report xml +addopts = --cov openedx_events --cov-report term-missing --cov-report xml norecursedirs = .* docs requirements site-packages [testenv] deps = - django32: Django>=3.2,<4.0 django42: Django>=4.2,<4.3 -r{toxinidir}/requirements/test.txt commands = @@ -72,10 +69,8 @@ allowlist_externals = deps = -r{toxinidir}/requirements/quality.txt commands = - touch tests/__init__.py - pylint openedx_events tests test_utils manage.py setup.py - rm tests/__init__.py - pycodestyle openedx_events tests manage.py setup.py - pydocstyle openedx_events tests manage.py setup.py - isort --check-only --diff tests test_utils openedx_events manage.py setup.py + pylint openedx_events test_utils manage.py setup.py + pycodestyle openedx_events manage.py setup.py + pydocstyle openedx_events manage.py setup.py + isort --check-only --diff test_utils openedx_events manage.py setup.py make selfcheck