Skip to content

Commit 34c9659

Browse files
ikalchevakxbdracopjkundertIvan Kalchev
authored
V4.9.2 (#482)
* Late-import base36 and QR code libraries; remove SUPPORT_QR_CODE flag * Increase idle connection check interval to 300s (#475) This check was creating a lot of TimerHandles when the user had multiple bridges. We do not need to check very often as connections usually stay around for 24+hours * Implement zerocopy writes for the encrypted protocol (#476) * Implement zerocopy writes for the encrypted protocol With Python 3.12+ and later `transport.writelines` is implemented as [`sendmsg(..., IOV_MAX)`](python/cpython#91166) which allows us to avoid joining the bytes and sending them in one go. Older Python will effectively do the same thing we do now `b"".join(...)` * update tests * Revert "Late-import base36 and QR code libraries; remove SUPPORT_QR_CODE flag" (#477) * Avoid os.chmod failing on Windows if file non-existant (#471) * Avoid os.chmod failing on Windows if file non-existant * Update accessory_driver.py --------- Co-authored-by: Ivan Kalchev <25887324+ikalchev@users.noreply.github.com> * Fix mdns tests (#478) * Fix pylint complaints (#480) * Address remaining pylint complaints (#481) * Address remaining pylint complaints * Address remaining pylint complaints * v4.9.2 --------- Co-authored-by: Aarni Koskela <akx@iki.fi> Co-authored-by: J. Nick Koston <nick@koston.org> Co-authored-by: Perry Kundert <perry@kundert.ca> Co-authored-by: Ivan Kalchev <ii.kalchev@gmail.com>
1 parent 5265b54 commit 34c9659

File tree

12 files changed

+65
-53
lines changed

12 files changed

+65
-53
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ Sections
1616
### Developers
1717
-->
1818

19+
## [4.9.2] - 2024-11-03
20+
21+
- Implement zerocopy writes for the encrypted protocol. [#476](https://github.com/ikalchev/HAP-python/pull/476)
22+
- Linter and test fixe.
23+
1924
## [4.9.1] - 2023-10-25
2025

2126
- Fix handling of explict close. [#467](https://github.com/ikalchev/HAP-python/pull/467)

pyhap/accessory.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ def xhm_uri(self) -> str:
207207
int(self.driver.state.pincode.replace(b"-", b""), 10) & 0x7FFFFFFF
208208
) # pincode
209209

210-
encoded_payload = base36.dumps(payload).upper()
210+
encoded_payload = base36.dumps(payload).upper() # pylint: disable=possibly-used-before-assignment
211211
encoded_payload = encoded_payload.rjust(9, "0")
212212

213213
return "X-HM://" + encoded_payload + self.driver.state.setup_id

pyhap/accessory_driver.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ def start(self):
323323
and os.name != "nt"
324324
):
325325
logger.debug("Setting child watcher")
326-
watcher = asyncio.SafeChildWatcher()
326+
watcher = asyncio.SafeChildWatcher() # pylint: disable=deprecated-class
327327
watcher.attach_loop(self.loop)
328328
asyncio.set_child_watcher(watcher)
329329
else:
@@ -642,16 +642,19 @@ def persist(self):
642642
tmp_filename = None
643643
try:
644644
temp_dir = os.path.dirname(self.persist_file)
645+
logger.debug("Creating temp persist file in '%s'", temp_dir)
645646
with tempfile.NamedTemporaryFile(
646647
mode="w", dir=temp_dir, delete=False
647648
) as file_handle:
648649
tmp_filename = file_handle.name
650+
logger.debug("Created temp persist file '%s' named '%s'", file_handle, tmp_filename)
649651
self.encoder.persist(file_handle, self.state)
650652
if (
651653
os.name == "nt"
652654
): # Or `[WinError 5] Access Denied` will be raised on Windows
653655
os.chmod(tmp_filename, 0o644)
654-
os.chmod(self.persist_file, 0o644)
656+
if os.path.exists(self.persist_file):
657+
os.chmod(self.persist_file, 0o644)
655658
os.replace(tmp_filename, self.persist_file)
656659
except Exception: # pylint: disable=broad-except
657660
logger.exception("Failed to persist accessory state")

pyhap/const.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""This module contains constants used by other modules."""
22
MAJOR_VERSION = 4
33
MINOR_VERSION = 9
4-
PATCH_VERSION = 1
4+
PATCH_VERSION = 2
55
__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
66
__version__ = f"{__short_version__}.{PATCH_VERSION}"
77
REQUIRED_PYTHON_VER = (3, 7)

pyhap/hap_crypto.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import logging
44
import struct
55
from struct import Struct
6-
from typing import List
6+
from typing import Iterable, List
77

88
from chacha20poly1305_reuseable import ChaCha20Poly1305Reusable as ChaCha20Poly1305
99
from cryptography.hazmat.backends import default_backend
@@ -112,7 +112,7 @@ def decrypt(self) -> bytes:
112112

113113
return result
114114

115-
def encrypt(self, data: bytes) -> bytes:
115+
def encrypt(self, data: bytes) -> Iterable[bytes]:
116116
"""Encrypt and send the return bytes."""
117117
result: List[bytes] = []
118118
offset = 0
@@ -127,7 +127,4 @@ def encrypt(self, data: bytes) -> bytes:
127127
offset += length
128128
self._out_count += 1
129129

130-
# Join the result once instead of concatenating each time
131-
# as this is much faster than generating an new immutable
132-
# byte string each time.
133-
return b"".join(result)
130+
return result

pyhap/hap_protocol.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def write(self, data: bytes) -> None:
104104
self.handler.client_uuid,
105105
data,
106106
)
107-
self.transport.write(result)
107+
self.transport.writelines(result)
108108
else:
109109
logger.debug(
110110
"%s (%s): Send unencrypted: %s",

pyhap/hap_server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
logger = logging.getLogger(__name__)
1818

19-
IDLE_CONNECTION_CHECK_INTERVAL_SECONDS = 120
19+
IDLE_CONNECTION_CHECK_INTERVAL_SECONDS = 300
2020

2121

2222
class HAPServer:

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ disable = [
7777
"too-many-return-statements",
7878
"too-many-statements",
7979
"too-many-boolean-expressions",
80+
"too-many-positional-arguments",
8081
"unused-argument",
8182
"wrong-import-order",
8283
"unused-argument",

tests/test_accessory_driver.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -961,7 +961,7 @@ def test_mdns_service_info(driver: AccessoryDriver):
961961
assert mdns_info.server == "Test-Accessory-000000.local."
962962
assert mdns_info.port == port
963963
assert mdns_info.addresses == [b"\xac\x00\x00\x01"]
964-
assert mdns_info.properties == {
964+
assert mdns_info.decoded_properties == {
965965
"md": "Test Accessory",
966966
"pv": "1.1",
967967
"id": "00:00:00:00:00:00",
@@ -990,7 +990,7 @@ def test_mdns_service_info_with_specified_server(driver: AccessoryDriver):
990990
assert mdns_info.server == "hap1.local."
991991
assert mdns_info.port == port
992992
assert mdns_info.addresses == [b"\xac\x00\x00\x01"]
993-
assert mdns_info.properties == {
993+
assert mdns_info.decoded_properties == {
994994
"md": "Test Accessory",
995995
"pv": "1.1",
996996
"id": "00:00:00:00:00:00",

tests/test_hap_crypto.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def test_round_trip():
1515
crypto.OUT_CIPHER_INFO = crypto.IN_CIPHER_INFO
1616
crypto.reset(key)
1717

18-
encrypted = bytearray(crypto.encrypt(plaintext))
18+
encrypted = bytearray(b"".join(crypto.encrypt(plaintext)))
1919

2020
# Receive no data
2121
assert crypto.decrypt() == b""

0 commit comments

Comments
 (0)