diff --git a/README.md b/README.md index 242ef15..5561b10 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,11 @@ Ab Version `0.10.3` kann dort optional eine VLAN-Gruppe ausgewählt werden. Sie dient als dynamischer Filter für die VLAN-Mehrfachauswahl und wird nicht als zusätzliche Eigenschaft der Verbindung gespeichert. +Ab Version `0.10.4` verwendet die Patchpanel-Automatik die numerische +Portkennung unabhängig von zusätzlichen Bezeichnungen wie `LC`, `Front` oder +`Rear`. Damit werden auch kleinere LC/LC-Patchpanels, etwa mit sechs Ports, +fortlaufend eins-zu-eins zugeordnet. + ## Kompatibilität - NetBox `>=4.6.5,<4.7` diff --git a/netbox_utilities/__init__.py b/netbox_utilities/__init__.py index fe72679..419e17a 100644 --- a/netbox_utilities/__init__.py +++ b/netbox_utilities/__init__.py @@ -1,6 +1,6 @@ from netbox.plugins import PluginConfig, get_plugin_config -__version__ = "0.10.3" +__version__ = "0.10.4" class NetBoxUtilitiesConfig(PluginConfig): diff --git a/netbox_utilities/patchpanel.py b/netbox_utilities/patchpanel.py index 9d5a6f5..401f64e 100644 --- a/netbox_utilities/patchpanel.py +++ b/netbox_utilities/patchpanel.py @@ -26,6 +26,9 @@ def port_identifier(port): name = str(getattr(port, "name", "")).casefold() name = re.sub(r"\b(?:front|rear)(?:[\s_-]*port)?(?=\b|\d)", " ", name) name = re.sub(r"^(?:fp|rp|f|r)(?=\s*[-_.:/]?\s*\d)", "", name) + numbers = tuple(int(token) for token in re.findall(r"\d+", name)) + if numbers: + return numbers tokens = re.findall(r"\d+|[^\W\d_]+", name) identifier = tuple(int(token) if token.isdigit() else token for token in tokens) return identifier or None diff --git a/netbox_utilities/tests/test_patchpanel_lc.py b/netbox_utilities/tests/test_patchpanel_lc.py new file mode 100644 index 0000000..3362542 --- /dev/null +++ b/netbox_utilities/tests/test_patchpanel_lc.py @@ -0,0 +1,34 @@ +from types import SimpleNamespace + +from django.test import SimpleTestCase + +from netbox_utilities.patchpanel import pair_ports, port_identifier + + +def port(pk, name): + return SimpleNamespace(pk=pk, name=name) + + +class LCPatchpanelPairingTest(SimpleTestCase): + def test_uses_numeric_identifier_despite_connector_labels(self): + self.assertEqual(port_identifier(port(1, "LC Front 01")), (1,)) + self.assertEqual(port_identifier(port(2, "Rear 1")), (1,)) + + def test_pairs_all_six_lc_ports_by_number(self): + front_ports = [port(number, f"LC Front {number}") for number in range(1, 7)] + rear_ports = [port(100 + number, f"Rear {number}") for number in range(1, 7)] + + pairs = pair_ports(front_ports, rear_ports) + + self.assertEqual( + [(front.pk, rear.pk) for front, rear in pairs], + [(number, 100 + number) for number in range(1, 7)], + ) + + def test_keeps_compound_numeric_identifiers_distinct(self): + front_ports = [port(12, "Cassette 1 LC 2"), port(13, "Cassette 1 LC 3")] + rear_ports = [port(112, "Rear 1/2"), port(113, "Rear 1/3")] + + pairs = pair_ports(front_ports, rear_ports) + + self.assertEqual([(front.pk, rear.pk) for front, rear in pairs], [(12, 112), (13, 113)]) diff --git a/netbox_utilities/tests/test_reorder_rack.py b/netbox_utilities/tests/test_reorder_rack.py index 7a317e7..75aaa02 100644 --- a/netbox_utilities/tests/test_reorder_rack.py +++ b/netbox_utilities/tests/test_reorder_rack.py @@ -449,7 +449,7 @@ class ReorderRackFrontendTest(SimpleTestCase): self.assertEqual(template_name, "netbox_utilities/reorder_rack.html") self.assertEqual(context["reorder_devices"][0]["label"], "LEO-Fritzbox") self.assertEqual(context["reorder_devices"][0]["grid_width"], 6) - self.assertEqual(context["asset_version"], "0.10.3") + self.assertEqual(context["asset_version"], "0.10.4") self.assertIs(context["reorder_rack_width_data"], get_width_data.return_value) get_width_data.assert_called_once() self.assertIs(get_width_data.call_args.kwargs["rack"], rack) diff --git a/netbox_utilities/tests/test_topology_views.py b/netbox_utilities/tests/test_topology_views.py index b7e86a0..9d8b49d 100644 --- a/netbox_utilities/tests/test_topology_views.py +++ b/netbox_utilities/tests/test_topology_views.py @@ -246,7 +246,7 @@ class TopologyViewsRackWidthTest(SimpleTestCase): self.assertIn('id="netbox-utilities-topology-rack-width-styles"', html) self.assertIn('.rack-device[href="/dcim/devices/334/"]', html) self.assertIn("left: calc(50% + 3px) !important", html) - self.assertIn("netbox_utilities/topology-rack-width.js?v=0.10.3", html) + self.assertIn("netbox_utilities/topology-rack-width.js?v=0.10.4", html) self.assertIn("left:calc(0% + 3px)!important", html) self.assertIn("left:calc(50% + 3px)!important", html) self.assertIn("width:calc(50% - 6px)!important", html) diff --git a/pyproject.toml b/pyproject.toml index 26852df..9dc1a9b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "netbox-utilities" -version = "0.10.3" +version = "0.10.4" description = "Navigation, tenant utilities, connection VLANs, partial-width racks, and bulk operations for NetBox 4.6" readme = "README.md" requires-python = ">=3.12"