Repository navigation
refactor(settings): move the settings mechanism into the framework; SM009 catches dynamic imports (#500) - #564
Merged
Merged
Conversation
…work (#500) register_module_settings and ModuleSettingsRegistry move to simple_module_core.module_settings (registry created lazily on app.state), hydration to simple_module_core.settings_hydrate behind an OverrideSource protocol, secret-field masking to simple_module_core.secret_fields, and the Setting model, its constants, the read-only override queries and hydrate_settings_sync to simple_module_db.stored_settings. The table and its metadata owner are unchanged; no migration. The hosting layer imports these statically: the lifespan hydrates through a session-backed source, host settings always register, and the pre-app read and secret-key bootstrap build their SQL from the shared column constants. Boot works with the settings plugin disabled. build_module_metadata and the test schema collect settings_setting without the plugin. The plugin keeps its write path, admin UI and reload; its old modules re-export the moved objects (registration, module_registry and hydrate with a DeprecationWarning). Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4
…e framework (#500) The seven modules that reached settings.registration through importlib (users, file_storage, site_lock, api_tokens, tenants, background_tasks, keycloak) now import register_module_settings statically from simple_module_core.module_settings; branding, mail, background_tasks' worker and every test move off the deprecated plugin paths. Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4
…mework-500 # Conflicts: # CHANGELOG.md
Keep hydrate_settings' pre-#500 keyword name 'store' so keyword callers of the settings.hydrate shim keep working, and attribute the shims' DeprecationWarning to the importer instead of importlib's frozen frames. Claude-Session: https://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4
Deploying simple-module-python with
|
| Latest commit: |
fb15944
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://d1bdcd2e.simple-module-python.pages.dev |
| Branch Preview URL: | https://refactor-settings-framework.simple-module-python.pages.dev |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
…mework-500 # Conflicts: # CHANGELOG.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #500.
The framework couldn't boot without the
settingsplugin, but reached into it only throughimportlibstrings and raw SQL that SM009 couldn't see. Importing the plugin normally wasn't an option, becausesettingsalready depends onsimple_module_hosting. So the mechanism moves down into the framework, and the plugin keeps the admin UI and the write path.register_module_settings,ModuleSettingsRegistrysimple_module_core.module_settingsOverrideSourceprotocolsimple_module_core.settings_hydratesimple_module_core.secret_fieldsSettingmodel, table and column constants, read-only override queries,hydrate_settings_syncsimple_module_db.stored_settings_lifespan,_hydrate_stepand_settings_registrationimport statically._preapp_configand_secret_keybuild their SQL from the shared column constants instead of f-strings.settings_settingtable is unchanged. The migration environment and the test schema collect it explicitly, so it exists even when the plugin is turned off.settingsdisabled: registration, hydration and secret-key storage now keep working; only the admin pages go away. A new test covers a boot without the plugin.importlib.import_module,import_module,__import__andfind_speccalls whose literal name, or fixed f-string prefix, is a plugin package. Aliased imports count too. The repo itself has 0 hits.settings.registration,settings.module_registry,settings.hydrate,settings.models,settings._secretsand the moved names instoreandconstantsre-export the same objects. There is exactly oneSettingclass.DeprecationWarning, to be removed no earlier than 0.1.0.hydrate_settingskeeps itsstore=keyword.register_module_settingsthroughimportlibnow import it normally. Everything in the repo uses the new paths.make new-moduleandsmpytemplates now useDbBackedSettingsplusregister_module_settings.settingswill see autogenerate emitsettings_setting.Decisions from review
depends_on=[Settings]; changing module order belongs to Design: a user-directory protocol so modules stop importingusers.models(Keycloak installs break) #501;SettingsServices.module_registrykeeps its default factory, since it's a public constructor;Verification
make lintpasses.make test-py: 4995 passed, 22 skipped.make test-js: 668 passed.alembic checkreports no new operations; its only output is ausers_access_token.expires_attype difference that main reports too./health200.test_bg_outbox_eager_platform.py::test_eager_publish_from_a_plain_session_is_deliveredfailed once in each of two earlier full runs, with a 3 swait_fortimeout. It passed on its own 3 out of 3 times and in the later full runs, so it looks load-related, but that isn't proven./admin/settings/and/admin/doctor/: 9 passed, 0 P0–P2. It covered all 9 module cards, an edit that persists after reload, SMTP password masking, field errors on invalid values, and Doctor reporting no SM009. There were two P3 observations, both of which already happen on main:public_base_urlaccepts a non-URL, and a raw override accepts an unknown key.Test plan
alembic check)/admin/settings/edits still persist, and secrets stay maskedhttps://claude.ai/code/session_01M9neheZZEe3sVpDi2S3zT4