Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 0.164.3 #3331

Merged
merged 3 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ repos:
- id: check-toml
- id: debug-statements
- repo: https://github.com/scop/pre-commit-shfmt
rev: v3.10.0-1
rev: v3.10.0-2
hooks:
- id: shfmt
- repo: https://github.com/adrienverge/yamllint.git
Expand Down Expand Up @@ -51,7 +51,7 @@ repos:
- --exclude-files
- "_test.js$"
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.7.4"
rev: "v0.8.1"
hooks:
- id: ruff-format
- id: ruff
Expand Down
6 changes: 6 additions & 0 deletions RELEASE.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
Release Notes
=============

Version 0.164.3
---------------

- feat: add emeritus api list view (#3329)
- [pre-commit.ci] pre-commit autoupdate (#3326)

Version 0.164.2 (Released December 02, 2024)
---------------

Expand Down
2 changes: 1 addition & 1 deletion authentication/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def process_exception(self, request, exception):
url = self.get_redirect_uri(request, exception)

if url: # noqa: RET503
url += ("?" in url and "&" or "?") + "message={}&backend={}".format( # noqa: UP032
url += (("?" in url and "&") or "?") + "message={}&backend={}".format( # noqa: UP032
quote(message), backend_name
)
return redirect(url)
2 changes: 1 addition & 1 deletion b2b_ecommerce/api_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@


@pytest.fixture(autouse=True)
def cybersource_settings(settings): # noqa: PT004
def cybersource_settings(settings):
"""
Set cybersource settings
"""
Expand Down
2 changes: 1 addition & 1 deletion b2b_ecommerce/views_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@


@pytest.fixture(autouse=True)
def ecommerce_settings(settings): # noqa: PT004
def ecommerce_settings(settings):
"""
Set cybersource settings
"""
Expand Down
4 changes: 2 additions & 2 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def pytest_configure(config):


@pytest.fixture(scope="session", autouse=True)
def clean_up_files(): # noqa: PT004
def clean_up_files():
"""
Fixture that removes the media root folder after the suite has finished running,
effectively deleting any files that were created by factories over the course of the test suite.
Expand All @@ -76,7 +76,7 @@ def clean_up_files(): # noqa: PT004


@pytest.fixture(scope="session")
def django_db_setup(django_db_setup, django_db_blocker): # noqa: ARG001, PT004
def django_db_setup(django_db_setup, django_db_blocker): # noqa: ARG001
"""
Creates all the index pages during the tests setup as index pages are required by the factories.
"""
Expand Down
6 changes: 6 additions & 0 deletions courses/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from rest_framework import routers

from courses.views import v1
from courses.views.v1 import EmeritusCourseListView

router = routers.SimpleRouter()
router.register(r"programs", v1.ProgramViewSet, basename="programs_api")
Expand All @@ -29,4 +30,9 @@
re_path(
r"^api/enrollments/", v1.UserEnrollmentsView.as_view(), name="user-enrollments"
),
path(
"api/emeritus_courses/",
EmeritusCourseListView.as_view(),
name="emeritus_courses",
),
]
24 changes: 23 additions & 1 deletion courses/views/v1/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from mitol.digitalcredentials.mixins import DigitalCredentialsRequestViewSetMixin
from rest_framework import status, viewsets
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.permissions import IsAdminUser, IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

Expand All @@ -27,6 +27,7 @@
ProgramEnrollmentSerializer,
ProgramSerializer,
)
from courses.sync_external_courses.emeritus_api import fetch_emeritus_courses
from ecommerce.models import Product


Expand Down Expand Up @@ -202,3 +203,24 @@ def get_queryset(self):
Returns parent topics with course count > 0.
"""
return CourseTopic.parent_topics_with_courses()


class EmeritusCourseListView(APIView):
"""
ReadOnly View to list Emeritus courses.
"""

permission_classes = [IsAdminUser]

def get(self, request, *args, **kwargs): # noqa: ARG002
"""
Get Emeritus courses list from the Emeritus API and return it.
"""
try:
data = fetch_emeritus_courses()
return Response(data, status=status.HTTP_200_OK)
except Exception as e: # noqa: BLE001
return Response(
{"error": "Some error occurred.", "details": str(e)},
status=status.HTTP_500_INTERNAL_SERVER_ERROR,
)
32 changes: 32 additions & 0 deletions courses/views_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
Tests for course views
"""

import json
import operator as op
from datetime import timedelta
from pathlib import Path

import pytest
from django.contrib.auth.models import AnonymousUser
Expand Down Expand Up @@ -611,3 +613,33 @@ def test_course_topics_api(client, django_assert_num_queries):
assert len(resp_json) == 1
assert resp_json[0]["name"] == parent_topic.name
assert resp_json[0]["course_count"] == 4


@pytest.mark.parametrize("expected_status_code", [200, 500])
def test_emeritus_course_list_view(admin_drf_client, mocker, expected_status_code):
"""
Test that the Emeritus API List calls fetch_emeritus_courses and returns its mocked response.
"""
if expected_status_code == 200:
with Path(
"courses/sync_external_courses/test_data/batch_test.json"
).open() as test_data_file:
mocked_response = json.load(test_data_file)["rows"]

patched_fetch_emeritus_courses = mocker.patch(
"courses.views.v1.fetch_emeritus_courses", return_value=mocked_response
)
else:
patched_fetch_emeritus_courses = mocker.patch(
"courses.views.v1.fetch_emeritus_courses",
side_effect=Exception("Some error occurred."),
)
mocked_response = {
"error": "Some error occurred.",
"details": "Some error occurred.",
}

response = admin_drf_client.get(reverse("emeritus_courses"))
assert response.json() == mocked_response
assert response.status_code == expected_status_code
patched_fetch_emeritus_courses.assert_called_once()
2 changes: 1 addition & 1 deletion ecommerce/api_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@


@pytest.fixture(autouse=True)
def cybersource_settings(settings): # noqa: PT004
def cybersource_settings(settings):
"""
Set cybersource settings
"""
Expand Down
2 changes: 1 addition & 1 deletion ecommerce/views_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def render_json(serializer):


@pytest.fixture(autouse=True)
def ecommerce_settings(settings): # noqa: PT004
def ecommerce_settings(settings):
"""
Set cybersource settings
"""
Expand Down
2 changes: 1 addition & 1 deletion fixtures/autouse.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@


@pytest.fixture(autouse=True)
def disable_hubspot_api(settings): # noqa: PT004
def disable_hubspot_api(settings):
"""Disable Hubspot API by default for tests"""
settings.MITOL_HUBSPOT_API_PRIVATE_TOKEN = None
2 changes: 1 addition & 1 deletion fixtures/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def valid_address_dict():


@pytest.fixture
def nplusone_fail(settings): # noqa: PT004
def nplusone_fail(settings):
"""Configures the nplusone app to raise errors"""
settings.NPLUSONE_RAISE = True

Expand Down
2 changes: 1 addition & 1 deletion hubspot_xpro/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ def get_hubspot_id_for_object(
return hubspot_obj.id
elif raise_error:
raise ValueError(
"Hubspot id could not be found for %s for id %d"
"Hubspot id could not be found for %s for id %d" # noqa: UP031
% (content_type.name, obj.id)
)

Expand Down
2 changes: 1 addition & 1 deletion mail/api_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@


@pytest.fixture
def email_settings(settings): # noqa: PT004
def email_settings(settings):
"""Default settings for email tests"""
settings.MAILGUN_RECIPIENT_OVERRIDE = None

Expand Down
2 changes: 1 addition & 1 deletion mitxpro/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from mitxpro.celery_utils import OffsettingSchedule
from mitxpro.sentry import init_sentry

VERSION = "0.164.2"
VERSION = "0.164.3"

env.reset()

Expand Down
2 changes: 1 addition & 1 deletion sheets/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@


@pytest.fixture(autouse=True)
def sheets_settings(settings): # noqa: PT004
def sheets_settings(settings):
"""Default settings for sheets tests"""
settings.FEATURES["COUPON_SHEETS"] = True
settings.SHEETS_REQ_EMAIL_COL = 7
Expand Down
2 changes: 1 addition & 1 deletion sheets/coupon_request_api_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@


@pytest.fixture
def courseware_objects(): # noqa: PT004
def courseware_objects():
"""Database objects that CSV data depends on"""
run = CourseRunFactory.create(courseware_id="course-v1:edX+DemoX+Demo_Course")
ProductVersionFactory.create(product__content_object=run)
Expand Down
Loading