From 2197ad7294b2eff14094d396cf1eee8b2cfa20fc Mon Sep 17 00:00:00 2001 From: Ed Hagerty Date: Wed, 24 Jul 2024 19:02:36 +0100 Subject: [PATCH 1/5] refactor will_set function to match the publish function to allow the msg/payload to be encoded bytes --- adafruit_minimqtt/adafruit_minimqtt.py | 62 ++++++++++++++++++++------ 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/adafruit_minimqtt/adafruit_minimqtt.py b/adafruit_minimqtt/adafruit_minimqtt.py index 53e9801..514d429 100644 --- a/adafruit_minimqtt/adafruit_minimqtt.py +++ b/adafruit_minimqtt/adafruit_minimqtt.py @@ -269,38 +269,74 @@ def mqtt_msg(self, msg_size: int) -> None: def will_set( self, - topic: Optional[str] = None, - payload: Optional[Union[int, float, str]] = None, - qos: int = 0, + topic: str, + msg: Union[str, int, float, bytes], retain: bool = False, + qos: int = 0, ) -> None: """Sets the last will and testament properties. MUST be called before `connect()`. :param str topic: MQTT Broker topic. - :param int|float|str payload: Last will disconnection payload. - payloads of type int & float are converted to a string. + :param str|int|float|bytes msg: Last will disconnection msg. + msgs of type int & float are converted to a string. + msgs of type byetes are left unchanged, as it is in the publish function. :param int qos: Quality of Service level, defaults to zero. Conventional options are ``0`` (send at most once), ``1`` (send at least once), or ``2`` (send exactly once). - .. note:: Only options ``1`` or ``0`` are QoS levels supported by this library. - :param bool retain: Specifies if the payload is to be retained when + :param bool retain: Specifies if the msg is to be retained when it is published. """ self.logger.debug("Setting last will properties") - self._valid_qos(qos) if self._is_connected: raise MMQTTException("Last Will should only be called before connect().") - if payload is None: - payload = "" - if isinstance(payload, (int, float, str)): - payload = str(payload).encode() + + # check topic/msg/qos kwargs + self._valid_topic(topic) + if "+" in topic or "#" in topic: + raise MMQTTException("Publish topic can not contain wildcards.") + + if msg is None: + raise MMQTTException("Message can not be None.") + if isinstance(msg, (int, float)): + msg = str(msg).encode("ascii") + elif isinstance(msg, str): + msg = str(msg).encode("utf-8") + elif isinstance(msg, bytes): + pass else: raise MMQTTException("Invalid message data type.") + if len(msg) > MQTT_MSG_MAX_SZ: + raise MMQTTException(f"Message size larger than {MQTT_MSG_MAX_SZ} bytes.") + + self._valid_qos(qos) + assert ( + 0 <= qos <= 1 + ), "Quality of Service Level 2 is unsupported by this library." + + # fixed header. [3.3.1.2], [3.3.1.3] + pub_hdr_fixed = bytearray([MQTT_PUBLISH | retain | qos << 1]) + + # variable header = 2-byte Topic length (big endian) + pub_hdr_var = bytearray(struct.pack(">H", len(topic.encode("utf-8")))) + pub_hdr_var.extend(topic.encode("utf-8")) # Topic name + + remaining_length = 2 + len(msg) + len(topic.encode("utf-8")) + if qos > 0: + # packet identifier where QoS level is 1 or 2. [3.3.2.2] + remaining_length += 2 + self._pid = self._pid + 1 if self._pid < 0xFFFF else 1 + pub_hdr_var.append(self._pid >> 8) + pub_hdr_var.append(self._pid & 0xFF) + + self._encode_remaining_length(pub_hdr_fixed, remaining_length) + self._lw_qos = qos self._lw_topic = topic - self._lw_msg = payload + self._lw_msg = msg self._lw_retain = retain + self.logger.debug("Last will properties successfully set") + def add_topic_callback(self, mqtt_topic: str, callback_method) -> None: """Registers a callback_method for a specific MQTT topic. From 88787e69f55070c3f4395faa30773a5408bb7943 Mon Sep 17 00:00:00 2001 From: Ed Hagerty Date: Thu, 25 Jul 2024 13:30:00 +0100 Subject: [PATCH 2/5] trying to correctly set up pre-commit --- .pre-commit-config.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 09cc1f1..fdeed90 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,21 +4,21 @@ repos: - repo: https://github.com/python/black - rev: 24.2.0 + rev: 24.4.2 hooks: - id: black - repo: https://github.com/fsfe/reuse-tool - rev: v1.1.2 + rev: v4.0.3 hooks: - id: reuse - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.6.0 hooks: - id: check-yaml - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/pycqa/pylint - rev: v2.17.4 + rev: v3.2.6 hooks: - id: pylint name: pylint (library code) From 65ea984e61da52a5ae43553f96988b5df7008ed6 Mon Sep 17 00:00:00 2001 From: Ed Hagerty Date: Thu, 25 Jul 2024 13:31:45 +0100 Subject: [PATCH 3/5] trying to correctly set up pre-commit --- adafruit_minimqtt/adafruit_minimqtt.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_minimqtt/adafruit_minimqtt.py b/adafruit_minimqtt/adafruit_minimqtt.py index 514d429..0cbc266 100644 --- a/adafruit_minimqtt/adafruit_minimqtt.py +++ b/adafruit_minimqtt/adafruit_minimqtt.py @@ -267,6 +267,7 @@ def mqtt_msg(self, msg_size: int) -> None: if msg_size < MQTT_MSG_MAX_SZ: self._msg_size_lim = msg_size + # pylint: disable=too-many-branches, too-many-statements def will_set( self, topic: str, @@ -337,7 +338,6 @@ def will_set( self._lw_retain = retain self.logger.debug("Last will properties successfully set") - def add_topic_callback(self, mqtt_topic: str, callback_method) -> None: """Registers a callback_method for a specific MQTT topic. From 2d3708d1c61d07b841c7ebca55b486d5e628e2cf Mon Sep 17 00:00:00 2001 From: Ed Hagerty Date: Thu, 25 Jul 2024 13:42:39 +0100 Subject: [PATCH 4/5] having to fix adafruit code to migrate to yield-from --- adafruit_minimqtt/matcher.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/adafruit_minimqtt/matcher.py b/adafruit_minimqtt/matcher.py index c14a351..1162d3c 100644 --- a/adafruit_minimqtt/matcher.py +++ b/adafruit_minimqtt/matcher.py @@ -88,11 +88,9 @@ def rec(node: MQTTMatcher.Node, i: int = 0): else: part = lst[i] if part in node.children: - for content in rec(node.children[part], i + 1): - yield content + yield from rec(node.children[part], i + 1) if "+" in node.children and (normal or i > 0): - for content in rec(node.children["+"], i + 1): - yield content + yield from rec(node.children["+"], i + 1) if "#" in node.children and (normal or i > 0): content = node.children["#"].content if content is not None: From 9c0ecfc30b7da49565d6ba89469ce226124bb397 Mon Sep 17 00:00:00 2001 From: foamyguy Date: Sun, 25 Aug 2024 10:38:36 -0500 Subject: [PATCH 5/5] revert pre-commit versions --- .pre-commit-config.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fdeed90..09cc1f1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,21 +4,21 @@ repos: - repo: https://github.com/python/black - rev: 24.4.2 + rev: 24.2.0 hooks: - id: black - repo: https://github.com/fsfe/reuse-tool - rev: v4.0.3 + rev: v1.1.2 hooks: - id: reuse - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.6.0 + rev: v4.4.0 hooks: - id: check-yaml - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/pycqa/pylint - rev: v3.2.6 + rev: v2.17.4 hooks: - id: pylint name: pylint (library code)