@@ -712,10 +712,19 @@ certhost : Optional dict or list of dict/lists: {hostname: [certname, certver
712712 def __del__( self ) :
713713 """ Class destructor method """
714714 try :
715- self.__srv_handler.send ( b"LOGOUT\n" )
715+ self.__send ( b"LOGOUT\n" )
716716 except :
717717 pass
718718
719+ def __send(self, data):
720+ """ Internal method to send data through the socket with error handling """
721+ try:
722+ self.__srv_handler.sendall(data)
723+ except (AttributeError, socket.error) as e:
724+ if self.__debug:
725+ print("[DEBUG] Send failed: %s" % str(e))
726+ raise e
727+
719728 def __read_until(self, finished_reading_data):
720729 data = self.__recv_leftover
721730 while True:
@@ -753,7 +762,7 @@ if something goes wrong.
753762 if self.__use_ssl :
754763 if self.__debug :
755764 print( "[DEBUG] Requesting STARTTLS" )
756- self.__srv_handler.send ( b"STARTTLS\n" )
765+ self.__send ( b"STARTTLS\n" )
757766 result = self.__read_until( b"\n" )
758767 if result[:11] == b"OK STARTTLS" :
759768 if self.__debug :
@@ -806,19 +815,19 @@ if something goes wrong.
806815 self.__use_ssl = False
807816
808817 if self.__login != None :
809- self.__srv_handler.send ( ("USERNAME %s\n" % self.__login).encode('ascii') )
818+ self.__send ( ("USERNAME %s\n" % self.__login).encode('ascii') )
810819 result = self.__read_until( b"\n" )
811820 if result[:2] != b"OK" :
812821 raise PyNUTError( result.replace( b"\n", b"" ).decode('ascii') )
813822
814823 if self.__password != None :
815- self.__srv_handler.send ( ("PASSWORD %s\n" % self.__password).encode('ascii') )
824+ self.__send ( ("PASSWORD %s\n" % self.__password).encode('ascii') )
816825 result = self.__read_until( b"\n" )
817826 if result[:2] != b"OK" :
818827 if result == b"ERR INVALID-ARGUMENT\n" :
819828 # Quote the password (if it has whitespace etc)
820829 # TODO: Escape special chard like NUT does?
821- self.__srv_handler.send ( ("PASSWORD \"%s\"\n" % self.__password).encode('ascii') )
830+ self.__send ( ("PASSWORD \"%s\"\n" % self.__password).encode('ascii') )
822831 result = self.__read_until( b"\n" )
823832 if result[:2] != b"OK" :
824833 raise PyNUTError( result.replace( b"\n", b"" ).decode('ascii') )
@@ -849,7 +858,7 @@ if something goes wrong.
849858 # TOTHINK # raise PyNUTError( "Invalid setting for TRACKING mode was requested" )
850859 return None
851860
852- self.__srv_handler.send ( ("SET TRACKING %s\n" % value).encode('ascii') )
861+ self.__send ( ("SET TRACKING %s\n" % value).encode('ascii') )
853862 result = self.__read_until( b"\n" )
854863 if result == b"OK\n" :
855864 self.__tracking = value
@@ -879,7 +888,7 @@ if something goes wrong.
879888 if self.__debug :
880889 print( "[DEBUG] GetTrackingResult for %s" % tracking_id )
881890
882- self.__srv_handler.send ( ("GET TRACKING %s\n" % tracking_id).encode('ascii') )
891+ self.__send ( ("GET TRACKING %s\n" % tracking_id).encode('ascii') )
883892 result = self.__read_until( b"\n" )
884893 if result in [b"PENDING\n", b"SUCCESS\n"]:
885894 return result.replace( b"\n", b"" ).decode('ascii')
@@ -929,12 +938,14 @@ if something goes wrong.
929938 """
930939 result = None
931940 try:
932- self.__srv_handler.send ( ("PROTVER\n").encode('ascii') )
941+ self.__send ( ("PROTVER\n").encode('ascii') )
933942 result = self.__read_until( b"\n" )
934943 except PyNUTError as ignored:
935944 # Deprecated and hidden, but may be what ancient NUT servers say
936945 # May throw if the error is due to (non-)connection
937- self.__srv_handler.send( ("NETVER\n").encode('ascii') )
946+ # Here we assume that any other exceptions are due to broken
947+ # connection etc. and forward them to caller right away.
948+ self.__send( ("NETVER\n").encode('ascii') )
938949 result = self.__read_until( b"\n" )
939950
940951 # print ( "[DEBUG] isValidProtocolVersion: version_re='%s' result='%s'" % (str(version_re), str(result)))
@@ -960,7 +971,7 @@ if something goes wrong.
960971 if self.__debug :
961972 print( "[DEBUG] GetVariableType for %s / %s" % ( ups, var ) )
962973
963- self.__srv_handler.send ( ("GET TYPE %s %s\n" % ( ups, var )).encode('ascii') )
974+ self.__send ( ("GET TYPE %s %s\n" % ( ups, var )).encode('ascii') )
964975 result = self.__read_until( b"\n" )
965976 if result[:4] == b"TYPE" :
966977 # TYPE <ups> <var> <type>
@@ -975,7 +986,7 @@ if something goes wrong.
975986 if self.__debug :
976987 print( "[DEBUG] GetVariableDescription for %s / %s" % ( ups, var ) )
977988
978- self.__srv_handler.send ( ("GET DESC %s %s\n" % ( ups, var )).encode('ascii') )
989+ self.__send ( ("GET DESC %s %s\n" % ( ups, var )).encode('ascii') )
979990 result = self.__read_until( b"\n" )
980991 if result[:4] == b"DESC" :
981992 # DESC <ups> <var> "<description>"
@@ -990,7 +1001,7 @@ if something goes wrong.
9901001 if self.__debug :
9911002 print( "[DEBUG] GetEnumList for %s / %s" % ( ups, var ) )
9921003
993- self.__srv_handler.send ( ("LIST ENUM %s %s\n" % ( ups, var )).encode('ascii') )
1004+ self.__send ( ("LIST ENUM %s %s\n" % ( ups, var )).encode('ascii') )
9941005 result = self.__read_until( b"\n" )
9951006 if result != ("BEGIN LIST ENUM %s %s\n" % ( ups, var )).encode('ascii') :
9961007 raise PyNUTError( result.replace( b"\n", b"" ).decode('ascii') )
@@ -1011,7 +1022,7 @@ if something goes wrong.
10111022 if self.__debug :
10121023 print( "[DEBUG] GetRangeList for %s / %s" % ( ups, var ) )
10131024
1014- self.__srv_handler.send ( ("LIST RANGE %s %s\n" % ( ups, var )).encode('ascii') )
1025+ self.__send ( ("LIST RANGE %s %s\n" % ( ups, var )).encode('ascii') )
10151026 result = self.__read_until( b"\n" )
10161027 if result != ("BEGIN LIST RANGE %s %s\n" % ( ups, var )).encode('ascii') :
10171028 raise PyNUTError( result.replace( b"\n", b"" ).decode('ascii') )
@@ -1034,7 +1045,7 @@ if something goes wrong.
10341045 if self.__debug :
10351046 print( "[DEBUG] GetDeviceNumLogins for %s" % ups )
10361047
1037- self.__srv_handler.send ( ("GET NUMLOGINS %s\n" % ups).encode('ascii') )
1048+ self.__send ( ("GET NUMLOGINS %s\n" % ups).encode('ascii') )
10381049 result = self.__read_until( b"\n" )
10391050 if result[:9] == b"NUMLOGINS" :
10401051 # NUMLOGINS <ups> <value>
@@ -1054,7 +1065,7 @@ which is of little concern for Python2 but is important in Python3
10541065 if self.__debug :
10551066 print( "[DEBUG] GetUPSList from server" )
10561067
1057- self.__srv_handler.send ( b"LIST UPS\n" )
1068+ self.__send ( b"LIST UPS\n" )
10581069 result = self.__read_until( b"\n" )
10591070 if result != b"BEGIN LIST UPS\n":
10601071 raise PyNUTError( result.replace( b"\n", b"" ).decode('ascii') )
@@ -1094,7 +1105,7 @@ available vars.
10941105 if self.__debug :
10951106 print( "[DEBUG] GetUPSVars called..." )
10961107
1097- self.__srv_handler.send ( ("LIST VAR %s\n" % ups).encode('ascii') )
1108+ self.__send ( ("LIST VAR %s\n" % ups).encode('ascii') )
10981109 result = self.__read_until( b"\n" )
10991110 if result != ("BEGIN LIST VAR %s\n" % ups).encode('ascii') :
11001111 raise PyNUTError( result.replace( b"\n", b"" ).decode('ascii') )
@@ -1120,7 +1131,7 @@ The result is True (reachable) or False (unreachable)
11201131 if self.__debug :
11211132 print( "[DEBUG] CheckUPSAvailable called..." )
11221133
1123- self.__srv_handler.send ( ("LIST CMD %s\n" % ups).encode('ascii') )
1134+ self.__send ( ("LIST CMD %s\n" % ups).encode('ascii') )
11241135 result = self.__read_until( b"\n" )
11251136 if result != ("BEGIN LIST CMD %s\n" % ups).encode('ascii') :
11261137 return False
@@ -1137,7 +1148,7 @@ of the command as value
11371148 if self.__debug :
11381149 print( "[DEBUG] GetUPSCommands called..." )
11391150
1140- self.__srv_handler.send ( ("LIST CMD %s\n" % ups).encode('ascii') )
1151+ self.__send ( ("LIST CMD %s\n" % ups).encode('ascii') )
11411152 result = self.__read_until( b"\n" )
11421153 if result != ("BEGIN LIST CMD %s\n" % ups).encode('ascii') :
11431154 raise PyNUTError( result.replace( b"\n", b"" ).decode('ascii') )
@@ -1152,7 +1163,7 @@ of the command as value
11521163
11531164 # For each var we try to get the available description
11541165 try :
1155- self.__srv_handler.send ( ("GET CMDDESC %s %s\n" % ( ups, var )).encode('ascii') )
1166+ self.__send ( ("GET CMDDESC %s %s\n" % ( ups, var )).encode('ascii') )
11561167 temp = self.__read_until( b"\n" )
11571168 if temp[:7] != b"CMDDESC" :
11581169 raise PyNUTError
@@ -1208,7 +1219,7 @@ rights to set it (maybe login/password).
12081219 do_wait = True
12091220 self.EnableTrackingModeOnce()
12101221
1211- self.__srv_handler.send ( ("SET VAR %s %s %s\n" % ( ups, var, value )).encode('ascii') )
1222+ self.__send ( ("SET VAR %s %s %s\n" % ( ups, var, value )).encode('ascii') )
12121223 result = self.__read_until( b"\n" )
12131224 if ( result == b"OK\n" ) :
12141225 return( "OK" )
@@ -1240,7 +1251,7 @@ Returns OK on success or raises an error
12401251 do_wait = True
12411252 self.EnableTrackingModeOnce()
12421253
1243- self.__srv_handler.send ( ("INSTCMD %s %s\n" % ( ups, command )).encode('ascii') )
1254+ self.__send ( ("INSTCMD %s %s\n" % ( ups, command )).encode('ascii') )
12441255 result = self.__read_until( b"\n" )
12451256 if ( result == b"OK\n" ) :
12461257 return( "OK" )
@@ -1281,7 +1292,7 @@ of connection.
12811292 print( "[DEBUG] DeviceLogin: %s is not a valid UPS" % ups )
12821293 raise PyNUTError( "ERR UNKNOWN-UPS" )
12831294
1284- self.__srv_handler.send ( ("LOGIN %s\n" % ups).encode('ascii') )
1295+ self.__send ( ("LOGIN %s\n" % ups).encode('ascii') )
12851296 result = self.__read_until( b"\n" )
12861297 if ( result.startswith( ("User %s@" % self.__login).encode('ascii')) and result.endswith (("[%s]\n" % ups).encode('ascii')) ):
12871298 # User dummy-user@127.0.0.1 logged into UPS [dummy]
@@ -1303,14 +1314,14 @@ NOTE: API changed since NUT 2.8.0 to replace MASTER with PRIMARY
13031314 if self.__debug :
13041315 print( "[DEBUG] PRIMARY called..." )
13051316
1306- self.__srv_handler.send ( ("PRIMARY %s\n" % ups).encode('ascii') )
1317+ self.__send ( ("PRIMARY %s\n" % ups).encode('ascii') )
13071318 result = self.__read_until( b"\n" )
13081319 if ( result == b"OK PRIMARY-GRANTED\n" ) :
13091320 return( "OK" )
13101321
13111322 if self.__debug :
13121323 print( "[DEBUG] Retrying: MASTER called..." )
1313- self.__srv_handler.send ( ("MASTER %s\n" % ups).encode('ascii') )
1324+ self.__send ( ("MASTER %s\n" % ups).encode('ascii') )
13141325 result = self.__read_until( b"\n" )
13151326 if ( result == b"OK MASTER-GRANTED\n" ) :
13161327 return( "OK" )
@@ -1331,7 +1342,7 @@ Returns OK on success or raises an error
13311342
13321343 if self.__debug :
13331344 print( "[DEBUG] FSD called..." )
1334- self.__srv_handler.send ( ("FSD %s\n" % ups).encode('ascii') )
1345+ self.__send ( ("FSD %s\n" % ups).encode('ascii') )
13351346 result = self.__read_until( b"\n" )
13361347 if ( result == b"OK FSD-SET\n" ) :
13371348 return( "OK" )
@@ -1374,11 +1385,11 @@ The result is a dictionary containing 'key->val' pairs of 'UPSName' and a list o
13741385 raise PyNUTError( "ERR UNKNOWN-UPS" )
13751386
13761387 if ups:
1377- self.__srv_handler.send ( ("LIST CLIENT %s\n" % ups).encode('ascii') )
1388+ self.__send ( ("LIST CLIENT %s\n" % ups).encode('ascii') )
13781389 else:
13791390 # NOTE: Currently NUT does not support just listing all clients
13801391 # (not providing an "ups" argument) => NUT_ERR_INVALID_ARGUMENT
1381- self.__srv_handler.send ( b"LIST CLIENT\n" )
1392+ self.__send ( b"LIST CLIENT\n" )
13821393 result = self.__read_until( b"\n" )
13831394 if ( (ups and result != ("BEGIN LIST CLIENT %s\n" % ups).encode('ascii')) or (ups is None and result != b"BEGIN LIST CLIENT\n") ):
13841395 if ups is None and (result == b"ERR INVALID-ARGUMENT\n") :
0 commit comments