Skip to content

[packet] move MQTT 3 implementation to mqtt3 namespace#313

Draft
ajmirsky wants to merge 2 commits into
Yakifo:mainfrom
ajmirsky:upstream/mqtt3-namespace-and-mqtt5-scaffold
Draft

[packet] move MQTT 3 implementation to mqtt3 namespace#313
ajmirsky wants to merge 2 commits into
Yakifo:mainfrom
ajmirsky:upstream/mqtt3-namespace-and-mqtt5-scaffold

Conversation

@ajmirsky

@ajmirsky ajmirsky commented May 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • move the existing MQTT 3.1.1 packet and protocol modules under
  • keep as a compatibility shim for existing imports
  • add empty package scaffolding for later MQTT 5 work
  • update internal imports, samples, docs, and tests to use the explicit MQTT 3 namespace

Notes

This is the prerequisite branch for the MQTT 5 properties subsystem split.

Tests

Not run for this split branch. The stacked properties branch was validated with:
============================= test session starts ==============================
platform darwin -- Python 3.10.17, pytest-8.3.5, pluggy-1.6.0 -- /Users/andrew/dev/amqtt/.venv/bin/python
cachedir: .pytest_cache
hypothesis profile 'default'
rootdir: /Users/andrew/dev/amqtt
configfile: pyproject.toml
plugins: docker-3.2.3, anyio-4.9.0, logdog-0.1.0, timeout-2.4.0, hypothesis-6.131.30, cov-6.1.1, asyncio-1.0.0
timeout: 15.0s
timeout method: signal
timeout func_only: False
asyncio: mode=auto, asyncio_default_fixture_loop_scope=function, asyncio_default_test_loop_scope=function
collecting ... collected 76 items

tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[1] PASSED [ 1%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[2] PASSED [ 2%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[3] PASSED [ 3%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[8] PASSED [ 5%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[9] PASSED [ 6%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[11] PASSED [ 7%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[17] PASSED [ 9%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[18] PASSED [ 10%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[19] PASSED [ 11%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[21] PASSED [ 13%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[22] PASSED [ 14%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[23] PASSED [ 15%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[24] PASSED [ 17%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[25] PASSED [ 18%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[26] PASSED [ 19%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[28] PASSED [ 21%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[31] PASSED [ 22%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[33] PASSED [ 23%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[34] PASSED [ 25%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[35] PASSED [ 26%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[36] PASSED [ 27%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[37] PASSED [ 28%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[38] PASSED [ 30%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[39] PASSED [ 31%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[40] PASSED [ 32%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[41] PASSED [ 34%]
tests/mqtt5/test_properties.py::test_property_round_trip_for_every_identifier[42] PASSED [ 35%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[1-1-\x01\x01] PASSED [ 36%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[2-60-\x02\x00\x00\x00<] PASSED [ 38%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[3-text/plain-\x03\x00\ntext/plain] PASSED [ 39%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[8-reply/to-\x08\x00\x08reply/to] PASSED [ 40%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[9-abc-\t\x00\x03abc] PASSED [ 42%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[11-42-\x0b*] PASSED [ 43%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[17-300-\x11\x00\x00\x01,] PASSED [ 44%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[18-client-1-\x12\x00\x08client-1] PASSED [ 46%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[19-30-\x13\x00\x1e] PASSED [ 47%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[21-token-\x15\x00\x05token] PASSED [ 48%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[22-secret-\x16\x00\x06secret] PASSED [ 50%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[23-1-\x17\x01] PASSED [ 51%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[24-5-\x18\x00\x00\x00\x05] PASSED [ 52%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[25-1-\x19\x01] PASSED [ 53%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[26-info-\x1a\x00\x04info] PASSED [ 55%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[28-mqtt://other-\x1c\x00\x0cmqtt://other] PASSED [ 56%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[31-ok-\x1f\x00\x02ok] PASSED [ 57%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[33-10-!\x00\n] PASSED [ 59%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[34-4-"\x00\x04] PASSED [ 60%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[35-2-#\x00\x02] PASSED [ 61%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[36-1-$\x01] PASSED [ 63%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[37-1-%\x01] PASSED [ 64%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[38-value22-&\x00\x01k\x00\x01v] PASSED [ 65%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[39-1024-'\x00\x00\x04\x00] PASSED [ 67%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[40-1-(\x01] PASSED [ 68%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[41-1-)\x01] PASSED [ 69%]
tests/mqtt5/test_properties.py::test_property_wire_bytes[42-1-*\x01] PASSED [ 71%]
tests/mqtt5/test_properties.py::test_decode_spec_example_empty_properties PASSED [ 72%]
tests/mqtt5/test_properties.py::test_duplicate_non_repeatable_property_raises PASSED [ 73%]
tests/mqtt5/test_properties.py::test_duplicate_user_properties_are_preserved_in_order PASSED [ 75%]
tests/mqtt5/test_properties.py::test_decode_duplicate_non_repeatable_property_raises PASSED [ 76%]
tests/mqtt5/test_properties.py::test_malformed_properties_raise_mqtt_error[] PASSED [ 77%]
tests/mqtt5/test_properties.py::test_malformed_properties_raise_mqtt_error[\x02\x03] PASSED [ 78%]
tests/mqtt5/test_properties.py::test_malformed_properties_raise_mqtt_error[\x01\xff] PASSED [ 80%]
tests/mqtt5/test_properties.py::test_malformed_properties_raise_mqtt_error[\x05\x03\x00\xffbad] PASSED [ 81%]
tests/mqtt5/test_properties.py::test_malformed_properties_raise_mqtt_error[\x00\x01] PASSED [ 82%]
tests/mqtt5/test_properties.py::test_properties_decode_never_crashes PASSED [ 84%]
tests/mqtt5/test_properties.py::test_mqtt3_fixed_header_uses_shared_variable_byte_integer_helpers PASSED [ 85%]
tests/test_codecs.py::TestCodecs::test_bytes_to_hex_str PASSED [ 86%]
tests/test_codecs.py::TestCodecs::test_bytes_to_int PASSED [ 88%]
tests/test_codecs.py::TestCodecs::test_decode_string PASSED [ 89%]
tests/test_codecs.py::TestCodecs::test_encode_string PASSED [ 90%]
tests/test_codecs.py::TestCodecs::test_int_to_bytes_supports_four_byte_values PASSED [ 92%]
tests/test_codecs.py::TestCodecs::test_variable_byte_integer_round_trip PASSED [ 93%]
tests/mqtt/test_packet.py::TestMQTTFixedHeaderTest::test_from_bytes PASSED [ 94%]
tests/mqtt/test_packet.py::TestMQTTFixedHeaderTest::test_from_bytes_ko_with_length PASSED [ 96%]
tests/mqtt/test_packet.py::TestMQTTFixedHeaderTest::test_from_bytes_with_length PASSED [ 97%]
tests/mqtt/test_packet.py::TestMQTTFixedHeaderTest::test_to_bytes PASSED [ 98%]
tests/mqtt/test_packet.py::TestMQTTFixedHeaderTest::test_to_bytes_2 PASSED [100%]

================================ tests coverage ================================
______________ coverage: platform darwin, python 3.10.17-final-0 _______________

Name Stmts Miss Branch BrPart Cover Missing

amqtt/init.py 1 0 0 0 100%
amqtt/adapters.py 129 63 18 1 46% 27, 32, 45, 50, 55, 60, 65, 75-76, 79-80, 87-96, 100, 110-111, 115, 119-122, 128-129, 132, 135, 150, 156, 167-169, 172-173, 176-177, 180-183, 186, 189-196, 213, 223, 226, 230, 233, 236, 239, 242
amqtt/broker.py 651 547 196 0 12% 47-51, 63-68, 71-74, 80-83, 89-91, 98, 101, 104, 107, 114-116, 120, 123, 127-128, 132, 136, 140, 148-154, 189-224, 227-234, 237, 244-268, 272-297, 302-317, 328-347, 351-376, 380-409, 413-421, 424, 427, 430, 434, 438-467, 478-529, 532-537, 549-592, 597-643, 660-687, 698-710, 719-728, 737-779, 783-785, 789-793, 806-820, 829-849, 852-875, 890-894, 898-908, 912-918, 927-941, 945-977, 981-1031, 1034-1048, 1051-1061, 1070-1073, 1076-1091, 1094-1114, 1120-1135, 1138-1141, 1155-1179, 1183, 1187, 1191
amqtt/client.py 303 303 98 0 0% 1-616
amqtt/codecs_amqtt.py 115 28 30 7 74% 27, 49-50, 66-67, 128-129, 151-152, 154-155, 167, 173-176, 185-189, 219-222, 232, 237-239
amqtt/contexts.py 234 86 60 0 50% 29-32, 52, 60, 64-70, 74, 78-79, 83, 87-92, 125-134, 138-140, 145, 152, 191-211, 216-228, 260-266, 283-285, 303-305, 310, 356-366, 371-374
amqtt/contrib/init.py 26 26 6 0 0% 3-47
amqtt/contrib/auth_db/init.py 27 27 2 0 0% 2-52
amqtt/contrib/auth_db/managers.py 141 141 16 0 0% 1-190
amqtt/contrib/auth_db/models.py 77 77 10 0 0% 1-122
amqtt/contrib/auth_db/plugin.py 66 66 10 0 0% 1-111
amqtt/contrib/auth_db/topic_mgr_cli.py 86 86 20 0 0% 1-151
amqtt/contrib/auth_db/user_mgr_cli.py 98 98 24 0 0% 1-161
amqtt/contrib/cert.py 73 73 8 0 0% 1-246
amqtt/contrib/http.py 130 130 26 0 0% 1-181
amqtt/contrib/jwt.py 85 85 6 0 0% 1-119
amqtt/contrib/ldap.py 86 86 8 0 0% 1-138
amqtt/contrib/persistence.py 168 168 36 0 0% 1-264
amqtt/contrib/shadows/init.py 3 3 0 0 0% 3-6
amqtt/contrib/shadows/messages.py 78 78 10 0 0% 1-113
amqtt/contrib/shadows/models.py 69 69 8 0 0% 1-131
amqtt/contrib/shadows/plugin.py 99 99 18 0 0% 1-197
amqtt/contrib/shadows/states.py 119 119 34 0 0% 1-206
amqtt/errors.py 20 2 0 0 90% 22, 45
amqtt/events.py 23 0 0 0 100%
amqtt/mqtt3/init.py 29 8 2 0 68% 71-78
amqtt/mqtt3/connack.py 69 37 12 0 40% 20-22, 26-29, 32-37, 41, 54-62, 66-67, 71-74, 78-81, 85-88, 92-95
amqtt/mqtt3/connect.py 349 223 90 0 29% 31-35, 39, 45-48, 51, 56-70, 73-84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140-141, 162-168, 172, 184-219, 226-243, 256-265, 269-272, 276-279, 283-286, 290-293, 297-300, 304-307, 311-314, 318-321, 325-328, 332-335, 339-342, 346-349, 353-356, 360-363, 367-370, 374-377, 381-384, 388-391, 395-398, 402-405, 409-412, 416-419, 423-426, 430-433, 437-440, 444-447, 451-454, 458-461, 465-468, 472-475, 479-482, 486-489
amqtt/mqtt3/constants.py 3 0 0 0 100%
amqtt/mqtt3/disconnect.py 15 9 4 0 32% 10-19
amqtt/mqtt3/packet.py 141 51 12 0 59% 54-56, 60, 64, 77, 81, 91-92, 100, 105, 114-115, 118, 126-127, 131, 141-142, 146, 156, 172-175, 179-181, 185-193, 203-221, 225, 229
amqtt/mqtt3/pingreq.py 15 9 4 0 32% 10-19
amqtt/mqtt3/pingresp.py 19 10 4 0 39% 12-21, 25
amqtt/mqtt3/protocol/init.py 0 0 0 0 100%
amqtt/mqtt3/protocol/broker_handler.py 168 124 52 0 20% 37-38, 43-44, 54-57, 60-63, 67-75, 79-81, 84, 87, 91-95, 99, 104-109, 112, 115-123, 126-133, 136, 139, 142-143, 146-147, 150-155, 166-249
amqtt/mqtt3/protocol/client_handler.py 147 147 38 0 0% 1-205
amqtt/mqtt3/protocol/handler.py 517 444 186 0 10% 76-99, 102-110, 113-118, 121-123, 126, 129-140, 144-161, 164-177, 181-198, 219-235, 243-254, 263-287, 296-341, 351-438, 441-547, 566-582, 585-600, 603-606, 609-612, 615-618, 621-624, 627-630, 633-636, 639-642, 645-648, 651-654, 657-660, 663-666, 669-672, 675-685, 688-695, 698-705, 708-715, 718-731
amqtt/mqtt3/puback.py 30 17 8 0 34% 13-16, 20-23, 30-38, 42-43
amqtt/mqtt3/pubcomp.py 32 19 8 0 32% 16-27, 31-32, 36-39, 43-46
amqtt/mqtt3/publish.py 141 85 26 0 34% 14-19, 23, 26-30, 34-37, 44-45, 52, 61-72, 76, 93-103, 107-113, 116-118, 121-124, 127, 131, 135, 139, 143, 147, 151-152, 156-159, 163-166, 170-173, 177-180, 184-187, 191-194
amqtt/mqtt3/pubrec.py 32 19 8 0 32% 16-25, 29-30, 34-37, 41-44
amqtt/mqtt3/pubrel.py 32 19 8 0 32% 16-25, 29-30, 34-37, 41-44
amqtt/mqtt3/suback.py 55 32 10 0 35% 19-20, 24, 31-34, 43-56, 69-79, 83-85
amqtt/mqtt3/subscribe.py 55 36 10 0 29% 14-15, 22-26, 35-51, 55, 68-78, 82-84
amqtt/mqtt3/unsuback.py 20 11 4 0 38% 17-29, 33-34
amqtt/mqtt3/unsubscribe.py 50 32 10 0 30% 14-15, 18-21, 30-44, 57-67, 71-73
amqtt/mqtt5/init.py 0 0 0 0 100%
amqtt/mqtt5/properties.py 221 57 114 26 72% 38-39, 62-63, 87, 101-102, 143-148, 152, 156, 161, 166, 172-174, 183-186, 191-196, 211, 213->exit, 214, 217, 218->exit, 219->exit, 220, 226-227, 237-238, 258-259, 265->270, 267-268, 275-276, 297->exit, 304-305, 310-311, 315-316, 319-321, 326-327, 331-332
amqtt/mqtt5/property_ids.py 64 1 0 0 98% 273
amqtt/mqtt5/protocol/init.py 0 0 0 0 100%
amqtt/mqtt/init.py 71 71 12 0 0% 2-121
amqtt/plugins/init.py 22 14 10 0 25% 11-12, 15-17, 20-34, 38
amqtt/plugins/authentication.py 82 82 26 0 0% 1-114
amqtt/plugins/base.py 59 39 26 0 24% 32-34, 39-46, 50-58, 72-76, 79-88, 104, 111-119, 122-127, 140
amqtt/plugins/logging_amqtt.py 33 33 12 0 0% 1-52
amqtt/plugins/manager.py 234 183 76 0 16% 41, 45-48, 63-81, 85, 98-148, 152-178, 182-199, 203-222, 226-256, 266-269, 272-275, 279-282, 290, 293, 296-306, 320-338, 353-371, 379, 392, 402
amqtt/plugins/persistence.py 7 7 0 0 0% 1-11
amqtt/plugins/sys/init.py 0 0 0 0 100%
amqtt/plugins/sys/broker.py 133 133 30 0 0% 1-244
amqtt/plugins/topic_checking.py 78 78 32 0 0% 1-105
amqtt/session.py 141 99 16 0 27% 43-81, 91, 100-102, 111-112, 121-122, 129-166, 169-192, 199-204, 207-210, 214-222, 226, 230, 234, 242, 251-255, 263-265, 269-272, 276-278
amqtt/utils.py 49 32 10 1 31% 15, 26-30, 35-41, 46-52, 58-64, 77-88

TOTAL 6020 4621 1504 35 20%
Coverage HTML written to dir htmlcov
============================== 76 passed in 0.95s ==============================

ajmirsky added 2 commits May 8, 2026 16:30
…mqtt module as deprecated. allows for a namespace for mqtt 5 implementation
@ajmirsky ajmirsky marked this pull request as draft May 8, 2026 20:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant