Skip to content

Commit 342b8c9

Browse files
authoredFeb 15, 2023
Merge pull request #150 from vladak/logging_null_handler
use NullHandler for logging by default
·
8.0.27.2.2
2 parents 75cc3b2 + d9d5cce commit 342b8c9

File tree

1 file changed

+87
-104
lines changed

1 file changed

+87
-104
lines changed
 

‎adafruit_minimqtt/adafruit_minimqtt.py‎

Lines changed: 87 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@
3131
import struct
3232
import time
3333
from random import randint
34+
3435
from micropython import const
36+
3537
from .matcher import MQTTMatcher
3638

3739
__version__ = "0.0.0+auto.0"
@@ -124,6 +126,19 @@ def wrap_socket(self, socket, server_hostname=None):
124126
return _FakeSSLSocket(socket, self._iface.TLS_MODE)
125127

126128

129+
class NullLogger:
130+
"""Fake logger class that does not do anything"""
131+
132+
# pylint: disable=unused-argument
133+
def nothing(self, msg: str, *args) -> None:
134+
"""no action"""
135+
pass
136+
137+
def __init__(self):
138+
for log_level in ["debug", "info", "warning", "error", "critical"]:
139+
setattr(NullLogger, log_level, self.nothing)
140+
141+
127142
class MQTT:
128143
"""MQTT Client for CircuitPython.
129144
@@ -186,7 +201,9 @@ def __init__(
186201
self._msg_size_lim = MQTT_MSG_SZ_LIM
187202
self._pid = 0
188203
self._timestamp = 0
189-
self.logger = None
204+
self.logger = NullLogger()
205+
"""An optional logging attribute that can be set with with a Logger
206+
to enable debug logging."""
190207

191208
self._reconnect_attempt = 0
192209
self._reconnect_timeout = float(0)
@@ -270,9 +287,9 @@ def _get_connect_socket(self, host, port, *, timeout=1):
270287
"ssl_context must be set before using adafruit_mqtt for secure MQTT."
271288
)
272289

273-
if self.logger is not None and port == MQTT_TLS_PORT:
290+
if port == MQTT_TLS_PORT:
274291
self.logger.info(f"Establishing a SECURE SSL connection to {host}:{port}")
275-
elif self.logger is not None:
292+
else:
276293
self.logger.info(f"Establishing an INSECURE connection to {host}:{port}")
277294

278295
addr_info = self._socket_pool.getaddrinfo(
@@ -283,10 +300,9 @@ def _get_connect_socket(self, host, port, *, timeout=1):
283300
sock = self._socket_pool.socket(addr_info[0], addr_info[1])
284301
except OSError as exc:
285302
# Do not consider this for back-off.
286-
if self.logger is not None:
287-
self.logger.warning(
288-
f"Failed to create socket for host {addr_info[0]} and port {addr_info[1]}"
289-
)
303+
self.logger.warning(
304+
f"Failed to create socket for host {addr_info[0]} and port {addr_info[1]}"
305+
)
290306
raise TemporaryError from exc
291307

292308
connect_host = addr_info[-1][0]
@@ -300,8 +316,7 @@ def _get_connect_socket(self, host, port, *, timeout=1):
300316
sock.connect((connect_host, port))
301317
except MemoryError as exc:
302318
sock.close()
303-
if self.logger is not None:
304-
self.logger.warning(f"Failed to allocate memory for connect: {exc}")
319+
self.logger.warning(f"Failed to allocate memory for connect: {exc}")
305320
# Do not consider this for back-off.
306321
raise TemporaryError from exc
307322
except OSError as exc:
@@ -352,8 +367,7 @@ def will_set(self, topic=None, payload=None, qos=0, retain=False):
352367
:param bool retain: Specifies if the payload is to be retained when
353368
it is published.
354369
"""
355-
if self.logger is not None:
356-
self.logger.debug("Setting last will properties")
370+
self.logger.debug("Setting last will properties")
357371
self._valid_qos(qos)
358372
if self._is_connected:
359373
raise MMQTTException("Last Will should only be called before connect().")
@@ -447,10 +461,10 @@ def connect(self, clean_session=True, host=None, port=None, keep_alive=None):
447461
self._recompute_reconnect_backoff()
448462
else:
449463
self._reset_reconnect_backoff()
450-
if self.logger is not None:
451-
self.logger.debug(
452-
f"Attempting to connect to MQTT broker (attempt #{self._reconnect_attempt})"
453-
)
464+
465+
self.logger.debug(
466+
f"Attempting to connect to MQTT broker (attempt #{self._reconnect_attempt})"
467+
)
454468

