From e73905769c1fa3bb6d6cc61d4616edf87beacd68 Mon Sep 17 00:00:00 2001 From: Federico Capoano Date: Fri, 21 Aug 2026 19:45:45 -0300 Subject: [PATCH 1/3] [deps] Replaced Exscript with telnetlib3 #166 Closes #166. --- netdiff/parsers/base.py | 2 +- requirements.txt | 2 +- tests/test_base.py | 9 +++++++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/netdiff/parsers/base.py b/netdiff/parsers/base.py index dd3eddb..033306f 100644 --- a/netdiff/parsers/base.py +++ b/netdiff/parsers/base.py @@ -2,7 +2,7 @@ import networkx import requests -from Exscript.protocols import telnetlib +from telnetlib3 import telnetlib from ..exceptions import ConversionException, TopologyRetrievalError from ..utils import _netjson_networkgraph, diff diff --git a/requirements.txt b/requirements.txt index dd10cb3..cd61d0c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,4 @@ requests<3.0 libcnml<0.10.0 openvpn-status>=0.2,<0.3 networkx>=3.4,<3.7 -Exscript>=2.6.32 +telnetlib3>=5,<6 diff --git a/tests/test_base.py b/tests/test_base.py index e0fe6b9..4c799b4 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -3,9 +3,11 @@ import responses from requests.exceptions import ConnectionError +from telnetlib3 import telnetlib as telnetlib3 from netdiff import get_version from netdiff.exceptions import ConversionException, NetJsonError, TopologyRetrievalError +from netdiff.parsers import base from netdiff.parsers.base import BaseParser from netdiff.utils import _netjson_networkgraph @@ -18,6 +20,9 @@ class TestBaseParser(unittest.TestCase): """BaseParser tests""" + def test_telnet_uses_telnetlib3(self): + self.assertIs(base.telnetlib, telnetlib3) + def _load_contents(self, file): return open(os.path.abspath(file)).read() @@ -63,13 +68,13 @@ def request_callback(request): with self.assertRaises(TopologyRetrievalError): BaseParser(url="http://connectionerror.com") - @mock.patch("Exscript.protocols.telnetlib.Telnet") + @mock.patch("netdiff.parsers.base.telnetlib.Telnet") def test_telnet_retrieval_error(self, MockClass): MockClass.side_effect = ValueError("testing exception") with self.assertRaises(TopologyRetrievalError): BaseParser(url="telnet://wrong.com") - @mock.patch("Exscript.protocols.telnetlib.Telnet") + @mock.patch("netdiff.parsers.base.telnetlib.Telnet") def test_telnet_retrieval(self, MockClass): with self.assertRaises(ConversionException): BaseParser(url="telnet://127.0.0.1") From b84cce14df661473216591386b0284a6c69b01bf Mon Sep 17 00:00:00 2001 From: Federico Capoano Date: Sat, 22 Aug 2026 11:18:39 -0300 Subject: [PATCH 2/3] [chores] Addressed review feedback --- tests/test_base.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/test_base.py b/tests/test_base.py index 4c799b4..60f62ec 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -76,8 +76,16 @@ def test_telnet_retrieval_error(self, MockClass): @mock.patch("netdiff.parsers.base.telnetlib.Telnet") def test_telnet_retrieval(self, MockClass): - with self.assertRaises(ConversionException): - BaseParser(url="telnet://127.0.0.1") + telnet = MockClass.return_value + telnet.read_all.return_value = b"{}" + + parser = BaseParser(url="telnet://127.0.0.1:23") + + self.assertIsInstance(parser.original_data, dict) + MockClass.assert_called_once_with("127.0.0.1", 23, timeout=None) + telnet.write.assert_called_once_with(b"\r\n") + telnet.read_all.assert_called_once_with() + telnet.close.assert_called_once_with() def test_topology_retrieval_error_file(self): with self.assertRaises(TopologyRetrievalError): From 26188a0620296ddd87987c7c54e4555c10a46707 Mon Sep 17 00:00:00 2001 From: Federico Capoano Date: Sat, 22 Aug 2026 11:51:26 -0300 Subject: [PATCH 3/3] [chores] Addressed review feedback --- tests/test_base.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/test_base.py b/tests/test_base.py index 60f62ec..19176d4 100644 --- a/tests/test_base.py +++ b/tests/test_base.py @@ -78,9 +78,7 @@ def test_telnet_retrieval_error(self, MockClass): def test_telnet_retrieval(self, MockClass): telnet = MockClass.return_value telnet.read_all.return_value = b"{}" - parser = BaseParser(url="telnet://127.0.0.1:23") - self.assertIsInstance(parser.original_data, dict) MockClass.assert_called_once_with("127.0.0.1", 23, timeout=None) telnet.write.assert_called_once_with(b"\r\n")