diff --git a/.circleci/config.yml b/.circleci/config.yml index 2799e957..b3f03a68 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -14,13 +14,9 @@ workflows: only: /v?[0-9]+(\.[0-9]+)*/ matrix: parameters: - python_version: ["3.5", "3.8"] - debian_version: ["stretch", "buster"] - exclude: - - python_version: "3.8" - debian_version: "stretch" - - python_version: "3.5" - debian_version: "buster" + python_version: ["3.8"] + debian_version: ["buster"] + django_version: ["django22", "django32"] - pypi: requires: - test @@ -35,12 +31,10 @@ jobs: parameters: django_version: type: string - default: django22 python_version: type: string debian_version: type: string - default: stretch docker: # specify the version you desire here # use `-browsers` prefix for selenium tests, e.g. `3.6.1-browsers` diff --git a/Makefile b/Makefile index 79251821..e0718c95 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ python-test: clean ## Run tests python-quality-test: $(TOX) pylint ./eox_core $(TOX) pycodestyle ./eox_core - $(TOX) isort --check-only --recursive --diff ./eox_core + $(TOX) isort --check-only --diff ./eox_core run-tests: python-test python-quality-test diff --git a/README.rst b/README.rst index f89d1093..46e25014 100644 --- a/README.rst +++ b/README.rst @@ -92,6 +92,8 @@ Compatibility Notes +-------------------+----------+ | Lilac | >= 4.9 | +-------------------+----------+ +| Maple | >= 6.0 | ++-------------------+----------+ The following changes to the plugin settings are necessary. If the release you are looking for is not listed, then the accumulation of changes from previous releases is enough. @@ -128,6 +130,14 @@ not listed, then the accumulation of changes from previous releases is enough. EOX_CORE_PRE_ENROLLMENT_BACKEND: "eox_core.edxapp_wrapper.backends.pre_enrollment_l_v1" EOX_CORE_ENROLLMENT_BACKEND: "eox_core.edxapp_wrapper.backends.enrollment_l_v1" +**Maple** + +.. code-block:: yaml + + EOX_CORE_USERS_BACKEND: "eox_core.edxapp_wrapper.backends.users_m_v1" + EOX_CORE_PRE_ENROLLMENT_BACKEND: "eox_core.edxapp_wrapper.backends.pre_enrollment_l_v1" + EOX_CORE_ENROLLMENT_BACKEND: "eox_core.edxapp_wrapper.backends.enrollment_l_v1" + These settings can be changed in ``eox_core/settings/common.py`` or, for example, in ansible configurations. **NOTE**: the current ``common.py`` works with Open edX juniper version. diff --git a/eox_core/api/data/v1/fields.py b/eox_core/api/data/v1/fields.py index a0939394..bfe50990 100644 --- a/eox_core/api/data/v1/fields.py +++ b/eox_core/api/data/v1/fields.py @@ -3,7 +3,7 @@ """ from __future__ import unicode_literals -from django.utils import six +import six from rest_framework import relations diff --git a/eox_core/api/v1/views.py b/eox_core/api/v1/views.py index 564a5a74..6a59717d 100644 --- a/eox_core/api/v1/views.py +++ b/eox_core/api/v1/views.py @@ -8,9 +8,9 @@ import logging import edx_api_doc_tools as apidocs +import six from django.conf import settings from django.contrib.sites.shortcuts import get_current_site -from django.utils import six from rest_framework import status from rest_framework.authentication import SessionAuthentication from rest_framework.exceptions import APIException, NotFound, ValidationError diff --git a/eox_core/edxapp_wrapper/backends/users_m_v1.py b/eox_core/edxapp_wrapper/backends/users_m_v1.py new file mode 100644 index 00000000..03b4b848 --- /dev/null +++ b/eox_core/edxapp_wrapper/backends/users_m_v1.py @@ -0,0 +1,357 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Backend for the create_edxapp_user that works under the open-release/lilac.master tag +""" +import logging + +from common.djangoapps.student.helpers import ( # pylint: disable=import-error,no-name-in-module + create_or_set_user_attribute_created_on_site, + do_create_account, +) +from common.djangoapps.student.models import ( # pylint: disable=import-error,no-name-in-module + CourseEnrollment, + LoginFailures, + Registration, + UserAttribute, + UserProfile, + UserSignupSource, + create_comments_service_user, + email_exists_or_retired, + get_retired_email_by_email, + username_exists_or_retired, +) +from django import forms +from django.conf import settings +from django.contrib.auth import get_user_model +from django.db import transaction +from edx_django_utils.user import generate_password # pylint: disable=import-error,unused-import +from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY # pylint: disable=import-error +from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers # pylint: disable=import-error +from openedx.core.djangoapps.user_api.accounts import USERNAME_MAX_LENGTH # pylint: disable=import-error,unused-import +from openedx.core.djangoapps.user_api.accounts.serializers import UserReadOnlySerializer # pylint: disable=import-error +from openedx.core.djangoapps.user_api.accounts.views import \ + _set_unusable_password # pylint: disable=import-error,unused-import +from openedx.core.djangoapps.user_api.models import UserRetirementStatus # pylint: disable=import-error +from openedx.core.djangoapps.user_api.preferences import api as preferences_api # pylint: disable=import-error +from openedx.core.djangoapps.user_authn.views.register import \ + REGISTER_USER as post_register # pylint: disable=import-error +from openedx.core.djangoapps.user_authn.views.registration_form import ( # pylint: disable=import-error + AccountCreationForm, +) +from openedx.core.djangolib.oauth2_retirement_utils import \ + retire_dot_oauth2_models # pylint: disable=import-error,unused-import +from openedx_events.learning.data import UserData, UserPersonalData # pylint: disable=import-error +from openedx_events.learning.signals import STUDENT_REGISTRATION_COMPLETED # pylint: disable=import-error +from rest_framework import status +from rest_framework.exceptions import NotFound +from social_django.models import UserSocialAuth # pylint: disable=import-error + +LOG = logging.getLogger(__name__) +User = get_user_model() # pylint: disable=invalid-name + + +def get_user_read_only_serializer(): + """ + Great serializer that fits our needs + """ + return UserReadOnlySerializer + + +def check_edxapp_account_conflicts(email, username): + """ + Exposed function to check conflicts + """ + conflicts = [] + + if username and username_exists_or_retired(username): + conflicts.append("username") + + if email and email_exists_or_retired(email): + conflicts.append("email") + + return conflicts + + +class EdnxAccountCreationForm(AccountCreationForm): + """ + A form to extend the behaviour of the AccountCreationForm. + For now the purpose of this form is to allow to make the + password optional if the flag 'skip_password' is True. + This form it's currently only used for validation, not rendering. + """ + + def __init__( # pylint:disable=too-many-arguments + self, + data=None, + extra_fields=None, + extended_profile_fields=None, + do_third_party_auth=True, + tos_required=True, + ): + super().__init__( + data=data, + extra_fields=extra_fields, + extended_profile_fields=extended_profile_fields, + do_third_party_auth=do_third_party_auth, + tos_required=tos_required, + ) + + if data.pop("skip_password", False): + self.fields['password'] = forms.CharField(required=False) + + +def create_edxapp_user(*args, **kwargs): + """ + Creates a user on the open edx django site using calls to + functions defined in the edx-platform codebase + + Example call: + + data = { + 'email': "address@example.org", + 'username': "Username", + 'password': "P4ssW0rd", + 'fullname': "Full Name", + 'activate': True, + 'site': request.site, + 'language_preference': 'es-419', + } + user = create_edxapp_user(**data) + + """ + errors = [] + + extra_fields = getattr(settings, "REGISTRATION_EXTRA_FIELDS", {}) + extended_profile_fields = getattr(settings, "extended_profile_fields", []) + kwargs["name"] = kwargs.pop("fullname", None) + email = kwargs.get("email") + username = kwargs.get("username") + conflicts = check_edxapp_account_conflicts(email=email, username=username) + if conflicts: + return None, [f"Fatal: account collition with the provided: {', '.join(conflicts)}"] + + # Go ahead and create the new user + with transaction.atomic(): + # In theory is possible to extend the registration form with a custom app + # An example form app for this can be found at http://github.com/open-craft/custom-form-app + # form = get_registration_extension_form(data=params) + # if not form: + form = EdnxAccountCreationForm( + data=kwargs, + tos_required=False, + extra_fields=extra_fields, + extended_profile_fields=extended_profile_fields, + # enforce_password_policy=enforce_password_policy, + ) + (user, profile, registration) = do_create_account(form) # pylint: disable=unused-variable + + site = kwargs.pop("site", False) + if site: + create_or_set_user_attribute_created_on_site(user, site) + else: + errors.append("The user was not assigned to any site") + + try: + create_comments_service_user(user) + except Exception: # pylint: disable=broad-except + errors.append("No comments_service_user was created") + + # TODO: link account with third party auth + + # Announce registration through API call + post_register.send_robust(sender=None, user=user) # pylint: disable=no-member + + STUDENT_REGISTRATION_COMPLETED.send_event( + user=UserData( + pii=UserPersonalData( + username=user.username, + email=user.email, + name=user.profile.name, # pylint: disable=no-member + ), + id=user.id, + is_active=user.is_active, + ), + ) + + lang_pref = kwargs.pop("language_preference", False) + if lang_pref: + try: + preferences_api.set_user_preference(user, LANGUAGE_KEY, lang_pref) + except Exception: # pylint: disable=broad-except + errors.append(f"Could not set lang preference '{lang_pref}' for user '{user.username}'") + + if kwargs.pop("activate_user", False): + user.is_active = True + user.save() + + # TODO: run conditional email sequence + + return user, errors + + +def get_edxapp_user(**kwargs): + """ + Retrieve a user by username and/or email + + The user will be returned only if it belongs to the calling site + + Examples: + >>> get_edxapp_user( + { + "username": "Bob", + "site": request.site + } + ) + >>> get_edxapp_user( + { + "email": "Bob@mailserver.com", + "site": request.site + } + ) + """ + params = {key: kwargs.get(key) for key in ['username', 'email'] if key in kwargs} + site = kwargs.get('site') + try: + domain = site.domain + except AttributeError: + domain = None + + try: + user = User.objects.get(**params) + for source_method in FetchUserSiteSources.get_enabled_source_methods(): + if source_method(user, domain): + break + else: + raise User.DoesNotExist + except User.DoesNotExist: + raise NotFound(f'No user found by {str(params)} on site {domain}.') from User.DoesNotExist + return user + + +def delete_edxapp_user(*args, **kwargs): + """ + Deletes a user from the platform. + """ + msg = None + + user = kwargs.get("user") + case_id = kwargs.get("case_id") + site = kwargs.get("site") + is_support_user = kwargs.get("is_support_user") + + user_response = f"The user {user.username} <{user.email}> " + + signup_sources = user.usersignupsource_set.all() + sources = [signup_source.site for signup_source in signup_sources] + + if site and site.name.upper() in (source.upper() for source in sources): + if len(sources) == 1: + with transaction.atomic(): + support_label = "_support" if is_support_user else "" + user.email = f"{user.email}{case_id}.ednx{support_label}_retired" + user.save() + + # Add user to retirement queue. + UserRetirementStatus.create_retirement(user) + + # Unlink LMS social auth accounts + UserSocialAuth.objects.filter(user_id=user.id).delete() + + # Change LMS password & email + user.email = get_retired_email_by_email(user.email) + user.save() + _set_unusable_password(user) + + # Remove the activation keys sent by email to the user for account activation. + Registration.objects.filter(user=user).delete() + + # Delete OAuth tokens associated with the user. + retire_dot_oauth2_models(user) + + # Delete user signup source object + signup_sources[0].delete() + + msg = f"{user_response} has been removed" + else: + for signup_source in signup_sources: + if signup_source.site.upper() == site.name.upper(): + signup_source.delete() + + msg = f"{user_response} has more than one signup source. The signup source from the site {site} has been deleted" + + return msg, status.HTTP_200_OK + + raise NotFound(f"{user_response} does not have a signup source on the site {site}") + + +def get_course_team_user(*args, **kwargs): + """ + Get _course_team_user function. + We need to check if the SERVICE_VARIANT is equal to cms, since + contentstore is a module registered in the INSTALLED_APPS + of the cms only. + """ + if settings.SERVICE_VARIANT == 'cms': + from contentstore.views.user import _course_team_user # pylint: disable=import-error,import-outside-toplevel + return _course_team_user(*args, **kwargs) + return None + + +class FetchUserSiteSources: + """ + Methods to make the comparison to check if an user belongs to a site plus the + get_enabled_source_methods that just brings an array of functions enabled to do so + """ + + @classmethod + def get_enabled_source_methods(cls): + """ Brings the array of methods to check if an user belongs to a site. """ + sources = configuration_helpers.get_value( + 'EOX_CORE_USER_ORIGIN_SITE_SOURCES', + getattr(settings, 'EOX_CORE_USER_ORIGIN_SITE_SOURCES') + ) + return [getattr(cls, source) for source in sources] + + @staticmethod + def fetch_from_created_on_site_prop(user, domain): + """ Fetch option. """ + if not domain: + return False + return UserAttribute.get_user_attribute(user, 'created_on_site') == domain + + @staticmethod + def fetch_from_user_signup_source(user, domain): + """ Read the signup source. """ + return len(UserSignupSource.objects.filter(user=user, site=domain)) > 0 + + @staticmethod + def fetch_from_unfiltered_table(user, site): + """ Fetch option that does not take into account the multi-tentancy model of the installation. """ + return bool(user) + + +def get_course_enrollment(): + """ get CourseEnrollment model """ + return CourseEnrollment + + +def get_user_signup_source(): + """ get UserSignupSource model """ + return UserSignupSource + + +def get_login_failures(): + """ get LoginFailures model """ + return LoginFailures + + +def get_user_profile(): + """ Gets the UserProfile model """ + + return UserProfile + + +def get_user_attribute(): + """ Gets the UserAttribute model """ + return UserAttribute diff --git a/eox_core/views.py b/eox_core/views.py index 7ddc3817..c4e2cc46 100644 --- a/eox_core/views.py +++ b/eox_core/views.py @@ -7,8 +7,8 @@ from os.path import dirname, realpath from subprocess import CalledProcessError, check_output +import six from django.http import HttpResponse -from django.utils import six import eox_core diff --git a/requirements/base.in b/requirements/base.in index fd9a8e2e..64abe01a 100644 --- a/requirements/base.in +++ b/requirements/base.in @@ -1,12 +1,13 @@ # Main requirements of your plugin application. -c constraints.txt +six celery djangorestframework django-filter django-oauth-toolkit django-oauth2-provider django-waffle -edx-api-doc-tools==1.4.0 +edx-api-doc-tools==1.5.0 edx-proctoring edx-opaque-keys[django] diff --git a/requirements/base.txt b/requirements/base.txt index 831b96b0..8b31ee27 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -1,25 +1,27 @@ # -# This file is autogenerated by pip-compile +# This file is autogenerated by pip-compile with python 3.8 # To update, run: # # make upgrade # -amqp==1.4.9 - # via kombu -anyjson==0.3.3 +amqp==2.6.1 # via kombu appdirs==1.4.4 # via fs -billiard==3.3.0.23 +asgiref==3.5.0 + # via django +billiard==3.6.4.0 # via celery -celery==3.1.26.post2 +celery==4.4.7 # via # -c requirements/constraints.txt # -r requirements/base.in # event-tracking -certifi==2021.5.30 +certifi==2021.10.8 # via requests -chardet==4.0.0 +cffi==1.15.0 + # via cryptography +charset-normalizer==2.0.12 # via requests coreapi==2.3.3 # via drf-yasg @@ -27,17 +29,36 @@ coreschema==0.0.4 # via # coreapi # drf-yasg +cryptography==36.0.1 + # via pyjwt +django==3.2.12 + # via + # -c requirements/constraints.txt + # django-crum + # django-filter + # django-model-utils + # django-oauth-toolkit + # djangorestframework + # drf-jwt + # drf-yasg + # edx-api-doc-tools + # edx-django-utils + # edx-drf-extensions + # edx-proctoring + # edx-when + # event-tracking + # jsonfield django-crum==0.7.9 # via # edx-django-utils # edx-proctoring -django-filter==2.2.0 +django-filter==21.1 # via # -c requirements/constraints.txt # -r requirements/base.in -django-ipware==3.0.2 +django-ipware==4.0.2 # via edx-proctoring -django-model-utils==4.0.0 +django-model-utils==4.2.0 # via # -c requirements/constraints.txt # edx-proctoring @@ -48,33 +69,18 @@ django-oauth-toolkit==1.3.2 # -r requirements/base.in django-oauth2-provider==0.2.6.1 # via -r requirements/base.in -django-waffle==0.18.0 +django-simple-history==3.0.0 + # via edx-proctoring +django-waffle==2.2.1 # via # -c requirements/constraints.txt # -r requirements/base.in # edx-django-utils # edx-drf-extensions # edx-proctoring -django-webpack-loader==1.1.0 +django-webpack-loader==1.4.1 # via edx-proctoring -django==2.2.24 - # via - # django-crum - # django-filter - # django-model-utils - # django-oauth-toolkit - # drf-jwt - # drf-yasg - # edx-api-doc-tools - # edx-django-utils - # edx-drf-extensions - # edx-opaque-keys - # edx-proctoring - # edx-when - # event-tracking - # jsonfield2 - # rest-condition -djangorestframework==3.9.4 +djangorestframework==3.13.1 # via # -c requirements/constraints.txt # -r requirements/base.in @@ -83,111 +89,116 @@ djangorestframework==3.9.4 # edx-api-doc-tools # edx-drf-extensions # edx-proctoring - # rest-condition -drf-jwt==1.14.0 +drf-jwt==1.19.2 # via edx-drf-extensions -drf-yasg==1.17.1 +drf-yasg==1.20.0 # via edx-api-doc-tools -edx-api-doc-tools==1.4.0 +edx-api-doc-tools==1.5.0 # via -r requirements/base.in -edx-django-utils==3.13.0 +edx-django-utils==4.4.0 # via # -c requirements/constraints.txt # edx-drf-extensions # edx-rest-api-client # edx-when -edx-drf-extensions==6.0.0 + # event-tracking +edx-drf-extensions==8.0.0 # via # -c requirements/constraints.txt # edx-proctoring # edx-when -edx-opaque-keys[django]==2.1.0 +edx-opaque-keys[django]==2.3.0 # via # -c requirements/constraints.txt # -r requirements/base.in # edx-drf-extensions # edx-proctoring # edx-when -edx-proctoring==2.4.0 +edx-proctoring==4.7.1 # via # -c requirements/constraints.txt # -r requirements/base.in -edx-rest-api-client==5.3.0 +edx-rest-api-client==5.5.0 # via edx-proctoring -edx-when==1.3.0 +edx-when==2.2.2 # via # -c requirements/constraints.txt # edx-proctoring -event-tracking==1.0.4 +event-tracking==2.1.0 # via edx-proctoring -fs==2.4.13 +fs==2.4.15 # via xblock future==0.18.2 # via pyjwkest -idna==2.10 +idna==3.3 # via requests inflection==0.5.1 # via drf-yasg itypes==1.2.0 # via coreapi -jinja2==2.11.3 +jinja2==3.0.3 # via coreschema -jsonfield2==3.0.3 +jsonfield==3.1.0 # via # -c requirements/constraints.txt # edx-proctoring -kombu==3.0.37 +kombu==4.6.11 # via celery -lxml==4.6.3 +lxml==4.8.0 # via xblock -markupsafe==1.1.1 +markupsafe==2.1.0 # via # jinja2 # xblock -newrelic==5.24.0.153 +newrelic==7.2.1.168 # via # -c requirements/constraints.txt # edx-django-utils -oauthlib==3.1.0 +oauthlib==3.2.0 # via django-oauth-toolkit -packaging==20.9 +packaging==21.3 # via drf-yasg -pbr==5.6.0 +pbr==5.8.1 # via stevedore -psutil==5.8.0 +psutil==5.9.0 # via edx-django-utils -pycryptodomex==3.10.1 +pycparser==2.21 + # via cffi +pycryptodomex==3.14.1 # via # edx-proctoring # pyjwkest pyjwkest==1.4.2 # via edx-drf-extensions -pyjwt==1.7.1 +pyjwt[crypto]==2.3.0 # via # drf-jwt + # edx-drf-extensions + # edx-proctoring # edx-rest-api-client -pymongo==3.11.4 +pymongo==3.12.3 # via # edx-opaque-keys # event-tracking -pyparsing==2.4.7 +pyparsing==3.0.7 # via packaging -python-dateutil==2.8.1 +python-dateutil==2.8.2 # via # edx-drf-extensions # edx-proctoring # xblock -pytz==2021.1 +pytz==2021.3 # via # celery # django + # djangorestframework # edx-proctoring # event-tracking # fs # xblock -pyyaml==5.3.1 +pyyaml==6.0 # via xblock -requests==2.25.1 +requests==2.27.1 # via # coreapi # django-oauth-toolkit @@ -195,49 +206,47 @@ requests==2.25.1 # edx-rest-api-client # pyjwkest # slumber -rest-condition==1.0.3 - # via edx-drf-extensions -ruamel.yaml.clib==0.2.4 - # via ruamel.yaml -ruamel.yaml==0.17.10 +ruamel-yaml==0.17.21 # via drf-yasg -rules==3.0 +ruamel-yaml-clib==0.2.6 + # via ruamel-yaml +rules==3.1 # via edx-proctoring -semantic-version==2.8.5 +semantic-version==2.9.0 # via edx-drf-extensions -shortuuid==1.0.1 +shortuuid==1.0.8 # via django-oauth2-provider six==1.16.0 # via - # drf-yasg + # -r requirements/base.in # edx-drf-extensions - # edx-opaque-keys # event-tracking # fs # pyjwkest # python-dateutil - # stevedore slumber==0.7.1 # via edx-rest-api-client -sqlparse==0.4.1 +sqlparse==0.4.2 # via django -stevedore==1.32.0 +stevedore==3.5.0 # via # edx-django-utils # edx-opaque-keys -typing==3.7.4.3 - # via fs -uritemplate==3.0.1 +uritemplate==4.1.1 # via # coreapi # drf-yasg -urllib3==1.26.6 +urllib3==1.26.8 # via requests -web-fragments==1.0.0 +vine==1.3.0 + # via + # amqp + # celery +web-fragments==2.0.0 # via xblock webob==1.8.7 # via xblock -xblock==1.4.2 +xblock==1.6.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 932cfdd3..c27992da 100644 --- a/requirements/constraints.txt +++ b/requirements/constraints.txt @@ -12,26 +12,23 @@ futures; python_version == "2.7" # TODO: Add constraint explanation -pylint==2.5.0 -pycodestyle==2.5.0 +pylint==2.12.2 +pycodestyle==2.8.0 # Keep same platform version -celery==3.1.26.post2 -djangorestframework==3.9.4 -django-filter==2.2.0 -django-model-utils==4.0.0 +django<=3.2.12 +celery==4.4.7 +djangorestframework==3.13.1 +django-filter==21.1 +django-model-utils==4.2.0 django-oauth-toolkit==1.3.2 -django-waffle==0.18.0 -edx-drf-extensions==6.0.0 -edx-opaque-keys==2.1.0 -edx-proctoring==2.4.0 -factory-boy==2.10.0 -jsonfield2==3.0.3 - -# Older versions may give us problems for python 3.5 -django-countries==6.0 -edx-django-utils==3.13.0 -edx-when==1.3.0 - -# The New Relic Python agent only supports Python 2.7 and 3.6+ -newrelic==5.24.0.153 +django-waffle==2.2.1 +edx-drf-extensions==8.0.0 +edx-opaque-keys==2.3.0 +edx-proctoring==4.7.1 +factory-boy==3.2.0 +jsonfield==3.1.0 +django-countries==7.2.1 +edx-django-utils==4.4.0 +edx-when==2.2.2 +newrelic==7.2.1.168 diff --git a/requirements/django.txt b/requirements/django.txt new file mode 100644 index 00000000..dfff22f7 --- /dev/null +++ b/requirements/django.txt @@ -0,0 +1 @@ +django==3.2.12 \ No newline at end of file diff --git a/requirements/django22.txt b/requirements/django22.txt new file mode 100644 index 00000000..fadeb821 --- /dev/null +++ b/requirements/django22.txt @@ -0,0 +1 @@ +django==2.2.27 \ No newline at end of file diff --git a/requirements/pip-tools.txt b/requirements/pip-tools.txt index aa6ffb82..36ddaf6a 100644 --- a/requirements/pip-tools.txt +++ b/requirements/pip-tools.txt @@ -1,13 +1,20 @@ # -# This file is autogenerated by pip-compile +# This file is autogenerated by pip-compile with python 3.8 # To update, run: # # make upgrade # -click==7.1.2 +click==8.0.4 # via pip-tools -pip-tools==5.5.0 +pep517==0.12.0 + # via pip-tools +pip-tools==6.5.1 # via -r requirements/pip-tools.in +tomli==2.0.1 + # via pep517 +wheel==0.37.1 + # via pip-tools # The following packages are considered to be unsafe in a requirements file: # pip +# setuptools diff --git a/requirements/test.txt b/requirements/test.txt index 2e475a56..dad4b382 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -1,14 +1,10 @@ # -# This file is autogenerated by pip-compile +# This file is autogenerated by pip-compile with python 3.8 # To update, run: # # make upgrade # -amqp==1.4.9 - # via - # -r requirements/base.txt - # kombu -anyjson==0.3.3 +amqp==2.6.1 # via # -r requirements/base.txt # kombu @@ -16,24 +12,32 @@ appdirs==1.4.4 # via # -r requirements/base.txt # fs -astroid==2.4.2 +asgiref==3.5.0 + # via + # -r requirements/base.txt + # django +astroid==2.9.3 # via pylint -attrs==21.2.0 +attrs==21.4.0 # via pytest -billiard==3.3.0.23 +billiard==3.6.4.0 # via # -r requirements/base.txt # celery -celery==3.1.26.post2 +celery==4.4.7 # via # -c requirements/constraints.txt # -r requirements/base.txt # event-tracking -certifi==2021.5.30 +certifi==2021.10.8 # via # -r requirements/base.txt # requests -chardet==4.0.0 +cffi==1.15.0 + # via + # -r requirements/base.txt + # cryptography +charset-normalizer==2.0.12 # via # -r requirements/base.txt # requests @@ -46,9 +50,13 @@ coreschema==0.0.4 # -r requirements/base.txt # coreapi # drf-yasg -coverage==5.5 +coverage==6.3.2 # via -r requirements/test.in -django-countries==6.0 +cryptography==36.0.1 + # via + # -r requirements/base.txt + # pyjwt +django-countries==7.2.1 # via # -c requirements/constraints.txt # -r requirements/test.in @@ -57,15 +65,15 @@ django-crum==0.7.9 # -r requirements/base.txt # edx-django-utils # edx-proctoring -django-filter==2.2.0 +django-filter==21.1 # via # -c requirements/constraints.txt # -r requirements/base.txt -django-ipware==3.0.2 +django-ipware==4.0.2 # via # -r requirements/base.txt # edx-proctoring -django-model-utils==4.0.0 +django-model-utils==4.2.0 # via # -c requirements/constraints.txt # -r requirements/base.txt @@ -77,36 +85,22 @@ django-oauth-toolkit==1.3.2 # -r requirements/base.txt django-oauth2-provider==0.2.6.1 # via -r requirements/base.txt -django-waffle==0.18.0 +django-simple-history==3.0.0 # via - # -c requirements/constraints.txt # -r requirements/base.txt - # edx-django-utils - # edx-drf-extensions # edx-proctoring -django-webpack-loader==1.1.0 +django-waffle==2.2.1 # via + # -c requirements/constraints.txt # -r requirements/base.txt + # edx-django-utils + # edx-drf-extensions # edx-proctoring -django==2.2.24 +django-webpack-loader==1.4.1 # via # -r requirements/base.txt - # django-crum - # django-filter - # django-model-utils - # django-oauth-toolkit - # drf-jwt - # drf-yasg - # edx-api-doc-tools - # edx-django-utils - # edx-drf-extensions - # edx-opaque-keys # edx-proctoring - # edx-when - # event-tracking - # jsonfield2 - # rest-condition -djangorestframework==3.9.4 +djangorestframework==3.13.1 # via # -c requirements/constraints.txt # -r requirements/base.txt @@ -115,61 +109,61 @@ djangorestframework==3.9.4 # edx-api-doc-tools # edx-drf-extensions # edx-proctoring - # rest-condition -drf-jwt==1.14.0 +drf-jwt==1.19.2 # via # -r requirements/base.txt # edx-drf-extensions -drf-yasg==1.17.1 +drf-yasg==1.20.0 # via # -r requirements/base.txt # edx-api-doc-tools -edx-api-doc-tools==1.4.0 +edx-api-doc-tools==1.5.0 # via -r requirements/base.txt -edx-django-utils==3.13.0 +edx-django-utils==4.4.0 # via # -c requirements/constraints.txt # -r requirements/base.txt # edx-drf-extensions # edx-rest-api-client # edx-when -edx-drf-extensions==6.0.0 + # event-tracking +edx-drf-extensions==8.0.0 # via # -c requirements/constraints.txt # -r requirements/base.txt # edx-proctoring # edx-when -edx-opaque-keys[django]==2.1.0 +edx-opaque-keys[django]==2.3.0 # via # -c requirements/constraints.txt # -r requirements/base.txt # edx-drf-extensions # edx-proctoring # edx-when -edx-proctoring==2.4.0 +edx-proctoring==4.7.1 # via # -c requirements/constraints.txt # -r requirements/base.txt -edx-rest-api-client==5.3.0 +edx-rest-api-client==5.5.0 # via # -r requirements/base.txt # edx-proctoring -edx-when==1.3.0 +edx-when==2.2.2 # via # -c requirements/constraints.txt # -r requirements/base.txt # edx-proctoring -event-tracking==1.0.4 +event-tracking==2.1.0 # via # -r requirements/base.txt # edx-proctoring -factory-boy==2.10.0 +factory-boy==3.2.0 # via # -c requirements/constraints.txt # -r requirements/test.in -faker==5.0.0 +faker==13.2.0 # via factory-boy -fs==2.4.13 +fs==2.4.15 # via # -r requirements/base.txt # xblock @@ -177,87 +171,87 @@ future==0.18.2 # via # -r requirements/base.txt # pyjwkest -idna==2.10 +idna==3.3 # via # -r requirements/base.txt # requests -importlib-metadata==2.1.1 - # via - # pluggy - # pytest inflection==0.5.1 # via # -r requirements/base.txt # drf-yasg iniconfig==1.1.1 # via pytest -isort==4.3.21 +isort==5.10.1 # via pylint itypes==1.2.0 # via # -r requirements/base.txt # coreapi -jinja2==2.11.3 +jinja2==3.0.3 # via # -r requirements/base.txt # coreschema -jsonfield2==3.0.3 +jsonfield==3.1.0 # via # -c requirements/constraints.txt # -r requirements/base.txt # edx-proctoring -kombu==3.0.37 +kombu==4.6.11 # via # -r requirements/base.txt # celery -lazy-object-proxy==1.4.3 +lazy-object-proxy==1.7.1 # via astroid -lxml==4.6.3 +lxml==4.8.0 # via # -r requirements/base.txt # xblock -markupsafe==1.1.1 +markupsafe==2.1.0 # via # -r requirements/base.txt # jinja2 # xblock mccabe==0.6.1 # via pylint -mock==3.0.5 +mock==4.0.3 # via -r requirements/test.in -newrelic==5.24.0.153 +newrelic==7.2.1.168 # via # -c requirements/constraints.txt # -r requirements/base.txt # edx-django-utils -oauthlib==3.1.0 +oauthlib==3.2.0 # via # -r requirements/base.txt # django-oauth-toolkit -packaging==20.9 +packaging==21.3 # via # -r requirements/base.txt # drf-yasg # pytest -pathlib2==2.3.5 - # via pytest -pbr==5.6.0 +pbr==5.8.1 # via # -r requirements/base.txt # stevedore -pluggy==0.13.1 +platformdirs==2.5.1 + # via pylint +pluggy==1.0.0 # via pytest -psutil==5.8.0 +psutil==5.9.0 # via # -r requirements/base.txt # edx-django-utils -py==1.10.0 +py==1.11.0 # via pytest -pycodestyle==2.5.0 +pycodestyle==2.8.0 # via # -c requirements/constraints.txt # -r requirements/test.in -pycryptodomex==3.10.1 +pycparser==2.21 + # via + # -r requirements/base.txt + # cffi +pycryptodomex==3.14.1 # via # -r requirements/base.txt # edx-proctoring @@ -266,51 +260,54 @@ pyjwkest==1.4.2 # via # -r requirements/base.txt # edx-drf-extensions -pyjwt==1.7.1 +pyjwt[crypto]==2.3.0 # via # -r requirements/base.txt # drf-jwt + # edx-drf-extensions + # edx-proctoring # edx-rest-api-client -pylint==2.5.0 +pylint==2.12.2 # via # -c requirements/constraints.txt # -r requirements/test.in -pymongo==3.11.4 +pymongo==3.12.3 # via # -r requirements/base.txt # edx-opaque-keys # event-tracking -pyparsing==2.4.7 +pyparsing==3.0.7 # via # -r requirements/base.txt # packaging -pytest-django==4.4.0 - # via -r requirements/test.in -pytest==6.1.2 +pytest==7.0.1 # via # -r requirements/test.in # pytest-django -python-dateutil==2.8.1 +pytest-django==4.5.2 + # via -r requirements/test.in +python-dateutil==2.8.2 # via # -r requirements/base.txt # edx-drf-extensions # edx-proctoring # faker # xblock -pytz==2021.1 +pytz==2021.3 # via # -r requirements/base.txt # celery # django + # djangorestframework # edx-proctoring # event-tracking # fs # xblock -pyyaml==5.3.1 +pyyaml==6.0 # via # -r requirements/base.txt # xblock -requests==2.25.1 +requests==2.27.1 # via # -r requirements/base.txt # coreapi @@ -319,81 +316,72 @@ requests==2.25.1 # edx-rest-api-client # pyjwkest # slumber -rest-condition==1.0.3 - # via - # -r requirements/base.txt - # edx-drf-extensions -ruamel.yaml.clib==0.2.4 +ruamel-yaml==0.17.21 # via # -r requirements/base.txt - # ruamel.yaml -ruamel.yaml==0.17.10 + # drf-yasg +ruamel-yaml-clib==0.2.6 # via # -r requirements/base.txt - # drf-yasg -rules==3.0 + # ruamel-yaml +rules==3.1 # via # -r requirements/base.txt # edx-proctoring -semantic-version==2.8.5 +semantic-version==2.9.0 # via # -r requirements/base.txt # edx-drf-extensions -shortuuid==1.0.1 +shortuuid==1.0.8 # via # -r requirements/base.txt # django-oauth2-provider six==1.16.0 # via # -r requirements/base.txt - # astroid - # drf-yasg # edx-drf-extensions - # edx-opaque-keys # event-tracking # fs - # mock - # pathlib2 # pyjwkest # python-dateutil - # stevedore slumber==0.7.1 # via # -r requirements/base.txt # edx-rest-api-client -sqlparse==0.4.1 +sqlparse==0.4.2 # via # -r requirements/base.txt # django -stevedore==1.32.0 +stevedore==3.5.0 # via # -r requirements/base.txt # edx-django-utils # edx-opaque-keys -testfixtures==6.17.1 +testfixtures==6.18.4 # via -r requirements/test.in -text-unidecode==1.3 - # via faker toml==0.10.2 + # via pylint +tomli==2.0.1 + # via pytest +typing-extensions==4.1.1 # via + # astroid # pylint - # pytest -typed-ast==1.4.3 - # via astroid -typing==3.7.4.3 - # via - # -r requirements/base.txt - # fs -uritemplate==3.0.1 +uritemplate==4.1.1 # via # -r requirements/base.txt # coreapi # drf-yasg -urllib3==1.26.6 +urllib3==1.26.8 # via # -r requirements/base.txt # requests -web-fragments==1.0.0 +vine==1.3.0 + # via + # -r requirements/base.txt + # amqp + # celery +web-fragments==2.0.0 # via # -r requirements/base.txt # xblock @@ -401,14 +389,12 @@ webob==1.8.7 # via # -r requirements/base.txt # xblock -wrapt==1.12.1 +wrapt==1.13.3 # via astroid -xblock==1.4.2 +xblock==1.6.1 # via # -r requirements/base.txt # edx-when -zipp==1.2.0 - # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: # setuptools diff --git a/requirements/tox.txt b/requirements/tox.txt index 970b838f..c48cbacf 100644 --- a/requirements/tox.txt +++ b/requirements/tox.txt @@ -1,31 +1,24 @@ # -# This file is autogenerated by pip-compile +# This file is autogenerated by pip-compile with python 3.8 # To update, run: # # make upgrade # -appdirs==1.4.4 +distlib==0.3.4 # via virtualenv -distlib==0.3.2 - # via virtualenv -filelock==3.0.12 - # via - # tox - # virtualenv -importlib-metadata==2.1.1 +filelock==3.6.0 # via - # pluggy # tox # virtualenv -importlib-resources==3.2.1 - # via virtualenv -packaging==20.9 +packaging==21.3 # via tox -pluggy==0.13.1 +platformdirs==2.5.1 + # via virtualenv +pluggy==1.0.0 # via tox -py==1.10.0 +py==1.11.0 # via tox -pyparsing==2.4.7 +pyparsing==3.0.7 # via packaging six==1.16.0 # via @@ -33,11 +26,7 @@ six==1.16.0 # virtualenv toml==0.10.2 # via tox -tox==3.23.1 +tox==3.24.5 # via -r requirements/tox.in -virtualenv==20.4.7 +virtualenv==20.13.2 # via tox -zipp==1.2.0 - # via - # importlib-metadata - # importlib-resources diff --git a/setup.py b/setup.py index d38841c9..b17608bf 100644 --- a/setup.py +++ b/setup.py @@ -51,7 +51,7 @@ def is_requirement(line): setup( name="eox-core", - python_requires='>=3.5', + python_requires='>=3.8', version=version, author="eduNEXT", author_email="contact@edunext.co", @@ -62,6 +62,7 @@ def is_requirement(line): classifiers=[ 'Development Status :: 5 - Production/Stable', 'Framework :: Django :: 2.2', + 'Framework :: Django :: 3.2', 'Intended Audience :: Developers', 'License :: OSI Approved :: GNU Affero General Public License v3', 'Operating System :: OS Independent', diff --git a/tox.ini b/tox.ini index 52c6d30b..d2e3d9b6 100644 --- a/tox.ini +++ b/tox.ini @@ -1,15 +1,15 @@ [tox] -envlist = py{35,38}-django22 +envlist = py{38}-django{22,32} [testenv] passenv = TEST_INTEGRATION envdir= - # Use the same environment for all commands running under a specific python version - py35: {toxworkdir}/py35 py38: {toxworkdir}/py38 deps = + django22: -r requirements/django22.txt + django32: -r requirements/django.txt -rrequirements/test.txt commands = {posargs}