Skip to content

Commit fbd1f4b

Browse files
authored
Merge pull request #419 from ikalchev/v4.5.0
V4.5.0
2 parents 6c2b95c + d900089 commit fbd1f4b

20 files changed

+57
-33
lines changed

.github/workflows/ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ jobs:
99
runs-on: ubuntu-latest
1010
strategy:
1111
matrix:
12-
python-version: [3.6, 3.7, 3.8, 3.9]
12+
python-version: [3.7, 3.8, 3.9, "3.10"]
1313

1414
steps:
1515
- uses: actions/checkout@v1

CHANGELOG.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,25 @@ Sections
1515
### Breaking Changes
1616
### Developers
1717
-->
18+
19+
## [4.5.0] - 2022-06-28
20+
21+
- Speed up "get accessories". [#418](https://github.com/ikalchev/HAP-python/pull/418)
22+
- Increase minimum python version to 3.7. [#417](https://github.com/ikalchev/HAP-python/pull/417)
23+
- Speed up encryption by using ChaCha20Poly1305Reusable. [#413](https://github.com/ikalchev/HAP-python/pull/413)
24+
- Speed up serialization using orjson. [#412](https://github.com/ikalchev/HAP-python/pull/412)
25+
- Avoid redundant parsing of the URL. [#402](https://github.com/ikalchev/HAP-python/pull/402)
26+
1827
## [4.4.0] - 2022-11-01
1928

2029
### Added
21-
- Allow invalid client values when enabled. [#392](https://github.com/ikalchev/HAP- python/pull/392)
30+
- Allow invalid client values when enabled. [#392](https://github.com/ikalchev/HAP-python/pull/392)
2231

2332
## [4.3.0] - 2021-10-07
2433

2534
### Fixed
2635
- Only send the latest state in case of multiple events for the same characteristic. [#385](https://github.com/ikalchev/HAP-python/pull/385)
27-
- Handle invalid formats from clients. [#387](https://github.com/ikalchev/HAP- python/pull/387)
36+
- Handle invalid formats from clients. [#387](https://github.com/ikalchev/HAP-python/pull/387)
2837

2938
## [4.2.1] - 2021-09-06
3039

docs/source/conf.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
#
6161
# This is also used if you do content translation via gettext catalogs.
6262
# Usually you set "language" from the command line for these cases.
63-
language = None
63+
#language = None
6464

6565
# List of patterns, relative to source directory, that match files and
6666
# directories to ignore when looking for source files.
@@ -158,4 +158,4 @@
158158
]
159159

160160

161-
# -- Extension configuration -------------------------------------------------
161+
# -- Extension configuration -------------------------------------------------

pyhap/accessory.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ def setup_message(self):
245245
)
246246
else:
247247
print(
248-
"To use the QR Code feature, use 'pip install " "HAP-python[QRCode]'",
248+
"To use the QR Code feature, use 'pip install HAP-python[QRCode]'",
249249
flush=True,
250250
)
251251
print(

pyhap/camera.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -842,7 +842,7 @@ async def start_stream(self, session_info, stream_config):
842842

843843
return True
844844

845-
async def stop_stream(self, session_info): # pylint: disable=no-self-use
845+
async def stop_stream(self, session_info):
846846
"""Stop the stream for the given ``session_id``.
847847
848848
This method can be implemented if custom stop stream commands are needed. The
@@ -886,7 +886,7 @@ async def reconfigure_stream(self, session_info, stream_config):
886886
"""
887887
await self.start_stream(session_info, stream_config)
888888

889-
def get_snapshot(self, image_size): # pylint: disable=unused-argument, no-self-use
889+
def get_snapshot(self, image_size): # pylint: disable=unused-argument
890890
"""Return a jpeg of a snapshot from the camera.
891891
892892
Overwrite to implement getting snapshots from your camera.

pyhap/characteristic.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@
8282
PROP_UNIT = "unit"
8383
PROP_VALID_VALUES = "ValidValues"
8484

85-
PROP_NUMERIC = (PROP_MAX_VALUE, PROP_MIN_VALUE, PROP_MIN_STEP, PROP_UNIT)
85+
PROP_NUMERIC = {PROP_MAX_VALUE, PROP_MIN_VALUE, PROP_MIN_STEP, PROP_UNIT}
8686

8787
CHAR_BUTTON_EVENT = UUID("00000126-0000-1000-8000-0026BB765291")
8888
CHAR_PROGRAMMABLE_SWITCH_EVENT = UUID("00000073-0000-1000-8000-0026BB765291")
@@ -358,7 +358,10 @@ def to_HAP(self):
358358
value = self.get_value()
359359
if self.properties[PROP_FORMAT] in HAP_FORMAT_NUMERICS:
360360
hap_rep.update(
361-
{k: self.properties[k] for k in self.properties.keys() & PROP_NUMERIC}
361+
{
362+
k: self.properties[k]
363+
for k in PROP_NUMERIC.intersection(self.properties)
364+
}
362365
)
363366

364367
if PROP_VALID_VALUES in self.properties:

pyhap/const.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
"""This module contains constants used by other modules."""
22
MAJOR_VERSION = 4
3-
MINOR_VERSION = 4
3+
MINOR_VERSION = 5
44
PATCH_VERSION = 0
55
__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
66
__version__ = f"{__short_version__}.{PATCH_VERSION}"
7-
REQUIRED_PYTHON_VER = (3, 6)
7+
REQUIRED_PYTHON_VER = (3, 7)
88

99
BASE_UUID = "-0000-1000-8000-0026BB765291"
1010

pyhap/hap_crypto.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
import logging
33
import struct
44

5+
from chacha20poly1305_reuseable import ChaCha20Poly1305Reusable as ChaCha20Poly1305
56
from cryptography.hazmat.backends import default_backend
67
from cryptography.hazmat.primitives import hashes
7-
from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305
88
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
99

1010
logger = logging.getLogger(__name__)

pyhap/hap_handler.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,14 @@
44
"""
55
import asyncio
66
from http import HTTPStatus
7-
import json
87
import logging
98
from urllib.parse import parse_qs, urlparse
109
import uuid
1110

1211
from cryptography.exceptions import InvalidSignature, InvalidTag
1312
from cryptography.hazmat.primitives import serialization
1413
from cryptography.hazmat.primitives.asymmetric import ed25519, x25519
15-
from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305
14+
from chacha20poly1305_reuseable import ChaCha20Poly1305Reusable as ChaCha20Poly1305
1615

1716
from pyhap import tlv
1817
from pyhap.const import (
@@ -25,7 +24,7 @@
2524
from pyhap.util import long_to_bytes
2625

2726
from .hap_crypto import hap_hkdf, pad_tls_nonce
28-
from .util import to_hap_json
27+
from .util import to_hap_json, from_hap_json
2928

3029
# iOS will terminate the connection if it does not respond within
3130
# 10 seconds, so we only allow 9 seconds to avoid this.
@@ -145,6 +144,7 @@ def __init__(self, accessory_handler, client_address):
145144
self.command = None
146145
self.headers = None
147146
self.request_body = None
147+
self.parsed_url = None
148148

149149
self.response = None
150150

@@ -199,6 +199,7 @@ def dispatch(self, request, body=None):
199199
self.command = request.method.decode()
200200
self.headers = {k.decode(): v.decode() for k, v in request.headers}
201201
self.request_body = body
202+
self.parsed_url = urlparse(self.path)
202203
response = HAPResponse()
203204
self.response = response
204205

@@ -210,7 +211,7 @@ def dispatch(self, request, body=None):
210211
self.headers,
211212
)
212213

213-
path = urlparse(self.path).path
214+
path = self.parsed_url.path
214215
try:
215216
getattr(self, self.HANDLERS[self.command][path])()
216217
except UnprivilegedRequestException:
@@ -584,7 +585,7 @@ def handle_get_characteristics(self):
584585
raise UnprivilegedRequestException
585586

586587
# Check that char exists and ...
587-
params = parse_qs(urlparse(self.path).query)
588+
params = parse_qs(self.parsed_url.query)
588589
response = self.accessory_handler.get_characteristics(
589590
params["id"][0].split(",")
590591
)
@@ -612,7 +613,7 @@ def handle_set_characteristics(self):
612613
self.send_response(HTTPStatus.UNAUTHORIZED)
613614
return
614615

615-
requested_chars = json.loads(self.request_body.decode("utf-8"))
616+
requested_chars = from_hap_json(self.request_body.decode("utf-8"))
616617
logger.debug(
617618
"%s: Set characteristics content: %s", self.client_address, requested_chars
618619
)
@@ -637,7 +638,7 @@ def handle_prepare(self):
637638
self.send_response(HTTPStatus.UNAUTHORIZED)
638639
return
639640

640-
request = json.loads(self.request_body.decode("utf-8"))
641+
request = from_hap_json(self.request_body.decode("utf-8"))
641642
logger.debug("%s: prepare content: %s", self.client_address, request)
642643

643644
response = self.accessory_handler.prepare(request, self.client_address)
@@ -742,7 +743,7 @@ def _send_tlv_pairing_response(self, data):
742743

743744
def handle_resource(self):
744745
"""Get a snapshot from the camera."""
745-
data = json.loads(self.request_body.decode("utf-8"))
746+
data = from_hap_json(self.request_body.decode("utf-8"))
746747

747748
if self.accessory_handler.accessory.category == CATEGORY_BRIDGE:
748749
accessory = self.accessory_handler.accessory.accessories.get(data["aid"])

pyhap/hap_protocol.py

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

1919
logger = logging.getLogger(__name__)
2020

21-
HIGH_WRITE_BUFFER_SIZE = 2 ** 19
21+
HIGH_WRITE_BUFFER_SIZE = 2**19
2222
# We timeout idle connections after 90 hours as we must
2323
# clean up unused sockets periodically. 90 hours was choosen
2424
# as its the longest time we expect a user to be away from

0 commit comments

Comments
 (0)