fix(plugin): use app_name instead of plugin_path when deregistering models#11536
fix(plugin): use app_name instead of plugin_path when deregistering models#11536SchrodingersGat merged 7 commits intoinventree:masterfrom
Conversation
…odels _deactivate_mixin uses plugin_path (the full dotted module path) as the key into Django's apps.all_models when removing plugin models during reload. However, Django registers models under the app_label (the short app_name), not the full plugin_path. For plugins with nested module paths (e.g. "myplugin.myplugin"), plugin_path != app_name. Since apps.all_models is a defaultdict, looking up plugin_path silently creates an empty OrderedDict, then .pop(model) raises KeyError because the model was never in that dict — it was registered under app_name. This causes recurring KeyError crashes every plugin reload cycle (~1 minute) for any external plugin with a nested package structure. The fix: - Use app_name (already computed at line 98) instead of plugin_path - Add default None to .pop() for defensive safety - Consistent with line 123 which already correctly uses app_name
…eyerror fix(plugin): use app_name instead of plugin_path when deregistering models
✅ Deploy Preview for inventree-web-pui-preview canceled.
|
|
@nino-tan-smartee thank you for the PR; please add a unit test that ensures the fixed issues does not appear again |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #11536 +/- ##
=======================================
Coverage 88.06% 88.07%
=======================================
Files 1297 1297
Lines 59222 59239 +17
Branches 1934 1934
=======================================
+ Hits 52156 52172 +16
- Misses 6586 6587 +1
Partials 480 480
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
Ensures _deactivate_mixin uses app_name (last path component) instead of the full plugin_path when looking up models in apps.all_models, preventing KeyError for external plugins with nested module structures.
…eyerror test(plugin): add unit test for nested plugin path model deregistration
@matmair I added the unit test |
matmair
left a comment
There was a problem hiding this comment.
Thank you for this PR; good stuff
|
@nino-tan-smartee please confirm when you have successfully completed your test plan! |
nino-tan-smartee
left a comment
There was a problem hiding this comment.
Test plan confirmed — all items verified. Ready to merge.
|
@nino-tan-smartee thanks for confirming |
…odels (#11536) * fix(plugin): use app_name instead of plugin_path when deregistering models _deactivate_mixin uses plugin_path (the full dotted module path) as the key into Django's apps.all_models when removing plugin models during reload. However, Django registers models under the app_label (the short app_name), not the full plugin_path. For plugins with nested module paths (e.g. "myplugin.myplugin"), plugin_path != app_name. Since apps.all_models is a defaultdict, looking up plugin_path silently creates an empty OrderedDict, then .pop(model) raises KeyError because the model was never in that dict — it was registered under app_name. This causes recurring KeyError crashes every plugin reload cycle (~1 minute) for any external plugin with a nested package structure. The fix: - Use app_name (already computed at line 98) instead of plugin_path - Add default None to .pop() for defensive safety - Consistent with line 123 which already correctly uses app_name * test(plugin): add unit test for nested plugin path model deregistration Ensures _deactivate_mixin uses app_name (last path component) instead of the full plugin_path when looking up models in apps.all_models, preventing KeyError for external plugins with nested module structures. * style: fix ruff format for context manager parenthesization (cherry picked from commit 468f0f9)
💚 All backports created successfully
Questions ?Please refer to the Backport tool documentation and see the Github Action logs for details |
…odels (#11536) (#11553) * fix(plugin): use app_name instead of plugin_path when deregistering models _deactivate_mixin uses plugin_path (the full dotted module path) as the key into Django's apps.all_models when removing plugin models during reload. However, Django registers models under the app_label (the short app_name), not the full plugin_path. For plugins with nested module paths (e.g. "myplugin.myplugin"), plugin_path != app_name. Since apps.all_models is a defaultdict, looking up plugin_path silently creates an empty OrderedDict, then .pop(model) raises KeyError because the model was never in that dict — it was registered under app_name. This causes recurring KeyError crashes every plugin reload cycle (~1 minute) for any external plugin with a nested package structure. The fix: - Use app_name (already computed at line 98) instead of plugin_path - Add default None to .pop() for defensive safety - Consistent with line 123 which already correctly uses app_name * test(plugin): add unit test for nested plugin path model deregistration Ensures _deactivate_mixin uses app_name (last path component) instead of the full plugin_path when looking up models in apps.all_models, preventing KeyError for external plugins with nested module structures. * style: fix ruff format for context manager parenthesization (cherry picked from commit 468f0f9) Co-authored-by: nino-tan-smartee <nino.tan@smartsourcing.co>
Summary
_deactivate_mixinusesplugin_path(full dotted module path) as the key intoapps.all_modelswhen removing plugin models during reloadapp_label(shortapp_name), not the fullplugin_pathmyplugin.myplugin),plugin_path != app_nameapps.all_modelsis adefaultdict, looking upplugin_pathsilently creates an emptyOrderedDict, then.pop(model)raisesKeyErrorKeyErrorcrashes every plugin reload cycle (~1 minute) for any external plugin with a nested package structureFix
app_name(already computed at line 98) instead ofplugin_pathon line 118Noneto.pop()for defensive safetyapp_nameReproduction
purchase_quotation/purchase_quotation/)KeyError: '<model_name>'in error reports every plugin reload cycleTest plan