Skip to content

feat: migrate callers off FEATURES-as-dict access - #38772

Merged
feanil merged 30 commits into
masterfrom
feanil/features-dict-migration
Jul 13, 2026
Merged

feat: migrate callers off FEATURES-as-dict access#38772
feanil merged 30 commits into
masterfrom
feanil/features-dict-migration

Conversation

@feanil

@feanil feanil commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Second PR in the FEATURES-as-dict migration stack. #38818 (the bridge) is merged.

Per-flag refactor: commits that move callers off settings.FEATURES['X'] / patch.dict(settings.FEATURES, …) and onto settings.X / @override_settings(X=…). The underlying flat settings already exist in lms/envs/common.py, cms/envs/common.py, and the shared openedx/envs/common.py — the env files were previously flattened, so this PR only touches call sites (plus a few flag definitions that needed to move into the shared file).

settings.X vs getattr(settings, 'X', <default>)

Most reads drop the getattr fallback in favor of a bare settings.X — but not all. The rule is: a bare settings.X requires that the setting be defined in the common.py file of every process that can reach the read.

  • Setting defined in openedx/envs/common.py (shared, imported by both LMS and CMS) — use bare settings.X at every caller.
  • Setting defined only in lms/envs/common.py — use bare settings.X only if the caller is exclusively reachable from the LMS process. If the caller lives under common/djangoapps/ or openedx/core/ and can be pulled in by CMS test collection or CMS request handling, keep getattr(settings, 'X', <default>) so CMS doesn't AttributeError.
  • Setting defined only in cms/envs/common.py — the mirror rule. Bare settings.X at CMS-only callers; getattr at shared/LMS-reachable callers. This deliberately keeps Studio-only concepts (e.g. ENABLE_CREATOR_GROUP, DISABLE_COURSE_CREATION) from leaking into LMS settings.
  • Setting not previously defined anywhere — the migration adds an explicit definition (with a proper .. toggle_name: / .. setting_name: annotation) in the smallest common file that covers all callers, then drops getattr at the call sites.

hasattr(settings, 'X') is used in a few module-load contexts (test util constants) where we specifically want "is the setting defined" rather than "what is its value" — safe against a missing setting on either process.

Stack:

@feanil
feanil force-pushed the feanil/fix-deprecation-warnings branch from 1b8c4e8 to 7f5dbc2 Compare June 16, 2026 18:52
@feanil
feanil force-pushed the feanil/features-dict-migration branch 3 times, most recently from 9ffdb02 to f9359f9 Compare June 17, 2026 14:27
Base automatically changed from feanil/fix-deprecation-warnings to master June 17, 2026 15:33
@feanil
feanil force-pushed the feanil/features-dict-migration branch 4 times, most recently from 60dd592 to 4ecd09f Compare June 23, 2026 18:42
@feanil
feanil force-pushed the feanil/features-dict-migration branch 4 times, most recently from 858d762 to 346382f Compare June 26, 2026 19:30
@feanil
feanil changed the base branch from master to feanil/features-dict-bridge June 26, 2026 19:31
@feanil
feanil force-pushed the feanil/features-dict-migration branch from 346382f to 520006a Compare June 26, 2026 19:59

@kdmccormick kdmccormick left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good once rebased & green.

As I mentioned before I dislike all the new getattr invocations, but I've come around that it's the right way to push through this FEATURES refactor. I wrote up a followup ticket which we can put into the config simplification epic somewhere post-FEATURES-refactor #38861

Comment on lines 11 to +12
TPA_FEATURES_KEY = 'ENABLE_THIRD_PARTY_AUTH'
TPA_FEATURE_ENABLED = TPA_FEATURES_KEY in settings.FEATURES
TPA_FEATURE_ENABLED = hasattr(settings, TPA_FEATURES_KEY)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not your problem to fix, but 🤮🤮🤮

@feanil
feanil force-pushed the feanil/features-dict-bridge branch from 3a686d6 to 1299ef1 Compare July 9, 2026 13:57
@feanil
feanil force-pushed the feanil/features-dict-migration branch from 520006a to 20636c5 Compare July 9, 2026 14:03
Base automatically changed from feanil/features-dict-bridge to master July 9, 2026 14:21
@feanil
feanil force-pushed the feanil/features-dict-migration branch 4 times, most recently from df5644a to 7009266 Compare July 10, 2026 13:58
feanil and others added 3 commits July 10, 2026 16:47
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Production reads use getattr(settings, ...); tests use
@override_settings(ENABLE_CREATOR_GROUP=...). Mixed-flag patches keep the
other flag in patch.dict until its own migration.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Production reads use getattr(settings, ...); tests use
  @override_settings(CERTIFICATES_HTML_VIEW=...).
- Drop now-unused FEATURES_WITH_CERTS_ENABLED/_DISABLED helpers.
- FEATURES_WITH_CUSTOM_CERTS_ENABLED keeps CUSTOM_CERTIFICATE_TEMPLATES_ENABLED
  until that flag migrates.
- Mixed-flag patches keep the other flag in patch.dict.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@feanil
feanil force-pushed the feanil/features-dict-migration branch 2 times, most recently from 113517b to 873ee59 Compare July 10, 2026 21:05
feanil and others added 4 commits July 13, 2026 08:54
…s-dict

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Flat setting was already being assigned to via the instructor plugin's
plugin_settings hook (settings.MAX_ENROLLMENT_INSTR_BUTTONS = 200) — only
the readers were still going through settings.FEATURES.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@feanil
feanil force-pushed the feanil/features-dict-migration branch from 1f85e3b to 4c7f254 Compare July 13, 2026 12:55
@feanil
feanil marked this pull request as ready for review July 13, 2026 12:56
@feanil
feanil requested review from a team, farhan, irtazaakram and salman2013 as code owners July 13, 2026 12:56
@feanil
feanil enabled auto-merge (rebase) July 13, 2026 12:58
feanil and others added 2 commits July 13, 2026 09:33
…as-dict

Flat setting was already being assigned in the instructor plugin's
plugin_settings hook — only the two readers were still going through
settings.FEATURES.get. Also fixes the annotation that read
FEATURES['ENABLE_CERTIFICATES_INSTRUCTOR_MANAGE] (missing closing quote,
wrong location).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…dict

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants