Skip to content

Commit 9a58b59

Browse files
Faraz32123claude
andcommitted
feat: configure drf-spectacular on LMS for enrollment API schema generation
Adds drf-spectacular support to LMS so the openedx-platform-sdk can generate enrollment v2 API bindings from a proper LMS schema rather than mounting enrollment URLs in CMS as a workaround. Changes: - openedx/envs/common.py: add DEFAULT_SCHEMA_CLASS to REST_FRAMEWORK so drf-spectacular's AutoSchema is used across all LMS environments - lms/envs/common.py: add drf_spectacular to INSTALLED_APPS - lms/lib/spectacular.py: preprocessing hook that filters to enrollment v2 endpoints only (/api/enrollment/v\d+/) - lms/envs/devstack.py, lms/envs/production.py: SPECTACULAR_SETTINGS with path prefix trim and enrollment-only title - lms/urls.py: expose schema at /lms-api/schema/ via SpectacularAPIView - cms/lib/spectacular.py: revert enrollment URL workaround (no longer needed) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 794c440 commit 9a58b59

7 files changed

Lines changed: 57 additions & 3 deletions

File tree

cms/lib/spectacular.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@ def cms_api_filter(endpoints):
1212
CMS_PATH_PATTERN = re.compile(r"^/api/contentstore/v\d+/")
1313

1414
for path, path_regex, method, callback in endpoints:
15-
if CMS_PATH_PATTERN.match(path) or (
16-
path.startswith("/api/courses/")
17-
and "bulk_enable_disable_discussions" in path
15+
if (
16+
CMS_PATH_PATTERN.match(path)
17+
or (
18+
path.startswith("/api/courses/")
19+
and "bulk_enable_disable_discussions" in path
20+
)
1821
):
1922
filtered.append((path, path_regex, method, callback))
2023

lms/envs/common.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2040,6 +2040,7 @@
20402040

20412041
# API Documentation
20422042
'drf_yasg',
2043+
'drf_spectacular',
20432044

20442045
# edx-drf-extensions
20452046
'csrf.apps.CsrfAppConfig', # Enables frontend apps to retrieve CSRF tokens.

lms/envs/devstack.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,19 @@ def should_show_debug_toolbar(request): # pylint: disable=missing-function-docs
582582
'COMPLETE',
583583
]
584584

585+
###################### drf-spectacular (LMS enrollment schema) ######################
586+
SPECTACULAR_SETTINGS = {
587+
'TITLE': 'LMS Enrollment API',
588+
'VERSION': '0.1.0',
589+
'SERVE_INCLUDE_SCHEMA': False,
590+
'PREPROCESSING_HOOKS': ['lms.lib.spectacular.lms_api_filter'],
591+
'SCHEMA_PATH_PREFIX': '/api/enrollment',
592+
'SCHEMA_PATH_PREFIX_TRIM': '/api/enrollment',
593+
'SERVERS': [
594+
{'url': LMS_ROOT_URL, 'description': 'Local'}, # noqa: F405
595+
],
596+
}
597+
585598
################# New settings must go ABOVE this line #################
586599
########################################################################
587600
# See if the developer has any local overrides.

lms/envs/production.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,19 @@ def get_env_setting(setting):
397397
MIDDLEWARE.extend(_YAML_TOKENS.get('EXTRA_MIDDLEWARE_CLASSES', [])) # noqa: F405
398398

399399

400+
###################### drf-spectacular (LMS enrollment schema) ######################
401+
SPECTACULAR_SETTINGS = {
402+
'TITLE': 'LMS Enrollment API',
403+
'VERSION': '0.1.0',
404+
'SERVE_INCLUDE_SCHEMA': False,
405+
'PREPROCESSING_HOOKS': ['lms.lib.spectacular.lms_api_filter'],
406+
'SCHEMA_PATH_PREFIX': '/api/enrollment',
407+
'SCHEMA_PATH_PREFIX_TRIM': '/api/enrollment',
408+
'SERVERS': [
409+
{'url': LMS_ROOT_URL, 'description': 'Local'}, # noqa: F405
410+
],
411+
}
412+
400413
#######################################################################################################################
401414
#### DERIVE ANY DERIVED SETTINGS
402415
####

lms/lib/spectacular.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
"""Helper functions for drf-spectacular (LMS schema)."""
2+
3+
import re
4+
5+
6+
def lms_api_filter(endpoints):
7+
"""
8+
Pre-processing hook: keep only enrollment v2 endpoints tagged for the SDK.
9+
"""
10+
filtered = []
11+
ENROLLMENT_PATH_PATTERN = re.compile(r"^/api/enrollment/v\d+/")
12+
13+
for path, path_regex, method, callback in endpoints:
14+
if ENROLLMENT_PATH_PATTERN.match(path):
15+
filtered.append((path, path_regex, method, callback))
16+
17+
return filtered

lms/urls.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from django.contrib import admin
99
from django.contrib.admin import autodiscover as django_autodiscover
1010
from django.urls import include, path, re_path
11+
from drf_spectacular.views import SpectacularAPIView
1112
from django.utils.translation import gettext_lazy as _
1213
from django.views.generic.base import RedirectView
1314
from edx_api_doc_tools import make_docs_urls
@@ -1068,3 +1069,8 @@
10681069
urlpatterns += [
10691070
path('xqueue/', include((submissions_urls, 'submissions'), namespace='submissions')),
10701071
]
1072+
1073+
# LMS API schema for openedx-platform-sdk generation.
1074+
urlpatterns += [
1075+
path('lms-api/schema/', SpectacularAPIView.as_view(), name='lms-schema'),
1076+
]

openedx/envs/common.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,7 @@ def add_optional_apps(optional_apps, installed_apps):
836836
'registration_validation': '30/minute',
837837
'high_service_user': '2000/minute',
838838
},
839+
'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
839840
}
840841

841842
# .. setting_name: REGISTRATION_VALIDATION_RATELIMIT

0 commit comments

Comments
 (0)