From b287f3d6c7844d5fe31a3a62c996e4889cf3abd6 Mon Sep 17 00:00:00 2001 From: Brad Walker Date: Sat, 16 May 2020 10:26:39 -0600 Subject: [PATCH 1/5] Remove py23_compat.text_type usage --- napalm_vyos/vyos.py | 59 +++++++++++++++++++++---------------------- test/unit/conftest.py | 4 +-- 2 files changed, 30 insertions(+), 33 deletions(-) diff --git a/napalm_vyos/vyos.py b/napalm_vyos/vyos.py index c2d87d8..e55e097 100644 --- a/napalm_vyos/vyos.py +++ b/napalm_vyos/vyos.py @@ -32,7 +32,6 @@ # NAPALM base import napalm.base.constants as C -from napalm.base.utils import py23_compat from napalm.base.base import NetworkDriver from napalm.base.exceptions import ConnectionException, MergeConfigException, \ ReplaceConfigException, CommitError, \ @@ -347,10 +346,10 @@ def get_interfaces(self): iface_name: { "is_up": bool(is_up), "is_enabled": bool(is_enabled), - "description": py23_compat.text_type(description), + "description": description, "last_flapped": float(-1), "speed": int(speed), - "mac_address": py23_compat.text_type(hw_id) + "mac_address": hw_id, } }) @@ -376,7 +375,7 @@ def get_arp_table(self, vrf=""): 192.168.1.3 ether 00:50:56:86:7b:06 C eth1 """ - if vrf: + if vrf: raise NotImplementedError( "VRF support has not been added for this getter on this platform." ) @@ -395,16 +394,16 @@ def get_arp_table(self, vrf=""): # ["10.129.2.254", "ether", "00:50:56:97:af:b1", "C", "eth0"] # [u'10.0.12.33', u'(incomplete)', u'eth1'] if "incomplete" in line[1]: - macaddr = py23_compat.text_type("00:00:00:00:00:00") + macaddr = "00:00:00:00:00:00" else: - macaddr = py23_compat.text_type(line[2]) + macaddr = line[2] arp_table.append( { - 'interface': py23_compat.text_type(line[-1]), + 'interface': line[-1], 'mac': macaddr, - 'ip': py23_compat.text_type(line[0]), - 'age': 0.0 + 'ip': line[0], + 'age': 0.0, } ) @@ -438,17 +437,17 @@ def get_ntp_stats(self): when = when if when != '-' else 0 ntp_stats.append({ - "remote": py23_compat.text_type(ip), - "referenceid": py23_compat.text_type(refid), + "remote": ip, + "referenceid": refid, "synchronized": bool(synchronized), "stratum": int(st), - "type": py23_compat.text_type(t), - "when": py23_compat.text_type(when), + "type": t, + "when": when, "hostpoll": int(hostpoll), "reachability": int(reachability), "delay": float(delay), "offset": float(offset), - "jitter": float(jitter) + "jitter": float(jitter), }) return ntp_stats @@ -462,7 +461,7 @@ def get_ntp_peers(self): if len(line) > 0: match = re.search("(\d+\.\d+\.\d+\.\d+)\s+", line) ntp_peers.update({ - py23_compat.text_type(match.group(1)): {} + match.group(1): {} }) return ntp_peers @@ -490,7 +489,7 @@ def get_bgp_neighbors(self): output[0]) if not match: return {} - router_id = py23_compat.text_type(match.group(1)) + router_id = match.group(1) local_as = int(match.group(2)) bgp_neighbor_data = dict() @@ -546,11 +545,11 @@ def get_bgp_neighbors(self): bgp_neighbor_data["global"]["peers"].setdefault(peer_id, {}) peer_dict = { - "description": py23_compat.text_type(""), + "description": "", "is_enabled": bool(is_enabled), "local_as": int(local_as), "is_up": bool(is_up), - "remote_id": py23_compat.text_type(remote_rid), + "remote_id": remote_rid, "uptime": int(self._bgp_time_conversion(up_time)), "remote_as": int(remote_as) } @@ -663,15 +662,15 @@ def get_snmp_information(self): for i in config["service"]["snmp"]["community"]: snmp["community"].update({ i: { - "acl": py23_compat.text_type(""), - "mode": py23_compat.text_type(config["service"]["snmp"]["community"][i]["authorization"]) + "acl": "", + "mode": config["service"]["snmp"]["community"][i]["authorization"], } }) snmp.update({ - "chassis_id": py23_compat.text_type(""), - "contact": py23_compat.text_type(config["service"]["snmp"]["contact"]), - "location": py23_compat.text_type(config["service"]["snmp"]["location"]) + "chassis_id": "", + "contact": config["service"]["snmp"]["contact"], + "location": config["service"]["snmp"]["location"], }) return snmp @@ -713,13 +712,13 @@ def get_facts(self): facts = { "uptime": int(uptime), - "vendor": py23_compat.text_type("VyOS"), - "os_version": py23_compat.text_type(version), - "serial_number": py23_compat.text_type(snumber), - "model": py23_compat.text_type(hwmodel), - "hostname": py23_compat.text_type(hostname), - "fqdn": py23_compat.text_type(fqdn), - "interface_list": iface_list + "vendor": "VyOS", + "os_version": version, + "serial_number": snumber, + "model": hwmodel, + "hostname": hostname, + "fqdn": fqdn, + "interface_list": iface_list, } return facts diff --git a/test/unit/conftest.py b/test/unit/conftest.py index c9ed747..6960292 100644 --- a/test/unit/conftest.py +++ b/test/unit/conftest.py @@ -5,7 +5,6 @@ from napalm.base.test import conftest as parent_conftest from napalm.base.test.double import BaseTestDouble -from napalm.base.utils import py23_compat from napalm_vyos import vyos @@ -55,5 +54,4 @@ class FakeVyOSDevice(BaseTestDouble): def send_command(self, command, **kwargs): filename = '{}.text'.format(self.sanitize_text(command)) full_path = self.find_file(filename) - result = self.read_txt_file(full_path) - return py23_compat.text_type(result) + return self.read_txt_file(full_path) From 3b53afd852d245109b8bdce89d814b3b7b2e3311 Mon Sep 17 00:00:00 2001 From: Brad Walker Date: Sat, 16 May 2020 10:31:22 -0600 Subject: [PATCH 2/5] Improve SyntaxWarning for empty string checks --- napalm_vyos/vyos.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/napalm_vyos/vyos.py b/napalm_vyos/vyos.py index e55e097..aa77558 100644 --- a/napalm_vyos/vyos.py +++ b/napalm_vyos/vyos.py @@ -178,7 +178,7 @@ def load_merge_candidate(self, filename=None, config=None): self.device.send_command("cp "+self._BOOT_FILENAME+" " + self._BACKUP_FILENAME) self._new_config = f.read() - cfg = [x for x in self._new_config.split("\n") if x is not ""] + cfg = [x for x in self._new_config.split("\n") if x] output_loadcmd = self.device.send_config_set(cfg) match_setfailed = re.findall("Delete failed", output_loadcmd) match_delfailed = re.findall("Set failed", output_loadcmd) @@ -498,7 +498,7 @@ def get_bgp_neighbors(self): bgp_neighbor_data["global"]["peers"] = {} # delete the header and empty element - bgp_info = [i.strip() for i in output[6:-2] if i is not ""] + bgp_info = [i.strip() for i in output[6:-2] if i] for i in bgp_info: if len(i) > 0: @@ -849,7 +849,7 @@ def ping(self, else: err = "" - if err is not "": + if err: ping_result["error"] = err else: # 'packet_info' example: From cbfe8ae0c4fb59062cb43e35a5201e76cd8ce91b Mon Sep 17 00:00:00 2001 From: Brad Walker Date: Sat, 16 May 2020 10:43:16 -0600 Subject: [PATCH 3/5] Fix invalid escape sequence DeprecationWarnings --- napalm_vyos/vyos.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/napalm_vyos/vyos.py b/napalm_vyos/vyos.py index aa77558..419d65f 100644 --- a/napalm_vyos/vyos.py +++ b/napalm_vyos/vyos.py @@ -308,7 +308,7 @@ def get_interfaces(self): output_iface = self.device.send_command("show interfaces") # Collect all interfaces' name and status - match = re.findall("(\S+)\s+[:\-\d/\.]+\s+([uAD])/([uAD])", output_iface) + match = re.findall(r"(\S+)\s+[:\-\d/\.]+\s+([uAD])/([uAD])", output_iface) # 'match' example: # [("br0", "u", "D"), ("eth0", "u", "u"), ("eth1", "u", "u")...] @@ -431,7 +431,7 @@ def get_ntp_stats(self): # 'remote' contains '*' if the machine synchronized with NTP server synchronized = "*" in remote - match = re.search("(\d+\.\d+\.\d+\.\d+)", remote) + match = re.search(r"(\d+\.\d+\.\d+\.\d+)", remote) ip = match.group(1) when = when if when != '-' else 0 @@ -459,7 +459,7 @@ def get_ntp_peers(self): for line in output_peers: if len(line) > 0: - match = re.search("(\d+\.\d+\.\d+\.\d+)\s+", line) + match = re.search(r"(\d+\.\d+\.\d+\.\d+)\s+", line) ntp_peers.update({ match.group(1): {} }) @@ -485,7 +485,7 @@ def get_bgp_neighbors(self): output = self.device.send_command("show ip bgp summary") output = output.split("\n") - match = re.search(".* router identifier (\d+\.\d+\.\d+\.\d+), local AS number (\d+)", + match = re.search(r".* router identifier (\d+\.\d+\.\d+\.\d+), local AS number (\d+)", output[0]) if not match: return {} @@ -537,10 +537,10 @@ def get_bgp_neighbors(self): """ bgp_detail = self.device.send_command("show ip bgp neighbors %s" % peer_id) - match_rid = re.search("remote router ID (\d+\.\d+\.\d+\.\d+).*", bgp_detail) + match_rid = re.search(r"remote router ID (\d+\.\d+\.\d+\.\d+).*", bgp_detail) remote_rid = match_rid.group(1) - match_prefix_accepted = re.search("(\d+) accepted prefixes", bgp_detail) + match_prefix_accepted = re.search(r"(\d+) accepted prefixes", bgp_detail) accepted_prefixes = match_prefix_accepted.group(1) bgp_neighbor_data["global"]["peers"].setdefault(peer_id, {}) @@ -573,19 +573,19 @@ def _bgp_time_conversion(self, bgp_uptime): return -1 else: if "y" in bgp_uptime: - match = re.search("(\d+)(\w)(\d+)(\w)(\d+)(\w)", bgp_uptime) + match = re.search(r"(\d+)(\w)(\d+)(\w)(\d+)(\w)", bgp_uptime) uptime = ((int(match.group(1)) * self._YEAR_SECONDS) + (int(match.group(3)) * self._WEEK_SECONDS) + (int(match.group(5)) * self._DAY_SECONDS)) return uptime elif "w" in bgp_uptime: - match = re.search("(\d+)(\w)(\d+)(\w)(\d+)(\w)", bgp_uptime) + match = re.search(r"(\d+)(\w)(\d+)(\w)(\d+)(\w)", bgp_uptime) uptime = ((int(match.group(1)) * self._WEEK_SECONDS) + (int(match.group(3)) * self._DAY_SECONDS) + (int(match.group(5)) * self._HOUR_SECONDS)) return uptime elif "d" in bgp_uptime: - match = re.search("(\d+)(\w)(\d+)(\w)(\d+)(\w)", bgp_uptime) + match = re.search(r"(\d+)(\w)(\d+)(\w)(\d+)(\w)", bgp_uptime) uptime = ((int(match.group(1)) * self._DAY_SECONDS) + (int(match.group(3)) * self._HOUR_SECONDS) + (int(match.group(5)) * self._MINUTE_SECONDS)) @@ -612,9 +612,9 @@ def get_interfaces_counters(self): 32776498 279273 0 0 0 0 """ output = self.device.send_command("show interfaces detail") - interfaces = re.findall("(\S+): <.*", output) + interfaces = re.findall(r"(\S+): <.*", output) # count = re.findall("(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+", output) - count = re.findall("(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)", output) + count = re.findall(r"(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)", output) counters = dict() j = 0 @@ -877,7 +877,7 @@ def ping(self, else: rtt_info = rtt_info[-2] - match = re.search("([\d\.]+)/([\d\.]+)/([\d\.]+)/([\d\.]+)", rtt_info) + match = re.search(r"([\d\.]+)/([\d\.]+)/([\d\.]+)/([\d\.]+)", rtt_info) if match is not None: rtt_min = float(match.group(1)) From 2bdb499b14109f154d850753f31096d3ba9538a6 Mon Sep 17 00:00:00 2001 From: Brad Walker Date: Sat, 16 May 2020 10:49:48 -0600 Subject: [PATCH 4/5] Replace _get_value with dict.get usage --- napalm_vyos/vyos.py | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/napalm_vyos/vyos.py b/napalm_vyos/vyos.py index 419d65f..c486533 100644 --- a/napalm_vyos/vyos.py +++ b/napalm_vyos/vyos.py @@ -327,17 +327,12 @@ def get_interfaces(self): ifaces_detail = config["interfaces"][iface_type] for iface_name in ifaces_detail: - description = self._get_value("description", ifaces_detail[iface_name]) - if description is None: - description = "" - speed = self._get_value("speed", ifaces_detail[iface_name]) - if speed is None: - speed = 0 + details = ifaces_detail[iface_name] + description = details.get("description", "") + speed = details.get("speed", "0") if speed == "auto": speed = 0 - hw_id = self._get_value("hw-id", ifaces_detail[iface_name]) - if hw_id is None: - hw_id = "00:00:00:00:00:00" + hw_id = details.get("hw-id", "00:00:00:00:00:00") is_up = (iface_state[iface_name]["Link"] == "u") is_enabled = (iface_state[iface_name]["State"] == "u") @@ -355,13 +350,6 @@ def get_interfaces(self): return iface_dict - @staticmethod - def _get_value(key, target_dict): - if key in target_dict: - return target_dict[key] - else: - return None - def get_arp_table(self, vrf=""): # 'age' is not implemented yet From d2d0f2723f72a729ea002819d4f94c5c343dc4c0 Mon Sep 17 00:00:00 2001 From: Brad Walker Date: Sat, 16 May 2020 10:26:56 -0600 Subject: [PATCH 5/5] Bump minor version and use NAPALM 3 --- .travis.yml | 6 +++--- requirements-dev.txt | 1 - requirements.txt | 4 ++-- setup.py | 8 +++----- tox.ini | 2 +- 5 files changed, 9 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index c43fe17..898b699 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ language: python python: -- 2.7 -- 3.4 -- 3.5 +- 3.6 +- 3.7 +- 3.8 install: - pip install tox-travis - pip install coveralls diff --git a/requirements-dev.txt b/requirements-dev.txt index 17764d7..6b6a977 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,4 +1,3 @@ -future coveralls pytest pytest-cov diff --git a/requirements.txt b/requirements.txt index 50c91a5..ebbf543 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -napalm==2.* +napalm>=3.0 paramiko -netmiko>=1.1.0 +netmiko>=3.1.0 vyattaconfparser diff --git a/setup.py b/setup.py index bf90a64..164a3b4 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ setup( name="napalm-vyos", - version="0.1.6", + version="0.2.0", packages=find_packages(), author="Piotr Pieprzycki", author_email="piotr.pieprzycki@dreamlab.pl", @@ -19,12 +19,10 @@ classifiers=[ 'Topic :: Utilities', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', 'Operating System :: POSIX :: Linux', 'Operating System :: MacOS', ], diff --git a/tox.ini b/tox.ini index 9a30816..1bb34d7 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py27,py35 +envlist = py36,py37,py38 [testenv] deps =