diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index c1027ad5..00000000 --- a/.coveragerc +++ /dev/null @@ -1,8 +0,0 @@ -[run] -branch = True -data_file = .coverage -source=futurex_openedx_extensions -omit = - test_settings.py - */migrations/* - */static/* diff --git a/.coveragerc-palm b/.coveragerc-palm new file mode 100644 index 00000000..02143464 --- /dev/null +++ b/.coveragerc-palm @@ -0,0 +1,13 @@ +[run] +branch = True +data_file = .coverage +source=futurex_openedx_extensions +omit = + test_settings_palm.py + test_settings_redwood.py + */migrations/* + */static/* + # Ignore the models_switch.py file since it cannot be tested in all environments, so coverage will never be 100% + futurex_openedx_extensions/upgrade/models_switch.py + # Version specific code for anything not palm + futurex_openedx_extensions/upgrade/releases/redwood/* diff --git a/.coveragerc-redwood b/.coveragerc-redwood new file mode 100644 index 00000000..dbb1a132 --- /dev/null +++ b/.coveragerc-redwood @@ -0,0 +1,13 @@ +[run] +branch = True +data_file = .coverage +source=futurex_openedx_extensions +omit = + test_settings_palm.py + test_settings_redwood.py + */migrations/* + */static/* + # Ignore the models_switch.py file since it cannot be tested in all environments, so coverage will never be 100% + futurex_openedx_extensions/upgrade/models_switch.py + # Version specific code for anything not redwood + futurex_openedx_extensions/upgrade/releases/palm/* diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a4ceefb5..ee7c76b2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,28 +7,29 @@ on: jobs: run_tests: - name: tests - runs-on: ${{ matrix.os }} + name: ci + runs-on: ubuntu-22.04 strategy: matrix: - os: [ubuntu-20.04] - python-version: ['3.8'] - toxenv: [quality, django32, django40] + include: + - python-version: '3.8' + tox-env: quality + - python-version: '3.8' + tox-env: py38-palm + - python-version: '3.8' + tox-env: py38-redwood + - python-version: '3.11' + tox-env: py311-redwood steps: - - uses: actions/checkout@v4 - - name: setup python - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} + - 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.in - - name: Install Dependencies - run: pip install -r requirements/ci.txt - - - name: Run Tests - env: - TOXENV: ${{ matrix.toxenv }} - run: tox + - name: Run Tests + run: tox -e ${{ matrix.tox-env }} diff --git a/.gitignore b/.gitignore index 1b7ee7d6..56b6a1eb 100644 --- a/.gitignore +++ b/.gitignore @@ -65,6 +65,6 @@ requirements/private.in requirements/private.txt # temporary tests migration files -/test_utils/edx_platform_mocks/fake_models/migrations/ +/test_utils/edx_platform_mocks_shared/fake_models/migrations/ default.db diff --git a/futurex_openedx_extensions/__init__.py b/futurex_openedx_extensions/__init__.py index 4dad3d16..1cb5b424 100644 --- a/futurex_openedx_extensions/__init__.py +++ b/futurex_openedx_extensions/__init__.py @@ -1,3 +1,3 @@ """One-line description for README and other doc files.""" -__version__ = '0.9.17' +__version__ = '0.9.18-dev' diff --git a/futurex_openedx_extensions/dashboard/details/courses.py b/futurex_openedx_extensions/dashboard/details/courses.py index 5fa548a8..700816bb 100644 --- a/futurex_openedx_extensions/dashboard/details/courses.py +++ b/futurex_openedx_extensions/dashboard/details/courses.py @@ -1,7 +1,6 @@ """Courses details collectors""" from __future__ import annotations -from common.djangoapps.student.models import CourseEnrollment from completion.models import BlockCompletion from django.contrib.auth import get_user_model from django.db.models import ( @@ -32,6 +31,7 @@ get_one_user_queryset, update_removable_annotations, ) +from futurex_openedx_extensions.upgrade.models_switch import CourseEnrollment def annotate_courses_rating_queryset( diff --git a/futurex_openedx_extensions/dashboard/details/learners.py b/futurex_openedx_extensions/dashboard/details/learners.py index d1737e92..f3db3492 100644 --- a/futurex_openedx_extensions/dashboard/details/learners.py +++ b/futurex_openedx_extensions/dashboard/details/learners.py @@ -3,7 +3,6 @@ from datetime import timedelta -from common.djangoapps.student.models import CourseEnrollment from django.contrib.auth import get_user_model from django.db.models import BooleanField, Case, Count, Exists, IntegerField, OuterRef, Q, Subquery, Value, When from django.db.models.functions import Coalesce @@ -24,6 +23,7 @@ get_permitted_learners_queryset, update_removable_annotations, ) +from futurex_openedx_extensions.upgrade.models_switch import CourseEnrollment def get_courses_count_for_learner_queryset( diff --git a/futurex_openedx_extensions/dashboard/serializers.py b/futurex_openedx_extensions/dashboard/serializers.py index 9a62760d..98b3f914 100644 --- a/futurex_openedx_extensions/dashboard/serializers.py +++ b/futurex_openedx_extensions/dashboard/serializers.py @@ -4,7 +4,6 @@ import re from typing import Any, Dict, Tuple -from common.djangoapps.student.models import CourseEnrollment from django.contrib.auth import get_user_model from django.utils.timezone import now from lms.djangoapps.courseware.courses import get_course_blocks_completion_summary @@ -38,6 +37,7 @@ get_user_course_access_roles, ) from futurex_openedx_extensions.helpers.tenants import get_tenants_by_org +from futurex_openedx_extensions.upgrade.models_switch import CourseEnrollment class DataExportTaskSerializer(ModelSerializerOptionalFields): diff --git a/futurex_openedx_extensions/dashboard/statistics/courses.py b/futurex_openedx_extensions/dashboard/statistics/courses.py index fe712d20..c53adfe1 100644 --- a/futurex_openedx_extensions/dashboard/statistics/courses.py +++ b/futurex_openedx_extensions/dashboard/statistics/courses.py @@ -3,7 +3,6 @@ from typing import Dict -from common.djangoapps.student.models import CourseEnrollment from django.db.models import BooleanField, Case, CharField, Count, Q, Sum, Value, When from django.db.models.functions import Coalesce, Lower from django.db.models.query import QuerySet @@ -12,6 +11,7 @@ from futurex_openedx_extensions.dashboard.details.courses import annotate_courses_rating_queryset from futurex_openedx_extensions.helpers.constants import COURSE_STATUSES from futurex_openedx_extensions.helpers.querysets import check_staff_exist_queryset, get_base_queryset_courses +from futurex_openedx_extensions.upgrade.models_switch import CourseEnrollment def get_courses_count( diff --git a/futurex_openedx_extensions/dashboard/views.py b/futurex_openedx_extensions/dashboard/views.py index af56e7a2..412d1c72 100644 --- a/futurex_openedx_extensions/dashboard/views.py +++ b/futurex_openedx_extensions/dashboard/views.py @@ -4,7 +4,6 @@ from typing import Any, Dict from urllib.parse import parse_qs, urlencode, urlsplit, urlunsplit -from common.djangoapps.student.models import get_user_by_username_or_email from django.contrib.auth import get_user_model from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.core.paginator import EmptyPage @@ -69,6 +68,7 @@ ) from futurex_openedx_extensions.helpers.tenants import get_tenants_info from futurex_openedx_extensions.helpers.users import get_user_by_key +from futurex_openedx_extensions.upgrade.models_switch import get_user_by_username_or_email default_auth_classes = FX_VIEW_DEFAULT_AUTH_CLASSES.copy() diff --git a/futurex_openedx_extensions/helpers/caching.py b/futurex_openedx_extensions/helpers/caching.py index 49b77831..2be171e0 100644 --- a/futurex_openedx_extensions/helpers/caching.py +++ b/futurex_openedx_extensions/helpers/caching.py @@ -41,7 +41,7 @@ def wrapped(*args: Any, **kwargs: Any) -> Dict[str, Any]: *args, **kwargs ) if callable(key_generator_or_name) else key_generator_or_name - except Exception as exc: # pylint: disable=broad-except + except Exception as exc: log.exception('cache_dict: error generating cache key: %s', exc) result = cache.get(cache_key) if cache_key else None diff --git a/futurex_openedx_extensions/helpers/export_csv.py b/futurex_openedx_extensions/helpers/export_csv.py index 2ac4112f..1f987c7e 100644 --- a/futurex_openedx_extensions/helpers/export_csv.py +++ b/futurex_openedx_extensions/helpers/export_csv.py @@ -183,7 +183,7 @@ def _generate_csv_with_tracked_progress( try: os.remove(tmp_file.name) log.info('CSV Export: temporary file removed for task %s...', task_id) - except Exception as exc: # pylint: disable=broad-exception-caught + except Exception as exc: log.info('CSV Export: failed to remove temporary file for task %s: %s', task_id, str(exc)) return storage_path diff --git a/futurex_openedx_extensions/helpers/models.py b/futurex_openedx_extensions/helpers/models.py index 67b8eabe..7e2056be 100644 --- a/futurex_openedx_extensions/helpers/models.py +++ b/futurex_openedx_extensions/helpers/models.py @@ -4,11 +4,10 @@ import re from typing import Any, Dict, List, Tuple -from common.djangoapps.student.models import CourseAccessRole from django.contrib.auth import get_user_model from django.core.exceptions import ValidationError from django.db import models -from django.db.models import BooleanField, Case, Exists, F, OuterRef, Q, Value, When +from django.db.models import BooleanField, Case, Exists, OuterRef, Q, Value, When from django.utils import timezone from eox_tenant.models import TenantConfig from opaque_keys.edx.django.models import CourseKeyField @@ -18,6 +17,7 @@ from futurex_openedx_extensions.helpers import constants as cs from futurex_openedx_extensions.helpers.converters import DateMethods, get_allowed_roles from futurex_openedx_extensions.helpers.exceptions import FXCodedException, FXExceptionCodes +from futurex_openedx_extensions.upgrade.models_switch import CourseAccessRole User = get_user_model() @@ -46,9 +46,23 @@ def get_queryset(self) -> models.QuerySet: allowed_roles = get_allowed_roles(cs.COURSE_ACCESS_ROLES_USER_VIEW_MAPPING) queryset = queryset.annotate( - is_user_active=F('user__is_active'), + is_user_active=Case( + When( + user__is_active=True, + then=Value(True) + ), + default=Value(False), + output_field=BooleanField(), + ), ).annotate( - is_user_system_staff=F('user__is_superuser').bitor(F('user__is_staff')), + is_user_system_staff=Case( + When( + Q(user__is_superuser=True) | Q(user__is_staff=True), + then=Value(True), + ), + default=Value(False), + output_field=BooleanField(), + ), ).annotate( has_access_role=Exists( CourseAccessRole.objects.filter( diff --git a/futurex_openedx_extensions/helpers/querysets.py b/futurex_openedx_extensions/helpers/querysets.py index 51056f97..de99f24f 100644 --- a/futurex_openedx_extensions/helpers/querysets.py +++ b/futurex_openedx_extensions/helpers/querysets.py @@ -3,7 +3,6 @@ from typing import List -from common.djangoapps.student.models import CourseAccessRole, CourseEnrollment, UserSignupSource from django.contrib.auth import get_user_model from django.db.models import BooleanField, Case, Count, Exists, OuterRef, Q, Value, When from django.db.models.query import QuerySet @@ -16,6 +15,7 @@ from futurex_openedx_extensions.helpers.extractors import get_partial_access_course_ids from futurex_openedx_extensions.helpers.tenants import get_tenants_sites from futurex_openedx_extensions.helpers.users import get_user_by_key +from futurex_openedx_extensions.upgrade.models_switch import CourseAccessRole, CourseEnrollment, UserSignupSource def verify_queryset_removable_annotations(queryset: QuerySet) -> None: diff --git a/futurex_openedx_extensions/helpers/roles.py b/futurex_openedx_extensions/helpers/roles.py index c853b29f..90063184 100644 --- a/futurex_openedx_extensions/helpers/roles.py +++ b/futurex_openedx_extensions/helpers/roles.py @@ -8,7 +8,6 @@ from enum import Enum from typing import Any, Dict, List, Tuple -from common.djangoapps.student.models import CourseAccessRole, UserSignupSource from django.contrib.auth import get_user_model from django.core.cache import cache from django.db import DatabaseError, transaction @@ -44,6 +43,7 @@ get_tenants_sites, ) from futurex_openedx_extensions.helpers.users import get_user_by_key, is_system_staff_user +from futurex_openedx_extensions.upgrade.models_switch import CourseAccessRole, UserSignupSource logger = logging.getLogger(__name__) @@ -1279,7 +1279,7 @@ def add_course_access_roles( # pylint: disable=too-many-arguments, too-many-bra status = _add_course_access_roles_one_user( caller, user_info['user'], role, orgs, course_ids, orgs_of_courses['courses'], dry_run ) - except Exception as exc: # pylint: disable=broad-except + except Exception as exc: result['failed'].append({ 'user_id': user_info['user'].id, 'username': user_info['user'].username, @@ -1557,7 +1557,7 @@ def update_course_access_roles( # pylint: disable=too-many-branches, too-many-s 'reason_message': str(exc), }) - except Exception as exc: # pylint: disable=broad-except + except Exception as exc: result['failed'].append({ 'reason_code': FXExceptionCodes.UNKNOWN_ERROR.value, 'reason_message': f'{type(exc).__name__}: {str(exc)}', diff --git a/futurex_openedx_extensions/helpers/signals.py b/futurex_openedx_extensions/helpers/signals.py index 88c130b3..509bba40 100644 --- a/futurex_openedx_extensions/helpers/signals.py +++ b/futurex_openedx_extensions/helpers/signals.py @@ -3,7 +3,6 @@ from typing import Any -from common.djangoapps.student.models import CourseAccessRole from django.core.cache import cache from django.db.models.signals import post_delete, post_save from django.dispatch import receiver @@ -14,6 +13,7 @@ add_missing_signup_source_record, cache_name_user_course_access_roles, ) +from futurex_openedx_extensions.upgrade.models_switch import CourseAccessRole @receiver(post_save, sender=CourseAccessRole) diff --git a/futurex_openedx_extensions/helpers/tenants.py b/futurex_openedx_extensions/helpers/tenants.py index 581c151e..92273718 100644 --- a/futurex_openedx_extensions/helpers/tenants.py +++ b/futurex_openedx_extensions/helpers/tenants.py @@ -54,9 +54,10 @@ def fix_lms_base(domain_name: str) -> str: return '' lms_root_parts = urlparse(settings.LMS_ROOT_URL) + + if not (domain_name.startswith('http://') or domain_name.startswith('https://')): + domain_name = f'{lms_root_parts.scheme}://{domain_name}' domain_name_parts = urlparse(domain_name) - if not domain_name_parts.scheme: - domain_name_parts = urlparse(f'{lms_root_parts.scheme}://{domain_name}') port = f':{domain_name_parts.port}' if domain_name_parts.port else '' diff --git a/futurex_openedx_extensions/helpers/theme.py b/futurex_openedx_extensions/helpers/theme.py index b8ea1568..95f3a77c 100644 --- a/futurex_openedx_extensions/helpers/theme.py +++ b/futurex_openedx_extensions/helpers/theme.py @@ -1,12 +1,12 @@ """"Theme helpers""" from typing import Any, Optional -from common.djangoapps.student.models import CourseAccessRole from django.conf import settings from futurex_openedx_extensions.helpers.roles import get_accessible_tenant_ids from futurex_openedx_extensions.helpers.tenants import get_all_tenants_info from futurex_openedx_extensions.helpers.users import is_system_staff_user +from futurex_openedx_extensions.upgrade.models_switch import CourseAccessRole def get_fx_dashboard_url(request: Any) -> Optional[str]: diff --git a/futurex_openedx_extensions/helpers/users.py b/futurex_openedx_extensions/helpers/users.py index 9fc81d3c..18e02579 100644 --- a/futurex_openedx_extensions/helpers/users.py +++ b/futurex_openedx_extensions/helpers/users.py @@ -3,11 +3,11 @@ from typing import Any, Dict -from common.djangoapps.student.models import get_user_by_username_or_email from django.contrib.auth import get_user_model from futurex_openedx_extensions.helpers import constants as cs from futurex_openedx_extensions.helpers.exceptions import FXCodedException, FXExceptionCodes +from futurex_openedx_extensions.upgrade.models_switch import get_user_by_username_or_email def is_user_instance(user: Any) -> bool: diff --git a/test_utils/edx_platform_mocks/__init__.py b/futurex_openedx_extensions/upgrade/__init__.py similarity index 100% rename from test_utils/edx_platform_mocks/__init__.py rename to futurex_openedx_extensions/upgrade/__init__.py diff --git a/futurex_openedx_extensions/upgrade/apps.py b/futurex_openedx_extensions/upgrade/apps.py new file mode 100644 index 00000000..a7b20a02 --- /dev/null +++ b/futurex_openedx_extensions/upgrade/apps.py @@ -0,0 +1,28 @@ +"""upgrade Django application initialization""" +from __future__ import annotations + +from django.apps import AppConfig + + +class UpgradeConfig(AppConfig): + """Configuration for the helpers Django application""" + + name = 'futurex_openedx_extensions.upgrade' + label = 'fx_upgrade' + + # pylint: disable=duplicate-code + plugin_app = { + 'settings_config': { + 'lms.djangoapp': { + 'production': { + 'relative_path': 'settings.common_production', + }, + }, + 'cms.djangoapp': { + 'production': { + 'relative_path': 'settings.common_production', + }, + }, + }, + } + # pylint: enable=duplicate-code diff --git a/futurex_openedx_extensions/upgrade/models_switch.py b/futurex_openedx_extensions/upgrade/models_switch.py new file mode 100644 index 00000000..035a124c --- /dev/null +++ b/futurex_openedx_extensions/upgrade/models_switch.py @@ -0,0 +1,26 @@ +"""Models switch for different Open edX platform versions.""" +from futurex_openedx_extensions.upgrade.utils import ( + FX_CURRENT_EDX_PLATFORM_VERSION, + FX_EDX_PLATFORM_VERSION_PALM, + FX_EDX_PLATFORM_VERSION_REDWOOD, +) + +if FX_CURRENT_EDX_PLATFORM_VERSION == FX_EDX_PLATFORM_VERSION_PALM: + from futurex_openedx_extensions.upgrade.releases.palm.models import ( # pylint: disable=unused-import + CourseAccessRole, + CourseEnrollment, + SocialLink, + UserProfile, + UserSignupSource, + get_user_by_username_or_email, + ) + +elif FX_CURRENT_EDX_PLATFORM_VERSION == FX_EDX_PLATFORM_VERSION_REDWOOD: + from futurex_openedx_extensions.upgrade.releases.redwood.models import ( + CourseAccessRole, + CourseEnrollment, + SocialLink, + UserProfile, + UserSignupSource, + get_user_by_username_or_email, + ) diff --git a/test_utils/edx_platform_mocks/fake_models/__init__.py b/futurex_openedx_extensions/upgrade/releases/__init__.py similarity index 100% rename from test_utils/edx_platform_mocks/fake_models/__init__.py rename to futurex_openedx_extensions/upgrade/releases/__init__.py diff --git a/futurex_openedx_extensions/upgrade/releases/palm/__init__.py b/futurex_openedx_extensions/upgrade/releases/palm/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/futurex_openedx_extensions/upgrade/releases/palm/models.py b/futurex_openedx_extensions/upgrade/releases/palm/models.py new file mode 100644 index 00000000..39b4cb79 --- /dev/null +++ b/futurex_openedx_extensions/upgrade/releases/palm/models.py @@ -0,0 +1,9 @@ +"""Imports from palm""" +from common.djangoapps.student.models import ( # pylint: disable=unused-import + CourseAccessRole, + CourseEnrollment, + SocialLink, + UserProfile, + UserSignupSource, + get_user_by_username_or_email, +) diff --git a/futurex_openedx_extensions/upgrade/releases/redwood/__init__.py b/futurex_openedx_extensions/upgrade/releases/redwood/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/futurex_openedx_extensions/upgrade/releases/redwood/models.py b/futurex_openedx_extensions/upgrade/releases/redwood/models.py new file mode 100644 index 00000000..81302284 --- /dev/null +++ b/futurex_openedx_extensions/upgrade/releases/redwood/models.py @@ -0,0 +1,9 @@ +"""Imports from redwood""" +from common.djangoapps.student.models.course_enrollment import CourseEnrollment # pylint: disable=unused-import +from common.djangoapps.student.models.user import ( # pylint: disable=unused-import + CourseAccessRole, + SocialLink, + UserProfile, + UserSignupSource, + get_user_by_username_or_email, +) diff --git a/futurex_openedx_extensions/upgrade/settings/__init__.py b/futurex_openedx_extensions/upgrade/settings/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/futurex_openedx_extensions/upgrade/settings/common_production.py b/futurex_openedx_extensions/upgrade/settings/common_production.py new file mode 100644 index 00000000..f2c9b111 --- /dev/null +++ b/futurex_openedx_extensions/upgrade/settings/common_production.py @@ -0,0 +1,8 @@ +"""Common Settings""" +from __future__ import annotations + +from typing import Any + + +def plugin_settings(settings: Any) -> None: # pylint: disable=unused-argument + """plugin settings""" diff --git a/futurex_openedx_extensions/upgrade/utils.py b/futurex_openedx_extensions/upgrade/utils.py new file mode 100644 index 00000000..c017c12d --- /dev/null +++ b/futurex_openedx_extensions/upgrade/utils.py @@ -0,0 +1,35 @@ +"""Utilit functions for upgrade tasks.""" +from __future__ import annotations + +import logging + +from django.conf import settings + +log = logging.getLogger(__name__) + +FX_EDX_PLATFORM_VERSION_PALM = 'palm' +FX_EDX_PLATFORM_VERSION_REDWOOD = 'redwood' + +FX_DASHBOARD_DEFAULT_EDX_PLATFORM_VERSION = FX_EDX_PLATFORM_VERSION_PALM +FX_DASHBOARD_SUPPORTED_EDX_PLATFORM_VERSION = [FX_EDX_PLATFORM_VERSION_PALM, FX_EDX_PLATFORM_VERSION_REDWOOD] + + +def get_default_version() -> str: + """Get the default version of the edx-platform.""" + return FX_DASHBOARD_DEFAULT_EDX_PLATFORM_VERSION + + +def get_current_version() -> str: + """Get the current version of the edx-platform.""" + default = get_default_version() + result = getattr(settings, 'FX_EDX_PLATFORM_VERSION', default) or default + if result not in FX_DASHBOARD_SUPPORTED_EDX_PLATFORM_VERSION: + log.error( + 'FX_EDX_PLATFORM_VERSION was set to (%s) which is not a supported version. ' + 'Defaulting to (%s).', result, default, + ) + result = default + return result + + +FX_CURRENT_EDX_PLATFORM_VERSION = get_current_version() diff --git a/requirements/base.in b/requirements/base.in index 13566cec..8e7f6d6a 100644 --- a/requirements/base.in +++ b/requirements/base.in @@ -1,8 +1,3 @@ # Core requirements for using this application --c constraints.txt Django # Web application framework -django-model-utils # Provides TimeStampedModel abstract base class - -eox-tenant<11.0.0 -clickhouse-connect>0.5,<0.6 # as used in tutor-contrib-aspects v0.38.0 diff --git a/requirements/base.txt b/requirements/base.txt deleted file mode 100644 index a6a52565..00000000 --- a/requirements/base.txt +++ /dev/null @@ -1,35 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.8 -# by the following command: -# -# make upgrade -# -asgiref==3.8.1 - # via django -backports-zoneinfo==0.2.1 - # via django -certifi==2024.8.30 - # via clickhouse-connect -clickhouse-connect==0.5.25 - # via -r requirements/base.in -django==4.2.16 - # via - # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt - # -r requirements/base.in - # django-model-utils -django-model-utils==5.0.0 - # via -r requirements/base.in -eox-tenant==10.0.0 - # via -r requirements/base.in -lz4==4.3.3 - # via clickhouse-connect -pytz==2024.2 - # via clickhouse-connect -sqlparse==0.5.1 - # via django -typing-extensions==4.12.2 - # via asgiref -urllib3==2.2.3 - # via clickhouse-connect -zstandard==0.23.0 - # via clickhouse-connect diff --git a/requirements/ci.in b/requirements/ci.in index 3586cbe3..ae07f2cd 100644 --- a/requirements/ci.in +++ b/requirements/ci.in @@ -1,5 +1,5 @@ # Requirements for running tests in CI --c constraints.txt +-r pip.in # Core dependencies for installing other packages -tox # Virtualenv management for tests +tox # Virtualenv management for tests diff --git a/requirements/ci.txt b/requirements/ci.txt deleted file mode 100644 index e5197b0c..00000000 --- a/requirements/ci.txt +++ /dev/null @@ -1,40 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.8 -# by the following command: -# -# make upgrade -# -cachetools==5.5.0 - # via tox -chardet==5.2.0 - # via tox -colorama==0.4.6 - # via tox -distlib==0.3.9 - # via virtualenv -filelock==3.16.1 - # via - # tox - # virtualenv -packaging==24.2 - # via - # pyproject-api - # tox -platformdirs==4.3.6 - # via - # tox - # virtualenv -pluggy==1.5.0 - # via tox -pyproject-api==1.8.0 - # via tox -tomli==2.0.2 - # via - # pyproject-api - # tox -tox==4.23.2 - # via -r requirements/ci.in -typing-extensions==4.12.2 - # via tox -virtualenv==20.27.1 - # via tox diff --git a/requirements/constraints-palm.txt b/requirements/constraints-palm.txt new file mode 100644 index 00000000..a2ad5b48 --- /dev/null +++ b/requirements/constraints-palm.txt @@ -0,0 +1,13 @@ +-c https://raw.githubusercontent.com/nelc/edx-platform/refs/heads/open-release/palm.nelp/requirements/constraints.txt + +# Nelc specific requirements +eox-tenant==v10.0.0 +clickhouse-connect>0.5,<0.6 # as used in tutor-contrib-aspects v0.51.1 + +# edx-platform related requirements. Pinned to the versions used in Palm. +edx-opaque-keys==2.3.0 +edx-lint<5.4.0 +django-filter==23.1 +django-mysql==4.9.0 +jsonfield==3.1.0 +python-dateutil==2.8.2 diff --git a/requirements/constraints-redwood.txt b/requirements/constraints-redwood.txt new file mode 100644 index 00000000..483fb6d8 --- /dev/null +++ b/requirements/constraints-redwood.txt @@ -0,0 +1,13 @@ +-c https://raw.githubusercontent.com/nelc/edx-platform/refs/heads/open-release/redwood.nelp/requirements/constraints.txt + +# Nelc specific requirements +eox-tenant0.5,<1.0 # as used in tutor-contrib-aspects v1.2.0 + +# edx-platform related requirements. Pinned to the versions used in Redwood. +edx-opaque-keys==2.9.0 +edx-lint==5.3.6 +django-filter==24.2 +django-mysql==4.13.0 +jsonfield==3.1.0 +python-dateutil==2.9.0.post0 diff --git a/requirements/constraints.txt b/requirements/constraints.txt deleted file mode 100644 index d91704bb..00000000 --- a/requirements/constraints.txt +++ /dev/null @@ -1,12 +0,0 @@ -# Version constraints for pip-installation. -# -# This file doesn't install any packages. It specifies version constraints -# that will be applied if a package is needed. -# -# When pinning something here, please provide an explanation of why. Ideally, -# link to other information that will help people in the future to remove the -# pin when possible. Writing an issue against the offending project and -# linking to it here is good. - -# Common constraints for edx repos --c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt diff --git a/requirements/dev.in b/requirements/dev.in index eb8c92c5..0374012a 100644 --- a/requirements/dev.in +++ b/requirements/dev.in @@ -1,9 +1,8 @@ # Additional requirements for development of this application --c constraints.txt --r pip-tools.txt # pip-tools and its dependencies, for managing requirements files --r quality.txt # Core and quality check dependencies --r ci.txt # dependencies for setting up testing in CI +-r pip-tools.in # pip-tools and its dependencies, for managing requirements files +-r quality.in # Core and quality check dependencies +-r ci.in # dependencies for setting up testing in CI diff-cover # Changeset diff test coverage edx-i18n-tools # For i18n_tool dummy diff --git a/requirements/dev.txt b/requirements/dev.txt deleted file mode 100644 index 008b2f0b..00000000 --- a/requirements/dev.txt +++ /dev/null @@ -1,359 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.8 -# by the following command: -# -# make upgrade -# -asgiref==3.8.1 - # via - # -r requirements/quality.txt - # django -astroid==3.2.4 - # via - # -r requirements/quality.txt - # pylint - # pylint-celery -backports-zoneinfo==0.2.1 ; python_version < "3.9" - # via - # -r requirements/quality.txt - # django - # djangorestframework -build==1.2.2.post1 - # via - # -r requirements/pip-tools.txt - # pip-tools -cachetools==5.5.0 - # via - # -r requirements/ci.txt - # tox -certifi==2024.8.30 - # via - # -r requirements/quality.txt - # clickhouse-connect -chardet==5.2.0 - # via - # -r requirements/ci.txt - # diff-cover - # tox -click==8.1.7 - # via - # -r requirements/pip-tools.txt - # -r requirements/quality.txt - # click-log - # code-annotations - # edx-lint - # pip-tools -click-log==0.4.0 - # via - # -r requirements/quality.txt - # edx-lint -clickhouse-connect==0.5.25 - # via -r requirements/quality.txt -code-annotations==1.8.0 - # via - # -r requirements/quality.txt - # edx-lint -colorama==0.4.6 - # via - # -r requirements/ci.txt - # tox -coverage[toml]==7.6.1 - # via - # -r requirements/quality.txt - # pytest-cov -ddt==1.7.2 - # via -r requirements/quality.txt -deepdiff==8.0.1 - # via -r requirements/quality.txt -diff-cover==9.2.0 - # via -r requirements/dev.in -dill==0.3.9 - # via - # -r requirements/quality.txt - # pylint -distlib==0.3.9 - # via - # -r requirements/ci.txt - # virtualenv -django==4.2.16 - # via - # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt - # -r requirements/quality.txt - # django-crum - # django-filter - # django-model-utils - # django-mysql - # djangorestframework - # edx-i18n-tools - # jsonfield - # openedx-filters -django-crum==0.7.9 - # via -r requirements/quality.txt -django-filter==23.5 - # via -r requirements/quality.txt -django-model-utils==5.0.0 - # via -r requirements/quality.txt -django-mysql==4.14.0 - # via -r requirements/quality.txt -django-simple-history==3.0.0 - # via - # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt - # -r requirements/quality.txt -djangorestframework==3.15.1 - # via -r requirements/quality.txt -dnspython==2.6.1 - # via - # -r requirements/quality.txt - # pymongo -edx-i18n-tools==1.6.3 - # via -r requirements/dev.in -edx-lint==5.3.7 - # via -r requirements/quality.txt -edx-opaque-keys[django]==2.11.0 - # via -r requirements/quality.txt -eox-tenant==10.0.0 - # via -r requirements/quality.txt -exceptiongroup==1.2.2 - # via - # -r requirements/quality.txt - # pytest -filelock==3.16.1 - # via - # -r requirements/ci.txt - # tox - # virtualenv -flake8==7.1.1 - # via - # -r requirements/quality.txt - # flake8-quotes -flake8-quotes==3.4.0 - # via -r requirements/quality.txt -importlib-metadata==8.5.0 - # via - # -r requirements/pip-tools.txt - # build -iniconfig==2.0.0 - # via - # -r requirements/quality.txt - # pytest -isort==5.13.2 - # via - # -r requirements/quality.txt - # pylint -jinja2==3.1.4 - # via - # -r requirements/quality.txt - # code-annotations - # diff-cover -jsonfield==3.1.0 - # via -r requirements/quality.txt -lxml[html-clean,html_clean]==5.3.0 - # via - # edx-i18n-tools - # lxml-html-clean -lxml-html-clean==0.3.1 - # via lxml -lz4==4.3.3 - # via - # -r requirements/quality.txt - # clickhouse-connect -markupsafe==2.1.5 - # via - # -r requirements/quality.txt - # jinja2 -mccabe==0.7.0 - # via - # -r requirements/quality.txt - # flake8 - # pylint -mypy==1.13.0 - # via -r requirements/quality.txt -mypy-extensions==1.0.0 - # via - # -r requirements/quality.txt - # mypy -numpy==1.24.4 - # via -r requirements/quality.txt -openedx-filters==1.9.0 - # via -r requirements/quality.txt -orderly-set==5.2.2 - # via - # -r requirements/quality.txt - # deepdiff -packaging==24.2 - # via - # -r requirements/ci.txt - # -r requirements/pip-tools.txt - # -r requirements/quality.txt - # build - # pyproject-api - # pytest - # tox -path==16.16.0 - # via edx-i18n-tools -pbr==6.1.0 - # via - # -r requirements/quality.txt - # stevedore -pip-tools==7.4.1 - # via -r requirements/pip-tools.txt -platformdirs==4.3.6 - # via - # -r requirements/ci.txt - # -r requirements/quality.txt - # pylint - # tox - # virtualenv -pluggy==1.5.0 - # via - # -r requirements/ci.txt - # -r requirements/quality.txt - # diff-cover - # pytest - # tox -polib==1.2.0 - # via edx-i18n-tools -pycodestyle==2.12.1 - # via - # -r requirements/quality.txt - # flake8 -pydocstyle==6.3.0 - # via -r requirements/quality.txt -pyflakes==3.2.0 - # via - # -r requirements/quality.txt - # flake8 -pygments==2.18.0 - # via diff-cover -pylint==3.2.7 - # via - # -r requirements/quality.txt - # edx-lint - # pylint-celery - # pylint-django - # pylint-plugin-utils -pylint-celery==0.3 - # via - # -r requirements/quality.txt - # edx-lint -pylint-django==2.5.5 - # via - # -r requirements/quality.txt - # edx-lint -pylint-plugin-utils==0.8.2 - # via - # -r requirements/quality.txt - # pylint-celery - # pylint-django -pymongo==4.10.1 - # via - # -r requirements/quality.txt - # edx-opaque-keys -pyproject-api==1.8.0 - # via - # -r requirements/ci.txt - # tox -pyproject-hooks==1.2.0 - # via - # -r requirements/pip-tools.txt - # build - # pip-tools -pytest==8.3.3 - # via - # -r requirements/quality.txt - # pytest-cov - # pytest-django -pytest-cov==5.0.0 - # via -r requirements/quality.txt -pytest-django==4.9.0 - # via -r requirements/quality.txt -python-dateutil==2.9.0.post0 - # via -r requirements/quality.txt -python-slugify==8.0.4 - # via - # -r requirements/quality.txt - # code-annotations -pytz==2024.2 - # via - # -r requirements/quality.txt - # clickhouse-connect -pyyaml==6.0.2 - # via - # -r requirements/quality.txt - # code-annotations - # edx-i18n-tools -six==1.16.0 - # via - # -r requirements/quality.txt - # edx-lint - # python-dateutil -snowballstemmer==2.2.0 - # via - # -r requirements/quality.txt - # pydocstyle -sqlparse==0.5.1 - # via - # -r requirements/quality.txt - # django -stevedore==5.3.0 - # via - # -r requirements/quality.txt - # code-annotations - # edx-opaque-keys -text-unidecode==1.3 - # via - # -r requirements/quality.txt - # python-slugify -tomli==2.0.2 - # via - # -r requirements/ci.txt - # -r requirements/pip-tools.txt - # -r requirements/quality.txt - # build - # coverage - # mypy - # pip-tools - # pylint - # pyproject-api - # pytest - # tox -tomlkit==0.13.2 - # via - # -r requirements/quality.txt - # pylint -tox==4.23.2 - # via -r requirements/ci.txt -typing-extensions==4.12.2 - # via - # -r requirements/ci.txt - # -r requirements/quality.txt - # asgiref - # astroid - # edx-opaque-keys - # mypy - # pylint - # tox -urllib3==2.2.3 - # via - # -r requirements/quality.txt - # clickhouse-connect -virtualenv==20.27.1 - # via - # -r requirements/ci.txt - # tox -wheel==0.45.0 - # via - # -r requirements/pip-tools.txt - # pip-tools -zipp==3.20.2 - # via - # -r requirements/pip-tools.txt - # importlib-metadata -zstandard==0.23.0 - # via - # -r requirements/quality.txt - # clickhouse-connect - -# The following packages are considered to be unsafe in a requirements file: -# pip -# setuptools diff --git a/requirements/doc.in b/requirements/doc.in index a8b02901..ae6530d6 100644 --- a/requirements/doc.in +++ b/requirements/doc.in @@ -1,7 +1,6 @@ # Requirements for documentation validation --c constraints.txt --r test.txt # Core and testing dependencies for this package +-r test.in # Core and testing dependencies for this package doc8 # reStructuredText style checker sphinx-book-theme # Common theme for all Open edX projects diff --git a/requirements/doc.txt b/requirements/doc.txt deleted file mode 100644 index 0adfc634..00000000 --- a/requirements/doc.txt +++ /dev/null @@ -1,310 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.8 -# by the following command: -# -# make upgrade -# -accessible-pygments==0.0.4 - # via pydata-sphinx-theme -alabaster==0.7.13 - # via sphinx -asgiref==3.8.1 - # via - # -r requirements/test.txt - # django -babel==2.16.0 - # via - # pydata-sphinx-theme - # sphinx -backports-tarfile==1.2.0 - # via jaraco-context -backports-zoneinfo==0.2.1 ; python_version < "3.9" - # via - # -r requirements/test.txt - # django - # djangorestframework -beautifulsoup4==4.12.3 - # via pydata-sphinx-theme -build==1.2.2.post1 - # via -r requirements/doc.in -certifi==2024.8.30 - # via - # -r requirements/test.txt - # clickhouse-connect - # requests -cffi==1.17.1 - # via cryptography -charset-normalizer==3.4.0 - # via requests -click==8.1.7 - # via - # -r requirements/test.txt - # code-annotations -clickhouse-connect==0.5.25 - # via -r requirements/test.txt -code-annotations==1.8.0 - # via -r requirements/test.txt -coverage[toml]==7.6.1 - # via - # -r requirements/test.txt - # pytest-cov -cryptography==43.0.3 - # via secretstorage -ddt==1.7.2 - # via -r requirements/test.txt -deepdiff==8.0.1 - # via -r requirements/test.txt -django==4.2.16 - # via - # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt - # -r requirements/test.txt - # django-crum - # django-filter - # django-model-utils - # django-mysql - # djangorestframework - # jsonfield - # openedx-filters -django-crum==0.7.9 - # via -r requirements/test.txt -django-filter==23.5 - # via -r requirements/test.txt -django-model-utils==5.0.0 - # via -r requirements/test.txt -django-mysql==4.14.0 - # via -r requirements/test.txt -django-simple-history==3.0.0 - # via - # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt - # -r requirements/test.txt -djangorestframework==3.15.1 - # via -r requirements/test.txt -dnspython==2.6.1 - # via - # -r requirements/test.txt - # pymongo -doc8==1.1.2 - # via -r requirements/doc.in -docutils==0.19 - # via - # doc8 - # pydata-sphinx-theme - # readme-renderer - # restructuredtext-lint - # sphinx -edx-opaque-keys[django]==2.11.0 - # via -r requirements/test.txt -eox-tenant==10.0.0 - # via -r requirements/test.txt -exceptiongroup==1.2.2 - # via - # -r requirements/test.txt - # pytest -idna==3.10 - # via requests -imagesize==1.4.1 - # via sphinx -importlib-metadata==8.5.0 - # via - # build - # keyring - # sphinx - # twine -importlib-resources==6.4.5 - # via keyring -iniconfig==2.0.0 - # via - # -r requirements/test.txt - # pytest -jaraco-classes==3.4.0 - # via keyring -jaraco-context==6.0.1 - # via keyring -jaraco-functools==4.1.0 - # via keyring -jeepney==0.8.0 - # via - # keyring - # secretstorage -jinja2==3.1.4 - # via - # -r requirements/test.txt - # code-annotations - # sphinx -jsonfield==3.1.0 - # via -r requirements/test.txt -keyring==25.5.0 - # via twine -lz4==4.3.3 - # via - # -r requirements/test.txt - # clickhouse-connect -markdown-it-py==3.0.0 - # via rich -markupsafe==2.1.5 - # via - # -r requirements/test.txt - # jinja2 -mdurl==0.1.2 - # via markdown-it-py -more-itertools==10.5.0 - # via - # jaraco-classes - # jaraco-functools -nh3==0.2.18 - # via readme-renderer -numpy==1.24.4 - # via -r requirements/test.txt -openedx-filters==1.9.0 - # via -r requirements/test.txt -orderly-set==5.2.2 - # via - # -r requirements/test.txt - # deepdiff -packaging==24.2 - # via - # -r requirements/test.txt - # build - # pydata-sphinx-theme - # pytest - # sphinx -pbr==6.1.0 - # via - # -r requirements/test.txt - # stevedore -pkginfo==1.10.0 - # via twine -pluggy==1.5.0 - # via - # -r requirements/test.txt - # pytest -pycparser==2.22 - # via cffi -pydata-sphinx-theme==0.14.4 - # via sphinx-book-theme -pygments==2.18.0 - # via - # accessible-pygments - # doc8 - # pydata-sphinx-theme - # readme-renderer - # rich - # sphinx -pymongo==4.10.1 - # via - # -r requirements/test.txt - # edx-opaque-keys -pyproject-hooks==1.2.0 - # via build -pytest==8.3.3 - # via - # -r requirements/test.txt - # pytest-cov - # pytest-django -pytest-cov==5.0.0 - # via -r requirements/test.txt -pytest-django==4.9.0 - # via -r requirements/test.txt -python-dateutil==2.9.0.post0 - # via -r requirements/test.txt -python-slugify==8.0.4 - # via - # -r requirements/test.txt - # code-annotations -pytz==2024.2 - # via - # -r requirements/test.txt - # babel - # clickhouse-connect -pyyaml==6.0.2 - # via - # -r requirements/test.txt - # code-annotations -readme-renderer==43.0 - # via twine -requests==2.32.3 - # via - # requests-toolbelt - # sphinx - # twine -requests-toolbelt==1.0.0 - # via twine -restructuredtext-lint==1.4.0 - # via doc8 -rfc3986==2.0.0 - # via twine -rich==13.9.4 - # via twine -secretstorage==3.3.3 - # via keyring -six==1.16.0 - # via - # -r requirements/test.txt - # python-dateutil -snowballstemmer==2.2.0 - # via sphinx -soupsieve==2.6 - # via beautifulsoup4 -sphinx==6.2.1 - # via - # -r requirements/doc.in - # pydata-sphinx-theme - # sphinx-book-theme -sphinx-book-theme==1.0.1 - # via -r requirements/doc.in -sphinxcontrib-applehelp==1.0.4 - # via sphinx -sphinxcontrib-devhelp==1.0.2 - # via sphinx -sphinxcontrib-htmlhelp==2.0.1 - # via sphinx -sphinxcontrib-jsmath==1.0.1 - # via sphinx -sphinxcontrib-qthelp==1.0.3 - # via sphinx -sphinxcontrib-serializinghtml==1.1.5 - # via sphinx -sqlparse==0.5.1 - # via - # -r requirements/test.txt - # django -stevedore==5.3.0 - # via - # -r requirements/test.txt - # code-annotations - # doc8 - # edx-opaque-keys -text-unidecode==1.3 - # via - # -r requirements/test.txt - # python-slugify -tomli==2.0.2 - # via - # -r requirements/test.txt - # build - # coverage - # doc8 - # pytest -twine==5.1.1 - # via -r requirements/doc.in -typing-extensions==4.12.2 - # via - # -r requirements/test.txt - # asgiref - # edx-opaque-keys - # pydata-sphinx-theme - # rich -urllib3==2.2.3 - # via - # -r requirements/test.txt - # clickhouse-connect - # requests - # twine -zipp==3.20.2 - # via - # importlib-metadata - # importlib-resources -zstandard==0.23.0 - # via - # -r requirements/test.txt - # clickhouse-connect diff --git a/requirements/pip-tools.in b/requirements/pip-tools.in deleted file mode 100644 index 0295d2c8..00000000 --- a/requirements/pip-tools.in +++ /dev/null @@ -1,5 +0,0 @@ -# Just the dependencies to run pip-tools, mainly for the "upgrade" make target - --c constraints.txt - -pip-tools # Contains pip-compile, used to generate pip requirements files diff --git a/requirements/pip-tools.txt b/requirements/pip-tools.txt deleted file mode 100644 index 5a41db6b..00000000 --- a/requirements/pip-tools.txt +++ /dev/null @@ -1,32 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.8 -# by the following command: -# -# make upgrade -# -build==1.2.2.post1 - # via pip-tools -click==8.1.7 - # via pip-tools -importlib-metadata==8.5.0 - # via build -packaging==24.2 - # via build -pip-tools==7.4.1 - # via -r requirements/pip-tools.in -pyproject-hooks==1.2.0 - # via - # build - # pip-tools -tomli==2.0.2 - # via - # build - # pip-tools -wheel==0.45.0 - # via pip-tools -zipp==3.20.2 - # via importlib-metadata - -# The following packages are considered to be unsafe in a requirements file: -# pip -# setuptools diff --git a/requirements/pip.in b/requirements/pip.in index 716c6f28..21ce8e9d 100644 --- a/requirements/pip.in +++ b/requirements/pip.in @@ -1,5 +1,4 @@ # Core dependencies for installing other packages --c constraints.txt pip setuptools diff --git a/requirements/pip.txt b/requirements/pip.txt deleted file mode 100644 index 90b28c57..00000000 --- a/requirements/pip.txt +++ /dev/null @@ -1,16 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.8 -# by the following command: -# -# make upgrade -# -wheel==0.45.0 - # via -r requirements/pip.in - -# The following packages are considered to be unsafe in a requirements file: -pip==24.2 - # via - # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt - # -r requirements/pip.in -setuptools==75.3.0 - # via -r requirements/pip.in diff --git a/requirements/private.readme b/requirements/private.readme deleted file mode 100644 index 5600a107..00000000 --- a/requirements/private.readme +++ /dev/null @@ -1,15 +0,0 @@ -# If there are any Python packages you want to keep in your virtualenv beyond -# those listed in the official requirements files, create a "private.in" file -# and list them there. Generate the corresponding "private.txt" file pinning -# all of their indirect dependencies to specific versions as follows: - -# pip-compile private.in - -# This allows you to use "pip-sync" without removing these packages: - -# pip-sync requirements/*.txt - -# "private.in" and "private.txt" aren't checked into git to avoid merge -# conflicts, and the presence of this file allows "private.*" to be -# included in scripted pip-sync usage without requiring that those files be -# created first. diff --git a/requirements/quality.in b/requirements/quality.in index 4155b14f..0bbd887b 100644 --- a/requirements/quality.in +++ b/requirements/quality.in @@ -1,13 +1,11 @@ # Requirements for code quality checks --c constraints.txt +-r test.in # Core and testing dependencies for this package --r test.txt # Core and testing dependencies for this package - -edx-lint<5.4.0 # edX pylint rules and plugins - version 5.4.0 has a compatibility issue with Python 3.8 -isort # to standardize order of imports -pycodestyle # PEP 8 compliance validation -pydocstyle # PEP 257 compliance validation -mypy # static type checker -flake8 # to enforce PEP 8 compliance -flake8-quotes # to enforce single quotes +edx-lint # edX pylint rules and plugins +isort # to standardize order of imports +pycodestyle # PEP 8 compliance validation +pydocstyle # PEP 257 compliance validation +mypy # static type checker +flake8 # to enforce PEP 8 compliance, but mainly to run the flake8-quotes plugin +flake8-quotes # to enforce single quotes diff --git a/requirements/quality.txt b/requirements/quality.txt deleted file mode 100644 index 67c5095c..00000000 --- a/requirements/quality.txt +++ /dev/null @@ -1,241 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.8 -# by the following command: -# -# make upgrade -# -asgiref==3.8.1 - # via - # -r requirements/test.txt - # django -astroid==3.2.4 - # via - # pylint - # pylint-celery -backports-zoneinfo==0.2.1 ; python_version < "3.9" - # via - # -r requirements/test.txt - # django - # djangorestframework -certifi==2024.8.30 - # via - # -r requirements/test.txt - # clickhouse-connect -click==8.1.7 - # via - # -r requirements/test.txt - # click-log - # code-annotations - # edx-lint -click-log==0.4.0 - # via edx-lint -clickhouse-connect==0.5.25 - # via -r requirements/test.txt -code-annotations==1.8.0 - # via - # -r requirements/test.txt - # edx-lint -coverage[toml]==7.6.1 - # via - # -r requirements/test.txt - # pytest-cov -ddt==1.7.2 - # via -r requirements/test.txt -deepdiff==8.0.1 - # via -r requirements/test.txt -dill==0.3.9 - # via pylint -django==4.2.16 - # via - # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt - # -r requirements/test.txt - # django-crum - # django-filter - # django-model-utils - # django-mysql - # djangorestframework - # jsonfield - # openedx-filters -django-crum==0.7.9 - # via -r requirements/test.txt -django-filter==23.5 - # via -r requirements/test.txt -django-model-utils==5.0.0 - # via -r requirements/test.txt -django-mysql==4.14.0 - # via -r requirements/test.txt -django-simple-history==3.0.0 - # via - # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt - # -r requirements/test.txt -djangorestframework==3.15.1 - # via -r requirements/test.txt -dnspython==2.6.1 - # via - # -r requirements/test.txt - # pymongo -edx-lint==5.3.7 - # via -r requirements/quality.in -edx-opaque-keys[django]==2.11.0 - # via -r requirements/test.txt -eox-tenant==10.0.0 - # via -r requirements/test.txt -exceptiongroup==1.2.2 - # via - # -r requirements/test.txt - # pytest -flake8==7.1.1 - # via - # -r requirements/quality.in - # flake8-quotes -flake8-quotes==3.4.0 - # via -r requirements/quality.in -iniconfig==2.0.0 - # via - # -r requirements/test.txt - # pytest -isort==5.13.2 - # via - # -r requirements/quality.in - # pylint -jinja2==3.1.4 - # via - # -r requirements/test.txt - # code-annotations -jsonfield==3.1.0 - # via -r requirements/test.txt -lz4==4.3.3 - # via - # -r requirements/test.txt - # clickhouse-connect -markupsafe==2.1.5 - # via - # -r requirements/test.txt - # jinja2 -mccabe==0.7.0 - # via - # flake8 - # pylint -mypy==1.13.0 - # via -r requirements/quality.in -mypy-extensions==1.0.0 - # via mypy -numpy==1.24.4 - # via -r requirements/test.txt -openedx-filters==1.9.0 - # via -r requirements/test.txt -orderly-set==5.2.2 - # via - # -r requirements/test.txt - # deepdiff -packaging==24.2 - # via - # -r requirements/test.txt - # pytest -pbr==6.1.0 - # via - # -r requirements/test.txt - # stevedore -platformdirs==4.3.6 - # via pylint -pluggy==1.5.0 - # via - # -r requirements/test.txt - # pytest -pycodestyle==2.12.1 - # via - # -r requirements/quality.in - # flake8 -pydocstyle==6.3.0 - # via -r requirements/quality.in -pyflakes==3.2.0 - # via flake8 -pylint==3.2.7 - # via - # edx-lint - # pylint-celery - # pylint-django - # pylint-plugin-utils -pylint-celery==0.3 - # via edx-lint -pylint-django==2.5.5 - # via edx-lint -pylint-plugin-utils==0.8.2 - # via - # pylint-celery - # pylint-django -pymongo==4.10.1 - # via - # -r requirements/test.txt - # edx-opaque-keys -pytest==8.3.3 - # via - # -r requirements/test.txt - # pytest-cov - # pytest-django -pytest-cov==5.0.0 - # via -r requirements/test.txt -pytest-django==4.9.0 - # via -r requirements/test.txt -python-dateutil==2.9.0.post0 - # via -r requirements/test.txt -python-slugify==8.0.4 - # via - # -r requirements/test.txt - # code-annotations -pytz==2024.2 - # via - # -r requirements/test.txt - # clickhouse-connect -pyyaml==6.0.2 - # via - # -r requirements/test.txt - # code-annotations -six==1.16.0 - # via - # -r requirements/test.txt - # edx-lint - # python-dateutil -snowballstemmer==2.2.0 - # via pydocstyle -sqlparse==0.5.1 - # via - # -r requirements/test.txt - # django -stevedore==5.3.0 - # via - # -r requirements/test.txt - # code-annotations - # edx-opaque-keys -text-unidecode==1.3 - # via - # -r requirements/test.txt - # python-slugify -tomli==2.0.2 - # via - # -r requirements/test.txt - # coverage - # mypy - # pylint - # pytest -tomlkit==0.13.2 - # via pylint -typing-extensions==4.12.2 - # via - # -r requirements/test.txt - # asgiref - # astroid - # edx-opaque-keys - # mypy - # pylint -urllib3==2.2.3 - # via - # -r requirements/test.txt - # clickhouse-connect -zstandard==0.23.0 - # via - # -r requirements/test.txt - # clickhouse-connect - -# The following packages are considered to be unsafe in a requirements file: -# setuptools diff --git a/requirements/test.in b/requirements/test.in index 6d31944d..0d9e00d4 100644 --- a/requirements/test.in +++ b/requirements/test.in @@ -1,28 +1,24 @@ # Requirements for test runs. --c constraints.txt --r base.txt # Core dependencies for this package +-r base.in # Core dependencies for this package +# unit-test packages and dependencies +code-annotations # provides commands used by the pii_check make target. +ddt # data-driven-tests for unittest +deepdiff # for deep comparison of objects +numpy # required by deepdiff pytest-cov # pytest extension for code coverage statistics pytest-django # pytest extension for better Django support -code-annotations # provides commands used by the pii_check make target. -ddt -deepdiff -numpy # Required by deepdiff -# eox-tenant requirements -six -djangorestframework<3.15.2 # 3.15.2 dropped support for Django 3.2 -django-crum +# Nelc specific requirements +eox-tenant +clickhouse-connect + +# edx-platform related requirements. Pinned to the versions used in Palm. +edx-opaque-keys[django] +djangorestframework +django-filter django-mysql +django-simple-history jsonfield -edx-opaque-keys[django] -openedx_filters - -# Python 3.8 compatibility -backports.zoneinfo;python_version<"3.9" - -# other requirements -django-simple-history<3.7.0 # 3.7.0 dropped support for Django 3.2 -django-filter<24.0.0 # 24.0.0 requires Django 4 python-dateutil diff --git a/requirements/test.txt b/requirements/test.txt deleted file mode 100644 index e660d654..00000000 --- a/requirements/test.txt +++ /dev/null @@ -1,139 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.8 -# by the following command: -# -# make upgrade -# -asgiref==3.8.1 - # via - # -r requirements/base.txt - # django -backports-zoneinfo==0.2.1 ; python_version < "3.9" - # via - # -r requirements/base.txt - # -r requirements/test.in - # django - # djangorestframework -certifi==2024.8.30 - # via - # -r requirements/base.txt - # clickhouse-connect -click==8.1.7 - # via code-annotations -clickhouse-connect==0.5.25 - # via -r requirements/base.txt -code-annotations==1.8.0 - # via -r requirements/test.in -coverage[toml]==7.6.1 - # via pytest-cov -ddt==1.7.2 - # via -r requirements/test.in -deepdiff==8.0.1 - # via -r requirements/test.in - # via - # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt - # -r requirements/base.txt - # django-crum - # django-filter - # django-model-utils - # django-mysql - # djangorestframework - # jsonfield - # openedx-filters -django-crum==0.7.9 - # via -r requirements/test.in -django-filter==23.5 - # via -r requirements/test.in -django-model-utils==5.0.0 - # via -r requirements/base.txt -django-mysql==4.14.0 - # via -r requirements/test.in -django-simple-history==3.0.0 - # via - # -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt - # -r requirements/test.in -djangorestframework==3.15.1 - # via -r requirements/test.in -dnspython==2.6.1 - # via pymongo -edx-opaque-keys[django]==2.11.0 - # via -r requirements/test.in -eox-tenant==10.0.0 - # via -r requirements/base.txt -exceptiongroup==1.2.2 - # via pytest -iniconfig==2.0.0 - # via pytest -jinja2==3.1.4 - # via code-annotations -jsonfield==3.1.0 - # via -r requirements/test.in -lz4==4.3.3 - # via - # -r requirements/base.txt - # clickhouse-connect -markupsafe==2.1.5 - # via jinja2 -numpy==1.24.4 - # via -r requirements/test.in -openedx-filters==1.9.0 - # via -r requirements/test.in -orderly-set==5.2.2 - # via deepdiff -packaging==24.2 - # via pytest -pbr==6.1.0 - # via stevedore -pluggy==1.5.0 - # via pytest -pymongo==4.10.1 - # via edx-opaque-keys -pytest==8.3.3 - # via - # pytest-cov - # pytest-django -pytest-cov==5.0.0 - # via -r requirements/test.in -pytest-django==4.9.0 - # via -r requirements/test.in -python-dateutil==2.9.0.post0 - # via -r requirements/test.in -python-slugify==8.0.4 - # via code-annotations -pytz==2024.2 - # via - # -r requirements/base.txt - # clickhouse-connect -pyyaml==6.0.2 - # via code-annotations -six==1.16.0 - # via - # -r requirements/test.in - # python-dateutil -sqlparse==0.5.1 - # via - # -r requirements/base.txt - # django -stevedore==5.3.0 - # via - # code-annotations - # edx-opaque-keys -text-unidecode==1.3 - # via python-slugify -tomli==2.0.2 - # via - # coverage - # pytest -typing-extensions==4.12.2 - # via - # -r requirements/base.txt - # asgiref - # edx-opaque-keys -urllib3==2.2.3 - # via - # -r requirements/base.txt - # clickhouse-connect -zstandard==0.23.0 - # via - # -r requirements/base.txt - # clickhouse-connect diff --git a/setup.py b/setup.py index c26945e9..4392e11a 100755 --- a/setup.py +++ b/setup.py @@ -147,7 +147,7 @@ def is_requirement(line): package_data={ 'futurex_openedx_extensions': ['helpers/assets/*.yml'], }, - install_requires=load_requirements('requirements/base.in'), + install_requires=[], python_requires='>=3.8', zip_safe=False, keywords='Python edx', @@ -165,6 +165,7 @@ def is_requirement(line): 'lms.djangoapp': [ 'fx_dashboard = futurex_openedx_extensions.dashboard.apps:DashboardConfig', 'fx_helpers = futurex_openedx_extensions.helpers.apps:HelpersConfig', + 'fx_upgrade = futurex_openedx_extensions.upgrade.apps:UpgradeConfig', ], }, ) diff --git a/test_utils/eox_settings.py b/test_settings_palm.py similarity index 70% rename from test_utils/eox_settings.py rename to test_settings_palm.py index 676c7971..82c909e3 100644 --- a/test_utils/eox_settings.py +++ b/test_settings_palm.py @@ -1,4 +1,8 @@ -"""EOX test settings.""" +"""Test settings for edx-platform-palm""" +from test_utils.test_settings_common import * + +# edx-platform version +FX_EDX_PLATFORM_VERSION = 'palm' # eox-tenant settings EOX_TENANT_USERS_BACKEND = 'eox_tenant.edxapp_wrapper.backends.users_l_v1' diff --git a/test_settings_redwood.py b/test_settings_redwood.py new file mode 100644 index 00000000..67dd4648 --- /dev/null +++ b/test_settings_redwood.py @@ -0,0 +1,11 @@ +"""Test settings for edx-platform-palm""" +from test_utils.test_settings_common import * + +# edx-platform version +FX_EDX_PLATFORM_VERSION = 'redwood' + +# eox-tenant settings +EOX_TENANT_USERS_BACKEND = 'eox_tenant.edxapp_wrapper.backends.users_p_v1' +GET_BRANDING_API = 'eox_tenant.edxapp_wrapper.backends.branding_api_l_v1' +GET_SITE_CONFIGURATION_MODULE = 'eox_tenant.edxapp_wrapper.backends.site_configuration_module_i_v1' +GET_THEMING_HELPERS = 'eox_tenant.edxapp_wrapper.backends.theming_helpers_h_v1' diff --git a/test_utils/edx_platform_mocks/common/djangoapps/student/admin.py b/test_utils/edx_platform_mocks_palm/common/djangoapps/student/admin.py similarity index 100% rename from test_utils/edx_platform_mocks/common/djangoapps/student/admin.py rename to test_utils/edx_platform_mocks_palm/common/djangoapps/student/admin.py diff --git a/test_utils/edx_platform_mocks/common/djangoapps/student/models.py b/test_utils/edx_platform_mocks_palm/common/djangoapps/student/models.py similarity index 100% rename from test_utils/edx_platform_mocks/common/djangoapps/student/models.py rename to test_utils/edx_platform_mocks_palm/common/djangoapps/student/models.py diff --git a/test_utils/edx_platform_mocks/common/djangoapps/student/roles.py b/test_utils/edx_platform_mocks_palm/common/djangoapps/student/roles.py similarity index 100% rename from test_utils/edx_platform_mocks/common/djangoapps/student/roles.py rename to test_utils/edx_platform_mocks_palm/common/djangoapps/student/roles.py diff --git a/test_utils/edx_platform_mocks/setup.py b/test_utils/edx_platform_mocks_palm/setup.py similarity index 75% rename from test_utils/edx_platform_mocks/setup.py rename to test_utils/edx_platform_mocks_palm/setup.py index b81a1482..3aacd989 100644 --- a/test_utils/edx_platform_mocks/setup.py +++ b/test_utils/edx_platform_mocks_palm/setup.py @@ -2,7 +2,7 @@ from setuptools import setup setup( - name='edx_platform_mocks', + name='edx_platform_mocks_palm', version='0.1.0', packages=[], ) diff --git a/test_utils/edx_platform_mocks_redwood/common/djangoapps/student/admin.py b/test_utils/edx_platform_mocks_redwood/common/djangoapps/student/admin.py new file mode 100644 index 00000000..21d00646 --- /dev/null +++ b/test_utils/edx_platform_mocks_redwood/common/djangoapps/student/admin.py @@ -0,0 +1,2 @@ +"""edx-platform Mocks""" +from fake_models.models import CourseAccessRoleForm # pylint: disable=unused-import diff --git a/test_utils/edx_platform_mocks_redwood/common/djangoapps/student/models/course_enrollment.py b/test_utils/edx_platform_mocks_redwood/common/djangoapps/student/models/course_enrollment.py new file mode 100644 index 00000000..e35fee06 --- /dev/null +++ b/test_utils/edx_platform_mocks_redwood/common/djangoapps/student/models/course_enrollment.py @@ -0,0 +1,2 @@ +"""edx-platform Mocks""" +from fake_models.models import CourseEnrollment # pylint: disable=unused-import diff --git a/test_utils/edx_platform_mocks_redwood/common/djangoapps/student/models/user.py b/test_utils/edx_platform_mocks_redwood/common/djangoapps/student/models/user.py new file mode 100644 index 00000000..10b2dbfd --- /dev/null +++ b/test_utils/edx_platform_mocks_redwood/common/djangoapps/student/models/user.py @@ -0,0 +1,8 @@ +"""edx-platform Mocks""" +from fake_models.functions import get_user_by_username_or_email # pylint: disable=unused-import +from fake_models.models import ( # pylint: disable=unused-import + CourseAccessRole, + SocialLink, + UserProfile, + UserSignupSource, +) diff --git a/test_utils/edx_platform_mocks_redwood/common/djangoapps/student/roles.py b/test_utils/edx_platform_mocks_redwood/common/djangoapps/student/roles.py new file mode 100644 index 00000000..b4fe2bed --- /dev/null +++ b/test_utils/edx_platform_mocks_redwood/common/djangoapps/student/roles.py @@ -0,0 +1,2 @@ +"""edx-platform Mocks""" +from fake_models.classes import REGISTERED_ACCESS_ROLES, CourseRole, OrgRole, RoleBase # pylint: disable=unused-import diff --git a/test_utils/edx_platform_mocks_redwood/setup.py b/test_utils/edx_platform_mocks_redwood/setup.py new file mode 100644 index 00000000..9669478c --- /dev/null +++ b/test_utils/edx_platform_mocks_redwood/setup.py @@ -0,0 +1,8 @@ +"""Setup for edx-platform mocks.""" +from setuptools import setup + +setup( + name='edx_platform_mocks_redwood', + version='0.1.0', + packages=[], +) diff --git a/test_utils/edx_platform_mocks_shared/__init__.py b/test_utils/edx_platform_mocks_shared/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test_utils/edx_platform_mocks/boto3.py b/test_utils/edx_platform_mocks_shared/boto3.py similarity index 100% rename from test_utils/edx_platform_mocks/boto3.py rename to test_utils/edx_platform_mocks_shared/boto3.py diff --git a/test_utils/edx_platform_mocks/celery.py b/test_utils/edx_platform_mocks_shared/celery.py similarity index 100% rename from test_utils/edx_platform_mocks/celery.py rename to test_utils/edx_platform_mocks_shared/celery.py diff --git a/test_utils/edx_platform_mocks/celery_utils/logged_task.py b/test_utils/edx_platform_mocks_shared/celery_utils/logged_task.py similarity index 100% rename from test_utils/edx_platform_mocks/celery_utils/logged_task.py rename to test_utils/edx_platform_mocks_shared/celery_utils/logged_task.py diff --git a/test_utils/edx_platform_mocks/cms/djangoapps/course_creators/models.py b/test_utils/edx_platform_mocks_shared/cms/djangoapps/course_creators/models.py similarity index 100% rename from test_utils/edx_platform_mocks/cms/djangoapps/course_creators/models.py rename to test_utils/edx_platform_mocks_shared/cms/djangoapps/course_creators/models.py diff --git a/test_utils/edx_platform_mocks/completion/models.py b/test_utils/edx_platform_mocks_shared/completion/models.py similarity index 100% rename from test_utils/edx_platform_mocks/completion/models.py rename to test_utils/edx_platform_mocks_shared/completion/models.py diff --git a/test_utils/edx_platform_mocks/custom_reg_form/models.py b/test_utils/edx_platform_mocks_shared/custom_reg_form/models.py similarity index 100% rename from test_utils/edx_platform_mocks/custom_reg_form/models.py rename to test_utils/edx_platform_mocks_shared/custom_reg_form/models.py diff --git a/test_utils/edx_platform_mocks/eox_nelp/course_experience/models.py b/test_utils/edx_platform_mocks_shared/eox_nelp/course_experience/models.py similarity index 100% rename from test_utils/edx_platform_mocks/eox_nelp/course_experience/models.py rename to test_utils/edx_platform_mocks_shared/eox_nelp/course_experience/models.py diff --git a/test_utils/edx_platform_mocks_shared/fake_models/__init__.py b/test_utils/edx_platform_mocks_shared/fake_models/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/test_utils/edx_platform_mocks/fake_models/classes.py b/test_utils/edx_platform_mocks_shared/fake_models/classes.py similarity index 100% rename from test_utils/edx_platform_mocks/fake_models/classes.py rename to test_utils/edx_platform_mocks_shared/fake_models/classes.py diff --git a/test_utils/edx_platform_mocks/fake_models/functions.py b/test_utils/edx_platform_mocks_shared/fake_models/functions.py similarity index 100% rename from test_utils/edx_platform_mocks/fake_models/functions.py rename to test_utils/edx_platform_mocks_shared/fake_models/functions.py diff --git a/test_utils/edx_platform_mocks/fake_models/models.py b/test_utils/edx_platform_mocks_shared/fake_models/models.py similarity index 100% rename from test_utils/edx_platform_mocks/fake_models/models.py rename to test_utils/edx_platform_mocks_shared/fake_models/models.py diff --git a/test_utils/edx_platform_mocks/fake_models/serializers.py b/test_utils/edx_platform_mocks_shared/fake_models/serializers.py similarity index 100% rename from test_utils/edx_platform_mocks/fake_models/serializers.py rename to test_utils/edx_platform_mocks_shared/fake_models/serializers.py diff --git a/test_utils/edx_platform_mocks/lms/djangoapps/certificates/api.py b/test_utils/edx_platform_mocks_shared/lms/djangoapps/certificates/api.py similarity index 100% rename from test_utils/edx_platform_mocks/lms/djangoapps/certificates/api.py rename to test_utils/edx_platform_mocks_shared/lms/djangoapps/certificates/api.py diff --git a/test_utils/edx_platform_mocks/lms/djangoapps/certificates/models.py b/test_utils/edx_platform_mocks_shared/lms/djangoapps/certificates/models.py similarity index 100% rename from test_utils/edx_platform_mocks/lms/djangoapps/certificates/models.py rename to test_utils/edx_platform_mocks_shared/lms/djangoapps/certificates/models.py diff --git a/test_utils/edx_platform_mocks/lms/djangoapps/courseware/courses.py b/test_utils/edx_platform_mocks_shared/lms/djangoapps/courseware/courses.py similarity index 100% rename from test_utils/edx_platform_mocks/lms/djangoapps/courseware/courses.py rename to test_utils/edx_platform_mocks_shared/lms/djangoapps/courseware/courses.py diff --git a/test_utils/edx_platform_mocks/lms/djangoapps/courseware/models.py b/test_utils/edx_platform_mocks_shared/lms/djangoapps/courseware/models.py similarity index 100% rename from test_utils/edx_platform_mocks/lms/djangoapps/courseware/models.py rename to test_utils/edx_platform_mocks_shared/lms/djangoapps/courseware/models.py diff --git a/test_utils/edx_platform_mocks/lms/djangoapps/grades/api.py b/test_utils/edx_platform_mocks_shared/lms/djangoapps/grades/api.py similarity index 100% rename from test_utils/edx_platform_mocks/lms/djangoapps/grades/api.py rename to test_utils/edx_platform_mocks_shared/lms/djangoapps/grades/api.py diff --git a/test_utils/edx_platform_mocks/lms/djangoapps/grades/context.py b/test_utils/edx_platform_mocks_shared/lms/djangoapps/grades/context.py similarity index 100% rename from test_utils/edx_platform_mocks/lms/djangoapps/grades/context.py rename to test_utils/edx_platform_mocks_shared/lms/djangoapps/grades/context.py diff --git a/test_utils/edx_platform_mocks/lms/djangoapps/grades/models.py b/test_utils/edx_platform_mocks_shared/lms/djangoapps/grades/models.py similarity index 100% rename from test_utils/edx_platform_mocks/lms/djangoapps/grades/models.py rename to test_utils/edx_platform_mocks_shared/lms/djangoapps/grades/models.py diff --git a/test_utils/edx_platform_mocks/openedx/core/djangoapps/content/block_structure/api.py b/test_utils/edx_platform_mocks_shared/openedx/core/djangoapps/content/block_structure/api.py similarity index 100% rename from test_utils/edx_platform_mocks/openedx/core/djangoapps/content/block_structure/api.py rename to test_utils/edx_platform_mocks_shared/openedx/core/djangoapps/content/block_structure/api.py diff --git a/test_utils/edx_platform_mocks/openedx/core/djangoapps/content/course_overviews/models.py b/test_utils/edx_platform_mocks_shared/openedx/core/djangoapps/content/course_overviews/models.py similarity index 100% rename from test_utils/edx_platform_mocks/openedx/core/djangoapps/content/course_overviews/models.py rename to test_utils/edx_platform_mocks_shared/openedx/core/djangoapps/content/course_overviews/models.py diff --git a/test_utils/edx_platform_mocks/openedx/core/djangoapps/site_configuration/helpers.py b/test_utils/edx_platform_mocks_shared/openedx/core/djangoapps/site_configuration/helpers.py similarity index 100% rename from test_utils/edx_platform_mocks/openedx/core/djangoapps/site_configuration/helpers.py rename to test_utils/edx_platform_mocks_shared/openedx/core/djangoapps/site_configuration/helpers.py diff --git a/test_utils/edx_platform_mocks/openedx/core/djangoapps/site_configuration/models.py b/test_utils/edx_platform_mocks_shared/openedx/core/djangoapps/site_configuration/models.py similarity index 100% rename from test_utils/edx_platform_mocks/openedx/core/djangoapps/site_configuration/models.py rename to test_utils/edx_platform_mocks_shared/openedx/core/djangoapps/site_configuration/models.py diff --git a/test_utils/edx_platform_mocks/openedx/core/djangoapps/theming/helpers.py b/test_utils/edx_platform_mocks_shared/openedx/core/djangoapps/theming/helpers.py similarity index 100% rename from test_utils/edx_platform_mocks/openedx/core/djangoapps/theming/helpers.py rename to test_utils/edx_platform_mocks_shared/openedx/core/djangoapps/theming/helpers.py diff --git a/test_utils/edx_platform_mocks/openedx/core/djangoapps/user_api/accounts/serializers.py b/test_utils/edx_platform_mocks_shared/openedx/core/djangoapps/user_api/accounts/serializers.py similarity index 100% rename from test_utils/edx_platform_mocks/openedx/core/djangoapps/user_api/accounts/serializers.py rename to test_utils/edx_platform_mocks_shared/openedx/core/djangoapps/user_api/accounts/serializers.py diff --git a/test_utils/edx_platform_mocks/openedx/core/lib/api/authentication.py b/test_utils/edx_platform_mocks_shared/openedx/core/lib/api/authentication.py similarity index 100% rename from test_utils/edx_platform_mocks/openedx/core/lib/api/authentication.py rename to test_utils/edx_platform_mocks_shared/openedx/core/lib/api/authentication.py diff --git a/test_utils/edx_platform_mocks/openedx/core/lib/courses.py b/test_utils/edx_platform_mocks_shared/openedx/core/lib/courses.py similarity index 100% rename from test_utils/edx_platform_mocks/openedx/core/lib/courses.py rename to test_utils/edx_platform_mocks_shared/openedx/core/lib/courses.py diff --git a/test_utils/edx_platform_mocks/organizations/models.py b/test_utils/edx_platform_mocks_shared/organizations/models.py similarity index 100% rename from test_utils/edx_platform_mocks/organizations/models.py rename to test_utils/edx_platform_mocks_shared/organizations/models.py diff --git a/test_utils/edx_platform_mocks_shared/setup.py b/test_utils/edx_platform_mocks_shared/setup.py new file mode 100644 index 00000000..ce5519dd --- /dev/null +++ b/test_utils/edx_platform_mocks_shared/setup.py @@ -0,0 +1,8 @@ +"""Setup for edx-platform mocks.""" +from setuptools import setup + +setup( + name='edx_platform_mocks_shared', + version='0.1.0', + packages=[], +) diff --git a/test_utils/edx_platform_mocks/storages/backends/s3boto3.py b/test_utils/edx_platform_mocks_shared/storages/backends/s3boto3.py similarity index 100% rename from test_utils/edx_platform_mocks/storages/backends/s3boto3.py rename to test_utils/edx_platform_mocks_shared/storages/backends/s3boto3.py diff --git a/test_utils/edx_platform_mocks/xmodule/modulestore/django.py b/test_utils/edx_platform_mocks_shared/xmodule/modulestore/django.py similarity index 100% rename from test_utils/edx_platform_mocks/xmodule/modulestore/django.py rename to test_utils/edx_platform_mocks_shared/xmodule/modulestore/django.py diff --git a/test_settings.py b/test_utils/test_settings_common.py similarity index 97% rename from test_settings.py rename to test_utils/test_settings_common.py index 6ca55bd2..ef621dea 100644 --- a/test_settings.py +++ b/test_utils/test_settings_common.py @@ -7,8 +7,6 @@ from os.path import abspath, dirname, join -from test_utils.eox_settings import * - def root(*args): """ @@ -101,4 +99,4 @@ def root(*args): CMS_ROOT_URL = 'https://studio.example.com' NELC_DASHBOARD_BASE = 'dashboard.example.com' -FX_DASHBOARD_STORAGE_DIR = 'test_dir' +FX_DASHBOARD_STORAGE_DIR = 'test_dir' diff --git a/tests/conftest.py b/tests/conftest.py index e5a8d68f..fe6c7d54 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,7 +3,6 @@ import pytest from cms.djangoapps.course_creators.models import CourseCreator -from common.djangoapps.student.models import CourseAccessRole, CourseEnrollment, UserSignupSource from custom_reg_form.models import ExtraInfo from django.contrib.auth import get_user_model from django.core.cache import cache @@ -15,6 +14,7 @@ from organizations.models import Organization from futurex_openedx_extensions.helpers import constants as cs +from futurex_openedx_extensions.upgrade.models_switch import CourseAccessRole, CourseEnrollment, UserSignupSource from tests.base_test_data import _base_data from tests.fixture_helpers import get_tenants_of_org, get_user1_fx_permission_info diff --git a/tests/test_dashboard/test_details/test_details_courses.py b/tests/test_dashboard/test_details/test_details_courses.py index e17602a2..a7562fdc 100644 --- a/tests/test_dashboard/test_details/test_details_courses.py +++ b/tests/test_dashboard/test_details/test_details_courses.py @@ -2,7 +2,6 @@ from unittest.mock import Mock, patch import pytest -from common.djangoapps.student.models import CourseEnrollment from completion.models import BlockCompletion from django.contrib.auth import get_user_model from django.utils.timezone import now, timedelta @@ -16,6 +15,7 @@ get_learner_courses_info_queryset, ) from futurex_openedx_extensions.helpers.exceptions import FXCodedException, FXExceptionCodes +from futurex_openedx_extensions.upgrade.models_switch import CourseEnrollment @pytest.mark.django_db diff --git a/tests/test_dashboard/test_details/test_details_learners.py b/tests/test_dashboard/test_details/test_details_learners.py index ee8f3176..c11eff20 100644 --- a/tests/test_dashboard/test_details/test_details_learners.py +++ b/tests/test_dashboard/test_details/test_details_learners.py @@ -2,7 +2,6 @@ from unittest.mock import Mock, patch import pytest -from common.djangoapps.student.models import CourseEnrollment from django.contrib.auth import get_user_model from lms.djangoapps.grades.models import PersistentCourseGrade @@ -15,6 +14,7 @@ get_learners_queryset, ) from futurex_openedx_extensions.helpers.exceptions import FXCodedException, FXExceptionCodes +from futurex_openedx_extensions.upgrade.models_switch import CourseEnrollment from tests.fixture_helpers import get_tenants_orgs diff --git a/tests/test_dashboard/test_serializers.py b/tests/test_dashboard/test_serializers.py index dfd640ba..1301d27a 100644 --- a/tests/test_dashboard/test_serializers.py +++ b/tests/test_dashboard/test_serializers.py @@ -3,7 +3,6 @@ import pytest from cms.djangoapps.course_creators.models import CourseCreator -from common.djangoapps.student.models import CourseAccessRole, CourseEnrollment, SocialLink, UserProfile from custom_reg_form.models import ExtraInfo from deepdiff import DeepDiff from django.contrib.auth import get_user_model @@ -30,6 +29,7 @@ from futurex_openedx_extensions.helpers import constants as cs from futurex_openedx_extensions.helpers.models import DataExportTask from futurex_openedx_extensions.helpers.roles import RoleType +from futurex_openedx_extensions.upgrade.models_switch import CourseAccessRole, CourseEnrollment, SocialLink, UserProfile def get_dummy_queryset(users_list=None): diff --git a/tests/test_dashboard/test_views.py b/tests/test_dashboard/test_views.py index 890151f0..46788c8c 100644 --- a/tests/test_dashboard/test_views.py +++ b/tests/test_dashboard/test_views.py @@ -5,7 +5,6 @@ import ddt import pytest -from common.djangoapps.student.models import CourseAccessRole from deepdiff import DeepDiff from django.contrib.auth import get_user_model from django.core.exceptions import ValidationError @@ -32,6 +31,7 @@ IsAnonymousOrSystemStaff, IsSystemStaff, ) +from futurex_openedx_extensions.upgrade.models_switch import CourseAccessRole from tests.base_test_data import expected_statistics from tests.fixture_helpers import get_all_orgs, get_test_data_dict, get_user1_fx_permission_info from tests.test_dashboard.test_mixins import MockPatcherMixin diff --git a/tests/test_helpers/test_admin.py b/tests/test_helpers/test_admin.py index 5229790f..e5cd48d5 100644 --- a/tests/test_helpers/test_admin.py +++ b/tests/test_helpers/test_admin.py @@ -201,7 +201,7 @@ def test_clickhouse_query_admin_load_missing_queries( response = clickhouse_query_admin.load_missing_queries(request) - ClickhouseQuery.load_missing_queries.assert_called_once() + ClickhouseQuery.load_missing_queries.assert_called_once() # pylint: disable=no-member assert isinstance(response, HttpResponseRedirect) assert response.url == '/admin/fx_helpers/clickhousequery' diff --git a/tests/test_helpers/test_models.py b/tests/test_helpers/test_models.py index 2a2f55fc..aac7181a 100644 --- a/tests/test_helpers/test_models.py +++ b/tests/test_helpers/test_models.py @@ -3,13 +3,13 @@ from unittest.mock import Mock, patch import pytest -from common.djangoapps.student.models import CourseAccessRole from django.core.exceptions import ValidationError from django.utils import timezone from futurex_openedx_extensions.helpers.clickhouse_operations import ClickhouseBaseError from futurex_openedx_extensions.helpers.exceptions import FXCodedException, FXExceptionCodes from futurex_openedx_extensions.helpers.models import ClickhouseQuery, DataExportTask, ViewUserMapping +from futurex_openedx_extensions.upgrade.models_switch import CourseAccessRole @pytest.fixture diff --git a/tests/test_helpers/test_permissions.py b/tests/test_helpers/test_permissions.py index 3b15dc1d..fa621d82 100644 --- a/tests/test_helpers/test_permissions.py +++ b/tests/test_helpers/test_permissions.py @@ -3,7 +3,6 @@ from unittest.mock import Mock, patch import pytest -from common.djangoapps.student.models import CourseAccessRole from deepdiff import DeepDiff from rest_framework.exceptions import NotAuthenticated, PermissionDenied from rest_framework.test import APIRequestFactory @@ -16,6 +15,7 @@ IsSystemStaff, get_tenant_limited_fx_permission_info, ) +from futurex_openedx_extensions.upgrade.models_switch import CourseAccessRole from tests.fixture_helpers import get_all_orgs, set_user diff --git a/tests/test_helpers/test_querysets.py b/tests/test_helpers/test_querysets.py index 3a60140f..908acb6d 100644 --- a/tests/test_helpers/test_querysets.py +++ b/tests/test_helpers/test_querysets.py @@ -2,13 +2,13 @@ from unittest.mock import Mock, patch import pytest -from common.djangoapps.student.models import CourseAccessRole, UserProfile from django.contrib.auth import get_user_model from django.db.models import Count from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from futurex_openedx_extensions.helpers import querysets from futurex_openedx_extensions.helpers.exceptions import FXCodedException, FXExceptionCodes +from futurex_openedx_extensions.upgrade.models_switch import CourseAccessRole, UserProfile from tests.fixture_helpers import get_tenants_orgs diff --git a/tests/test_helpers/test_roles.py b/tests/test_helpers/test_roles.py index 0a09c496..30a61a46 100644 --- a/tests/test_helpers/test_roles.py +++ b/tests/test_helpers/test_roles.py @@ -4,7 +4,6 @@ import pytest from cms.djangoapps.course_creators.models import CourseCreator -from common.djangoapps.student.models import CourseAccessRole, UserSignupSource from deepdiff import DeepDiff from django.contrib.auth import get_user_model from django.core.cache import cache @@ -48,6 +47,7 @@ validate_course_access_role, ) from futurex_openedx_extensions.helpers.tenants import get_all_tenant_ids +from futurex_openedx_extensions.upgrade.models_switch import CourseAccessRole, UserSignupSource from tests.fixture_helpers import ( get_all_orgs, get_test_data_dict, @@ -2047,7 +2047,8 @@ def test_update_course_access_course_roles_grouping( def test_get_accessible_tenant_ids_none(base_data): # pylint: disable=unused-argument """Verify that get_accessible_tenant_ids returns an empty list when user is None.""" result = get_accessible_tenant_ids(None) - assert result == [] + assert isinstance(result, list) + assert not result @pytest.mark.django_db diff --git a/tests/test_helpers/test_signals.py b/tests/test_helpers/test_signals.py index f56a5fe1..700536e7 100644 --- a/tests/test_helpers/test_signals.py +++ b/tests/test_helpers/test_signals.py @@ -2,12 +2,12 @@ from unittest.mock import patch import pytest -from common.djangoapps.student.models import CourseAccessRole from django.core.cache import cache from futurex_openedx_extensions.helpers.constants import CACHE_NAME_ALL_VIEW_ROLES from futurex_openedx_extensions.helpers.models import ViewAllowedRoles from futurex_openedx_extensions.helpers.roles import cache_name_user_course_access_roles +from futurex_openedx_extensions.upgrade.models_switch import CourseAccessRole @pytest.mark.django_db diff --git a/tests/test_upgrade/__init__.py b/tests/test_upgrade/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_upgrade/test_apps.py b/tests/test_upgrade/test_apps.py new file mode 100644 index 00000000..aa7753e5 --- /dev/null +++ b/tests/test_upgrade/test_apps.py @@ -0,0 +1,14 @@ +"""Tests for the apps module of the helpers app""" +from futurex_openedx_extensions.upgrade.apps import UpgradeConfig +from futurex_openedx_extensions.upgrade.settings import common_production + + +def test_app_name(): + """Test that the app name is correct""" + assert UpgradeConfig.name == 'futurex_openedx_extensions.upgrade' + + +def test_common_production_plugin_settings(): + """Verify settings contain the method plugin_settings""" + assert hasattr(common_production, 'plugin_settings'), 'settings is missing the method plugin_settings!' + common_production.plugin_settings({}) diff --git a/tests/test_upgrade/test_models_switch.py b/tests/test_upgrade/test_models_switch.py new file mode 100644 index 00000000..4ebfe1b8 --- /dev/null +++ b/tests/test_upgrade/test_models_switch.py @@ -0,0 +1,10 @@ +"""Tests for models_switch module""" + + +def test_models_switch(): + """Test that the models switch is correct""" + from futurex_openedx_extensions.upgrade.models_switch import ( \ + # pylint: disable=unused-import, import-outside-toplevel + CourseAccessRole, + ) + assert True, 'just verifying that the import works with no problems within the test environment' diff --git a/tests/test_upgrade/test_utils.py b/tests/test_upgrade/test_utils.py new file mode 100644 index 00000000..ee7a068d --- /dev/null +++ b/tests/test_upgrade/test_utils.py @@ -0,0 +1,64 @@ +"""Tests for the utils module of the upgrade app""" +from unittest.mock import patch + +import pytest +from django.conf import settings +from django.test import override_settings + +from futurex_openedx_extensions.upgrade import utils + + +def test_default_version_and_supported_versions(): + """Verify versions definitions""" + assert isinstance(utils.FX_DASHBOARD_SUPPORTED_EDX_PLATFORM_VERSION, list) + assert utils.FX_DASHBOARD_SUPPORTED_EDX_PLATFORM_VERSION + assert isinstance(utils.FX_DASHBOARD_DEFAULT_EDX_PLATFORM_VERSION, str) and len( + utils.FX_DASHBOARD_DEFAULT_EDX_PLATFORM_VERSION + ) > 2 + assert all( + isinstance(version, str) and len(version) > 2 for version in utils.FX_DASHBOARD_SUPPORTED_EDX_PLATFORM_VERSION + ) + + +def test_default_version_must_be_in_supported_versions(): + """Test that the default version is in the supported versions""" + assert utils.FX_DASHBOARD_DEFAULT_EDX_PLATFORM_VERSION in utils.FX_DASHBOARD_SUPPORTED_EDX_PLATFORM_VERSION + + +@patch('futurex_openedx_extensions.upgrade.utils.FX_DASHBOARD_DEFAULT_EDX_PLATFORM_VERSION', 'lolipop') +def test_get_default_version(): + """Verify that the default version is returned""" + assert utils.get_default_version() == 'lolipop' + + +@pytest.mark.parametrize('in_settings, test_in_log, expected_result', [ + ({'FX_EDX_PLATFORM_VERSION': None}, None, 'lolipop'), + ({'FX_EDX_PLATFORM_VERSION': ''}, None, 'lolipop'), + ({'FX_EDX_PLATFORM_VERSION': 'lolipop'}, None, 'lolipop'), + ({'FX_EDX_PLATFORM_VERSION': 'candy'}, None, 'candy'), + ({'FX_EDX_PLATFORM_VERSION': 'unsupported'}, 'unsupported', 'lolipop'), +]) +@patch('futurex_openedx_extensions.upgrade.utils.FX_DASHBOARD_DEFAULT_EDX_PLATFORM_VERSION', 'lolipop') +@patch('futurex_openedx_extensions.upgrade.utils.FX_DASHBOARD_SUPPORTED_EDX_PLATFORM_VERSION', ['lolipop', 'candy']) +def test_get_current_version(in_settings, test_in_log, expected_result, caplog): + """Verify that the current version is returned""" + assert hasattr(settings, 'FX_EDX_PLATFORM_VERSION') + + with override_settings(**in_settings): + assert utils.get_current_version() == expected_result + if test_in_log: + assert f'FX_EDX_PLATFORM_VERSION was set to ({test_in_log}) which is not a supported version. ' \ + f'Defaulting to ({expected_result}).' in caplog.text + else: + assert 'FX_EDX_PLATFORM_VERSION was set to' not in caplog.text + + +@patch('futurex_openedx_extensions.upgrade.utils.FX_DASHBOARD_DEFAULT_EDX_PLATFORM_VERSION', 'lolipop') +@patch('futurex_openedx_extensions.upgrade.utils.FX_DASHBOARD_SUPPORTED_EDX_PLATFORM_VERSION', ['lolipop', 'candy']) +def test_get_current_version_missing_settings(): + """Verify that the current version is returned from the default when the settings are missing""" + assert hasattr(settings, 'FX_EDX_PLATFORM_VERSION') + del settings.FX_EDX_PLATFORM_VERSION + assert not hasattr(settings, 'FX_EDX_PLATFORM_VERSION') + + assert utils.get_current_version() == 'lolipop' diff --git a/tox.ini b/tox.ini index 5c13d506..40dec6f2 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py38-django{32,40} +envlist = quality,py38-palm,py{38,311}-redwood [doc8] ; D001 = Line too long @@ -30,27 +30,36 @@ ignore = D101,D200,D203,D212,D215,D404,D405,D406,D407,D408,D409,D410,D411,D412,D match-dir = (?!migrations) [pytest] -DJANGO_SETTINGS_MODULE = test_settings addopts = --cov futurex_openedx_extensions --cov tests --cov-report term-missing --cov-report xml --cov-fail-under=100 norecursedirs = .* docs requirements site-packages [testenv] allowlist_externals = rm +setenv = + palm: DJANGO_SETTINGS_MODULE = test_settings_palm + palm: PYTEST_COV_CONFIG = {toxinidir}/.coveragerc-palm + redwood: DJANGO_SETTINGS_MODULE = test_settings_redwood + redwood: PYTEST_COV_CONFIG = {toxinidir}/.coveragerc-redwood deps = - django32: Django>=3.2,<4.0 - django40: Django>=4.0,<4.1 - -r{toxinidir}/requirements/test.txt - -e{toxinidir}/test_utils/edx_platform_mocks + palm: -c{toxinidir}/requirements/constraints-palm.txt + redwood: -c{toxinidir}/requirements/constraints-redwood.txt + -r{toxinidir}/requirements/test.in + -e{toxinidir}/test_utils/edx_platform_mocks_shared + palm: -e{toxinidir}/test_utils/edx_platform_mocks_palm + redwood: -e{toxinidir}/test_utils/edx_platform_mocks_redwood commands = - rm -Rf {toxinidir}/test_utils/edx_platform_mocks/fake_models/migrations + rm -Rf {toxinidir}/test_utils/edx_platform_mocks_shared/fake_models/migrations + rm -Rf {toxinidir}/test_utils/edx_platform_mocks_palm/fake_models/migrations + rm -Rf {toxinidir}/test_utils/edx_platform_mocks_redwood/fake_models/migrations python manage.py makemigrations fake_models python manage.py check - pytest {posargs} + pytest {posargs} --cov-config={env:PYTEST_COV_CONFIG} [testenv:docs] setenv = - DJANGO_SETTINGS_MODULE = test_settings + palm: DJANGO_SETTINGS_MODULE = test_settings_palm + redwood: DJANGO_SETTINGS_MODULE = test_settings_redwood PYTHONPATH = {toxinidir} # Adding the option here instead of as a default in the docs Makefile because that Makefile is generated by shpinx. SPHINXOPTS = -W @@ -58,7 +67,7 @@ allowlist_externals = make rm deps = - -r{toxinidir}/requirements/doc.txt + -r{toxinidir}/requirements/doc.in commands = doc8 --ignore-path docs/_build README.rst docs rm -f docs/futurex_openedx_extensions.rst @@ -71,20 +80,32 @@ commands = [testenv:quality] basepython = python3.8 deps = - -r{toxinidir}/requirements/quality.txt - -e{toxinidir}/test_utils/edx_platform_mocks + -c{toxinidir}/requirements/constraints-palm.txt + -r{toxinidir}/requirements/quality.in + -e{toxinidir}/test_utils/edx_platform_mocks_shared commands = flake8 futurex_openedx_extensions tests test_utils manage.py mypy futurex_openedx_extensions manage.py - pylint futurex_openedx_extensions tests test_utils manage.py pycodestyle futurex_openedx_extensions tests test_utils manage.py pydocstyle futurex_openedx_extensions tests test_utils manage.py - isort --check-only --diff tests test_utils manage.py futurex_openedx_extensions test_settings.py + + ; quality check for everything expect upgrade module. using palm mocks + ;(note: anything outside upgrade module is shared between all releases) + pip install -e {toxinidir}/test_utils/edx_platform_mocks_palm + pylint futurex_openedx_extensions tests test_utils manage.py --ignore-paths="^futurex_openedx_extensions/upgrade/" + ; quality check for upgrade module - palm only + pylint futurex_openedx_extensions/upgrade --ignore-paths="^futurex_openedx_extensions/upgrade/releases/(?!palm/).*" + ; quality check for upgrade module - redwood only + pip uninstall -y edx_platform_mocks_palm + pip install -e {toxinidir}/test_utils/edx_platform_mocks_redwood + pylint futurex_openedx_extensions/upgrade --ignore-paths="^futurex_openedx_extensions/upgrade/releases/(?!redwood/).*" + + isort --check-only --diff tests test_utils manage.py futurex_openedx_extensions test_settings_palm.py test_settings_redwood.py [testenv:pii_check] setenv = - DJANGO_SETTINGS_MODULE = test_settings + DJANGO_SETTINGS_MODULE = test_settings_palm deps = - -r{toxinidir}/requirements/test.txt + -r{toxinidir}/requirements/test.in commands = code_annotations django_find_annotations --config_file .pii_annotations.yml --lint --report --coverage