diff --git a/.github/workflows/bump_version.yml b/.github/workflows/bump_version.yml index a012ae864..1d1d62cce 100644 --- a/.github/workflows/bump_version.yml +++ b/.github/workflows/bump_version.yml @@ -23,7 +23,7 @@ jobs: default_prerelease_bump: false dry_run: true - name: Set up Python 3.8 - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: "3.8" - name: Create bumpversion @@ -40,7 +40,7 @@ jobs: - name: Commit bumpversion id: bumpversion if: steps.tag_version.outputs.new_version - uses: stefanzweifel/git-auto-commit-action@v4 + uses: stefanzweifel/git-auto-commit-action@v5 with: branch: ${{ github.ref }} commit_message: "docs(bumpversion): ${{ steps.tag_version.outputs.previous_tag }} → ${{ steps.tag_version.outputs.new_version }}" diff --git a/.github/workflows/pr_issue_assignment.yml b/.github/workflows/pr_issue_assignment.yml index 0796b4920..9c10320dc 100644 --- a/.github/workflows/pr_issue_assignment.yml +++ b/.github/workflows/pr_issue_assignment.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: 'Auto-assign PR-Issue' - uses: pozil/auto-assign-issue@v1.5.0 + uses: pozil/auto-assign-issue@v1.13.0 with: repo-token: ${{ secrets.DEDALO_PAT }} teams: django-plugins-teco diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index 5632c8a14..835bd2830 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -21,9 +21,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: '3.10' - name: Install dependencies @@ -34,7 +34,7 @@ jobs: run: | python -m build --sdist --wheel --outdir dist/ . - name: Publish package - uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 + uses: pypa/gh-action-pypi-publish@v1.8.10 with: user: __token__ password: ${{ secrets.PYPI_API_TOKEN }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 750c804c0..b64222596 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -11,11 +11,11 @@ jobs: strategy: max-parallel: 2 matrix: - python-version: ["3.8", "3.10"] + python-version: ["3.8"] django: ["32"] steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Cache dependency uses: actions/cache@v3 @@ -25,7 +25,7 @@ jobs: restore-keys: | ${{ runner.os }}-pip- - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} diff --git a/.pylintrc b/.pylintrc index 5b0fdf17b..4513b4a34 100644 --- a/.pylintrc +++ b/.pylintrc @@ -4,7 +4,6 @@ ignore = migrations,CVS [MESSAGES CONTROL] disable= unused-argument, - no-self-use, too-few-public-methods, fixme, line-too-long, diff --git a/README.rst b/README.rst index 1b3177633..1a0312622 100644 --- a/README.rst +++ b/README.rst @@ -9,74 +9,26 @@ endpoints in order to extend the functionality of the `edx-platform`_ and avoid API endpoints includes bulk creation of pre-activated users (for example, skip sending an activation email), enrollments and pre-enrollment operations. -Usage -===== +Installation +============ -Open edX releases before juniper --------------------------------- +#. Add this plugin in your Tutor ``config.yml`` in the ``OPENEDX_EXTRA_PIP_REQUIREMENTS`` variable. +#. Save your configuration with ``tutor config save``. +#. Build your open edx image with ``tutor images build openedx``. +#. Launch your platform with ``tutor local launch``. -#. Create the oauth client at http://localhost:18000/admin/oauth2/client/add/, copy the client-id and client-secret. +**Note:** To use all the features, you need to have `the tutor-forum plugin `_ and `the eox-tenant plugin `_. -#. Generate an auth-token using that client-id and client-secret: +Features +========= +- Support redirections with middlewares. +- Add pipelines to be used with ``openedx-filters``. +- Add a group of APIs. - .. code-block:: bash + .. image:: docs/_images/eox-core-apis.png + :alt: Eox-core APIs - $ curl -X POST -d "client_id=&client_secret= &grant_type=client_credentials" http://localhost:18000/oauth2/access_token/ - -#. Use the token to call the API as you need: - - * User creation API example - - .. code-block:: bash - - curl -X POST http://localhost:18000/eox-core/api/v1/user/ \ - -H "Authorization: Bearer " \ - -H "Accept: application/json" \ - -H "Content\-Type: application/json" \ - --data '{"username": "jsmith", "email": "jhon@example.com", "password": "qwerty123", "fullname": "Jhon Smith"}' - - * Enroll api example - - .. code-block:: bash - - curl -X POST http://localhost:18000/eox-core/api/v1/enrollment/ \ - -H "Authorization: Bearer " \ - -H "Accept: application/json" \ - -H "Content\-Type: application/json" \ - --data '{"course_id": "course-v1:edX+DemoX+Demo_Course", "email": "edx@example.com", "mode": "audit", "force": 1}' - - -Open edX releases after juniper -------------------------------- - -Instead of step 1, follow: - -#. Create a Django Oauth Toolkit Application at http://localhost:18000/admin/oauth2_provider/application/add/, - copy the client-id and client-secret. Then follow 2 and 3. - - -Installation on Open edX Devstack -================================= - -* Install either the Ironwood or Juniper version of the `Open edX devstack`_ - -* Clone the git repo: - - .. code-block:: bash - - cd ~/Documents/eoxstack/src/ # Assuming that devstack is in ~/Documents/eoxstack/devstack/ - sudo mkdir edxapp - cd edxapp - git clone git@github.com:eduNEXT/eox-core.git - -- Install plugin from your server (in this case the devstack docker lms shell): - - .. code-block:: bash - - cd ~/Documents/eoxstack/devstack # Change for your devstack path (if you are using devstack) - make lms-shell # Enter the devstack machine (or server where lms process lives) - cd /edx/src/edxapp/eox-core - pip install -e . +You can find more information in `Help for devs doc `_. Compatibility Notes -------------------- @@ -98,6 +50,8 @@ Compatibility Notes +------------------+--------------+ | Olive | >= 8.0 | +------------------+--------------+ +| Palm | >= 9.0 | ++------------------+--------------+ **NOTE**: The Maple version does not support Django 2.2 but it does support Django 3.2 as of eox-core 7.0. @@ -182,28 +136,6 @@ The plugin offers some integrations listed below: profiles_sample_rate: 0.5 another_client_parameter: 'value' - - -EOX core migration notes -======================== - -**Migrating to version 2.0.0** - -From version **2.0.0**, middlewares **RedirectionsMiddleware** and **PathRedirectionMiddleware** are now included in -this plugin. These middlewares were moved from the **`eox-tenant`_** plugin. - -if you installed **eox-core** alongside **eox-tenant** plugin, follow the steps below: - -- Upgrade eox-tenant to version **1.0.0** (previous releases are not compatible with eox-core 2.0.0) -- Run the plugin migrations as indicated below: - -.. code-block:: bash - - $ python manage.py lms migrate eox_tenant --settings= - $ python manage.py lms migrate eox_core --fake-initial --settings= - -In case eox-tenant is not installed on the platform, just run the eox-core migrations. - Auditing Django views ===================== diff --git a/docs/_images/eox-core-apis.png b/docs/_images/eox-core-apis.png new file mode 100644 index 000000000..d5cc612b9 Binary files /dev/null and b/docs/_images/eox-core-apis.png differ diff --git a/eox_core/edxapp_wrapper/backends/enrollment_l_v1.py b/eox_core/edxapp_wrapper/backends/enrollment_l_v1.py index 0ef87d94a..47ffbae53 100644 --- a/eox_core/edxapp_wrapper/backends/enrollment_l_v1.py +++ b/eox_core/edxapp_wrapper/backends/enrollment_l_v1.py @@ -324,7 +324,7 @@ def _create_or_update_enrollment(username, course_id, mode, is_active, try_updat if try_update: enrollment = api._data_api().update_course_enrollment(username, course_id, mode, is_active) else: - raise Exception(repr(err) + ", use force to update the existing enrollment") from err + raise APIException(repr(err) + ", use force to update the existing enrollment") from err return enrollment diff --git a/eox_core/edxapp_wrapper/backends/enrollment_o_v1.py b/eox_core/edxapp_wrapper/backends/enrollment_o_v1.py index 96e33d37d..0d2c163d9 100644 --- a/eox_core/edxapp_wrapper/backends/enrollment_o_v1.py +++ b/eox_core/edxapp_wrapper/backends/enrollment_o_v1.py @@ -324,7 +324,7 @@ def _create_or_update_enrollment(username, course_id, mode, is_active, try_updat if try_update: enrollment = api._data_api().update_course_enrollment(username, course_id, mode, is_active) else: - raise Exception(repr(err) + ", use force to update the existing enrollment") from err + raise Exception(repr(err) + ", use force to update the existing enrollment") from err # pylint: disable=broad-exception-raised return enrollment diff --git a/eox_core/middleware.py b/eox_core/middleware.py index 04e3d020c..61a571525 100644 --- a/eox_core/middleware.py +++ b/eox_core/middleware.py @@ -21,19 +21,13 @@ from django.urls import reverse from django.utils.deprecation import MiddlewareMixin from requests.exceptions import HTTPError +from social_core.exceptions import AuthAlreadyAssociated, AuthFailed, AuthUnreachableProvider from eox_core.edxapp_wrapper.configuration_helpers import get_configuration_helper from eox_core.edxapp_wrapper.third_party_auth import get_tpa_exception_middleware from eox_core.models import Redirection from eox_core.utils import cache, fasthash -try: - from social_core.exceptions import AuthAlreadyAssociated, AuthFailed, AuthUnreachableProvider -except ImportError: - AuthUnreachableProvider = Exception - AuthAlreadyAssociated = Exception - AuthFailed = Exception - try: from eox_tenant.pipeline import EoxTenantAuthException except ImportError: diff --git a/eox_core/models.py b/eox_core/models.py index ea8726323..669601be2 100644 --- a/eox_core/models.py +++ b/eox_core/models.py @@ -28,7 +28,7 @@ class Redirection(models.Model): scheme = models.CharField(max_length=5, choices=SCHEME, default=HTTP) status = models.IntegerField(choices=STATUS, default=301) - class Meta: # pylint: disable=no-init + class Meta: """ Model meta class. """ diff --git a/eox_core/pipeline.py b/eox_core/pipeline.py index be5bfbd7a..dbf8561e3 100644 --- a/eox_core/pipeline.py +++ b/eox_core/pipeline.py @@ -5,6 +5,7 @@ from crum import get_current_request from django.db.models.signals import post_save +from social_core.exceptions import AuthFailed, NotAllowedToDisconnect from eox_core.edxapp_wrapper.users import ( generate_password, @@ -14,12 +15,6 @@ ) from eox_core.logging import logging_pipeline_step -try: - from social_core.exceptions import AuthFailed, NotAllowedToDisconnect -except ImportError: - AuthFailed = object - NotAllowedToDisconnect = object - UserSignupSource = get_user_signup_source() # pylint: disable=invalid-name LOG = logging.getLogger(__name__) diff --git a/eox_core/social_tpa_backends.py b/eox_core/social_tpa_backends.py index 5936140ef..62e058e6e 100644 --- a/eox_core/social_tpa_backends.py +++ b/eox_core/social_tpa_backends.py @@ -5,25 +5,18 @@ from django.conf import settings from django.contrib.auth import get_user_model +from social_core.backends.open_id_connect import OpenIdConnectAuth +from social_core.exceptions import AuthMissingParameter from eox_core.edxapp_wrapper.configuration_helpers import get_configuration_helper -try: - from social_core.backends.open_id_connect import OpenIdConnectAuth -except ImportError: - OpenIdConnectAuth = object -try: - from social_core.exceptions import AuthMissingParameter -except ImportError: - AuthMissingParameter = Exception - configuration_helper = get_configuration_helper() # pylint: disable=invalid-name LOG = logging.getLogger(__name__) User = get_user_model() # pylint: disable=invalid-name -class ConfigurableOpenIdConnectAuth(OpenIdConnectAuth): +class ConfigurableOpenIdConnectAuth(OpenIdConnectAuth): # pylint: disable=abstract-method """ Generic backend that can be configured via the site settings """ diff --git a/eox_core/tests/integration/test_enrollment_integration.py b/eox_core/tests/integration/test_enrollment_integration.py index 6ed93e556..57cba454b 100644 --- a/eox_core/tests/integration/test_enrollment_integration.py +++ b/eox_core/tests/integration/test_enrollment_integration.py @@ -34,11 +34,11 @@ def setUpClass(cls): "grant_type": "client_credentials", } request_url = f"{cls.data['site1_data']['base_url']}/oauth2/access_token/" - response_site1 = requests.post(request_url, data=site1_data) + response_site1 = requests.post(request_url, data=site1_data, timeout=10) response_site1.raise_for_status() cls.data["site1_data"]["token"] = response_site1.json()["access_token"] request_url = f"{cls.data['site2_data']['base_url']}/oauth2/access_token/" - response_site2 = requests.post(request_url, data=site2_data) + response_site2 = requests.post(request_url, data=site2_data, timeout=10) response_site2.raise_for_status() cls.data["site2_data"]["token"] = response_site2.json()["access_token"] @@ -67,7 +67,7 @@ def test_read_valid_email_course(self): } request_url = f"{site1_data['base_url']}/{self.data['endpoint']}" - response = requests.get(request_url, data=data, headers=headers) + response = requests.get(request_url, data=data, headers=headers, timeout=10) response_content = response.json() self.assertEqual(response.status_code, 200) @@ -90,7 +90,7 @@ def test_read_invalid_enrollment(self): } request_url = f"{site1_data['base_url']}/{self.data['endpoint']}" - response = requests.get(request_url, data=data, headers=headers) + response = requests.get(request_url, data=data, headers=headers, timeout=10) self.assertEqual(response.status_code, 404) @@ -112,7 +112,7 @@ def test_read_invalid_enrollment_for_site(self): } request_url = f"{site2_data['base_url']}/{self.data['endpoint']}" - response = requests.get(request_url, data=data, headers=headers) + response = requests.get(request_url, data=data, headers=headers, timeout=10) self.assertEqual(response.status_code, 404) @@ -135,7 +135,7 @@ def test_create_enrollment_valid_user_mode_course(self): } request_url = f"{site1_data['base_url']}/{self.data['endpoint']}" - response = requests.post(request_url, data=data, headers=headers) + response = requests.post(request_url, data=data, headers=headers, timeout=10) self.assertEqual(response.status_code, 200) @@ -159,7 +159,7 @@ def test_force_create_enrollment_valid_user_mode_course(self): } request_url = f"{site1_data['base_url']}/{self.data['endpoint']}" - response = requests.post(request_url, data=data, headers=headers) + response = requests.post(request_url, data=data, headers=headers, timeout=10) self.assertEqual(response.status_code, 200) @@ -181,7 +181,7 @@ def test_create_valid_course_mode_invalid_user(self): } request_url = f"{site1_data['base_url']}/{self.data['endpoint']}" - response = requests.post(request_url, data=data, headers=headers) + response = requests.post(request_url, data=data, headers=headers, timeout=10) self.assertEqual(response.status_code, 400) @@ -204,7 +204,7 @@ def test_create_valid_course_mode_invalid_user_for_site(self): } request_url = f"{site1_data['base_url']}/{self.data['endpoint']}" - response = requests.post(request_url, data=data, headers=headers) + response = requests.post(request_url, data=data, headers=headers, timeout=10) self.assertEqual(response.status_code, 202) @@ -227,7 +227,7 @@ def test_create_valid_user_mode_invalid_course(self): } request_url = f"{site1_data['base_url']}/{self.data['endpoint']}" - response = requests.post(request_url, data=data, headers=headers) + response = requests.post(request_url, data=data, headers=headers, timeout=10) self.assertEqual(response.status_code, 400) @@ -251,7 +251,7 @@ def test_create_valid_user_mode_invalid_course_for_site(self): } request_url = f"{site2_data['base_url']}/{self.data['endpoint']}" - response = requests.post(request_url, data=data, headers=headers) + response = requests.post(request_url, data=data, headers=headers, timeout=10) self.assertEqual(response.status_code, 400) @@ -276,7 +276,7 @@ def test_force_create_valid_user_course_invalid_mode(self): } request_url = f"{site1_data['base_url']}/{self.data['endpoint']}" - response = requests.post(request_url, data=data, headers=headers) + response = requests.post(request_url, data=data, headers=headers, timeout=10) self.assertEqual(response.status_code, 400) @@ -297,7 +297,7 @@ def test_delete_valid_enrollment(self): } request_url = f"{site1_data['base_url']}/{self.data['endpoint']}" - response = requests.delete(request_url, data=data, headers=headers) + response = requests.delete(request_url, data=data, headers=headers, timeout=10) self.assertEqual(response.status_code, 204) @@ -318,7 +318,7 @@ def test_delete_invalid_enrollment(self): } request_url = f"{site1_data['base_url']}/{self.data['endpoint']}" - response = requests.delete(request_url, data=data, headers=headers) + response = requests.delete(request_url, data=data, headers=headers, timeout=10) self.assertEqual(response.status_code, 404) @@ -340,7 +340,7 @@ def test_delete_invalid_enrollment_for_site(self): } request_url = f"{site2_data['base_url']}/{self.data['endpoint']}" - response = requests.delete(request_url, data=data, headers=headers) + response = requests.delete(request_url, data=data, headers=headers, timeout=10) self.assertEqual(response.status_code, 404) @@ -368,7 +368,7 @@ def test_update_valid_enrollment_change_is_active(self): } request_url = f"{site1_data['base_url']}/{self.data['endpoint']}" - response = requests.put(request_url, data=data, headers=headers) + response = requests.put(request_url, data=data, headers=headers, timeout=10) response_content = response.json() self.assertEqual(response.status_code, 200) @@ -400,7 +400,7 @@ def test_update_valid_enrollment_change_valid_mode(self): } request_url = f"{site1_data['base_url']}/{self.data['endpoint']}" - response = requests.put(request_url, data=data, headers=headers) + response = requests.put(request_url, data=data, headers=headers, timeout=10) response_content = response.json() self.assertEqual(response.status_code, 200) @@ -425,7 +425,7 @@ def test_update_valid_enrollment_change_invalid_mode(self): } request_url = f"{site1_data['base_url']}/{self.data['endpoint']}" - response = requests.put(request_url, data=data, headers=headers) + response = requests.put(request_url, data=data, headers=headers, timeout=10) self.assertEqual(response.status_code, 400) @@ -448,7 +448,7 @@ def test_update_invalid_enrollment_change_valid_mode(self): } request_url = f"{site1_data['base_url']}/{self.data['endpoint']}" - response = requests.put(request_url, data=data, headers=headers) + response = requests.put(request_url, data=data, headers=headers, timeout=10) self.assertEqual(response.status_code, 202) @@ -471,7 +471,7 @@ def test_update_invalid_enrollment_change_is_active(self): } request_url = f"{site1_data['base_url']}/{self.data['endpoint']}" - response = requests.put(request_url, data=data, headers=headers) + response = requests.put(request_url, data=data, headers=headers, timeout=10) self.assertEqual(response.status_code, 202) @@ -501,7 +501,7 @@ def test_update_valid_enrollment_change_is_active_force_post(self): } request_url = f"{site1_data['base_url']}/{self.data['endpoint']}" - response = requests.post(request_url, data=data, headers=headers) + response = requests.post(request_url, data=data, headers=headers, timeout=10) response_content = response.json() self.assertEqual(response.status_code, 200) @@ -534,7 +534,7 @@ def test_update_valid_enrollment_change_valid_mode_force_post(self): } request_url = f"{site1_data['base_url']}/{self.data['endpoint']}" - response = requests.put(request_url, data=data, headers=headers) + response = requests.put(request_url, data=data, headers=headers, timeout=10) response_content = response.json() self.assertEqual(response.status_code, 200) @@ -557,7 +557,7 @@ def create_enrollment(data): "Host": data["site1_data"]["host"], } request_url = f"{data['site1_data']['base_url']}/{data['endpoint']}" - response = requests.post(request_url, data=req_data, headers=headers) + response = requests.post(request_url, data=req_data, headers=headers, timeout=10) response.raise_for_status() @@ -576,7 +576,7 @@ def delete_enrollment(data): "Host": data["site1_data"]["host"], } request_url = f"{data['site1_data']['base_url']}/{data['endpoint']}" - response = requests.delete(request_url, data=req_data, headers=headers) + response = requests.delete(request_url, data=req_data, headers=headers, timeout=10) if response.status_code == 404: return response.raise_for_status() diff --git a/eox_core/tests/integration/test_grade_integration.py b/eox_core/tests/integration/test_grade_integration.py index 225edf988..4813acbbb 100644 --- a/eox_core/tests/integration/test_grade_integration.py +++ b/eox_core/tests/integration/test_grade_integration.py @@ -35,11 +35,11 @@ def setUpClass(cls): "grant_type": "client_credentials", } request_url = f"{cls.data['site1_data']['base_url']}/oauth2/access_token/" - response_site1 = requests.post(request_url, data=site1_data) + response_site1 = requests.post(request_url, data=site1_data, timeout=10) response_site1.raise_for_status() cls.data["site1_data"]["token"] = response_site1.json()["access_token"] request_url = f"{cls.data['site2_data']['base_url']}/oauth2/access_token/" - response_site2 = requests.post(request_url, data=site2_data) + response_site2 = requests.post(request_url, data=site2_data, timeout=10) response_site2.raise_for_status() cls.data["site1_data"]["token"] = response_site1.json()["access_token"] cls.data["site2_data"]["token"] = response_site2.json()["access_token"] @@ -67,7 +67,7 @@ def test_read_valid_default_params(self): } request_url = f"{site1_data['base_url']}/{self.data['endpoint']}" - response = requests.get(request_url, data=data, headers=headers) + response = requests.get(request_url, data=data, headers=headers, timeout=10) response_content = response.json() self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -93,7 +93,7 @@ def test_read_detail_no_policy(self): } request_url = f"{site1_data['base_url']}/{self.data['endpoint']}" - response = requests.get(request_url, data=data, headers=headers) + response = requests.get(request_url, data=data, headers=headers, timeout=10) response_content = response.json() self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -120,7 +120,7 @@ def test_read_policy_detail(self): } request_url = f"{site1_data['base_url']}/{self.data['endpoint']}" - response = requests.get(request_url, data=data, headers=headers) + response = requests.get(request_url, data=data, headers=headers, timeout=10) response_content = response.json() self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -149,7 +149,7 @@ def test_read_invalid_enrollment_for_site(self): } request_url = f"{site2_data['base_url']}/{self.data['endpoint']}" - response = requests.get(request_url, data=data, headers=headers) + response = requests.get(request_url, data=data, headers=headers, timeout=10) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) @@ -169,5 +169,5 @@ def create_enrollment(data): "Host": data["site1_data"]["host"], } request_url = f"{data['site1_data']['base_url']}/eox-core/api/v1/enrollment/" - response = requests.post(request_url, data=req_data, headers=headers) + response = requests.post(request_url, data=req_data, headers=headers, timeout=10) response.raise_for_status() diff --git a/requirements/base.in b/requirements/base.in index 1091143d5..441d06023 100644 --- a/requirements/base.in +++ b/requirements/base.in @@ -10,8 +10,9 @@ django-oauth2-provider django-waffle edx-api-doc-tools edx-proctoring>=2.0.1 -edx-opaque-keys[django]==2.3.0 +edx-opaque-keys[django]<3.0.0 openedx-events django click edx-drf-extensions +social-auth-core diff --git a/requirements/base.txt b/requirements/base.txt index b45f787f7..0718b83f4 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -4,30 +4,34 @@ # # make upgrade # -amqp==5.1.1 +amqp==5.2.0 # via kombu appdirs==1.4.4 # via fs -asgiref==3.6.0 +asgiref==3.7.2 # via django -attrs==22.2.0 +attrs==23.1.0 # via openedx-events -billiard==3.6.4.0 +backports-zoneinfo[tzdata]==0.2.1 + # via + # celery + # kombu +billiard==4.2.0 # via celery -celery==5.2.7 +celery==5.3.6 # via # -c requirements/constraints.txt # -r requirements/base.in # event-tracking -certifi==2022.12.7 +certifi==2023.11.17 # via requests -cffi==1.15.1 +cffi==1.16.0 # via # cryptography # pynacl -charset-normalizer==3.0.1 +charset-normalizer==3.3.2 # via requests -click==8.1.3 +click==8.1.7 # via # -c requirements/constraints.txt # -r requirements/base.in @@ -40,17 +44,17 @@ click-didyoumean==0.3.0 # via celery click-plugins==1.1.1 # via celery -click-repl==0.2.0 +click-repl==0.3.0 # via celery -coreapi==2.3.3 - # via drf-yasg -coreschema==0.0.4 +cryptography==41.0.5 # via - # coreapi - # drf-yasg -cryptography==39.0.0 - # via pyjwt -django==3.2.16 + # pyjwt + # social-auth-core +defusedxml==0.8.0rc2 + # via + # python3-openid + # social-auth-core +django==3.2.23 # via # -c requirements/constraints.txt # -r requirements/base.in @@ -73,13 +77,13 @@ django-crum==0.7.9 # via # edx-django-utils # edx-proctoring -django-filter==21.1 +django-filter==23.4 # via # -c requirements/constraints.txt # -r requirements/base.in -django-ipware==4.0.2 +django-ipware==6.0.0 # via edx-proctoring -django-model-utils==4.2.0 +django-model-utils==4.3.1 # via # -c requirements/constraints.txt # edx-proctoring @@ -90,7 +94,7 @@ django-oauth-toolkit==1.3.2 # -r requirements/base.in django-oauth2-provider==0.2.6.1 # via -r requirements/base.in -django-simple-history==3.2.0 +django-simple-history==3.4.0 # via edx-proctoring django-waffle==3.0.0 # via @@ -99,7 +103,7 @@ django-waffle==3.0.0 # edx-django-utils # edx-drf-extensions # edx-proctoring -django-webpack-loader==1.8.0 +django-webpack-loader==2.0.1 # via edx-proctoring djangorestframework==3.12.4 # via @@ -112,98 +116,97 @@ djangorestframework==3.12.4 # edx-proctoring drf-jwt==1.19.2 # via edx-drf-extensions -drf-yasg==1.21.4 +drf-yasg==1.21.7 # via edx-api-doc-tools edx-api-doc-tools==1.6.0 # via # -c requirements/constraints.txt # -r requirements/base.in -edx-django-utils==5.2.0 +edx-django-utils==5.8.0 # via # -c requirements/constraints.txt # edx-drf-extensions # edx-rest-api-client # edx-when # event-tracking -edx-drf-extensions==8.3.1 +edx-drf-extensions==8.13.1 # via # -c requirements/constraints.txt + # -r requirements/base.in # edx-proctoring # edx-when -edx-opaque-keys[django]==2.3.0 +edx-opaque-keys[django]==2.5.1 # via # -c requirements/constraints.txt # -r requirements/base.in # edx-drf-extensions + # edx-opaque-keys # edx-proctoring # edx-when # openedx-events -edx-proctoring==4.13.3 +edx-proctoring==4.16.1 # via # -c requirements/constraints.txt # -r requirements/base.in -edx-rest-api-client==5.5.0 +edx-rest-api-client==5.6.1 # via edx-proctoring edx-when==2.3.0 # via # -c requirements/constraints.txt # edx-proctoring -event-tracking==2.1.0 +event-tracking==2.2.0 # via edx-proctoring -fastavro==1.7.0 +fastavro==1.9.0 # via openedx-events fs==2.4.16 # via xblock -future==0.18.3 - # via pyjwkest idna==3.4 # via requests inflection==0.5.1 # via drf-yasg -itypes==1.2.0 - # via coreapi -jinja2==3.1.2 - # via coreschema jsonfield==3.1.0 # via # -c requirements/constraints.txt # edx-proctoring -kombu==5.2.4 +kombu==5.3.4 # via celery -lxml==4.9.2 +lxml==4.9.3 + # via xblock +mako==1.3.0 # via xblock -markupsafe==2.1.2 +markupsafe==2.1.3 # via - # jinja2 + # mako # xblock -newrelic==8.5.0 +newrelic==9.2.0 # via edx-django-utils oauthlib==3.2.2 - # via django-oauth-toolkit -openedx-events==0.13.0 + # via + # django-oauth-toolkit + # requests-oauthlib + # social-auth-core +openedx-events==9.2.0 # via -r requirements/base.in -packaging==23.0 +packaging==23.2 # via drf-yasg -pbr==5.11.1 +pbr==6.0.0 # via stevedore -prompt-toolkit==3.0.36 +prompt-toolkit==3.0.41 # via click-repl -psutil==5.9.4 +psutil==5.9.6 # via edx-django-utils pycparser==2.21 # via cffi -pycryptodomex==3.16.0 - # via - # edx-proctoring - # pyjwkest -pyjwkest==1.4.2 - # via edx-drf-extensions -pyjwt[crypto]==2.6.0 +pycryptodomex==3.19.0 + # via edx-proctoring +pyjwt[crypto]==2.8.0 # via # drf-jwt # edx-drf-extensions # edx-proctoring # edx-rest-api-client + # pyjwt + # social-auth-core pymongo==3.13.0 # via # edx-opaque-keys @@ -212,72 +215,83 @@ pynacl==1.5.0 # via edx-django-utils python-dateutil==2.8.2 # via - # edx-drf-extensions + # celery # edx-proctoring # xblock -pytz==2022.7.1 +python-ipware==2.0.0 + # via django-ipware +python3-openid==3.2.0 + # via social-auth-core +pytz==2023.3.post1 # via - # celery # django # drf-yasg # edx-proctoring # event-tracking # xblock -pyyaml==6.0 - # via xblock -requests==2.28.2 +pyyaml==6.0.1 + # via + # drf-yasg + # xblock +requests==2.31.0 # via - # coreapi # django-oauth-toolkit # edx-drf-extensions # edx-rest-api-client - # pyjwkest + # requests-oauthlib # slumber -ruamel-yaml==0.17.21 - # via drf-yasg -ruamel-yaml-clib==0.2.7 - # via ruamel-yaml + # social-auth-core +requests-oauthlib==1.3.1 + # via social-auth-core rules==3.3 # via edx-proctoring semantic-version==2.10.0 # via edx-drf-extensions shortuuid==1.0.11 # via django-oauth2-provider +simplejson==3.19.2 + # via xblock six==1.16.0 # via # -r requirements/base.in - # click-repl - # edx-drf-extensions # event-tracking # fs - # pyjwkest # python-dateutil slumber==0.7.1 # via edx-rest-api-client -sqlparse==0.4.3 +social-auth-core==4.5.0 + # via -r requirements/base.in +sqlparse==0.4.4 # via django -stevedore==4.1.1 +stevedore==5.1.0 # via # edx-django-utils # edx-opaque-keys -uritemplate==4.1.1 +typing-extensions==4.8.0 # via - # coreapi - # drf-yasg -urllib3==1.26.14 + # asgiref + # edx-opaque-keys + # kombu +tzdata==2023.3 + # via + # backports-zoneinfo + # celery +uritemplate==4.1.1 + # via drf-yasg +urllib3==2.1.0 # via requests -vine==5.0.0 +vine==5.1.0 # via # amqp # celery # kombu -wcwidth==0.2.6 +wcwidth==0.2.12 # via prompt-toolkit -web-fragments==2.0.0 +web-fragments==2.1.0 # via xblock webob==1.8.7 # via xblock -xblock==1.6.1 +xblock==1.8.1 # via edx-when # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/constraints.txt b/requirements/constraints.txt index 37f9b236c..2fc625fa7 100644 --- a/requirements/constraints.txt +++ b/requirements/constraints.txt @@ -9,24 +9,24 @@ # linking to it here is good. # Test dependencies -pylint<2.14 +pylint<3.0 pycodestyle==2.8.0 factory-boy==3.2.1 -django-countries==7.4.2 +django-countries<8.0 # Keep same platform version click>=8.0,<9.0 celery>=5.2.2,<6.0.0 django<4.0 djangorestframework==3.12.4 -django-filter==21.1 -django-model-utils==4.2.0 -django-oauth-toolkit<=1.3.2 +django-filter<24.0 +django-model-utils<5.0 +django-oauth-toolkit==1.3.2 django-waffle==3.0.0 edx-api-doc-tools==1.6.0 -edx-drf-extensions==8.3.1 -edx-opaque-keys==2.3.0 -edx-proctoring>=2.0.1 +edx-drf-extensions<9.0 +edx-opaque-keys<3.0 +edx-proctoring<5.0 jsonfield==3.1.0 -edx-django-utils>=5.1.0 +edx-django-utils>=5.2.0 edx-when==2.3.0 diff --git a/requirements/django.txt b/requirements/django.txt index e92ee8ee6..d296127a5 100644 --- a/requirements/django.txt +++ b/requirements/django.txt @@ -1 +1 @@ -django==3.2.16 +django==3.2.23 diff --git a/requirements/pip-tools.txt b/requirements/pip-tools.txt index bd3f4f113..598494b9d 100644 --- a/requirements/pip-tools.txt +++ b/requirements/pip-tools.txt @@ -4,22 +4,29 @@ # # make upgrade # -build==0.10.0 +build==1.0.3 # via pip-tools -click==8.1.3 +click==8.1.7 # via # -c requirements/constraints.txt # pip-tools -packaging==23.0 +importlib-metadata==6.8.0 # via build -pip-tools==6.12.1 +packaging==23.2 + # via build +pip-tools==7.3.0 # via -r requirements/pip-tools.in pyproject-hooks==1.0.0 # via build tomli==2.0.1 - # via build -wheel==0.38.4 + # via + # build + # pip-tools + # pyproject-hooks +wheel==0.41.3 # via pip-tools +zipp==3.17.0 + # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: # pip diff --git a/requirements/test.txt b/requirements/test.txt index dd4295090..0872699bc 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -4,7 +4,7 @@ # # make upgrade # -amqp==5.1.1 +amqp==5.2.0 # via # -r requirements/base.txt # kombu @@ -12,40 +12,46 @@ appdirs==1.4.4 # via # -r requirements/base.txt # fs -asgiref==3.6.0 +asgiref==3.7.2 # via # -r requirements/base.txt # django -astroid==2.11.7 + # django-countries +astroid==2.15.8 # via pylint -attrs==22.2.0 +attrs==23.1.0 # via # -r requirements/base.txt # openedx-events - # pytest -billiard==3.6.4.0 +backports-zoneinfo[tzdata]==0.2.1 # via # -r requirements/base.txt + # backports-zoneinfo # celery -celery==5.2.7 + # kombu +billiard==4.2.0 + # via + # -r requirements/base.txt + # celery +celery==5.3.6 # via # -c requirements/constraints.txt # -r requirements/base.txt # event-tracking -certifi==2022.12.7 +certifi==2023.11.17 # via # -r requirements/base.txt # requests -cffi==1.15.1 +cffi==1.16.0 # via # -r requirements/base.txt # cryptography # pynacl -charset-normalizer==3.0.1 +charset-normalizer==3.3.2 # via # -r requirements/base.txt # requests -click==8.1.3 +click==8.1.7 # via # -c requirements/constraints.txt # -r requirements/base.txt @@ -62,26 +68,23 @@ click-plugins==1.1.1 # via # -r requirements/base.txt # celery -click-repl==0.2.0 +click-repl==0.3.0 # via # -r requirements/base.txt # celery -coreapi==2.3.3 - # via - # -r requirements/base.txt - # drf-yasg -coreschema==0.0.4 - # via - # -r requirements/base.txt - # coreapi - # drf-yasg -coverage==7.0.5 +coverage==7.3.2 # via -r requirements/test.in -cryptography==39.0.0 +cryptography==41.0.5 # via # -r requirements/base.txt # pyjwt -dill==0.3.6 + # social-auth-core +defusedxml==0.8.0rc2 + # via + # -r requirements/base.txt + # python3-openid + # social-auth-core +dill==0.3.7 # via pylint # via # -c requirements/constraints.txt @@ -101,7 +104,7 @@ dill==0.3.6 # event-tracking # jsonfield # openedx-events -django-countries==7.4.2 +django-countries==7.5.1 # via # -c requirements/constraints.txt # -r requirements/test.in @@ -110,15 +113,15 @@ django-crum==0.7.9 # -r requirements/base.txt # edx-django-utils # edx-proctoring -django-filter==21.1 +django-filter==23.4 # via # -c requirements/constraints.txt # -r requirements/base.txt -django-ipware==4.0.2 +django-ipware==6.0.0 # via # -r requirements/base.txt # edx-proctoring -django-model-utils==4.2.0 +django-model-utils==4.3.1 # via # -c requirements/constraints.txt # -r requirements/base.txt @@ -130,7 +133,7 @@ django-oauth-toolkit==1.3.2 # -r requirements/base.txt django-oauth2-provider==0.2.6.1 # via -r requirements/base.txt -django-simple-history==3.2.0 +django-simple-history==3.4.0 # via # -r requirements/base.txt # edx-proctoring @@ -141,7 +144,7 @@ django-waffle==3.0.0 # edx-django-utils # edx-drf-extensions # edx-proctoring -django-webpack-loader==1.8.0 +django-webpack-loader==2.0.1 # via # -r requirements/base.txt # edx-proctoring @@ -158,7 +161,7 @@ drf-jwt==1.19.2 # via # -r requirements/base.txt # edx-drf-extensions -drf-yasg==1.21.4 +drf-yasg==1.21.7 # via # -r requirements/base.txt # edx-api-doc-tools @@ -166,7 +169,7 @@ edx-api-doc-tools==1.6.0 # via # -c requirements/constraints.txt # -r requirements/base.txt -edx-django-utils==5.2.0 +edx-django-utils==5.8.0 # via # -c requirements/constraints.txt # -r requirements/base.txt @@ -174,25 +177,26 @@ edx-django-utils==5.2.0 # edx-rest-api-client # edx-when # event-tracking -edx-drf-extensions==8.3.1 +edx-drf-extensions==8.13.1 # via # -c requirements/constraints.txt # -r requirements/base.txt # edx-proctoring # edx-when -edx-opaque-keys[django]==2.3.0 +edx-opaque-keys[django]==2.5.1 # via # -c requirements/constraints.txt # -r requirements/base.txt # edx-drf-extensions + # edx-opaque-keys # edx-proctoring # edx-when # openedx-events -edx-proctoring==4.13.3 +edx-proctoring==4.16.1 # via # -c requirements/constraints.txt # -r requirements/base.txt -edx-rest-api-client==5.5.0 +edx-rest-api-client==5.6.1 # via # -r requirements/base.txt # edx-proctoring @@ -201,19 +205,19 @@ edx-when==2.3.0 # -c requirements/constraints.txt # -r requirements/base.txt # edx-proctoring -event-tracking==2.1.0 +event-tracking==2.2.0 # via # -r requirements/base.txt # edx-proctoring -exceptiongroup==1.1.0 +exceptiongroup==1.2.0 # via pytest factory-boy==3.2.1 # via # -c requirements/constraints.txt # -r requirements/test.in -faker==16.6.0 +faker==20.1.0 # via factory-boy -fastavro==1.7.0 +fastavro==1.9.0 # via # -r requirements/base.txt # openedx-events @@ -221,10 +225,6 @@ fs==2.4.16 # via # -r requirements/base.txt # xblock -future==0.18.3 - # via - # -r requirements/base.txt - # pyjwkest idna==3.4 # via # -r requirements/base.txt @@ -235,41 +235,37 @@ inflection==0.5.1 # drf-yasg iniconfig==2.0.0 # via pytest -isort==5.11.4 +isort==5.12.0 # via pylint -itypes==1.2.0 - # via - # -r requirements/base.txt - # coreapi -jinja2==3.1.2 - # via - # -r requirements/base.txt - # coreschema jsonfield==3.1.0 # via # -c requirements/constraints.txt # -r requirements/base.txt # edx-proctoring -kombu==5.2.4 +kombu==5.3.4 # via # -r requirements/base.txt # celery lazy-object-proxy==1.9.0 # via astroid -lxml==4.9.2 +lxml==4.9.3 # via # -r requirements/base.txt # xblock -markupsafe==2.1.2 +mako==1.3.0 # via # -r requirements/base.txt - # jinja2 + # xblock +markupsafe==2.1.3 + # via + # -r requirements/base.txt + # mako # xblock mccabe==0.7.0 # via pylint -mock==5.0.1 +mock==5.1.0 # via -r requirements/test.in -newrelic==8.5.0 +newrelic==9.2.0 # via # -r requirements/base.txt # edx-django-utils @@ -277,26 +273,28 @@ oauthlib==3.2.2 # via # -r requirements/base.txt # django-oauth-toolkit -openedx-events==0.13.0 + # requests-oauthlib + # social-auth-core +openedx-events==9.2.0 # via -r requirements/base.txt -packaging==23.0 +packaging==23.2 # via # -r requirements/base.txt # drf-yasg # pytest -pbr==5.11.1 +pbr==6.0.0 # via # -r requirements/base.txt # stevedore -platformdirs==2.6.2 +platformdirs==4.0.0 # via pylint -pluggy==1.0.0 +pluggy==1.3.0 # via pytest -prompt-toolkit==3.0.36 +prompt-toolkit==3.0.41 # via # -r requirements/base.txt # click-repl -psutil==5.9.4 +psutil==5.9.6 # via # -r requirements/base.txt # edx-django-utils @@ -308,23 +306,20 @@ pycparser==2.21 # via # -r requirements/base.txt # cffi -pycryptodomex==3.16.0 +pycryptodomex==3.19.0 # via # -r requirements/base.txt # edx-proctoring - # pyjwkest -pyjwkest==1.4.2 - # via - # -r requirements/base.txt - # edx-drf-extensions -pyjwt[crypto]==2.6.0 +pyjwt[crypto]==2.8.0 # via # -r requirements/base.txt # drf-jwt # edx-drf-extensions # edx-proctoring # edx-rest-api-client -pylint==2.13.9 + # pyjwt + # social-auth-core +pylint==2.17.7 # via # -c requirements/constraints.txt # -r requirements/test.in @@ -337,49 +332,53 @@ pynacl==1.5.0 # via # -r requirements/base.txt # edx-django-utils -pytest==7.2.1 +pytest==7.4.3 # via # -r requirements/test.in # pytest-django -pytest-django==4.5.2 +pytest-django==4.7.0 # via -r requirements/test.in python-dateutil==2.8.2 # via # -r requirements/base.txt - # edx-drf-extensions + # celery # edx-proctoring # faker # xblock -pytz==2022.7.1 +python-ipware==2.0.0 + # via + # -r requirements/base.txt + # django-ipware +python3-openid==3.2.0 + # via + # -r requirements/base.txt + # social-auth-core +pytz==2023.3.post1 # via # -r requirements/base.txt - # celery # django # drf-yasg # edx-proctoring # event-tracking # xblock -pyyaml==6.0 +pyyaml==6.0.1 # via # -r requirements/base.txt + # drf-yasg # xblock -requests==2.28.2 +requests==2.31.0 # via # -r requirements/base.txt - # coreapi # django-oauth-toolkit # edx-drf-extensions # edx-rest-api-client - # pyjwkest + # requests-oauthlib # slumber -ruamel-yaml==0.17.21 - # via - # -r requirements/base.txt - # drf-yasg -ruamel-yaml-clib==0.2.7 + # social-auth-core +requests-oauthlib==1.3.1 # via # -r requirements/base.txt - # ruamel-yaml + # social-auth-core rules==3.3 # via # -r requirements/base.txt @@ -392,59 +391,73 @@ shortuuid==1.0.11 # via # -r requirements/base.txt # django-oauth2-provider +simplejson==3.19.2 + # via + # -r requirements/base.txt + # xblock six==1.16.0 # via # -r requirements/base.txt - # click-repl - # edx-drf-extensions # event-tracking # fs - # pyjwkest # python-dateutil slumber==0.7.1 # via # -r requirements/base.txt # edx-rest-api-client -sqlparse==0.4.3 +social-auth-core==4.5.0 + # via -r requirements/base.txt +sqlparse==0.4.4 # via # -r requirements/base.txt # django -stevedore==4.1.1 +stevedore==5.1.0 # via # -r requirements/base.txt # edx-django-utils # edx-opaque-keys -testfixtures==7.0.4 +testfixtures==7.2.2 # via -r requirements/test.in tomli==2.0.1 # via # pylint # pytest -typing-extensions==4.4.0 +tomlkit==0.12.3 + # via pylint +typing-extensions==4.8.0 # via + # -r requirements/base.txt + # asgiref # astroid # django-countries + # edx-opaque-keys + # faker + # kombu # pylint +tzdata==2023.3 + # via + # -r requirements/base.txt + # backports-zoneinfo + # celery uritemplate==4.1.1 # via # -r requirements/base.txt - # coreapi # drf-yasg -urllib3==1.26.14 +urllib3==2.1.0 # via # -r requirements/base.txt # requests -vine==5.0.0 +vine==5.1.0 # via # -r requirements/base.txt # amqp # celery # kombu -wcwidth==0.2.6 +wcwidth==0.2.12 # via # -r requirements/base.txt # prompt-toolkit -web-fragments==2.0.0 +web-fragments==2.1.0 # via # -r requirements/base.txt # xblock @@ -452,9 +465,9 @@ webob==1.8.7 # via # -r requirements/base.txt # xblock -wrapt==1.14.1 +wrapt==1.16.0 # via astroid -xblock==1.6.1 +xblock==1.8.1 # via # -r requirements/base.txt # edx-when diff --git a/requirements/tox.txt b/requirements/tox.txt index c26a9f28f..219e1f9d7 100644 --- a/requirements/tox.txt +++ b/requirements/tox.txt @@ -4,35 +4,35 @@ # # make upgrade # -cachetools==5.3.0 +cachetools==5.3.2 # via tox -chardet==5.1.0 +chardet==5.2.0 # via tox colorama==0.4.6 # via tox -distlib==0.3.6 +distlib==0.3.7 # via virtualenv -filelock==3.9.0 +filelock==3.13.1 # via # tox # virtualenv -packaging==23.0 +packaging==23.2 # via # pyproject-api # tox -platformdirs==2.6.2 +platformdirs==4.0.0 # via # tox # virtualenv -pluggy==1.0.0 +pluggy==1.3.0 # via tox -pyproject-api==1.5.0 +pyproject-api==1.6.1 # via tox tomli==2.0.1 # via # pyproject-api # tox -tox==4.3.5 +tox==4.11.3 # via -r requirements/tox.in -virtualenv==20.17.1 +virtualenv==20.24.7 # via tox