* 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