Conversation
- Remove deprecated FEATURES_MAP import (replaced with dynamic registration) - Update _register_missing_plugin_models method signature to remove feature_mixins_map parameter - Simplify _is_model_registered to use registry['models'] structure instead of feature-based checking - Bump version to 4.4.0.1 to reflect NetBox 4.4 compatibility Fixes ImportError: cannot import name 'FEATURES_MAP' from 'netbox.models.features' Related to NetBox issue #20129 - dynamic model feature registration system
WalkthroughRefactors plugin model registration by removing per-feature mapping, updating method signatures, and changing readiness flow to check registration directly against the NetBox registry["models"]. Adjusts NetboxPluginReloaderConfig.ready() call parameters accordingly. Bumps package version from 4.4.0 to 4.4.0.1. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Django as Django App Loader
participant NPRC as NetboxPluginReloaderConfig
participant Reg as NetBox Registry
participant Apps as Django App Registry
Django->>NPRC: ready()
note right of NPRC: Initialize plugin model registration
NPRC->>NPRC: _register_missing_plugin_models(plugins, Apps, Reg, register_models)
loop For each plugin model
NPRC->>NPRC: _is_model_registered(app_label, model_name, Reg)
alt Not registered
NPRC->>Reg: register_models(app_label, model)
note over NPRC,Reg: Add to registry["models"]
else Already registered
NPRC-->>NPRC: Skip
end
end
NPRC-->>Django: ready() complete
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Pre-merge checks (3 passed)✅ Passed checks (3 passed)
Poem
Tip 👮 Agentic pre-merge checks are now available in preview!Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
Example: reviews:
pre_merge_checks:
custom_checks:
- name: "Undocumented Breaking Changes"
mode: "warning"
instructions: |
Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).Please share your feedback with us on this Discord post. ✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull Request Overview
This PR updates the NetBox Plugin Reloader for compatibility with NetBox 4.4, addressing the removal of deprecated FEATURES_MAP import and adapting to the new dynamic model registration system.
- Remove deprecated FEATURES_MAP import that causes ImportError in NetBox 4.4
- Update model registration method to work with simplified registry structure
- Bump version to 4.4.0.1 to indicate NetBox 4.4 compatibility
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| netbox_plugin_reloader/version.py | Version bump to 4.4.0.1 for NetBox 4.4 compatibility |
| netbox_plugin_reloader/init.py | Remove FEATURES_MAP import and update model registration logic to use registry['models'] |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (4)
netbox_plugin_reloader/__init__.py (4)
44-44: Call site updated to new signature — LGTM; minor robustness note.Passing settings.PLUGINS directly works when entries match app labels. If any entry is a dotted module whose AppConfig.label differs, consider a fallback that resolves by AppConfig.name as well.
- plugin_app_config = app_registry.get_app_config(plugin_name) + try: + plugin_app_config = app_registry.get_app_config(plugin_name) + except LookupError: + # Fallback: resolve by AppConfig.name + plugin_app_config = next( + ac for ac in app_registry.get_app_configs() + if ac.name == plugin_name or ac.label == plugin_name + )
50-56: Docstring still mentions “feature registry”; update to “models registry.”Reflects the new approach that checks registry["models"] directly.
- Iterates through the provided list of plugin names, identifies models that are missing from the NetBox feature registry, and registers them using the supplied registration function. Prints errors encountered during processing and reports the number of models registered if any were missed. + Iterates through the provided list of plugin names, identifies models that are missing from the NetBox models registry, and registers them using the supplied registration function. Logs errors encountered during processing and reports the number of models registered if any were missed.
71-74: Prefer logging over print for operational visibility.Use NetBox/Django logging so messages surface in logs and are testable.
- if unregistered_models: - model_register_function(*unregistered_models) - print(f"Plugin Reloader: Registered {len(unregistered_models)} previously missed models") + if unregistered_models: + import logging + logger = logging.getLogger("netbox.plugins") + model_register_function(*unregistered_models) + logger.info("Plugin Reloader: Registered %d previously missed models", len(unregistered_models))- except Exception as e: - print(f"Error processing plugin {plugin_name}: {e}") + except Exception as e: + import logging + logging.getLogger("netbox.plugins").exception( + "Plugin Reloader: Error processing plugin %s", plugin_name + )
75-85: Make _is_model_registered more defensive.Guard against missing/empty stores and tolerate different container types under registry["models"][app_label].
- return app_label in registry["models"] and model_name in registry["models"][app_label] + return model_name in registry.get("models", {}).get(app_label, ())The “models” store exists in the application registry and is organized by app label. (netbox.readthedocs.io)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
netbox_plugin_reloader/__init__.py(4 hunks)netbox_plugin_reloader/version.py(1 hunks)
🔇 Additional comments (5)
netbox_plugin_reloader/version.py (1)
3-3: Verify version consistency across packaging metadata and PluginConfig
Ensure pyproject.toml, setup.cfg/setup.py and any PluginConfig.version references align with__version__ = "4.4.0.1".netbox_plugin_reloader/__init__.py (4)
29-31: No functional change.Nothing to review in this whitespace/doc chunk.
39-39: register_models import path is appropriate for 4.x.Importing register_models from netbox.models.features remains valid and is used by NetBox core/apps and community guidance. Keep as-is. (github.com)
63-67: Registration check simplification is correct.Using the models store instead of per-feature stores matches NetBox 4.4’s registry structure. (netbox.readthedocs.io)
86-111: Form field refresh remains aligned with NetBox 4.x.Using ContentTypeMultipleChoiceField for object type selection is consistent with current forms (e.g., EventRule forms) and continues to work in 4.x. No change needed. (github.com)
Fixes ImportError: cannot import name 'FEATURES_MAP' from 'netbox.models.features' Related to NetBox issue #20129 - dynamic model feature registration system
Summary by CodeRabbit
New Features
Bug Fixes
Refactor
Chores