Skip to content

Commit

Permalink
Add more CiscoRange() fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
mpenning committed Oct 28, 2023
1 parent b982b41 commit 9f07565
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 35 deletions.
81 changes: 48 additions & 33 deletions ciscoconfparse/ccp_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -3196,8 +3196,6 @@ def parse_single_interface(self, interface_name=None, debug=False):
intf_short = self.parse_intf_short(re_intf_short=re_intf_short)

_prefix = intf_short["prefix"]
if False:
_slot_card_port_subinterface_channel = intf_short["slot_card_port_subinterface_channel"]
_sep1 = intf_short["sep1"]
_sep2 = intf_short["sep1"]
_slot = intf_short["slot"]
Expand All @@ -3213,8 +3211,6 @@ def parse_single_interface(self, interface_name=None, debug=False):
intf_long = self.parse_intf_long(re_intf_long=re_intf_long)

_prefix = intf_long["prefix"]
if False:
_slot_card_port_subinterface_channel = intf_long["slot_card_port_subinterface_channel"]
_sep1 = intf_long["sep1"]
_sep2 = intf_long["sep1"]
_slot = intf_long["slot"]
Expand Down Expand Up @@ -3399,7 +3395,10 @@ def parse_intf_long(self, re_intf_long=None, debug=False):
_slot = groupdict_slot_card_port["slot"]
_card = groupdict_slot_card_port["card"]
_port = groupdict_slot_card_port["port"]
_interface_class = self._interface_class
try:
_interface_class = re.split(r"\s+", groupdict_intf_long["slot_card_port_subinterface_channel"])[1]
except:
_interface_class = None

# Handle Ethernet1/48, where 48 is initially assigned to
# _card (should be port)
Expand Down Expand Up @@ -3945,6 +3944,7 @@ def parse_integers(self, text, debug=False):
# Append a whole range of interfaces...
begin_ordinal = int(_csv_part.split("-")[0].strip())
end_ordinal = int(_csv_part.split("-")[1].strip())
end_ordinal = int("".join(filter(str.isdigit, _csv_part.split("-")[1].strip())))
if debug is True:
logger.info(f"CiscoRange(text={text}, debug=True) : end_ordinal={end_ordinal}")
else:
Expand Down Expand Up @@ -4005,27 +4005,44 @@ def parse_cisco_interfaces(self, text, debug=False):
if debug is True:
logger.info(f" CiscoRange() idx: {idx} for --> _csv_part: {_csv_part} <--")

##############################################################

##################################################################
# Build base instances of begin_obj and this_obj
##############################################################
##################################################################
if idx == 0:
# Set the begin_obj...
begin_obj = CiscoInterface(_csv_part.split("-")[0], debug=debug)
self.begin_obj = begin_obj
self.this_obj = CiscoInterface(interface_dict=begin_obj.as_dict())
intf_dict = begin_obj.as_dict()

##############################################################
##############################################################
# Manually add interface class because begin_obj won't see
# it by default: 'multipoint' in 'Serial1/0-5 multipoint'
##############################################################
if "".join(filter(str.isdigit, text.split()[-1])) == '':
# if there are no digits in the last word, that's an
# interface_class...
_interface_class = text.split()[-1]
else:
_interface_class = None
# Rebuild begin_obj with the interface_class
if isinstance(_interface_class, str):
intf_dict["interface_class"] = _interface_class
begin_obj = CiscoInterface(interface_dict=intf_dict)
self.begin_obj = begin_obj

##################################################################
# this_obj will also be modified in the large per
# attribute if-clauses, below
##############################################################
##################################################################
# WAS DEEPCOPY
self.this_obj = copy.deepcopy(begin_obj)

##############################################################
##################################################################
# Walk all possible attributes to find which target_attribute
# we're iterating on...
##############################################################
##################################################################
iterate_attribute = None
for potential_iter_attr in ['channel', 'subinterface', 'port', 'card', 'slot']:
if isinstance(getattr(begin_obj, potential_iter_attr), int):
Expand Down Expand Up @@ -4072,7 +4089,9 @@ def parse_cisco_interfaces(self, text, debug=False):
# Append a whole range of interfaces...
obj = CiscoInterface(_csv_part.split("-")[0].strip(), debug=debug)
begin_ordinal = getattr(obj, self.iterate_attribute)
end_ordinal = int(_csv_part.split("-")[1].strip())
# parse end_ordinal from 'Eth1/2-4 multipoint'
# ref: https://stackoverflow.com/a/1450900
end_ordinal = int("".join(filter(str.isdigit, _csv_part.split("-")[1].strip())))
if debug is True:
logger.info(f"CiscoRange(text={text}, debug=True) : end_ordinal={end_ordinal}")
else:
Expand Down Expand Up @@ -4393,28 +4412,24 @@ def append(self, val, sort=True, ignore_errors=False, debug=False):
@logger.catch(reraise=True)
def insert(self, idx, val, sort=True):
"""CiscoRange().insert() is disabled because it currently generates a stackoverflow. Use CiscoRange().append() instead."""
# I have to use a bizarre way to deprecate CiscoRange().insert()
# due to the way DeepSource analyzes the code...
if idx != -3.14159265359:
error = "CiscoRange().insert() is disabled because it currently generates a stackoverflow."
logger.critical(error)
raise NotImplementedError(error)
else:
# Insert at the end of the list with new_last_list_idx = len(self._list)
if val in self._list:
raise DuplicateMember(val)
# WAS DEEPCOPY
new_list = copy.deepcopy(self._list)
# This function currently generates a stackoverflow...
raise NotImplementedError()

