Skip to content

refactor: hoist annotations for common settings with differing values - #37800

Merged
wgu-taylor-payne merged 1 commit into
openedx:masterfrom
WGU-Open-edX:tpayne/hoist-common-annotations
Jan 9, 2026
Merged

refactor: hoist annotations for common settings with differing values#37800
wgu-taylor-payne merged 1 commit into
openedx:masterfrom
WGU-Open-edX:tpayne/hoist-common-annotations

Conversation

@wgu-taylor-payne

@wgu-taylor-payne wgu-taylor-payne commented Dec 20, 2025

Copy link
Copy Markdown
Contributor

Description

Hoist annotations for annotated settings with a type definition of the setting. There turned out to be four such settings that had differing values between the CMS and LMS common.py modules:

  • ENABLE_DISCUSSION_HOME_PANEL
  • ENABLE_MAX_FAILED_LOGIN_ATTEMPTS
  • MAINTENANCE_BANNER_TEXT
  • STUDIO_NAME

(EVENT_BUS_PRODUCER_CONFIG is another but the annotation will be brought up to the common module in #37746).

Supporting information

Closes #37281.

Testing instructions

In addition to mypy and unit tests, I ran make docs and verified the settings rendered correctly in docs/_build/html/references/settings.html and docs/_build/html/references/featuretoggles.html.

Deadline

None

Other information

ADR 0022 - Simplify Django Settings

@openedx-webhooks openedx-webhooks added open-source-contribution PR author is not from Axim or 2U core contributor PR author is a Core Contributor (who may or may not have write access to this repo). labels Dec 20, 2025
@openedx-webhooks

Copy link
Copy Markdown

Thanks for the pull request, @wgu-taylor-payne!

This repository is currently maintained by @openedx/wg-maintenance-edx-platform.

Once you've gone through the following steps feel free to tag them in a comment and let them know that your changes are ready for engineering review.

🔘 Get product approval

If you haven't already, check this list to see if your contribution needs to go through the product review process.

  • If it does, you'll need to submit a product proposal for your contribution, and have it reviewed by the Product Working Group.
    • This process (including the steps you'll need to take) is documented here.
  • If it doesn't, simply proceed with the next step.
🔘 Provide context

To help your reviewers and other members of the community understand the purpose and larger context of your changes, feel free to add as much of the following information to the PR description as you can:

  • Dependencies

    This PR must be merged before / after / at the same time as ...

  • Blockers

    This PR is waiting for OEP-1234 to be accepted.

  • Timeline information

    This PR must be merged by XX date because ...

  • Partner information

    This is for a course on edx.org.

  • Supporting documentation
  • Relevant Open edX discussion forum threads
🔘 Get a green build

If one or more checks are failing, continue working on your changes until this is no longer the case and your build turns green.

Details
Where can I find more information?

If you'd like to get more details on all aspects of the review process for open source pull requests (OSPRs), check out the following resources:

When can I expect my changes to be merged?

Our goal is to get community contributions seen and reviewed as efficiently as possible.

However, the amount of time that it takes to review and merge a PR can vary significantly based on factors such as:

  • The size and impact of the changes that it introduces
  • The need for product review
  • Maintenance status of the parent repository

💡 As a result it may take up to several weeks or months to complete a review and merge your PR.

@github-project-automation github-project-automation Bot moved this to Needs Triage in Contributions Dec 20, 2025
@wgu-taylor-payne wgu-taylor-payne added the mao-onboarding Reviewing this will help onboard devs from an Axim mission-aligned organization (MAO). label Dec 20, 2025
@mphilbrick211 mphilbrick211 moved this from Needs Triage to Ready for Review in Contributions Dec 22, 2025
@feanil
feanil requested review from feanil and removed request for kdmccormick January 9, 2026 17:42
@wgu-taylor-payne
wgu-taylor-payne force-pushed the tpayne/hoist-common-annotations branch from 83ce4e9 to 359b378 Compare January 9, 2026 19:31
@wgu-taylor-payne
wgu-taylor-payne merged commit d49de13 into openedx:master Jan 9, 2026
65 checks passed
@github-project-automation github-project-automation Bot moved this from Ready for Review to Done in Contributions Jan 9, 2026
@AhtishamShahid

AhtishamShahid commented Jan 14, 2026

Copy link
Copy Markdown
Contributor

This PR has caused the following error because the value for ENABLE_MAX_FAILED_LOGIN_ATTEMPTS is not set .

lms-1  | 2026-01-14 06:24:37,225 ERROR 23 [openedx.core.djangoapps.theming.helpers] [user None] [ip 110.39.173.34] helpers.py:209 - Theme not found in any of the themes dirs. [Theme 'indigo' not found in any of the following themes dirs, 
lms-1  | Theme dirs: 
lms-1  | [Path('/openedx/themes')]]
lms-1  | Traceback (most recent call last):
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
lms-1  |     response = get_response(request)
lms-1  |                ^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response
lms-1  |     response = wrapped_callback(request, *callback_args, **callback_kwargs)
lms-1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/opt/pyenv/versions/3.11.8/lib/python3.11/contextlib.py", line 81, in inner
lms-1  |     return func(*args, **kwds)
lms-1  |            ^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/views/decorators/csrf.py", line 65, in _view_wrapper
lms-1  |     return view_func(request, *args, **kwargs)
lms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/views/generic/base.py", line 105, in view
lms-1  |     return self.dispatch(request, *args, **kwargs)
lms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/utils/decorators.py", line 48, in _wrapper
lms-1  |     return bound_method(*args, **kwargs)
lms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/views/decorators/debug.py", line 143, in sensitive_post_parameters_wrapper
lms-1  |     return view(request, *args, **kwargs)
lms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/user_authn/views/login.py", line 777, in dispatch
lms-1  |     return super().dispatch(request, *args, **kwargs)
lms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 515, in dispatch
lms-1  |     response = self.handle_exception(exc)
lms-1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 475, in handle_exception
lms-1  |     self.raise_uncaught_exception(exc)
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 486, in raise_uncaught_exception
lms-1  |     raise exc
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 512, in dispatch
lms-1  |     response = handler(request, *args, **kwargs)
lms-1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/utils/decorators.py", line 48, in _wrapper
lms-1  |     return bound_method(*args, **kwargs)
lms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/utils/decorators.py", line 192, in _view_wrapper
lms-1  |     result = _process_exception(request, e)
lms-1  |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/utils/decorators.py", line 190, in _view_wrapper
lms-1  |     response = view_func(request, *args, **kwargs)
lms-1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/user_authn/views/login.py", line 773, in post
lms-1  |     return login_user(request, api_version)
lms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/utils/decorators.py", line 192, in _view_wrapper
lms-1  |     result = _process_exception(request, e)
lms-1  |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/utils/decorators.py", line 190, in _view_wrapper
lms-1  |     response = view_func(request, *args, **kwargs)
lms-1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/views/decorators/http.py", line 64, in inner
lms-1  |     return func(request, *args, **kwargs)
lms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django_ratelimit/decorators.py", line 27, in _wrapped
lms-1  |     return fn(request, *args, **kw)
lms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django_ratelimit/decorators.py", line 27, in _wrapped
lms-1  |     return fn(request, *args, **kw)
lms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/user_authn/views/login.py", line 593, in login_user
lms-1  |     _check_excessive_login_attempts(user)
lms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/user_authn/views/login.py", line 158, in _check_excessive_login_attempts
lms-1  |     if user and LoginFailures.is_feature_enabled():
lms-1  |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/edx-platform/common/djangoapps/student/models/user.py", line 974, in is_feature_enabled
lms-1  |     return settings.FEATURES['ENABLE_MAX_FAILED_LOGIN_ATTEMPTS']
lms-1  |            ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/edx-platform/openedx/core/lib/features_setting_proxy.py", line 30, in __getitem__
lms-1  |     return self.ns[key]
lms-1  |            ~~~~~~~^^^^^
lms-1  | KeyError: 'ENABLE_MAX_FAILED_LOGIN_ATTEMPTS'
lms-1  | 
lms-1  | During handling of the above exception, another exception occurred:
lms-1  | 
lms-1  | Traceback (most recent call last):
lms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/theming/helpers.py", line 204, in get_current_theme
lms-1  |     themes_base_dir=get_theme_base_dir(site_theme.theme_dir_name),
lms-1  |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/theming/helpers.py", line 242, in get_theme_base_dir
lms-1  |     raise ValueError(
lms-1  | ValueError: Theme 'indigo' not found in any of the following themes dirs, 
lms-1  | Theme dirs: 
lms-1  | [Path('/openedx/themes')]
lms-1  | 2026-01-14 06:24:37,226 ERROR 23 [django.request] [user None] [ip 110.39.173.34] log.py:253 - Internal Server Error: /api/user/v2/account/login_session/
lms-1  | Traceback (most recent call last):
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
lms-1  |     response = get_response(request)
lms-1  |                ^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response
lms-1  |     response = wrapped_callback(request, *callback_args, **callback_kwargs)
lms-1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/opt/pyenv/versions/3.11.8/lib/python3.11/contextlib.py", line 81, in inner
lms-1  |     return func(*args, **kwds)
lms-1  |            ^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/views/decorators/csrf.py", line 65, in _view_wrapper
lms-1  |     return view_func(request, *args, **kwargs)
lms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/views/generic/base.py", line 105, in view
lms-1  |     return self.dispatch(request, *args, **kwargs)
lms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/utils/decorators.py", line 48, in _wrapper
lms-1  |     return bound_method(*args, **kwargs)
lms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/views/decorators/debug.py", line 143, in sensitive_post_parameters_wrapper
lms-1  |     return view(request, *args, **kwargs)
lms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/user_authn/views/login.py", line 777, in dispatch
lms-1  |     return super().dispatch(request, *args, **kwargs)
lms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 515, in dispatch
lms-1  |     response = self.handle_exception(exc)
lms-1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 475, in handle_exception
lms-1  |     self.raise_uncaught_exception(exc)
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 486, in raise_uncaught_exception
lms-1  |     raise exc
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/rest_framework/views.py", line 512, in dispatch
lms-1  |     response = handler(request, *args, **kwargs)
lms-1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/utils/decorators.py", line 48, in _wrapper
lms-1  |     return bound_method(*args, **kwargs)
lms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/utils/decorators.py", line 192, in _view_wrapper
lms-1  |     result = _process_exception(request, e)
lms-1  |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/utils/decorators.py", line 190, in _view_wrapper
lms-1  |     response = view_func(request, *args, **kwargs)
lms-1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/user_authn/views/login.py", line 773, in post
lms-1  |     return login_user(request, api_version)
lms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/utils/decorators.py", line 192, in _view_wrapper
lms-1  |     result = _process_exception(request, e)
lms-1  |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/utils/decorators.py", line 190, in _view_wrapper
lms-1  |     response = view_func(request, *args, **kwargs)
lms-1  |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django/views/decorators/http.py", line 64, in inner
lms-1  |     return func(request, *args, **kwargs)
lms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django_ratelimit/decorators.py", line 27, in _wrapped
lms-1  |     return fn(request, *args, **kw)
lms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/venv/lib/python3.11/site-packages/django_ratelimit/decorators.py", line 27, in _wrapped
lms-1  |     return fn(request, *args, **kw)
lms-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/user_authn/views/login.py", line 593, in login_user
lms-1  |     _check_excessive_login_attempts(user)
lms-1  |   File "/openedx/edx-platform/openedx/core/djangoapps/user_authn/views/login.py", line 158, in _check_excessive_login_attempts
lms-1  |     if user and LoginFailures.is_feature_enabled():
lms-1  |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/edx-platform/common/djangoapps/student/models/user.py", line 974, in is_feature_enabled
lms-1  |     return settings.FEATURES['ENABLE_MAX_FAILED_LOGIN_ATTEMPTS']
lms-1  |            ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
lms-1  |   File "/openedx/edx-platform/openedx/core/lib/features_setting_proxy.py", line 30, in __getitem__
lms-1  |     return self.ns[key]
lms-1  |            ~~~~~~~^^^^^
lms-1  | KeyError: 'ENABLE_MAX_FAILED_LOGIN_ATTEMPTS'
lms-1  | [pid: 23|app: 0|req: 33/96] 172.18.0.4 () {68 vars in 1554 bytes} [Wed Jan 14 06:24:37 2026] POST /api/user/v2/account/login_session/ => generated 8507 bytes in 225 msecs (HTTP/1.1 500) 9 headers in 474 bytes (1 switches on core 0)

@wgu-taylor-payne

Copy link
Copy Markdown
Contributor Author

@AhtishamShahid Apologies for the oversight and thank you for reverting. I've created a new PR that doesn't contain this error.

anfbermudezme pushed a commit to Pearson-Advance/edx-platform that referenced this pull request Feb 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core contributor PR author is a Core Contributor (who may or may not have write access to this repo). mao-onboarding Reviewing this will help onboard devs from an Axim mission-aligned organization (MAO). open-source-contribution PR author is not from Axim or 2U

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

Hoist annotations of common settings to openedx/envs/common.py

5 participants