9595
9696
9797class MMQTTException (Exception ):
98- """MiniMQTT Exception class."""
98+ """
99+ MiniMQTT Exception class.
100+
101+ Raised for various mostly protocol or network/system level errors.
102+ In general, the robust way to recover is to call reconnect().
103+ """
99104
100105 def __init__ (self , error , code = None ):
101106 super ().__init__ (error , code )
102107 self .code = code
103108
104109
110+ class MMQTTStateError (MMQTTException ):
111+ """
112+ MiniMQTT invalid state error.
113+
114+ Raised e.g. if a function is called in unexpected state.
115+ """
116+
117+
105118class NullLogger :
106119 """Fake logger class that does not do anything"""
107120
@@ -165,7 +178,7 @@ def __init__( # noqa: PLR0915, PLR0913, Too many statements, Too many arguments
165178 self ._use_binary_mode = use_binary_mode
166179
167180 if recv_timeout <= socket_timeout :
168- raise MMQTTException ("recv_timeout must be strictly greater than socket_timeout" )
181+ raise ValueError ("recv_timeout must be strictly greater than socket_timeout" )
169182 self ._socket_timeout = socket_timeout
170183 self ._recv_timeout = recv_timeout
171184
@@ -183,7 +196,7 @@ def __init__( # noqa: PLR0915, PLR0913, Too many statements, Too many arguments
183196 self ._reconnect_timeout = float (0 )
184197 self ._reconnect_maximum_backoff = 32
185198 if connect_retries <= 0 :
186- raise MMQTTException ("connect_retries must be positive" )
199+ raise ValueError ("connect_retries must be positive" )
187200 self ._reconnect_attempts_max = connect_retries
188201
189202 self .broker = broker
@@ -192,7 +205,7 @@ def __init__( # noqa: PLR0915, PLR0913, Too many statements, Too many arguments
192205 if (
193206 self ._password and len (password .encode ("utf-8" )) > MQTT_TOPIC_LENGTH_LIMIT
194207 ): # [MQTT-3.1.3.5]
195- raise MMQTTException ("Password length is too large." )
208+ raise ValueError ("Password length is too large." )
196209
197210 # The connection will be insecure unless is_ssl is set to True.
198211 # If the port is not specified, the security will be set based on the is_ssl parameter.
@@ -288,28 +301,27 @@ def will_set(
288301 """
289302 self .logger .debug ("Setting last will properties" )
290303 if self ._is_connected :
291- raise MMQTTException ("Last Will should only be called before connect()." )
304+ raise MMQTTStateError ("Last Will should only be called before connect()." )
292305
293306 # check topic/msg/qos kwargs
294307 self ._valid_topic (topic )
295308 if "+" in topic or "#" in topic :
296- raise MMQTTException ("Publish topic can not contain wildcards." )
309+ raise ValueError ("Publish topic can not contain wildcards." )
297310
298311 if msg is None :
299- raise MMQTTException ("Message can not be None." )
312+ raise ValueError ("Message can not be None." )
300313 if isinstance (msg , (int , float )):
301314 msg = str (msg ).encode ("ascii" )
302315 elif isinstance (msg , str ):
303316 msg = str (msg ).encode ("utf-8" )
304317 elif isinstance (msg , bytes ):
305318 pass
306319 else :
307- raise MMQTTException ("Invalid message data type." )
320+ raise ValueError ("Invalid message data type." )
308321 if len (msg ) > MQTT_MSG_MAX_SZ :
309- raise MMQTTException (f"Message size larger than { MQTT_MSG_MAX_SZ } bytes." )
322+ raise ValueError (f"Message size larger than { MQTT_MSG_MAX_SZ } bytes." )
310323
311324 self ._valid_qos (qos )
312- assert 0 <= qos <= 1 , "Quality of Service Level 2 is unsupported by this library."
313325
314326 # fixed header. [3.3.1.2], [3.3.1.3]
315327 pub_hdr_fixed = bytearray ([MQTT_PUBLISH | retain | qos << 1 ])
@@ -392,7 +404,7 @@ def username_pw_set(self, username: str, password: Optional[str] = None) -> None
392404
393405 """
394406 if self ._is_connected :
395- raise MMQTTException ("This method must be called before connect()." )
407+ raise MMQTTStateError ("This method must be called before connect()." )
396408 self ._username = username
397409 if password is not None :
398410 self ._password = password
@@ -672,21 +684,22 @@ def publish( # noqa: PLR0912, Too many branches
672684 self ._connected ()
673685 self ._valid_topic (topic )
674686 if "+" in topic or "#" in topic :
675- raise MMQTTException ("Publish topic can not contain wildcards." )
687+ raise ValueError ("Publish topic can not contain wildcards." )
676688 # check msg/qos kwargs
677689 if msg is None :
678- raise MMQTTException ("Message can not be None." )
690+ raise ValueError ("Message can not be None." )
679691 if isinstance (msg , (int , float )):
680692 msg = str (msg ).encode ("ascii" )
681693 elif isinstance (msg , str ):
682694 msg = str (msg ).encode ("utf-8" )
683695 elif isinstance (msg , bytes ):
684696 pass
685697 else :
686- raise MMQTTException ("Invalid message data type." )
698+ raise ValueError ("Invalid message data type." )
687699 if len (msg ) > MQTT_MSG_MAX_SZ :
688- raise MMQTTException (f"Message size larger than { MQTT_MSG_MAX_SZ } bytes." )
689- assert 0 <= qos <= 1 , "Quality of Service Level 2 is unsupported by this library."
700+ raise ValueError (f"Message size larger than { MQTT_MSG_MAX_SZ } bytes." )
701+
702+ self ._valid_qos (qos )
690703
691704 # fixed header. [3.3.1.2], [3.3.1.3]
692705 pub_hdr_fixed = bytearray ([MQTT_PUBLISH | retain | qos << 1 ])
@@ -851,7 +864,7 @@ def unsubscribe( # noqa: PLR0912, Too many branches
851864 topics .append (t )
852865 for t in topics :
853866 if t not in self ._subscribed_topics :
854- raise MMQTTException ("Topic must be subscribed to before attempting unsubscribe." )
867+ raise MMQTTStateError ("Topic must be subscribed to before attempting unsubscribe." )
855868 # Assemble packet
856869 self .logger .debug ("Sending UNSUBSCRIBE to broker..." )
857870 fixed_header = bytearray ([MQTT_UNSUB ])
@@ -961,7 +974,7 @@ def loop(self, timeout: float = 1.0) -> Optional[list[int]]:
961974
962975 """
963976 if timeout < self ._socket_timeout :
964- raise MMQTTException (
977+ raise ValueError (
965978 f"loop timeout ({ timeout } ) must be >= "
966979 + f"socket timeout ({ self ._socket_timeout } ))"
967980 )
@@ -1155,13 +1168,13 @@ def _valid_topic(topic: str) -> None:
11551168
11561169 """
11571170 if topic is None :
1158- raise MMQTTException ("Topic may not be NoneType" )
1171+ raise ValueError ("Topic may not be NoneType" )
11591172 # [MQTT-4.7.3-1]
11601173 if not topic :
1161- raise MMQTTException ("Topic may not be empty." )
1174+ raise ValueError ("Topic may not be empty." )
11621175 # [MQTT-4.7.3-3]
11631176 if len (topic .encode ("utf-8" )) > MQTT_TOPIC_LENGTH_LIMIT :
1164- raise MMQTTException ( "Topic length is too large. " )
1177+ raise ValueError ( f"Encoded topic length is larger than { MQTT_TOPIC_LENGTH_LIMIT } " )
11651178
11661179 @staticmethod
11671180 def _valid_qos (qos_level : int ) -> None :
@@ -1172,16 +1185,16 @@ def _valid_qos(qos_level: int) -> None:
11721185 """
11731186 if isinstance (qos_level , int ):
11741187 if qos_level < 0 or qos_level > 2 :
1175- raise MMQTTException ("QoS must be between 1 and 2." )
1188+ raise NotImplementedError ("QoS must be between 1 and 2." )
11761189 else :
1177- raise MMQTTException ("QoS must be an integer." )
1190+ raise ValueError ("QoS must be an integer." )
11781191
11791192 def _connected (self ) -> None :
11801193 """Returns MQTT client session status as True if connected, raises
1181- a `MMQTTException ` if `False`.
1194+ a `MMQTTStateError exception ` if `False`.
11821195 """
11831196 if not self .is_connected ():
1184- raise MMQTTException ("MiniMQTT is not connected" )
1197+ raise MMQTTStateError ("MiniMQTT is not connected" )
11851198
11861199 def is_connected (self ) -> bool :
11871200 """Returns MQTT client session status as True if connected, False
0 commit comments