File pynut-replace-telnetlib.patch of Package nut
From 94f6109dfcc34952b00179526b84a6d82eb24e34 Mon Sep 17 00:00:00 2001
From: cgarz <20268068+cgarz@users.noreply.github.com>
Date: Fri, 31 Jan 2025 06:06:00 +0000
Subject: [PATCH 01/16] added replacement read_until and leftover buffer
---
scripts/python/module/PyNUT.py.in | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/scripts/python/module/PyNUT.py.in b/scripts/python/module/PyNUT.py.in
index 6838fc373a..484df8b25a 100644
--- a/scripts/python/module/PyNUT.py.in
+++ b/scripts/python/module/PyNUT.py.in
@@ -84,6 +84,7 @@ class PyNUTClient :
__password = None
__timeout = None
__srv_handler = None
+ __recv_leftover = b''
__version = "1.6.0"
__release = "2023-01-18"
@@ -122,6 +123,19 @@ timeout : Timeout used to wait for network response
except :
pass
+ def __read_until(self, finished_reading_data):
+ data = self.__recv_leftover
+ while (data_end_index := data.find(finished_reading_data)) == -1:
+ data += self.__srv_handler.recv(50) # nut_telnetlib.py uses 50
+ data_end_index += len(finished_reading_data)
+
+ if data_end_index == len(data):
+ self.__recv_leftover = b''
+ else:
+ self.__recv_leftover = data[data_end_index:]
+ data = data[:data_end_index]
+ return data
+
def __connect( self ) :
""" Connects to the defined server
From 60a7ca19a87491be7b58f693977ea5a365290842 Mon Sep 17 00:00:00 2001
From: cgarz <20268068+cgarz@users.noreply.github.com>
Date: Fri, 31 Jan 2025 06:14:33 +0000
Subject: [PATCH 02/16] switch to socket send and replacement read_until
---
scripts/python/module/PyNUT.py.in | 107 ++++++++++++++----------------
1 file changed, 51 insertions(+), 56 deletions(-)
diff --git a/scripts/python/module/PyNUT.py.in b/scripts/python/module/PyNUT.py.in
index 484df8b25a..18f43954ca 100644
--- a/scripts/python/module/PyNUT.py.in
+++ b/scripts/python/module/PyNUT.py.in
@@ -55,8 +55,16 @@
# 2023-01-18 Jim Klimov <jimklimov+nut@gmail.com> - Version 1.6.0
# Added CheckUPSAvailable() method originally by Michal Hlavinka
# from 2013-01-07 RedHat/Fedora packaging
+#
+# 2024-07-01 Jim Klimov <jimklimov+nut@gmail.com> - Version 1.7.0
+# Re-arranged dependency on telnetlib module (deprecated/removed
+# since Python 3.11/3.13), so we can fall back on a privately
+# stashed copy until a better solution is developed.
+#
+# 2025-01-31 cgar <github.com/cgarz> - Version 1.8.0
+# Removed telnetlib dependency. Switched to using socket directly.
-import telnetlib
+import socket
class PyNUTError( Exception ) :
""" Base class for custom exceptions """
@@ -119,7 +113,7 @@ timeout : Timeout used to wait for network response
def __del__( self ) :
""" Class destructor method """
try :
- self.__srv_handler.write( b"LOGOUT\n" )
+ self.__srv_handler.send( b"LOGOUT\n" )
except :
pass
@@ -145,23 +139,24 @@ if something goes wrong.
if self.__debug :
print( "[DEBUG] Connecting to host" )
- self.__srv_handler = telnetlib.Telnet( self.__host, self.__port )
+ self.__srv_handler = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
+ self.__srv_handler.connect( (self.__host, self.__port) )
if self.__login != None :
- self.__srv_handler.write( ("USERNAME %s\n" % self.__login).encode('ascii') )
- result = self.__srv_handler.read_until( b"\n", self.__timeout )
+ self.__srv_handler.send( ("USERNAME %s\n" % self.__login).encode('ascii') )
+ result = self.__read_until( b"\n" )
if result[:2] != b"OK" :
raise PyNUTError( result.replace( b"\n", b"" ).decode('ascii') )
if self.__password != None :
- self.__srv_handler.write( ("PASSWORD %s\n" % self.__password).encode('ascii') )
- result = self.__srv_handler.read_until( b"\n", self.__timeout )
+ self.__srv_handler.send( ("PASSWORD %s\n" % self.__password).encode('ascii') )
+ result = self.__read_until( b"\n" )
if result[:2] != b"OK" :
if result == b"ERR INVALID-ARGUMENT\n" :
# Quote the password (if it has whitespace etc)
# TODO: Escape special chard like NUT does?
- self.__srv_handler.write( ("PASSWORD \"%s\"\n" % self.__password).encode('ascii') )
- result = self.__srv_handler.read_until( b"\n", self.__timeout )
+ self.__srv_handler.send( ("PASSWORD \"%s\"\n" % self.__password).encode('ascii') )
+ result = self.__read_until( b"\n" )
if result[:2] != b"OK" :
raise PyNUTError( result.replace( b"\n", b"" ).decode('ascii') )
else:
@@ -179,12 +174,12 @@ which is of little concern for Python2 but is important in Python3
if self.__debug :
print( "[DEBUG] GetUPSList from server" )
- self.__srv_handler.write( b"LIST UPS\n" )
- result = self.__srv_handler.read_until( b"\n" )
- if result != b"BEGIN LIST UPS\n" :
+ self.__srv_handler.send( b"LIST UPS\n" )
+ result = self.__read_until( b"\n" )
+ if result != b"BEGIN LIST UPS\n":
raise PyNUTError( result.replace( b"\n", b"" ).decode('ascii') )
- result = self.__srv_handler.read_until( b"END LIST UPS\n" )
+ result = self.__read_until( b"END LIST UPS\n" )
ups_list = {}
for line in result.split( b"\n" ) :
@@ -219,13 +214,13 @@ available vars.
if self.__debug :
print( "[DEBUG] GetUPSVars called..." )
- self.__srv_handler.write( ("LIST VAR %s\n" % ups).encode('ascii') )
- result = self.__srv_handler.read_until( b"\n" )
+ self.__srv_handler.send( ("LIST VAR %s\n" % ups).encode('ascii') )
+ result = self.__read_until( b"\n" )
if result != ("BEGIN LIST VAR %s\n" % ups).encode('ascii') :
raise PyNUTError( result.replace( b"\n", b"" ).decode('ascii') )
ups_vars = {}
- result = self.__srv_handler.read_until( ("END LIST VAR %s\n" % ups).encode('ascii') )
+ result = self.__read_until( ("END LIST VAR %s\n" % ups).encode('ascii') )
offset = len( ("VAR %s " % ups ).encode('ascii') )
end_offset = 0 - ( len( ("END LIST VAR %s\n" % ups).encode('ascii') ) + 1 )
@@ -245,12 +240,12 @@ The result is True (reachable) or False (unreachable)
if self.__debug :
print( "[DEBUG] CheckUPSAvailable called..." )
- self.__srv_handler.write( ("LIST CMD %s\n" % ups).encode('ascii') )
- result = self.__srv_handler.read_until( b"\n" )
+ self.__srv_handler.send( ("LIST CMD %s\n" % ups).encode('ascii') )
+ result = self.__read_until( b"\n" )
if result != ("BEGIN LIST CMD %s\n" % ups).encode('ascii') :
return False
- self.__srv_handler.read_until( ("END LIST CMD %s\n" % ups).encode('ascii') )
+ self.__read_until( ("END LIST CMD %s\n" % ups).encode('ascii') )
return True
def GetUPSCommands( self, ups="" ) :
@@ -262,13 +257,13 @@ of the command as value
if self.__debug :
print( "[DEBUG] GetUPSCommands called..." )
- self.__srv_handler.write( ("LIST CMD %s\n" % ups).encode('ascii') )
- result = self.__srv_handler.read_until( b"\n" )
+ self.__srv_handler.send( ("LIST CMD %s\n" % ups).encode('ascii') )
+ result = self.__read_until( b"\n" )
if result != ("BEGIN LIST CMD %s\n" % ups).encode('ascii') :
raise PyNUTError( result.replace( b"\n", b"" ).decode('ascii') )
ups_cmds = {}
- result = self.__srv_handler.read_until( ("END LIST CMD %s\n" % ups).encode('ascii') )
+ result = self.__read_until( ("END LIST CMD %s\n" % ups).encode('ascii') )
offset = len( ("CMD %s " % ups).encode('ascii') )
end_offset = 0 - ( len( ("END LIST CMD %s\n" % ups).encode('ascii') ) + 1 )
@@ -277,8 +272,8 @@ of the command as value
# For each var we try to get the available description
try :
- self.__srv_handler.write( ("GET CMDDESC %s %s\n" % ( ups, var )).encode('ascii') )
- temp = self.__srv_handler.read_until( b"\n" )
+ self.__srv_handler.send( ("GET CMDDESC %s %s\n" % ( ups, var )).encode('ascii') )
+ temp = self.__read_until( b"\n" )
if temp[:7] != b"CMDDESC" :
raise PyNUTError
else :
@@ -299,12 +294,12 @@ The result is presented as a dictionary containing 'key->val' pairs
if self.__debug :
print( "[DEBUG] GetUPSVars from '%s'..." % ups )
- self.__srv_handler.write( ("LIST RW %s\n" % ups).encode('ascii') )
- result = self.__srv_handler.read_until( b"\n" )
+ self.__srv_handler.send( ("LIST RW %s\n" % ups).encode('ascii') )
+ result = self.__read_until( b"\n" )
if ( result != ("BEGIN LIST RW %s\n" % ups).encode('ascii') ) :
raise PyNUTError( result.replace( b"\n", b"" ).decode('ascii') )
- result = self.__srv_handler.read_until( ("END LIST RW %s\n" % ups).encode('ascii') )
+ result = self.__read_until( ("END LIST RW %s\n" % ups).encode('ascii') )
offset = len( ("VAR %s" % ups).encode('ascii') )
end_offset = 0 - ( len( ("END LIST RW %s\n" % ups).encode('ascii') ) + 1 )
rw_vars = {}
@@ -327,8 +322,8 @@ The variable must be a writable value (cf GetRWVars) and you must have the prope
rights to set it (maybe login/password).
"""
- self.__srv_handler.write( ("SET VAR %s %s %s\n" % ( ups, var, value )).encode('ascii') )
- result = self.__srv_handler.read_until( b"\n" )
+ self.__srv_handler.send( ("SET VAR %s %s %s\n" % ( ups, var, value )).encode('ascii') )
+ result = self.__read_until( b"\n" )
if ( result == b"OK\n" ) :
return( "OK" )
else :
@@ -343,8 +338,8 @@ Returns OK on success or raises an error
if self.__debug :
print( "[DEBUG] RunUPSCommand called..." )
- self.__srv_handler.write( ("INSTCMD %s %s\n" % ( ups, command )).encode('ascii') )
- result = self.__srv_handler.read_until( b"\n" )
+ self.__srv_handler.send( ("INSTCMD %s %s\n" % ( ups, command )).encode('ascii') )
+ result = self.__read_until( b"\n" )
if ( result == b"OK\n" ) :
return( "OK" )
else :
@@ -369,12 +364,12 @@ of connection.
print( "[DEBUG] DeviceLogin: %s is not a valid UPS" % ups )
raise PyNUTError( "ERR UNKNOWN-UPS" )
- self.__srv_handler.write( ("LOGIN %s\n" % ups).encode('ascii') )
- result = self.__srv_handler.read_until( b"\n" )
+ self.__srv_handler.send( ("LOGIN %s\n" % ups).encode('ascii') )
+ result = self.__read_until( b"\n" )
if ( result.startswith( ("User %s@" % self.__login).encode('ascii')) and result.endswith (("[%s]\n" % ups).encode('ascii')) ):
# User dummy-user@127.0.0.1 logged into UPS [dummy]
# Read next line then
- result = self.__srv_handler.read_until( b"\n" )
+ result = self.__read_until( b"\n" )
if ( result == b"OK\n" ) :
return( "OK" )
else :
@@ -392,13 +387,13 @@ NOTE: API changed since NUT 2.8.0 to replace MASTER with PRIMARY
if self.__debug :
print( "[DEBUG] PRIMARY called..." )
- self.__srv_handler.write( ("PRIMARY %s\n" % ups).encode('ascii') )
- result = self.__srv_handler.read_until( b"\n" )
+ self.__srv_handler.send( ("PRIMARY %s\n" % ups).encode('ascii') )
+ result = self.__read_until( b"\n" )
if ( result != b"OK PRIMARY-GRANTED\n" ) :
if self.__debug :
print( "[DEBUG] Retrying: MASTER called..." )
- self.__srv_handler.write( ("MASTER %s\n" % ups).encode('ascii') )
- result = self.__srv_handler.read_until( b"\n" )
+ self.__srv_handler.send( ("MASTER %s\n" % ups).encode('ascii') )
+ result = self.__read_until( b"\n" )
if ( result != b"OK MASTER-GRANTED\n" ) :
if self.__debug :
print( "[DEBUG] Primary level functions are not available" )
@@ -406,8 +401,8 @@ NOTE: API changed since NUT 2.8.0 to replace MASTER with PRIMARY
if self.__debug :
print( "[DEBUG] FSD called..." )
- self.__srv_handler.write( ("FSD %s\n" % ups).encode('ascii') )
- result = self.__srv_handler.read_until( b"\n" )
+ self.__srv_handler.send( ("FSD %s\n" % ups).encode('ascii') )
+ result = self.__read_until( b"\n" )
if ( result == b"OK FSD-SET\n" ) :
return( "OK" )
else :
@@ -420,8 +415,8 @@ NOTE: API changed since NUT 2.8.0 to replace MASTER with PRIMARY
if self.__debug :
print( "[DEBUG] HELP called..." )
- self.__srv_handler.write( b"HELP\n" )
- return self.__srv_handler.read_until( b"\n" )
+ self.__srv_handler.send( b"HELP\n" )
+ return self.__read_until( b"\n" )
def ver(self) :
""" Send VER command
@@ -430,8 +425,8 @@ NOTE: API changed since NUT 2.8.0 to replace MASTER with PRIMARY
if self.__debug :
print( "[DEBUG] VER called..." )
- self.__srv_handler.write( b"VER\n" )
- return self.__srv_handler.read_until( b"\n" )
+ self.__srv_handler.send( b"VER\n" )
+ return self.__read_until( b"\n" )
def ListClients( self, ups = None ) :
""" Returns the list of connected clients from the NUT server
@@ -449,12 +444,12 @@ The result is a dictionary containing 'key->val' pairs of 'UPSName' and a list o
raise PyNUTError( "ERR UNKNOWN-UPS" )
if ups:
- self.__srv_handler.write( ("LIST CLIENT %s\n" % ups).encode('ascii') )
+ self.__srv_handler.send( ("LIST CLIENT %s\n" % ups).encode('ascii') )
else:
# NOTE: Currently NUT does not support just listing all clients
# (not providing an "ups" argument) => NUT_ERR_INVALID_ARGUMENT
- self.__srv_handler.write( b"LIST CLIENT\n" )
- result = self.__srv_handler.read_until( b"\n" )
+ self.__srv_handler.send( b"LIST CLIENT\n" )
+ result = self.__read_until( b"\n" )
if ( (ups and result != ("BEGIN LIST CLIENT %s\n" % ups).encode('ascii')) or (ups is None and result != b"BEGIN LIST CLIENT\n") ):
if ups is None and (result == b"ERR INVALID-ARGUMENT\n") :
# For ups==None, list all upses, list their clients
@@ -472,11 +467,11 @@ The result is a dictionary containing 'key->val' pairs of 'UPSName' and a list o
raise PyNUTError( result.replace( b"\n", b"" ).decode('ascii') )
- if ups :
- result = self.__srv_handler.read_until( ("END LIST CLIENT %s\n" % ups).encode('ascii') )
+ if ups:
+ result = self.__read_until( ("END LIST CLIENT %s\n" % ups).encode('ascii') )
else:
# Should not get here with current NUT:
- result = self.__srv_handler.read_until( b"END LIST CLIENT\n" )
+ result = self.__read_until( b"END LIST CLIENT\n" )
ups_list = {}
for line in result.split( b"\n" ):
From 1209078c62ad4b6138029f59b33dff4008235ad5 Mon Sep 17 00:00:00 2001
From: cgarz <20268068+cgarz@users.noreply.github.com>
Date: Fri, 31 Jan 2025 06:19:16 +0000
Subject: [PATCH 03/16] Switch to socket timeout, fix its init argument
---
scripts/python/module/PyNUT.py.in | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/scripts/python/module/PyNUT.py.in b/scripts/python/module/PyNUT.py.in
index 18f43954ca..66e4b6c0d6 100644
--- a/scripts/python/module/PyNUT.py.in
+++ b/scripts/python/module/PyNUT.py.in
@@ -105,7 +105,7 @@ timeout : Timeout used to wait for network response
self.__port = port
self.__login = login
self.__password = password
- self.__timeout = 5
+ self.__timeout = timeout
self.__connect()
@@ -141,6 +141,7 @@ if something goes wrong.
self.__srv_handler = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
self.__srv_handler.connect( (self.__host, self.__port) )
+ self.__srv_handler.settimeout( self.__timeout )
if self.__login != None :
self.__srv_handler.send( ("USERNAME %s\n" % self.__login).encode('ascii') )
From 7ee628f920bd11dd5565b0e10cbfa6fd54aa23c8 Mon Sep 17 00:00:00 2001
From: cgarz <20268068+cgarz@users.noreply.github.com>
Date: Tue, 4 Feb 2025 22:27:01 +0000
Subject: [PATCH 04/16] Remove walrus op for older python compatibility.
---
scripts/python/module/PyNUT.py.in | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/scripts/python/module/PyNUT.py.in b/scripts/python/module/PyNUT.py.in
index 66e4b6c0d6..ced5231193 100644
--- a/scripts/python/module/PyNUT.py.in
+++ b/scripts/python/module/PyNUT.py.in
@@ -119,8 +119,12 @@ timeout : Timeout used to wait for network response
def __read_until(self, finished_reading_data):
data = self.__recv_leftover
- while (data_end_index := data.find(finished_reading_data)) == -1:
- data += self.__srv_handler.recv(50) # nut_telnetlib.py uses 50
+ while True:
+ data_end_index = data.find(finished_reading_data)
+ if data_end_index == -1:
+ data += self.__srv_handler.recv(50) # nut_telnetlib.py uses 50
+ else:
+ break
data_end_index += len(finished_reading_data)
if data_end_index == len(data):
From 9f81e81af3f8bed3fb1e501b5c0b8f638f28f125 Mon Sep 17 00:00:00 2001
From: cgarz <20268068+cgarz@users.noreply.github.com>
Date: Fri, 7 Feb 2025 08:45:40 +0000
Subject: [PATCH 05/16] Use socket create_connection instead of connect,
Handles choosing IPv4 and IPv6 automatically.
---
scripts/python/module/PyNUT.py.in | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/scripts/python/module/PyNUT.py.in b/scripts/python/module/PyNUT.py.in
index ced5231193..b815c4af73 100644
--- a/scripts/python/module/PyNUT.py.in
+++ b/scripts/python/module/PyNUT.py.in
@@ -143,9 +143,10 @@ if something goes wrong.
if self.__debug :
print( "[DEBUG] Connecting to host" )
- self.__srv_handler = socket.socket( socket.AF_INET, socket.SOCK_STREAM )
- self.__srv_handler.connect( (self.__host, self.__port) )
- self.__srv_handler.settimeout( self.__timeout )
+ self.__srv_handler = socket.create_connection(
+ (self.__host, self.__port),
+ self.__timeout
+ )
if self.__login != None :
self.__srv_handler.send( ("USERNAME %s\n" % self.__login).encode('ascii') )
From cf0ea3e447f3d97237ba8575202437a59355bd3a Mon Sep 17 00:00:00 2001
From: cgarz <20268068+cgarz@users.noreply.github.com>
Date: Fri, 7 Feb 2025 08:47:38 +0000
Subject: [PATCH 06/16] Update PyNUT changelog, bump version to 1.8.0
---
scripts/python/module/PyNUT.py.in | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/scripts/python/module/PyNUT.py.in b/scripts/python/module/PyNUT.py.in
index b815c4af73..0e136d3669 100644
--- a/scripts/python/module/PyNUT.py.in
+++ b/scripts/python/module/PyNUT.py.in
@@ -74,8 +82,8 @@ class PyNUTClient :
__srv_handler = None
__recv_leftover = b''
- __version = "1.6.0"
- __release = "2023-01-18"
+ __version = "1.8.0"
+ __release = "2025-02-07"
def __init__( self, host="127.0.0.1", port=3493, login=None, password=None, debug=False, timeout=5 ) :
From 0488ec573943468fb0e0570c396b66c2dfcc35d9 Mon Sep 17 00:00:00 2001
From: cgarz <20268068+cgarz@users.noreply.github.com>
Date: Fri, 7 Feb 2025 08:57:21 +0000
Subject: [PATCH 12/16] Update setup.py.in, remove install_requires lib
---
scripts/python/module/setup.py.in | 5 -----
1 file changed, 5 deletions(-)
diff --git a/scripts/python/module/setup.py.in b/scripts/python/module/setup.py.in
index 10ada3ecd6..d520c960f9 100644
--- a/scripts/python/module/setup.py.in
+++ b/scripts/python/module/setup.py.in
@@ -30,7 +30,6 @@ setup(
#data_files = [('', ['tox.ini'])],
#scripts = ['PyNUTClient/test_nutclient.py', 'PyNUTClient/__init__.py'],
python_requires = '>=2.6',
- # install_requires = ['telnetlib'], # NOTE: telnetlib.py is part of Python core for tested 2.x and 3.x versions, not something 'pip' can download
keywords = ['pypi', 'cicd', 'python', 'nut', 'Network UPS Tools'],
classifiers = [
"Development Status :: 5 - Production/Stable",
From 6d671b039e6df10091f6219ed9ae7169bf25c6e5 Mon Sep 17 00:00:00 2001
From: Jim Klimov <jimklimov+nut@gmail.com>
Date: Fri, 7 Feb 2025 12:24:14 +0100
Subject: [PATCH 14/16] configure.ac: restore nut_with_pynut_py* checks from
v2.8.2, but test for "socket" instead of "telnetlib" module [#2183]
Signed-off-by: Jim Klimov <jimklimov+nut@gmail.com>
---
configure.ac | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
diff --git a/configure.ac b/configure.ac
index 07febb3cb8..8d278d8085 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2384,7 +2384,7 @@ if test x"${nut_with_pynut}" != xno \
if test -n "${PYTHON2}" \
&& (command -v ${PYTHON2} || which ${PYTHON2}) >/dev/null 2>/dev/null \
; then
- if ${PYTHON2} -c "import telnetlib" \
+ if ${PYTHON2} -c "import socket" \
; then
nut_with_pynut_py2="yes"
fi
@@ -2393,7 +2393,7 @@ if test x"${nut_with_pynut}" != xno \
if test -n "${PYTHON3}" \
&& (command -v ${PYTHON3} || which ${PYTHON3}) >/dev/null 2>/dev/null \
; then
- if ${PYTHON3} -c "import telnetlib" \
+ if ${PYTHON3} -c "import socket" \
; then
nut_with_pynut_py3="yes"
fi
@@ -2404,7 +2404,7 @@ if test x"${nut_with_pynut}" != xno \
&& (command -v ${PYTHON} || which ${PYTHON}) >/dev/null 2>/dev/null \
&& test "${PYTHON}" != "${PYTHON2}" -a "${PYTHON}" != "${PYTHON3}" \
; then
- if ${PYTHON} -c "import telnetlib" \
+ if ${PYTHON} -c "import socket" \
; then
nut_with_pynut_py="yes"
fi
From c5540c43d28d7bfcae9426b92a44a805d7ac27bd Mon Sep 17 00:00:00 2001
From: Jim Klimov <jimklimov+nut@gmail.com>
Date: Fri, 7 Feb 2025 15:32:34 +0100
Subject: [PATCH 16/16] tests/NIT/nit.sh: update comment about use of two
explicit localhost IPv4/6 addresses, not a name, for upsd.conf
Signed-off-by: Jim Klimov <jimklimov+nut@gmail.com>
---
tests/NIT/nit.sh | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/NIT/nit.sh b/tests/NIT/nit.sh
index befec52803..cf0a98bb7f 100755
--- a/tests/NIT/nit.sh
+++ b/tests/NIT/nit.sh
@@ -363,8 +363,8 @@ EOF
fi
# Some systems listining on symbolic "localhost" actually
- # only bind to IPv6, and Python telnetlib resolves IPv4
- # and fails its connection tests. Others fare well with
+ # only bind to IPv6, and some (Python) client might resolve
+ # IPv4 and fail its connection tests. Others fare well with
# both addresses in one command.
for LH in 127.0.0.1 '::1' ; do
if (