455469
try:
456470
ret = self._connect(
@@ -462,18 +476,15 @@ def connect(self, clean_session=True, host=None, port=None, keep_alive=None):
462476
self._reset_reconnect_backoff()
463477
return ret
464478
except TemporaryError as e:
465-
if self.logger is not None:
466-
self.logger.warning(f"temporary error when connecting: {e}")
479+
self.logger.warning(f"temporary error when connecting: {e}")
467480
backoff = False
468481
except OSError as e:
469482
last_exception = e
470-
if self.logger is not None:
471-
self.logger.info(f"failed to connect: {e}")
483+
self.logger.info(f"failed to connect: {e}")
472484
backoff = True
473485
except MMQTTException as e:
474486
last_exception = e
475-
if self.logger is not None:
476-
self.logger.info(f"MMQT error: {e}")
487+
self.logger.info(f"MMQT error: {e}")
477488
backoff = True
478489

479490
if self._reconnect_attempts_max > 1:
@@ -502,14 +513,12 @@ def _connect(self, clean_session=True, host=None, port=None, keep_alive=None):
502513
if keep_alive:
503514
self.keep_alive = keep_alive
504515

505-
if self.logger is not None:
506-
self.logger.debug("Attempting to establish MQTT connection...")
516+
self.logger.debug("Attempting to establish MQTT connection...")
507517

508518
if self._reconnect_attempt > 0:
509-
if self.logger is not None:
510-
self.logger.debug(
511-
f"Sleeping for {self._reconnect_timeout:.3} seconds due to connect back-off"
512-
)
519+
self.logger.debug(
520+
f"Sleeping for {self._reconnect_timeout:.3} seconds due to connect back-off"
521+
)
513522
time.sleep(self._reconnect_timeout)
514523

515524
# Get a new socket
@@ -565,11 +574,9 @@ def _connect(self, clean_session=True, host=None, port=None, keep_alive=None):
565574
fixed_header.append(remaining_length)
566575
fixed_header.append(0x00)
567576

568-
if self.logger is not None:
569-
self.logger.debug("Sending CONNECT packet to broker...")
570-
self.logger.debug(
571-
"Fixed Header: %s\nVariable Header: %s", fixed_header, var_header
572-
)
577+
self.logger.debug("Sending CONNECT to broker...")
578+
self.logger.debug(f"Fixed Header: {fixed_header}")
579+
self.logger.debug(f"Variable Header: {var_header}")
573580
self._sock.send(fixed_header)
574581
self._sock.send(var_header)
575582
# [MQTT-3.1.3-4]
@@ -581,8 +588,7 @@ def _connect(self, clean_session=True, host=None, port=None, keep_alive=None):
581588
if self._username is not None:
582589
self._send_str(self._username)
583590
self._send_str(self._password)
584-
if self.logger is not None:
585-
self.logger.debug("Receiving CONNACK packet from broker")
591+
self.logger.debug("Receiving CONNACK packet from broker")
586592
stamp = time.monotonic()
587593
while True:
588594
op = self._wait_for_msg()
@@ -607,15 +613,12 @@ def _connect(self, clean_session=True, host=None, port=None, keep_alive=None):
607613
def disconnect(self):
608614
"""Disconnects the MiniMQTT client from the MQTT broker."""
609615
self._connected()
610-
if self.logger is not None:
611-
self.logger.debug("Sending DISCONNECT packet to broker")
616+
self.logger.debug("Sending DISCONNECT packet to broker")
612617
try:
613618
self._sock.send(MQTT_DISCONNECT)
614619
except RuntimeError as e:
615-
if self.logger is not None:
616-
self.logger.warning(f"Unable to send DISCONNECT packet: {e}")
617-
if self.logger is not None:
618-
self.logger.debug("Closing socket")
620+
self.logger.warning(f"Unable to send DISCONNECT packet: {e}")
621+
self.logger.debug("Closing socket")
619622
self._sock.close()
620623
self._is_connected = False
621624
self._subscribed_topics = []
@@ -628,8 +631,7 @@ def ping(self):
628631
Returns response codes of any messages received while waiting for PINGRESP.
629632
"""
630633
self._connected()
631-
if self.logger is not None:
632-
self.logger.debug("Sending PINGREQ")
634+
self.logger.debug("Sending PINGREQ")
633635
self._sock.send(MQTT_PINGREQ)
634636
ping_timeout = self.keep_alive
635637
stamp = time.monotonic()
@@ -699,15 +701,14 @@ def publish(self, topic, msg, retain=False, qos=0):
699701
else:
700702
pub_hdr_fixed.append(remaining_length)
701703

702-
if self.logger is not None:
703-
self.logger.debug(
704-
"Sending PUBLISH\nTopic: %s\nMsg: %s\
705-
\nQoS: %d\nRetain? %r",
706-
topic,
707-
msg,
708-
qos,
709-
retain,
710-
)
704+
self.logger.debug(
705+
"Sending PUBLISH\nTopic: %s\nMsg: %s\
706+
\nQoS: %d\nRetain? %r",
707+
topic,
708+
msg,
709+
qos,
710+
retain,
711+
)
711712
self._sock.send(pub_hdr_fixed)
712713
self._sock.send(pub_hdr_var)
713714
self._sock.send(msg)
@@ -777,9 +778,8 @@ def subscribe(self, topic, qos=0):
777778
topic_size = len(t.encode("utf-8")).to_bytes(2, "big")
778779
qos_byte = q.to_bytes(1, "big")
779780
packet += topic_size + t.encode() + qos_byte
780-
if self.logger is not None:
781-
for t, q in topics:
782-
self.logger.debug("SUBSCRIBING to topic %s with QoS %d", t, q)
781+
for t, q in topics:
782+
self.logger.debug("SUBSCRIBING to topic %s with QoS %d", t, q)
783783
self._sock.send(packet)
784784
stamp = time.monotonic()
785785
while True:
@@ -831,12 +831,10 @@ def unsubscribe(self, topic):
831831
for t in topics:
832832
topic_size = len(t.encode("utf-8")).to_bytes(2, "big")
833833
packet += topic_size + t.encode()
834-
if self.logger is not None:
835-
for t in topics:
836-
self.logger.debug("UNSUBSCRIBING from topic %s", t)
834+
for t in topics:
835+
self.logger.debug("UNSUBSCRIBING from topic %s", t)
837836
self._sock.send(packet)
838-
if self.logger is not None:
839-
self.logger.debug("Waiting for UNSUBACK...")
837+
self.logger.debug("Waiting for UNSUBACK...")
840838
while True:
841839
stamp = time.monotonic()
842840
op = self._wait_for_msg()
@@ -865,38 +863,34 @@ def _recompute_reconnect_backoff(self):
865863
"""
866864
self._reconnect_attempt = self._reconnect_attempt + 1
867865
self._reconnect_timeout = 2**self._reconnect_attempt
868-
if self.logger is not None:
869-
# pylint: disable=consider-using-f-string
870-
self.logger.debug(
871-
"Reconnect timeout computed to {:.2f}".format(self._reconnect_timeout)
872-
)
866+
# pylint: disable=consider-using-f-string
867+
self.logger.debug(
868+
"Reconnect timeout computed to {:.2f}".format(self._reconnect_timeout)
869+
)
873870

874871
if self._reconnect_timeout > self._reconnect_maximum_backoff:
875-
if self.logger is not None:
876-
self.logger.debug(
877-
f"Truncating reconnect timeout to {self._reconnect_maximum_backoff} seconds"
878-
)
872+
self.logger.debug(
873+
f"Truncating reconnect timeout to {self._reconnect_maximum_backoff} seconds"
874+
)
879875
self._reconnect_timeout = float(self._reconnect_maximum_backoff)
880876

881877
# Add a sub-second jitter.
882878
# Even truncated timeout should have jitter added to it. This is why it is added here.
883879
jitter = randint(0, 1000) / 1000
884-
if self.logger is not None:
885-
# pylint: disable=consider-using-f-string
886-
self.logger.debug(
887-
"adding jitter {:.2f} to {:.2f} seconds".format(
888-
jitter, self._reconnect_timeout
889-
)
880+
# pylint: disable=consider-using-f-string
881+
self.logger.debug(
882+
"adding jitter {:.2f} to {:.2f} seconds".format(
883+
jitter, self._reconnect_timeout
890884
)
885+
)
891886
self._reconnect_timeout += jitter
892887

893888
def _reset_reconnect_backoff(self):
894889
"""
895890
Reset reconnect back-off to the initial state.
896891
897892
"""
898-
if self.logger is not None:
899-
self.logger.debug("Resetting reconnect backoff")
893+
self.logger.debug("Resetting reconnect backoff")
900894
self._reconnect_attempt = 0
901895
self._reconnect_timeout = float(0)
902896

@@ -909,17 +903,13 @@ def reconnect(self, resub_topics=True):
909903
910904
"""
911905

912-
if self.logger is not None:
913-
self.logger.debug("Attempting to reconnect with MQTT broker")
914-
906+
self.logger.debug("Attempting to reconnect with MQTT broker")
915907
ret = self.connect()
916-
if self.logger is not None:
917-
self.logger.debug("Reconnected with broker")
908+
self.logger.debug("Reconnected with broker")
918909
if resub_topics:
919-
if self.logger is not None:
920-
self.logger.debug(
921-
"Attempting to resubscribe to previously subscribed topics."
922-
)
910+
self.logger.debug(
911+
"Attempting to resubscribe to previously subscribed topics."
912+
)
923913
subscribed_topics = self._subscribed_topics.copy()
924914
self._subscribed_topics = []
925915
while subscribed_topics:
@@ -938,16 +928,16 @@ def loop(self, timeout=0):
938928
939929
"""
940930

931+
self.logger.debug(f"waiting for messages for {timeout} seconds")
941932
if self._timestamp == 0:
942933
self._timestamp = time.monotonic()
943934
current_time = time.monotonic()
944935
if current_time - self._timestamp >= self.keep_alive:
945936
self._timestamp = 0
946937
# Handle KeepAlive by expecting a PINGREQ/PINGRESP from the server
947-
if self.logger is not None:
948-
self.logger.debug(
949-
"KeepAlive period elapsed - requesting a PINGRESP from the server..."
950-
)
938+
self.logger.debug(
939+
"KeepAlive period elapsed - requesting a PINGRESP from the server..."
940+
)
951941
rcs = self.ping()
952942
return rcs
953943

@@ -960,10 +950,9 @@ def loop(self, timeout=0):
960950
if rc is None:
961951
break
962952
if time.monotonic() - stamp > self._recv_timeout:
963-
if self.logger is not None:
964-
self.logger.debug(
965-
f"Loop timed out, message queue not empty after {self._recv_timeout}s"
966-
)
953+
self.logger.debug(
954+
f"Loop timed out, message queue not empty after {self._recv_timeout}s"
955+
)
967956
break
968957
rcs.append(rc)
969958

@@ -996,8 +985,7 @@ def _wait_for_msg(self, timeout=0.1):
996985
# If we get here, it means that there is nothing to be received
997986
return None
998987
if res[0] & MQTT_PKT_TYPE_MASK == MQTT_PINGRESP:
999-
if self.logger is not None:
1000-
self.logger.debug("Got PINGRESP")
988+
self.logger.debug("Got PINGRESP")
1001989
sz = self._sock_exact_recv(1)[0]
1002990
if sz != 0x00:
1003991
raise MMQTTException(f"Unexpected PINGRESP returned from broker: {sz}.")
@@ -1029,10 +1017,7 @@ def _wait_for_msg(self, timeout=0.1):
10291017
# read message contents
10301018
raw_msg = self._sock_exact_recv(sz)
10311019
msg = raw_msg if self._use_binary_mode else str(raw_msg, "utf-8")
1032-
if self.logger is not None:
1033-
self.logger.debug(
1034-
"Receiving PUBLISH \nTopic: %s\nMsg: %s\n", topic, raw_msg
1035-
)
1020+
self.logger.debug("Receiving PUBLISH \nTopic: %s\nMsg: %s\n", topic, raw_msg)
10361021
self._handle_on_message(self, topic, msg)
10371022
if res[0] & 0x06 == 0x02:
10381023
pkt = bytearray(b"\x40\x02\0\0")
@@ -1101,8 +1086,7 @@ def _sock_exact_recv(self, bufsize):
11011086
# This will timeout with socket timeout (not keepalive timeout)
11021087
rc = self._sock.recv(bufsize)
11031088
if not rc:
1104-
if self.logger is not None:
1105-
self.logger.debug("_sock_exact_recv timeout")
1089+
self.logger.debug("_sock_exact_recv timeout")
11061090
# If no bytes waiting, raise same exception as socketpool
11071091
raise OSError(errno.ETIMEDOUT)
11081092
# If any bytes waiting, try to read them all,
@@ -1187,13 +1171,12 @@ def enable_logger(self, log_pkg, log_level=20, logger_name="log"):
11871171
:return logger object
11881172
11891173
"""
1174+
# pylint: disable=attribute-defined-outside-init
11901175
self.logger = log_pkg.getLogger(logger_name)
11911176
self.logger.setLevel(log_level)
11921177

11931178
return self.logger
11941179

11951180
def disable_logger(self):
11961181
"""Disables logging."""
1197-
if not self.logger:
1198-
raise MMQTTException("Can not disable logger, no logger found.")
1199-
self.logger = None
1182+
self.logger = NullLogger()

0 commit comments

Comments
 (0)
Please sign in to comment.