#pragma warning disable S2190
new_list = new_list.insert(int(idx), val)
#pragma warning restore S2190
if sort is True:
retval = self.attribute_sort(new_list, attribute="sort_list", reverse=False)
else:
retval = new_list
self._list = retval
return self
# Insert at the end of the list with new_last_list_idx = len(self._list)
if val in self._list:
raise DuplicateMember(val)
# WAS DEEPCOPY
new_list = copy.deepcopy(self._list)

#pragma warning disable S2190
new_list = new_list.insert(int(idx), val)
#pragma warning restore S2190
if sort is True:
retval = self.attribute_sort(new_list, attribute="sort_list", reverse=False)
else:
retval = new_list
self._list = retval
return self


# This method is on CiscoRange()
Expand Down
39 changes: 37 additions & 2 deletions tests/test_Ccp_Util.py
Original file line number Diff line number Diff line change
Expand Up @@ -880,8 +880,43 @@ def test_CiscoRange_15():
uut_str = "Eth 2/1/1,2,3-5"
assert CiscoRange(uut_str).as_set(result_type=str) == result_correct

def test_CiscoRange_16():
"""Basic interface port range test"""
result_correct = {"Eth7", "Eth8", "Eth9"}
uut_str = "Eth 7-9"
assert CiscoRange(uut_str).as_set(result_type=str) == result_correct

def test_CiscoRange_17():
"""Basic interface slot and port range test"""
result_correct = {"Eth1/7", "Eth1/8", "Eth1/9"}
uut_str = "Eth 1/7-9"
assert CiscoRange(uut_str).as_set(result_type=str) == result_correct

def test_CiscoRange_18():
"""Basic interface slot, card, and port range test"""
result_correct = {"Eth1/2/7", "Eth1/2/8", "Eth1/2/9"}
uut_str = "Eth 1/2/7-9"
assert CiscoRange(uut_str).as_set(result_type=str) == result_correct

def test_CiscoRange_19():
"""Basic interface slot, card, port, and subinterface range test"""
result_correct = {"Eth1/2/3.7", "Eth1/2/3.8", "Eth1/2/3.9"}
uut_str = "Eth 1/2/3.7-9"
assert CiscoRange(uut_str).as_set(result_type=str) == result_correct

def test_CiscoRange_20():
"""Basic interface slot, card, port, subinterface and channel range test"""
result_correct = {"Eth1/2/3.4:7", "Eth1/2/3.4:8", "Eth1/2/3.4:9"}
uut_str = "Eth 1/2/3.4:7-9"
assert CiscoRange(uut_str).as_set(result_type=str) == result_correct

def test_CiscoRange_21():
"""Basic interface slot, card, port, subinterface, channel and interface_class range test"""
result_correct = {"Eth1/2/3.4:7 multipoint", "Eth1/2/3.4:8 multipoint", "Eth1/2/3.4:9 multipoint"}
uut_str = "Eth 1/2/3.4:7-9 multipoint"
assert CiscoRange(uut_str).as_set(result_type=str) == result_correct

def test_CiscoRange_22():
"""Parse a string with a common prefix on all of the CiscoRange() inputs"""
result_correct = {
"Eth1/1", "Eth1/10", "Eth1/12", "Eth1/13", "Eth1/14",
Expand All @@ -892,7 +927,7 @@ def test_CiscoRange_18():
assert CiscoRange(uut_str).as_set(result_type=str) == result_correct


def test_CiscoRange_19():
def test_CiscoRange_23():
"""Check that the exact results are correct for CiscoRange().as_set() with a redundant input ('Eth1/1')"""
result_correct = {
CiscoInterface("Eth1/1"),
Expand All @@ -906,7 +941,7 @@ def test_CiscoRange_19():
# CiscoRange(text="foo", result_type=None) returns CiscoInterface() instances...
assert CiscoRange(uut_str, result_type=None).as_set(result_type=None) == result_correct

def test_CiscoRange_20():
def test_CiscoRange_24():
"""Check that the exact results are correct for CiscoRange().as_list() with a redundant input ('Eth1/1')"""
result_correct = [
CiscoInterface("Eth1/1"),
Expand Down

0 comments on commit 9f07565

Please sign in to comment.