From 825f2870ea3e27b26f1051b55791577fa500f17e Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Fri, 1 Mar 2024 10:25:45 -0600 Subject: [PATCH 01/26] feat: Add method to sort list of CIDRs --- netutils/ip.py | 20 ++++++++++++++++++++ netutils/utils.py | 1 + tests/unit/test_ip.py | 12 ++++++++++++ 3 files changed, 33 insertions(+) diff --git a/netutils/ip.py b/netutils/ip.py index 7926e3c5..8bf0d70b 100644 --- a/netutils/ip.py +++ b/netutils/ip.py @@ -1,4 +1,5 @@ """Functions for working with IP addresses.""" + import ipaddress import typing as t from operator import attrgetter @@ -596,3 +597,22 @@ def get_usable_range(ip_network: str) -> str: lower_bound = str(net[1]) upper_bound = str(net[-2]) return f"{lower_bound} - {upper_bound}" + + +def sort_list_cidrs(cidr_list: str) -> str: + """Given a concatenated list of CIDRs sorts them into the correct order and returns as concatenated string. + + Args: + cidr_list (str): Concatenated string list of CIDRs. + + Returns: + str: Sorted list of CIDRs. + """ + if "," not in cidr_list: + raise ValueError("Not a concatenated list of CIDRs as expected.") + return ",".join( + [ + obj.with_prefixlen + for obj in sorted([ipaddress.ip_network(cidr) for cidr in cidr_list.replace(" ", "").split(",")]) + ] + ) diff --git a/netutils/utils.py b/netutils/utils.py index 82677419..a2f8cfdc 100644 --- a/netutils/utils.py +++ b/netutils/utils.py @@ -91,6 +91,7 @@ "os_platform_object_builder": "platform_mapper.os_platform_object_builder", "juniper_junos_version_parser": "os_version.juniper_junos_version_parser", "hash_data": "hash.hash_data", + "sort_list_cidrs": "ip.sort_list_cidrs", } diff --git a/tests/unit/test_ip.py b/tests/unit/test_ip.py index f3898382..1d645a00 100644 --- a/tests/unit/test_ip.py +++ b/tests/unit/test_ip.py @@ -1,4 +1,5 @@ """Test for the IP functions.""" + import ipaddress import pytest @@ -617,3 +618,14 @@ def test_ipaddress_network(data): @pytest.mark.parametrize("data", IS_CLASSFUL) def test_is_classful(data): assert ip.is_classful(**data["sent"]) == data["received"] + + +def test_sort_list_cidrs(): + sent = "10.0.10.0/24, 10.0.100.0/24, 10.0.12.0/24, 10.0.200.0/24" + expected = "10.0.10.0/24,10.0.12.0/24,10.0.100.0/24,10.0.200.0/24" + assert expected == ip.sort_list_cidrs(sent) + + +def test_sort_list_cidrs_exception(): + with pytest.raises(ValueError, match="Not a concatenated list of CIDRs as expected."): + ip.sort_list_cidrs("10.1.1.1/24 10.2.2.2/16") From 0806d6409ad50b0f3d46b8c206d3f2b68d23a14c Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Fri, 1 Mar 2024 10:32:47 -0600 Subject: [PATCH 02/26] docs: Update docs --- docs/user/include_jinja_list.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/user/include_jinja_list.md b/docs/user/include_jinja_list.md index 7c67d29a..3ff36878 100644 --- a/docs/user/include_jinja_list.md +++ b/docs/user/include_jinja_list.md @@ -51,6 +51,7 @@ | is_netmask | netutils.ip.is_netmask | | is_network | netutils.ip.is_network | | netmask_to_cidr | netutils.ip.netmask_to_cidr | +| sort_list_cidrs | netutils.ip.sort_list_cidrs | | get_napalm_getters | netutils.lib_helpers.get_napalm_getters | | get_oui | netutils.mac.get_oui | | is_valid_mac | netutils.mac.is_valid_mac | From ebca83dd7469d8a201ebdb6147a783f91b58db97 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Fri, 1 Mar 2024 10:57:19 -0600 Subject: [PATCH 03/26] feat: Update method to handle list of strings --- netutils/ip.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/netutils/ip.py b/netutils/ip.py index 8bf0d70b..1e6eccde 100644 --- a/netutils/ip.py +++ b/netutils/ip.py @@ -599,20 +599,20 @@ def get_usable_range(ip_network: str) -> str: return f"{lower_bound} - {upper_bound}" -def sort_list_cidrs(cidr_list: str) -> str: +def sort_list_cidrs(cidr_list: t.Union[str, t.List[str]]) -> str: """Given a concatenated list of CIDRs sorts them into the correct order and returns as concatenated string. Args: - cidr_list (str): Concatenated string list of CIDRs. + cidr_list (t.Union[str, t.List[str]]): Concatenated string list of CIDRs or list of CIDR strings. Returns: str: Sorted list of CIDRs. """ - if "," not in cidr_list: + cidrs = [] + if isinstance(cidr_list, list): + cidrs = cidr_list + elif (isinstance(cidr_list, str) and "," not in cidr_list) or not isinstance(cidr_list, str): raise ValueError("Not a concatenated list of CIDRs as expected.") - return ",".join( - [ - obj.with_prefixlen - for obj in sorted([ipaddress.ip_network(cidr) for cidr in cidr_list.replace(" ", "").split(",")]) - ] - ) + elif isinstance(cidr_list, str): + cidrs = cidr_list.replace(" ", "").split(",") + return ",".join([obj.with_prefixlen for obj in sorted([ipaddress.ip_network(cidr) for cidr in cidrs])]) From 88b581623dabc4b9a615284e732e5973bc51e30d Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Fri, 1 Mar 2024 11:00:22 -0600 Subject: [PATCH 04/26] test: Update tests for new function --- tests/unit/test_ip.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/unit/test_ip.py b/tests/unit/test_ip.py index 1d645a00..7ea47a1e 100644 --- a/tests/unit/test_ip.py +++ b/tests/unit/test_ip.py @@ -626,6 +626,17 @@ def test_sort_list_cidrs(): assert expected == ip.sort_list_cidrs(sent) -def test_sort_list_cidrs_exception(): +def test_sort_list_cidrs_using_list(): + sent = ["10.0.10.0/24", "10.0.100.0/24", "10.0.12.0/24", "10.0.200.0/24"] + expected = "10.0.10.0/24,10.0.12.0/24,10.0.100.0/24,10.0.200.0/24" + assert expected == ip.sort_list_cidrs(sent) + + +def test_sort_list_cidrs_exception_invalid_list(): with pytest.raises(ValueError, match="Not a concatenated list of CIDRs as expected."): ip.sort_list_cidrs("10.1.1.1/24 10.2.2.2/16") + + +def test_sort_list_cidrs_exception_invalid_instance_type(): + with pytest.raises(ValueError, match="Not a concatenated list of CIDRs as expected."): + ip.sort_list_cidrs({"10.1.1.1/24", "10.2.2.2/16"}) From 7084b0d87427bc32395dc170ae3229cd7c8eb5c1 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Fri, 1 Mar 2024 11:22:08 -0600 Subject: [PATCH 05/26] test: Add test sorting CIDRs with same network but differing masks. --- tests/unit/test_ip.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/unit/test_ip.py b/tests/unit/test_ip.py index 7ea47a1e..3a6f39a2 100644 --- a/tests/unit/test_ip.py +++ b/tests/unit/test_ip.py @@ -626,6 +626,12 @@ def test_sort_list_cidrs(): assert expected == ip.sort_list_cidrs(sent) +def test_sort_list_cidrs_same_base(): + sent = "10.0.0.0/24, 10.0.0.0/16, 10.0.0.0/18" + expected = "10.0.0.0/16,10.0.0.0/18,10.0.0.0/24" + assert expected == ip.sort_list_cidrs(sent) + + def test_sort_list_cidrs_using_list(): sent = ["10.0.10.0/24", "10.0.100.0/24", "10.0.12.0/24", "10.0.200.0/24"] expected = "10.0.10.0/24,10.0.12.0/24,10.0.100.0/24,10.0.200.0/24" From f57b632e355d8a52350a0cc28d95c3184f472da5 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Fri, 1 Mar 2024 12:28:53 -0600 Subject: [PATCH 06/26] refactor: Update function to support sorting addresses and interfaces too. --- netutils/ip.py | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/netutils/ip.py b/netutils/ip.py index 1e6eccde..3ff73313 100644 --- a/netutils/ip.py +++ b/netutils/ip.py @@ -599,20 +599,33 @@ def get_usable_range(ip_network: str) -> str: return f"{lower_bound} - {upper_bound}" -def sort_list_cidrs(cidr_list: t.Union[str, t.List[str]]) -> str: +def sort_list_ips(ips: t.Union[str, t.List[str]], sort_type: str = "network") -> str: """Given a concatenated list of CIDRs sorts them into the correct order and returns as concatenated string. Args: - cidr_list (t.Union[str, t.List[str]]): Concatenated string list of CIDRs or list of CIDR strings. + ips (t.Union[str, t.List[str]]): Concatenated string list of CIDRs, IPAddresses, or Interfaces or list of the same strings. + sort_type (str): Whether the passed list are networks, IP addresses, or interfaces, ie "address", "interface", or "network". Returns: - str: Sorted list of CIDRs. + str: Sorted concatenated list of sort_type IPs. """ - cidrs = [] - if isinstance(cidr_list, list): - cidrs = cidr_list - elif (isinstance(cidr_list, str) and "," not in cidr_list) or not isinstance(cidr_list, str): - raise ValueError("Not a concatenated list of CIDRs as expected.") - elif isinstance(cidr_list, str): - cidrs = cidr_list.replace(" ", "").split(",") - return ",".join([obj.with_prefixlen for obj in sorted([ipaddress.ip_network(cidr) for cidr in cidrs])]) + if sort_type not in ["address", "interface", "network"]: + raise ValueError("Invalid sort type passed. Must be `address`, `interface`, or `network`.") + if isinstance(ips, list): + ips_list = ips + elif (isinstance(ips, str) and "," not in ips) or not isinstance(ips, str): + raise ValueError("Not a concatenated list of IPs as expected.") + elif isinstance(ips, str): + ips_list = ips.replace(" ", "").split(",") + else: + ips_list = [] + + functions = {"address": ipaddress.ip_address, "interface": ipaddress.ip_interface, "network": ipaddress.ip_network} + + try: + sorted_list = sorted(functions[sort_type](ip) for ip in ips_list) + if sort_type in ["interface", "network"]: + return ",".join([cidrs.with_prefixlen for cidrs in sorted_list]) + return ",".join([str(ip) for ip in sorted_list]) + except ValueError as err: + raise ValueError(f"Invalid IP of {sort_type} input: {err}") from err From 91b808fe2dbc7547e924f258a5b57b47ddafcb12 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Fri, 1 Mar 2024 12:29:18 -0600 Subject: [PATCH 07/26] test: Update tests validating sort_type and sorting addresses and interfaces. --- tests/unit/test_ip.py | 50 +++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/tests/unit/test_ip.py b/tests/unit/test_ip.py index 3a6f39a2..b2e2ef0b 100644 --- a/tests/unit/test_ip.py +++ b/tests/unit/test_ip.py @@ -472,6 +472,24 @@ {"sent": {"ip_network": "224.0.0.0/24"}, "received": False}, ] +SORTED_IPS = [ + { + "sent": "10.0.10.0/24, 10.0.100.0/24, 10.0.12.0/24, 10.0.200.0/24", + "expected": "10.0.10.0/24,10.0.12.0/24,10.0.100.0/24,10.0.200.0/24", + "sort_type": "network", + }, + { + "sent": "192.168.1.1,10.1.1.2,172.16.10.1", + "expected": "10.1.1.2,172.16.10.1,192.168.1.1", + "sort_type": "address", + }, + { + "sent": "192.168.1.1/24,10.1.1.2/32,172.16.10.1/16", + "expected": "10.1.1.2/32,172.16.10.1/16,192.168.1.1/24", + "sort_type": "interface", + }, +] + @pytest.mark.parametrize("data", IP_TO_HEX) def test_ip_to_hex(data): @@ -620,29 +638,33 @@ def test_is_classful(data): assert ip.is_classful(**data["sent"]) == data["received"] -def test_sort_list_cidrs(): - sent = "10.0.10.0/24, 10.0.100.0/24, 10.0.12.0/24, 10.0.200.0/24" - expected = "10.0.10.0/24,10.0.12.0/24,10.0.100.0/24,10.0.200.0/24" - assert expected == ip.sort_list_cidrs(sent) +@pytest.mark.parametrize("data", SORTED_IPS) +def test_sort_list_ips(data): + assert data["expected"] == ip.sort_list_ips(data["sent"], sort_type=data["sort_type"]) -def test_sort_list_cidrs_same_base(): +def test_sort_list_ips_networks_same_base(): sent = "10.0.0.0/24, 10.0.0.0/16, 10.0.0.0/18" expected = "10.0.0.0/16,10.0.0.0/18,10.0.0.0/24" - assert expected == ip.sort_list_cidrs(sent) + assert expected == ip.sort_list_ips(sent) -def test_sort_list_cidrs_using_list(): +def test_sort_list_ips_using_list(): sent = ["10.0.10.0/24", "10.0.100.0/24", "10.0.12.0/24", "10.0.200.0/24"] expected = "10.0.10.0/24,10.0.12.0/24,10.0.100.0/24,10.0.200.0/24" - assert expected == ip.sort_list_cidrs(sent) + assert expected == ip.sort_list_ips(sent) + + +def test_sort_list_ips_exception_invalid_list(): + with pytest.raises(ValueError, match="Not a concatenated list of IPs as expected."): + ip.sort_list_ips("10.1.1.1/24 10.2.2.2/16") -def test_sort_list_cidrs_exception_invalid_list(): - with pytest.raises(ValueError, match="Not a concatenated list of CIDRs as expected."): - ip.sort_list_cidrs("10.1.1.1/24 10.2.2.2/16") +def test_sort_list_ips_exception_invalid_instance_type(): + with pytest.raises(ValueError, match="Not a concatenated list of IPs as expected."): + ip.sort_list_ips({"10.1.1.1/24", "10.2.2.2/16"}) -def test_sort_list_cidrs_exception_invalid_instance_type(): - with pytest.raises(ValueError, match="Not a concatenated list of CIDRs as expected."): - ip.sort_list_cidrs({"10.1.1.1/24", "10.2.2.2/16"}) +def test_sort_list_ips_invalid_sort_type(): + with pytest.raises(ValueError, match="Invalid sort type passed. Must be `address`, `interface`, or `network`."): + ip.sort_list_ips("10.0.0.0/24,192.168.0.0/16", sort_type="wrong_type") From adf081547d9fce7341376373be4e4db494b06215 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Fri, 1 Mar 2024 12:42:30 -0600 Subject: [PATCH 08/26] fix: Remove unnecessary empty list for ips_list var --- netutils/ip.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/netutils/ip.py b/netutils/ip.py index 3ff73313..ab64b0ba 100644 --- a/netutils/ip.py +++ b/netutils/ip.py @@ -617,8 +617,6 @@ def sort_list_ips(ips: t.Union[str, t.List[str]], sort_type: str = "network") -> raise ValueError("Not a concatenated list of IPs as expected.") elif isinstance(ips, str): ips_list = ips.replace(" ", "").split(",") - else: - ips_list = [] functions = {"address": ipaddress.ip_address, "interface": ipaddress.ip_interface, "network": ipaddress.ip_network} From 2bd6c1d32b1e3b1de3d677c3d15e9716751a23af Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Fri, 1 Mar 2024 12:42:47 -0600 Subject: [PATCH 09/26] fix: Correct mapping for function to use sort_list_ips --- docs/user/include_jinja_list.md | 2 +- netutils/utils.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/user/include_jinja_list.md b/docs/user/include_jinja_list.md index 3ff36878..993b3441 100644 --- a/docs/user/include_jinja_list.md +++ b/docs/user/include_jinja_list.md @@ -51,7 +51,7 @@ | is_netmask | netutils.ip.is_netmask | | is_network | netutils.ip.is_network | | netmask_to_cidr | netutils.ip.netmask_to_cidr | -| sort_list_cidrs | netutils.ip.sort_list_cidrs | +| sort_list_ips | netutils.ip.sort_list_ips | | get_napalm_getters | netutils.lib_helpers.get_napalm_getters | | get_oui | netutils.mac.get_oui | | is_valid_mac | netutils.mac.is_valid_mac | diff --git a/netutils/utils.py b/netutils/utils.py index a2f8cfdc..2f78b2af 100644 --- a/netutils/utils.py +++ b/netutils/utils.py @@ -91,7 +91,7 @@ "os_platform_object_builder": "platform_mapper.os_platform_object_builder", "juniper_junos_version_parser": "os_version.juniper_junos_version_parser", "hash_data": "hash.hash_data", - "sort_list_cidrs": "ip.sort_list_cidrs", + "sort_list_ips": "ip.sort_list_ips", } From 6ea29494ee4db8252ae514172aebe4526611794f Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Fri, 1 Mar 2024 12:49:44 -0600 Subject: [PATCH 10/26] =?UTF-8?q?fix:=20=F0=9F=8F=B7=EF=B8=8F=20Update=20t?= =?UTF-8?q?ype=20hints=20to=20support=20py3.8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- netutils/ip.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/netutils/ip.py b/netutils/ip.py index ab64b0ba..09585ce8 100644 --- a/netutils/ip.py +++ b/netutils/ip.py @@ -599,12 +599,12 @@ def get_usable_range(ip_network: str) -> str: return f"{lower_bound} - {upper_bound}" -def sort_list_ips(ips: t.Union[str, t.List[str]], sort_type: str = "network") -> str: +def sort_list_ips(ips: t.Union[t.AnyStr, t.List[t.AnyStr]], sort_type: t.AnyStr = "network") -> str: """Given a concatenated list of CIDRs sorts them into the correct order and returns as concatenated string. Args: - ips (t.Union[str, t.List[str]]): Concatenated string list of CIDRs, IPAddresses, or Interfaces or list of the same strings. - sort_type (str): Whether the passed list are networks, IP addresses, or interfaces, ie "address", "interface", or "network". + ips (t.Union[t.AnyStr, t.List[t.AnyStr]]): Concatenated string list of CIDRs, IPAddresses, or Interfaces or list of the same strings. + sort_type (t.AnyStr): Whether the passed list are networks, IP addresses, or interfaces, ie "address", "interface", or "network". Returns: str: Sorted concatenated list of sort_type IPs. From ea152968714357c549a25a5b89f8b2a1b72e6bf9 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Fri, 1 Mar 2024 12:57:25 -0600 Subject: [PATCH 11/26] =?UTF-8?q?revert:=20=E2=8F=AA=EF=B8=8F=20Revert=20t?= =?UTF-8?q?yping=20changes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- netutils/ip.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/netutils/ip.py b/netutils/ip.py index 09585ce8..ab64b0ba 100644 --- a/netutils/ip.py +++ b/netutils/ip.py @@ -599,12 +599,12 @@ def get_usable_range(ip_network: str) -> str: return f"{lower_bound} - {upper_bound}" -def sort_list_ips(ips: t.Union[t.AnyStr, t.List[t.AnyStr]], sort_type: t.AnyStr = "network") -> str: +def sort_list_ips(ips: t.Union[str, t.List[str]], sort_type: str = "network") -> str: """Given a concatenated list of CIDRs sorts them into the correct order and returns as concatenated string. Args: - ips (t.Union[t.AnyStr, t.List[t.AnyStr]]): Concatenated string list of CIDRs, IPAddresses, or Interfaces or list of the same strings. - sort_type (t.AnyStr): Whether the passed list are networks, IP addresses, or interfaces, ie "address", "interface", or "network". + ips (t.Union[str, t.List[str]]): Concatenated string list of CIDRs, IPAddresses, or Interfaces or list of the same strings. + sort_type (str): Whether the passed list are networks, IP addresses, or interfaces, ie "address", "interface", or "network". Returns: str: Sorted concatenated list of sort_type IPs. From 1e3527d1f4b30aa60ac5ae6372e61868e345c48f Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Mon, 4 Mar 2024 08:13:09 -0600 Subject: [PATCH 12/26] =?UTF-8?q?fix:=20=F0=9F=90=9B=20Add=20type=20hint?= =?UTF-8?q?=20to=20function=5Fmap?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- netutils/ip.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/netutils/ip.py b/netutils/ip.py index ab64b0ba..8b765fc8 100644 --- a/netutils/ip.py +++ b/netutils/ip.py @@ -618,7 +618,11 @@ def sort_list_ips(ips: t.Union[str, t.List[str]], sort_type: str = "network") -> elif isinstance(ips, str): ips_list = ips.replace(" ", "").split(",") - functions = {"address": ipaddress.ip_address, "interface": ipaddress.ip_interface, "network": ipaddress.ip_network} + functions: t.Dict[str, t.Callable] = { + "address": ipaddress.ip_address, + "interface": ipaddress.ip_interface, + "network": ipaddress.ip_network, + } try: sorted_list = sorted(functions[sort_type](ip) for ip in ips_list) From 3594ddcf5267dd651d8092f4953908fcf70f6951 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Mon, 4 Mar 2024 08:16:43 -0600 Subject: [PATCH 13/26] =?UTF-8?q?fix:=20=F0=9F=90=9B=20Add=20type=20hints?= =?UTF-8?q?=20for=20Callable?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- netutils/ip.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netutils/ip.py b/netutils/ip.py index 8b765fc8..1702a676 100644 --- a/netutils/ip.py +++ b/netutils/ip.py @@ -618,7 +618,7 @@ def sort_list_ips(ips: t.Union[str, t.List[str]], sort_type: str = "network") -> elif isinstance(ips, str): ips_list = ips.replace(" ", "").split(",") - functions: t.Dict[str, t.Callable] = { + functions: t.Dict[str, t.Callable[[t.Any], t.Any]] = { "address": ipaddress.ip_address, "interface": ipaddress.ip_interface, "network": ipaddress.ip_network, From 5af1abdec5b03cf2a4e04b070204424c39997479 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Mon, 4 Mar 2024 10:46:13 -0600 Subject: [PATCH 14/26] =?UTF-8?q?docs:=20=F0=9F=93=9D=20Add=20example=20to?= =?UTF-8?q?=20docstrings=20for=20function?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- netutils/ip.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/netutils/ip.py b/netutils/ip.py index 1702a676..b964b265 100644 --- a/netutils/ip.py +++ b/netutils/ip.py @@ -602,6 +602,8 @@ def get_usable_range(ip_network: str) -> str: def sort_list_ips(ips: t.Union[str, t.List[str]], sort_type: str = "network") -> str: """Given a concatenated list of CIDRs sorts them into the correct order and returns as concatenated string. + Ex: "3.3.3.3,2.2.2.2,1.1.1.1" -> "1.1.1.1,2.2.2.2,3.3.3.3" + Args: ips (t.Union[str, t.List[str]]): Concatenated string list of CIDRs, IPAddresses, or Interfaces or list of the same strings. sort_type (str): Whether the passed list are networks, IP addresses, or interfaces, ie "address", "interface", or "network". From 39f05202d8fa1c22cec27826d3eb073cd11186f7 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Mon, 4 Mar 2024 12:07:08 -0600 Subject: [PATCH 15/26] =?UTF-8?q?docs:=20=F0=9F=93=9D=20Update=20example?= =?UTF-8?q?=20to=20match=20others?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- netutils/ip.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/netutils/ip.py b/netutils/ip.py index b964b265..54990a1f 100644 --- a/netutils/ip.py +++ b/netutils/ip.py @@ -602,7 +602,10 @@ def get_usable_range(ip_network: str) -> str: def sort_list_ips(ips: t.Union[str, t.List[str]], sort_type: str = "network") -> str: """Given a concatenated list of CIDRs sorts them into the correct order and returns as concatenated string. - Ex: "3.3.3.3,2.2.2.2,1.1.1.1" -> "1.1.1.1,2.2.2.2,3.3.3.3" + Examples: + >>> from netutils.ip import sort_list_ips + >>> sort_list_ips("3.3.3.3,2.2.2.2,1.1.1.1") + 1.1.1.1,2.2.2.2,3.3.3.3 Args: ips (t.Union[str, t.List[str]]): Concatenated string list of CIDRs, IPAddresses, or Interfaces or list of the same strings. From 2663808571ae76585e5e67cefd4d1dde7f31e644 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Mon, 4 Mar 2024 14:45:13 -0600 Subject: [PATCH 16/26] =?UTF-8?q?fix:=20=F0=9F=90=9B=20Correct=20example?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- netutils/ip.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netutils/ip.py b/netutils/ip.py index 54990a1f..4eca1b39 100644 --- a/netutils/ip.py +++ b/netutils/ip.py @@ -605,7 +605,7 @@ def sort_list_ips(ips: t.Union[str, t.List[str]], sort_type: str = "network") -> Examples: >>> from netutils.ip import sort_list_ips >>> sort_list_ips("3.3.3.3,2.2.2.2,1.1.1.1") - 1.1.1.1,2.2.2.2,3.3.3.3 + '1.1.1.1/32,2.2.2.2/32,3.3.3.3/32' Args: ips (t.Union[str, t.List[str]]): Concatenated string list of CIDRs, IPAddresses, or Interfaces or list of the same strings. From e437eb54a7d83840af75d6be61ccb5cc7f915622 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Wed, 6 Mar 2024 11:09:54 -0600 Subject: [PATCH 17/26] =?UTF-8?q?docs:=20=F0=9F=93=9D=20Add=20additional?= =?UTF-8?q?=20examples=20of=20what=20the=20function=20does.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- netutils/ip.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/netutils/ip.py b/netutils/ip.py index 4eca1b39..9867fb8e 100644 --- a/netutils/ip.py +++ b/netutils/ip.py @@ -606,6 +606,14 @@ def sort_list_ips(ips: t.Union[str, t.List[str]], sort_type: str = "network") -> >>> from netutils.ip import sort_list_ips >>> sort_list_ips("3.3.3.3,2.2.2.2,1.1.1.1") '1.1.1.1/32,2.2.2.2/32,3.3.3.3/32' + >>> sort_list_ips("10.0.20.0/24,10.0.20.0/23,10.0.19.0/24") + '10.0.19.0/24,10.0.20.0/23,10.0.20.0/24' + >>> sort_list_ips("10.0.20.0/24,10.0.20.0/23,10.0.19.0/24", "interface") + '10.0.19.0/24,10.0.20.0/23,10.0.20.0/24' + >>> sort_list_ips("10.0.20.20/24,10.0.20.1/23,10.0.19.5/24", "interface") + '10.0.19.5/24,10.0.20.1/23,10.0.20.20/24' + >>> sort_list_ips(["10.0.20.20", "10.0.20.1", "10.0.19.5"], "address") + '10.0.19.5,10.0.20.1,10.0.20.20' Args: ips (t.Union[str, t.List[str]]): Concatenated string list of CIDRs, IPAddresses, or Interfaces or list of the same strings. From 342a86e3a7b58198f87425499f280cc077d9a3be Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Wed, 6 Mar 2024 11:10:45 -0600 Subject: [PATCH 18/26] =?UTF-8?q?refactor:=20=E2=99=BB=EF=B8=8F=20Change?= =?UTF-8?q?=20function=20name=20to=20sort=5Fips?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/user/include_jinja_list.md | 2 +- netutils/ip.py | 14 +++++++------- netutils/utils.py | 2 +- tests/unit/test_ip.py | 24 ++++++++++++------------ 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/user/include_jinja_list.md b/docs/user/include_jinja_list.md index 993b3441..1e59540c 100644 --- a/docs/user/include_jinja_list.md +++ b/docs/user/include_jinja_list.md @@ -51,7 +51,7 @@ | is_netmask | netutils.ip.is_netmask | | is_network | netutils.ip.is_network | | netmask_to_cidr | netutils.ip.netmask_to_cidr | -| sort_list_ips | netutils.ip.sort_list_ips | +| sort_ips | netutils.ip.sort_ips | | get_napalm_getters | netutils.lib_helpers.get_napalm_getters | | get_oui | netutils.mac.get_oui | | is_valid_mac | netutils.mac.is_valid_mac | diff --git a/netutils/ip.py b/netutils/ip.py index 9867fb8e..72b785b8 100644 --- a/netutils/ip.py +++ b/netutils/ip.py @@ -599,20 +599,20 @@ def get_usable_range(ip_network: str) -> str: return f"{lower_bound} - {upper_bound}" -def sort_list_ips(ips: t.Union[str, t.List[str]], sort_type: str = "network") -> str: +def sort_ips(ips: t.Union[str, t.List[str]], sort_type: str = "network") -> str: """Given a concatenated list of CIDRs sorts them into the correct order and returns as concatenated string. Examples: - >>> from netutils.ip import sort_list_ips - >>> sort_list_ips("3.3.3.3,2.2.2.2,1.1.1.1") + >>> from netutils.ip import sort_ips + >>> sort_ips("3.3.3.3,2.2.2.2,1.1.1.1") '1.1.1.1/32,2.2.2.2/32,3.3.3.3/32' - >>> sort_list_ips("10.0.20.0/24,10.0.20.0/23,10.0.19.0/24") + >>> sort_ips("10.0.20.0/24,10.0.20.0/23,10.0.19.0/24") '10.0.19.0/24,10.0.20.0/23,10.0.20.0/24' - >>> sort_list_ips("10.0.20.0/24,10.0.20.0/23,10.0.19.0/24", "interface") + >>> sort_ips("10.0.20.0/24,10.0.20.0/23,10.0.19.0/24", "interface") '10.0.19.0/24,10.0.20.0/23,10.0.20.0/24' - >>> sort_list_ips("10.0.20.20/24,10.0.20.1/23,10.0.19.5/24", "interface") + >>> sort_ips("10.0.20.20/24,10.0.20.1/23,10.0.19.5/24", "interface") '10.0.19.5/24,10.0.20.1/23,10.0.20.20/24' - >>> sort_list_ips(["10.0.20.20", "10.0.20.1", "10.0.19.5"], "address") + >>> sort_ips(["10.0.20.20", "10.0.20.1", "10.0.19.5"], "address") '10.0.19.5,10.0.20.1,10.0.20.20' Args: diff --git a/netutils/utils.py b/netutils/utils.py index 2f78b2af..c3c4be07 100644 --- a/netutils/utils.py +++ b/netutils/utils.py @@ -91,7 +91,7 @@ "os_platform_object_builder": "platform_mapper.os_platform_object_builder", "juniper_junos_version_parser": "os_version.juniper_junos_version_parser", "hash_data": "hash.hash_data", - "sort_list_ips": "ip.sort_list_ips", + "sort_ips": "ip.sort_ips", } diff --git a/tests/unit/test_ip.py b/tests/unit/test_ip.py index b2e2ef0b..28868c74 100644 --- a/tests/unit/test_ip.py +++ b/tests/unit/test_ip.py @@ -639,32 +639,32 @@ def test_is_classful(data): @pytest.mark.parametrize("data", SORTED_IPS) -def test_sort_list_ips(data): - assert data["expected"] == ip.sort_list_ips(data["sent"], sort_type=data["sort_type"]) +def test_sort_ips(data): + assert data["expected"] == ip.sort_ips(data["sent"], sort_type=data["sort_type"]) -def test_sort_list_ips_networks_same_base(): +def test_sort_ips_networks_same_base(): sent = "10.0.0.0/24, 10.0.0.0/16, 10.0.0.0/18" expected = "10.0.0.0/16,10.0.0.0/18,10.0.0.0/24" - assert expected == ip.sort_list_ips(sent) + assert expected == ip.sort_ips(sent) -def test_sort_list_ips_using_list(): +def test_sort_ips_using_list(): sent = ["10.0.10.0/24", "10.0.100.0/24", "10.0.12.0/24", "10.0.200.0/24"] expected = "10.0.10.0/24,10.0.12.0/24,10.0.100.0/24,10.0.200.0/24" - assert expected == ip.sort_list_ips(sent) + assert expected == ip.sort_ips(sent) -def test_sort_list_ips_exception_invalid_list(): +def test_sort_ips_exception_invalid_list(): with pytest.raises(ValueError, match="Not a concatenated list of IPs as expected."): - ip.sort_list_ips("10.1.1.1/24 10.2.2.2/16") + ip.sort_ips("10.1.1.1/24 10.2.2.2/16") -def test_sort_list_ips_exception_invalid_instance_type(): +def test_sort_ips_exception_invalid_instance_type(): with pytest.raises(ValueError, match="Not a concatenated list of IPs as expected."): - ip.sort_list_ips({"10.1.1.1/24", "10.2.2.2/16"}) + ip.sort_ips({"10.1.1.1/24", "10.2.2.2/16"}) -def test_sort_list_ips_invalid_sort_type(): +def test_sort_ips_invalid_sort_type(): with pytest.raises(ValueError, match="Invalid sort type passed. Must be `address`, `interface`, or `network`."): - ip.sort_list_ips("10.0.0.0/24,192.168.0.0/16", sort_type="wrong_type") + ip.sort_ips("10.0.0.0/24,192.168.0.0/16", sort_type="wrong_type") From 55556de8685b8b0f1d4a0c3a5dca2c49ba187c55 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Thu, 7 Mar 2024 09:22:18 -0600 Subject: [PATCH 19/26] =?UTF-8?q?refactor:=20=E2=99=BB=EF=B8=8F=20Change?= =?UTF-8?q?=20method=20name=20to=20get=5Fips=5Fsorted=20to=20match=20other?= =?UTF-8?q?=20functions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/user/include_jinja_list.md | 2 +- netutils/ip.py | 14 +++++++------- netutils/utils.py | 2 +- tests/unit/test_ip.py | 24 ++++++++++++------------ 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/user/include_jinja_list.md b/docs/user/include_jinja_list.md index 1e59540c..802fcfd3 100644 --- a/docs/user/include_jinja_list.md +++ b/docs/user/include_jinja_list.md @@ -51,7 +51,7 @@ | is_netmask | netutils.ip.is_netmask | | is_network | netutils.ip.is_network | | netmask_to_cidr | netutils.ip.netmask_to_cidr | -| sort_ips | netutils.ip.sort_ips | +| get_ips_sorted | netutils.ip.get_ips_sorted | | get_napalm_getters | netutils.lib_helpers.get_napalm_getters | | get_oui | netutils.mac.get_oui | | is_valid_mac | netutils.mac.is_valid_mac | diff --git a/netutils/ip.py b/netutils/ip.py index 72b785b8..8ed800a0 100644 --- a/netutils/ip.py +++ b/netutils/ip.py @@ -599,20 +599,20 @@ def get_usable_range(ip_network: str) -> str: return f"{lower_bound} - {upper_bound}" -def sort_ips(ips: t.Union[str, t.List[str]], sort_type: str = "network") -> str: +def get_ips_sorted(ips: t.Union[str, t.List[str]], sort_type: str = "network") -> str: """Given a concatenated list of CIDRs sorts them into the correct order and returns as concatenated string. Examples: - >>> from netutils.ip import sort_ips - >>> sort_ips("3.3.3.3,2.2.2.2,1.1.1.1") + >>> from netutils.ip import get_ips_sorted + >>> get_ips_sorted("3.3.3.3,2.2.2.2,1.1.1.1") '1.1.1.1/32,2.2.2.2/32,3.3.3.3/32' - >>> sort_ips("10.0.20.0/24,10.0.20.0/23,10.0.19.0/24") + >>> get_ips_sorted("10.0.20.0/24,10.0.20.0/23,10.0.19.0/24") '10.0.19.0/24,10.0.20.0/23,10.0.20.0/24' - >>> sort_ips("10.0.20.0/24,10.0.20.0/23,10.0.19.0/24", "interface") + >>> get_ips_sorted("10.0.20.0/24,10.0.20.0/23,10.0.19.0/24", "interface") '10.0.19.0/24,10.0.20.0/23,10.0.20.0/24' - >>> sort_ips("10.0.20.20/24,10.0.20.1/23,10.0.19.5/24", "interface") + >>> get_ips_sorted("10.0.20.20/24,10.0.20.1/23,10.0.19.5/24", "interface") '10.0.19.5/24,10.0.20.1/23,10.0.20.20/24' - >>> sort_ips(["10.0.20.20", "10.0.20.1", "10.0.19.5"], "address") + >>> get_ips_sorted(["10.0.20.20", "10.0.20.1", "10.0.19.5"], "address") '10.0.19.5,10.0.20.1,10.0.20.20' Args: diff --git a/netutils/utils.py b/netutils/utils.py index c3c4be07..b9ff9416 100644 --- a/netutils/utils.py +++ b/netutils/utils.py @@ -91,7 +91,7 @@ "os_platform_object_builder": "platform_mapper.os_platform_object_builder", "juniper_junos_version_parser": "os_version.juniper_junos_version_parser", "hash_data": "hash.hash_data", - "sort_ips": "ip.sort_ips", + "get_ips_sorted": "ip.get_ips_sorted", } diff --git a/tests/unit/test_ip.py b/tests/unit/test_ip.py index 28868c74..7d3a103b 100644 --- a/tests/unit/test_ip.py +++ b/tests/unit/test_ip.py @@ -639,32 +639,32 @@ def test_is_classful(data): @pytest.mark.parametrize("data", SORTED_IPS) -def test_sort_ips(data): - assert data["expected"] == ip.sort_ips(data["sent"], sort_type=data["sort_type"]) +def test_get_ips_sorted(data): + assert data["expected"] == ip.get_ips_sorted(data["sent"], sort_type=data["sort_type"]) -def test_sort_ips_networks_same_base(): +def test_get_ips_sorted_networks_same_base(): sent = "10.0.0.0/24, 10.0.0.0/16, 10.0.0.0/18" expected = "10.0.0.0/16,10.0.0.0/18,10.0.0.0/24" - assert expected == ip.sort_ips(sent) + assert expected == ip.get_ips_sorted(sent) -def test_sort_ips_using_list(): +def test_get_ips_sorted_using_list(): sent = ["10.0.10.0/24", "10.0.100.0/24", "10.0.12.0/24", "10.0.200.0/24"] expected = "10.0.10.0/24,10.0.12.0/24,10.0.100.0/24,10.0.200.0/24" - assert expected == ip.sort_ips(sent) + assert expected == ip.get_ips_sorted(sent) -def test_sort_ips_exception_invalid_list(): +def test_get_ips_sorted_exception_invalid_list(): with pytest.raises(ValueError, match="Not a concatenated list of IPs as expected."): - ip.sort_ips("10.1.1.1/24 10.2.2.2/16") + ip.get_ips_sorted("10.1.1.1/24 10.2.2.2/16") -def test_sort_ips_exception_invalid_instance_type(): +def test_get_ips_sorted_exception_invalid_instance_type(): with pytest.raises(ValueError, match="Not a concatenated list of IPs as expected."): - ip.sort_ips({"10.1.1.1/24", "10.2.2.2/16"}) + ip.get_ips_sorted({"10.1.1.1/24", "10.2.2.2/16"}) -def test_sort_ips_invalid_sort_type(): +def test_get_ips_sorted_invalid_sort_type(): with pytest.raises(ValueError, match="Invalid sort type passed. Must be `address`, `interface`, or `network`."): - ip.sort_ips("10.0.0.0/24,192.168.0.0/16", sort_type="wrong_type") + ip.get_ips_sorted("10.0.0.0/24,192.168.0.0/16", sort_type="wrong_type") From 48b054665c1a285c52f00d1329096f6bd1ebe07e Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Thu, 7 Mar 2024 09:59:04 -0600 Subject: [PATCH 20/26] =?UTF-8?q?refactor:=20=E2=99=BB=EF=B8=8F=20Update?= =?UTF-8?q?=20function=20to=20return=20list=20of=20strings=20instead=20of?= =?UTF-8?q?=20concatenated=20string.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- netutils/ip.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/netutils/ip.py b/netutils/ip.py index 8ed800a0..f3366f09 100644 --- a/netutils/ip.py +++ b/netutils/ip.py @@ -599,28 +599,28 @@ def get_usable_range(ip_network: str) -> str: return f"{lower_bound} - {upper_bound}" -def get_ips_sorted(ips: t.Union[str, t.List[str]], sort_type: str = "network") -> str: +def get_ips_sorted(ips: t.Union[str, t.List[str]], sort_type: str = "network") -> list: """Given a concatenated list of CIDRs sorts them into the correct order and returns as concatenated string. Examples: >>> from netutils.ip import get_ips_sorted >>> get_ips_sorted("3.3.3.3,2.2.2.2,1.1.1.1") - '1.1.1.1/32,2.2.2.2/32,3.3.3.3/32' + ['1.1.1.1/32','2.2.2.2/32','3.3.3.3/32'] >>> get_ips_sorted("10.0.20.0/24,10.0.20.0/23,10.0.19.0/24") - '10.0.19.0/24,10.0.20.0/23,10.0.20.0/24' + ['10.0.19.0/24','10.0.20.0/23','10.0.20.0/24'] >>> get_ips_sorted("10.0.20.0/24,10.0.20.0/23,10.0.19.0/24", "interface") - '10.0.19.0/24,10.0.20.0/23,10.0.20.0/24' + ['10.0.19.0/24',10.0.20.0/23','10.0.20.0/24'] >>> get_ips_sorted("10.0.20.20/24,10.0.20.1/23,10.0.19.5/24", "interface") - '10.0.19.5/24,10.0.20.1/23,10.0.20.20/24' + ['10.0.19.5/24','10.0.20.1/23','10.0.20.20/24'] >>> get_ips_sorted(["10.0.20.20", "10.0.20.1", "10.0.19.5"], "address") - '10.0.19.5,10.0.20.1,10.0.20.20' + ['10.0.19.5','10.0.20.1','10.0.20.20'] Args: ips (t.Union[str, t.List[str]]): Concatenated string list of CIDRs, IPAddresses, or Interfaces or list of the same strings. sort_type (str): Whether the passed list are networks, IP addresses, or interfaces, ie "address", "interface", or "network". Returns: - str: Sorted concatenated list of sort_type IPs. + list: Sorted list of sort_type IPs. """ if sort_type not in ["address", "interface", "network"]: raise ValueError("Invalid sort type passed. Must be `address`, `interface`, or `network`.") @@ -640,7 +640,7 @@ def get_ips_sorted(ips: t.Union[str, t.List[str]], sort_type: str = "network") - try: sorted_list = sorted(functions[sort_type](ip) for ip in ips_list) if sort_type in ["interface", "network"]: - return ",".join([cidrs.with_prefixlen for cidrs in sorted_list]) - return ",".join([str(ip) for ip in sorted_list]) + return [cidrs.with_prefixlen for cidrs in sorted_list] + return [str(ip) for ip in sorted_list] except ValueError as err: raise ValueError(f"Invalid IP of {sort_type} input: {err}") from err From e2ae69ccf34b814bf7d0d93820074f23737ea25a Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Thu, 7 Mar 2024 09:59:34 -0600 Subject: [PATCH 21/26] =?UTF-8?q?test:=20=E2=9C=85=20Update=20tests=20to?= =?UTF-8?q?=20validate=20return=20of=20list=20and=20add=20more=20examples?= =?UTF-8?q?=20for=20tests.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/unit/test_ip.py | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/tests/unit/test_ip.py b/tests/unit/test_ip.py index 7d3a103b..b76447e0 100644 --- a/tests/unit/test_ip.py +++ b/tests/unit/test_ip.py @@ -473,19 +473,44 @@ ] SORTED_IPS = [ + { + "sent": "10.0.10.0/24,10.0.100.0/24,10.0.12.0/24,10.0.200.0/24", + "expected": ["10.0.10.0/24", "10.0.12.0/24", "10.0.100.0/24", "10.0.200.0/24"], + "sort_type": "network", + }, { "sent": "10.0.10.0/24, 10.0.100.0/24, 10.0.12.0/24, 10.0.200.0/24", - "expected": "10.0.10.0/24,10.0.12.0/24,10.0.100.0/24,10.0.200.0/24", + "expected": ["10.0.10.0/24", "10.0.12.0/24", "10.0.100.0/24", "10.0.200.0/24"], "sort_type": "network", }, { "sent": "192.168.1.1,10.1.1.2,172.16.10.1", - "expected": "10.1.1.2,172.16.10.1,192.168.1.1", + "expected": ["10.1.1.2", "172.16.10.1", "192.168.1.1"], "sort_type": "address", }, { "sent": "192.168.1.1/24,10.1.1.2/32,172.16.10.1/16", - "expected": "10.1.1.2/32,172.16.10.1/16,192.168.1.1/24", + "expected": ["10.1.1.2/32", "172.16.10.1/16", "192.168.1.1/24"], + "sort_type": "interface", + }, + { + "sent": "10.0.0.0/24, 10.0.0.0/16, 10.0.0.0/18", + "expected": ["10.0.0.0/16", "10.0.0.0/18", "10.0.0.0/24"], + "sort_type": "network", + }, + { + "sent": ["10.0.10.0/24", "10.0.100.0/24", "10.0.12.0/24", "10.0.200.0/24"], + "expected": ["10.0.10.0/24", "10.0.12.0/24", "10.0.100.0/24", "10.0.200.0/24"], + "sort_type": "network", + }, + { + "sent": ["192.168.1.1", "10.1.1.2", "172.16.10.1"], + "expected": ["10.1.1.2", "172.16.10.1", "192.168.1.1"], + "sort_type": "address", + }, + { + "sent": ["192.168.1.1/24", "10.1.1.2/32", "172.16.10.1/16"], + "expected": ["10.1.1.2/32", "172.16.10.1/16", "192.168.1.1/24"], "sort_type": "interface", }, ] @@ -643,18 +668,6 @@ def test_get_ips_sorted(data): assert data["expected"] == ip.get_ips_sorted(data["sent"], sort_type=data["sort_type"]) -def test_get_ips_sorted_networks_same_base(): - sent = "10.0.0.0/24, 10.0.0.0/16, 10.0.0.0/18" - expected = "10.0.0.0/16,10.0.0.0/18,10.0.0.0/24" - assert expected == ip.get_ips_sorted(sent) - - -def test_get_ips_sorted_using_list(): - sent = ["10.0.10.0/24", "10.0.100.0/24", "10.0.12.0/24", "10.0.200.0/24"] - expected = "10.0.10.0/24,10.0.12.0/24,10.0.100.0/24,10.0.200.0/24" - assert expected == ip.get_ips_sorted(sent) - - def test_get_ips_sorted_exception_invalid_list(): with pytest.raises(ValueError, match="Not a concatenated list of IPs as expected."): ip.get_ips_sorted("10.1.1.1/24 10.2.2.2/16") From 9aad2af89fe1fb6339db043cd7365245e4d98efb Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Thu, 7 Mar 2024 10:02:28 -0600 Subject: [PATCH 22/26] =?UTF-8?q?fix:=20=F0=9F=8F=B7=EF=B8=8F=20Correct=20?= =?UTF-8?q?type=20hint=20to=20List[str]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- netutils/ip.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/netutils/ip.py b/netutils/ip.py index f3366f09..11f314f6 100644 --- a/netutils/ip.py +++ b/netutils/ip.py @@ -599,7 +599,7 @@ def get_usable_range(ip_network: str) -> str: return f"{lower_bound} - {upper_bound}" -def get_ips_sorted(ips: t.Union[str, t.List[str]], sort_type: str = "network") -> list: +def get_ips_sorted(ips: t.Union[str, t.List[str]], sort_type: str = "network") -> t.List[str]: """Given a concatenated list of CIDRs sorts them into the correct order and returns as concatenated string. Examples: @@ -620,7 +620,7 @@ def get_ips_sorted(ips: t.Union[str, t.List[str]], sort_type: str = "network") - sort_type (str): Whether the passed list are networks, IP addresses, or interfaces, ie "address", "interface", or "network". Returns: - list: Sorted list of sort_type IPs. + t.List[str]: Sorted list of sort_type IPs. """ if sort_type not in ["address", "interface", "network"]: raise ValueError("Invalid sort type passed. Must be `address`, `interface`, or `network`.") From 2180c21f1310729c0827e505e6225a49258c9d7b Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Thu, 7 Mar 2024 10:14:08 -0600 Subject: [PATCH 23/26] =?UTF-8?q?fix:=20=E2=9C=85=20Correct=20docstring=20?= =?UTF-8?q?examples?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- netutils/ip.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/netutils/ip.py b/netutils/ip.py index 11f314f6..a441f59e 100644 --- a/netutils/ip.py +++ b/netutils/ip.py @@ -605,15 +605,15 @@ def get_ips_sorted(ips: t.Union[str, t.List[str]], sort_type: str = "network") - Examples: >>> from netutils.ip import get_ips_sorted >>> get_ips_sorted("3.3.3.3,2.2.2.2,1.1.1.1") - ['1.1.1.1/32','2.2.2.2/32','3.3.3.3/32'] + ['1.1.1.1/32', '2.2.2.2/32', '3.3.3.3/32'] >>> get_ips_sorted("10.0.20.0/24,10.0.20.0/23,10.0.19.0/24") - ['10.0.19.0/24','10.0.20.0/23','10.0.20.0/24'] + ['10.0.19.0/24', '10.0.20.0/23', '10.0.20.0/24'] >>> get_ips_sorted("10.0.20.0/24,10.0.20.0/23,10.0.19.0/24", "interface") - ['10.0.19.0/24',10.0.20.0/23','10.0.20.0/24'] + ['10.0.19.0/24', 10.0.20.0/23', '10.0.20.0/24'] >>> get_ips_sorted("10.0.20.20/24,10.0.20.1/23,10.0.19.5/24", "interface") - ['10.0.19.5/24','10.0.20.1/23','10.0.20.20/24'] + ['10.0.19.5/24', '10.0.20.1/23', '10.0.20.20/24'] >>> get_ips_sorted(["10.0.20.20", "10.0.20.1", "10.0.19.5"], "address") - ['10.0.19.5','10.0.20.1','10.0.20.20'] + ['10.0.19.5', '10.0.20.1', '10.0.20.20'] Args: ips (t.Union[str, t.List[str]]): Concatenated string list of CIDRs, IPAddresses, or Interfaces or list of the same strings. From db345347ac63ff0bcb63ae6b0b1b5ff6e7dbd7b6 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Thu, 7 Mar 2024 10:24:23 -0600 Subject: [PATCH 24/26] =?UTF-8?q?fix:=20=E2=9C=85=20Add=20missing=20quote?= =?UTF-8?q?=20in=20docstring=20example?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- netutils/ip.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netutils/ip.py b/netutils/ip.py index a441f59e..a1dcb8b6 100644 --- a/netutils/ip.py +++ b/netutils/ip.py @@ -609,7 +609,7 @@ def get_ips_sorted(ips: t.Union[str, t.List[str]], sort_type: str = "network") - >>> get_ips_sorted("10.0.20.0/24,10.0.20.0/23,10.0.19.0/24") ['10.0.19.0/24', '10.0.20.0/23', '10.0.20.0/24'] >>> get_ips_sorted("10.0.20.0/24,10.0.20.0/23,10.0.19.0/24", "interface") - ['10.0.19.0/24', 10.0.20.0/23', '10.0.20.0/24'] + ['10.0.19.0/24', '10.0.20.0/23', '10.0.20.0/24'] >>> get_ips_sorted("10.0.20.20/24,10.0.20.1/23,10.0.19.5/24", "interface") ['10.0.19.5/24', '10.0.20.1/23', '10.0.20.20/24'] >>> get_ips_sorted(["10.0.20.20", "10.0.20.1", "10.0.19.5"], "address") From 4d60ec773e5cf088ede142d4a3336a276f5e007b Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Thu, 7 Mar 2024 10:32:12 -0600 Subject: [PATCH 25/26] =?UTF-8?q?test:=20=E2=9C=85=20Re-run=20python=20dev?= =?UTF-8?q?elopment=5Fscripts.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/user/include_jinja_list.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user/include_jinja_list.md b/docs/user/include_jinja_list.md index 802fcfd3..11845433 100644 --- a/docs/user/include_jinja_list.md +++ b/docs/user/include_jinja_list.md @@ -34,6 +34,7 @@ | get_all_host | netutils.ip.get_all_host | | get_broadcast_address | netutils.ip.get_broadcast_address | | get_first_usable | netutils.ip.get_first_usable | +| get_ips_sorted | netutils.ip.get_ips_sorted | | get_peer_ip | netutils.ip.get_peer_ip | | get_range_ips | netutils.ip.get_range_ips | | get_usable_range | netutils.ip.get_usable_range | @@ -51,7 +52,6 @@ | is_netmask | netutils.ip.is_netmask | | is_network | netutils.ip.is_network | | netmask_to_cidr | netutils.ip.netmask_to_cidr | -| get_ips_sorted | netutils.ip.get_ips_sorted | | get_napalm_getters | netutils.lib_helpers.get_napalm_getters | | get_oui | netutils.mac.get_oui | | is_valid_mac | netutils.mac.is_valid_mac | From 24cf0cdcb4391cded70d787d1e5103e03387f259 Mon Sep 17 00:00:00 2001 From: Justin Drew <2396364+jdrew82@users.noreply.github.com> Date: Fri, 8 Mar 2024 11:07:52 -0600 Subject: [PATCH 26/26] =?UTF-8?q?docs:=20=F0=9F=93=9D=20Fix=20docstring?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- netutils/ip.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netutils/ip.py b/netutils/ip.py index a1dcb8b6..267e7329 100644 --- a/netutils/ip.py +++ b/netutils/ip.py @@ -600,7 +600,7 @@ def get_usable_range(ip_network: str) -> str: def get_ips_sorted(ips: t.Union[str, t.List[str]], sort_type: str = "network") -> t.List[str]: - """Given a concatenated list of CIDRs sorts them into the correct order and returns as concatenated string. + """Given a concatenated list of CIDRs sorts them into the correct order and returns them as a list. Examples: >>> from netutils.ip import get_ips_sorted