netbox-interface-name-rules 1.1.2__tar.gz → 1.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/PKG-INFO +7 -1
  2. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/README.md +6 -0
  3. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/__init__.py +4 -1
  4. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/api/serializers.py +17 -1
  5. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/api/views.py +2 -0
  6. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/engine.py +417 -192
  7. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/filters.py +7 -0
  8. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/forms.py +13 -0
  9. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/jobs.py +1 -0
  10. netbox_interface_name_rules-1.2.0/netbox_interface_name_rules/migrations/0009_interfacenamerule_enabled.py +19 -0
  11. netbox_interface_name_rules-1.2.0/netbox_interface_name_rules/migrations/0010_interfacenamerule_applies_to_device_interfaces.py +19 -0
  12. netbox_interface_name_rules-1.2.0/netbox_interface_name_rules/migrations/0011_remove_interfacenamerule_interfacenamerule_module_type_mode_check_and_more.py +39 -0
  13. netbox_interface_name_rules-1.2.0/netbox_interface_name_rules/migrations/0012_remove_interfacenamerule_interfacenamerule_unique_exact_and_more.py +39 -0
  14. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/models.py +68 -14
  15. netbox_interface_name_rules-1.2.0/netbox_interface_name_rules/signals.py +241 -0
  16. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/tables.py +56 -2
  17. netbox_interface_name_rules-1.2.0/netbox_interface_name_rules/tests/test_device_rules.py +285 -0
  18. netbox_interface_name_rules-1.2.0/netbox_interface_name_rules/tests/test_engine_advanced.py +680 -0
  19. netbox_interface_name_rules-1.2.0/netbox_interface_name_rules/tests/test_misc.py +466 -0
  20. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/tests/test_regex.py +10 -0
  21. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/tests/test_rules.py +26 -0
  22. netbox_interface_name_rules-1.2.0/netbox_interface_name_rules/tests/test_signals.py +258 -0
  23. netbox_interface_name_rules-1.2.0/netbox_interface_name_rules/tests/test_views.py +328 -0
  24. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/urls.py +1 -0
  25. netbox_interface_name_rules-1.2.0/netbox_interface_name_rules/utils.py +17 -0
  26. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/views.py +181 -107
  27. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules.egg-info/PKG-INFO +7 -1
  28. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules.egg-info/SOURCES.txt +10 -1
  29. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/pyproject.toml +25 -2
  30. netbox_interface_name_rules-1.1.2/netbox_interface_name_rules/signals.py +0 -78
  31. netbox_interface_name_rules-1.1.2/netbox_interface_name_rules/utils.py +0 -19
  32. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/LICENSE +0 -0
  33. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/api/__init__.py +0 -0
  34. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/api/urls.py +0 -0
  35. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/migrations/0001_initial.py +0 -0
  36. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/migrations/0002_regex_pattern_matching.py +0 -0
  37. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/migrations/0003_constraints.py +0 -0
  38. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/migrations/0004_nulls_distinct.py +0 -0
  39. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/migrations/0005_platform.py +0 -0
  40. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/migrations/0006_alter_interfacenamerule_options.py +0 -0
  41. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/migrations/0007_alter_optional_fks_set_null.py +0 -0
  42. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/migrations/0008_constraint_nonempty_pattern.py +0 -0
  43. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/migrations/__init__.py +0 -0
  44. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/navigation.py +0 -0
  45. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/tests/__init__.py +0 -0
  46. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/tests/test_api.py +0 -0
  47. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/tests/test_e2e.py +0 -0
  48. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules/tests/test_engine.py +0 -0
  49. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules.egg-info/dependency_links.txt +0 -0
  50. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/netbox_interface_name_rules.egg-info/top_level.txt +0 -0
  51. {netbox_interface_name_rules-1.1.2 → netbox_interface_name_rules-1.2.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: netbox-interface-name-rules
3
- Version: 1.1.2
3
+ Version: 1.2.0
4
4
  Summary: NetBox plugin for automatic interface renaming when modules are installed
5
5
  License-Expression: Apache-2.0
6
6
  Classifier: Programming Language :: Python :: 3
@@ -17,6 +17,7 @@ Dynamic: license-file
17
17
  [![PyPI](https://img.shields.io/pypi/v/netbox-interface-name-rules)](https://pypi.org/project/netbox-interface-name-rules/)
18
18
  [![PyPI - Downloads](https://img.shields.io/pypi/dm/netbox-interface-name-rules)](https://pypi.org/project/netbox-interface-name-rules/)
19
19
  [![CI](https://img.shields.io/github/actions/workflow/status/marcinpsk/netbox-InterfaceNameRules-plugin/test.yaml?branch=main&label=tests)](https://github.com/marcinpsk/netbox-InterfaceNameRules-plugin/actions/workflows/test.yaml)
20
+ [![Coverage](https://img.shields.io/endpoint?url=https://marcinpsk.github.io/netbox-InterfaceNameRules-plugin/coverage/badge.json)](https://marcinpsk.github.io/netbox-InterfaceNameRules-plugin/coverage/)
20
21
  [![License](https://img.shields.io/github/license/marcinpsk/netbox-InterfaceNameRules-plugin)](LICENSE)
21
22
  [![Python](https://img.shields.io/pypi/pyversions/netbox-interface-name-rules)](https://pypi.org/project/netbox-interface-name-rules/)
22
23
  [![NetBox](https://img.shields.io/badge/NetBox-%E2%89%A54.2.0-blue)](https://github.com/netbox-community/netbox)
@@ -71,6 +72,11 @@ PLUGINS = ['netbox_interface_name_rules']
71
72
 
72
73
  Apache 2.0
73
74
 
75
+ ## Documentation
76
+
77
+ - [Full documentation](https://marcinpsk.github.io/netbox-InterfaceNameRules-plugin/) — installation, configuration, examples
78
+ - [DeepWiki](https://deepwiki.com/marcinpsk/netbox-InterfaceNameRules-plugin) — AI-generated codebase overview
79
+
74
80
  ## Contributing
75
81
 
76
82
  See [CONTRIBUTING.md](CONTRIBUTING.md) for how to submit code or interface name rules.
@@ -3,6 +3,7 @@
3
3
  [![PyPI](https://img.shields.io/pypi/v/netbox-interface-name-rules)](https://pypi.org/project/netbox-interface-name-rules/)
4
4
  [![PyPI - Downloads](https://img.shields.io/pypi/dm/netbox-interface-name-rules)](https://pypi.org/project/netbox-interface-name-rules/)
5
5
  [![CI](https://img.shields.io/github/actions/workflow/status/marcinpsk/netbox-InterfaceNameRules-plugin/test.yaml?branch=main&label=tests)](https://github.com/marcinpsk/netbox-InterfaceNameRules-plugin/actions/workflows/test.yaml)
6
+ [![Coverage](https://img.shields.io/endpoint?url=https://marcinpsk.github.io/netbox-InterfaceNameRules-plugin/coverage/badge.json)](https://marcinpsk.github.io/netbox-InterfaceNameRules-plugin/coverage/)
6
7
  [![License](https://img.shields.io/github/license/marcinpsk/netbox-InterfaceNameRules-plugin)](LICENSE)
7
8
  [![Python](https://img.shields.io/pypi/pyversions/netbox-interface-name-rules)](https://pypi.org/project/netbox-interface-name-rules/)
8
9
  [![NetBox](https://img.shields.io/badge/NetBox-%E2%89%A54.2.0-blue)](https://github.com/netbox-community/netbox)
@@ -57,6 +58,11 @@ PLUGINS = ['netbox_interface_name_rules']
57
58
 
58
59
  Apache 2.0
59
60
 
61
+ ## Documentation
62
+
63
+ - [Full documentation](https://marcinpsk.github.io/netbox-InterfaceNameRules-plugin/) — installation, configuration, examples
64
+ - [DeepWiki](https://deepwiki.com/marcinpsk/netbox-InterfaceNameRules-plugin) — AI-generated codebase overview
65
+
60
66
  ## Contributing
61
67
 
62
68
  See [CONTRIBUTING.md](CONTRIBUTING.md) for how to submit code or interface name rules.
@@ -2,10 +2,12 @@
2
2
  # Copyright (C) 2025 Marcin Zieba <marcinpsk@gmail.com>
3
3
  from netbox.plugins import PluginConfig
4
4
 
5
- __version__ = "1.1.2"
5
+ __version__ = "1.2.0"
6
6
 
7
7
 
8
8
  class InterfaceNameRulesConfig(PluginConfig):
9
+ """NetBox plugin configuration for Interface Name Rules."""
10
+
9
11
  name = "netbox_interface_name_rules"
10
12
  verbose_name = "Interface Name Rules"
11
13
  description = "Automatic interface renaming when modules are installed into bays."
@@ -16,6 +18,7 @@ class InterfaceNameRulesConfig(PluginConfig):
16
18
  default_settings = {}
17
19
 
18
20
  def ready(self):
21
+ """Connect signal handlers after all apps are loaded."""
19
22
  super().ready()
20
23
  from . import signals # noqa: F401 — registers post_save handler
21
24
 
@@ -24,18 +24,30 @@ class InterfaceNameRuleSerializer(NetBoxModelSerializer):
24
24
  "channel_count",
25
25
  "channel_start",
26
26
  "description",
27
+ "enabled",
28
+ "applies_to_device_interfaces",
27
29
  ]
28
30
 
29
31
  def validate(self, attrs):
32
+ """Ensure module_type XOR module_type_pattern depending on regex mode."""
30
33
  attrs = super().validate(attrs)
31
34
  instance = self.instance
32
35
 
33
36
  # For PATCH requests, fall back to existing instance values for fields not in attrs
37
+ is_device_level = attrs.get(
38
+ "applies_to_device_interfaces", getattr(instance, "applies_to_device_interfaces", False)
39
+ )
34
40
  is_regex = attrs.get("module_type_is_regex", getattr(instance, "module_type_is_regex", False))
35
41
  module_type = attrs.get("module_type", getattr(instance, "module_type", None))
36
42
  pattern = attrs.get("module_type_pattern", getattr(instance, "module_type_pattern", ""))
37
43
 
38
- if is_regex:
44
+ if is_device_level:
45
+ # Device-level rules must not have a module_type FK
46
+ if module_type:
47
+ raise serializers.ValidationError(
48
+ {"module_type": "Module type must be empty for device-level interface rules."}
49
+ )
50
+ elif is_regex:
39
51
  if not pattern:
40
52
  raise serializers.ValidationError(
41
53
  {"module_type_pattern": "Regex pattern is required when regex mode is enabled."}
@@ -49,4 +61,8 @@ class InterfaceNameRuleSerializer(NetBoxModelSerializer):
49
61
  raise serializers.ValidationError(
50
62
  {"module_type": "module_type is required when regex mode is disabled."}
51
63
  )
64
+ if pattern:
65
+ raise serializers.ValidationError(
66
+ {"module_type_pattern": "Cannot set module_type_pattern when regex mode is disabled."}
67
+ )
52
68
  return attrs
@@ -8,5 +8,7 @@ from .serializers import InterfaceNameRuleSerializer
8
8
 
9
9
 
10
10
  class InterfaceNameRuleViewSet(NetBoxModelViewSet):
11
+ """REST API viewset for InterfaceNameRule."""
12
+
11
13
  queryset = InterfaceNameRule.objects.all()
12
14
  serializer_class = InterfaceNameRuleSerializer