8000 Small cleanups to the protocol handler (#465) · ikalchev/HAP-python@7d5fc4d · GitHub
[go: up one dir, main page]

Skip to content

Commit 7d5fc4d

Browse files
authored
Small cleanups to the protocol handler (#465)
1 parent e077ce5 commit 7d5fc4d

File tree

3 files changed

+50
-33
lines changed

3 files changed

+50
-33
lines changed

pyhap/hap_event.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
"""This module implements the HAP events."""
22

3+
from typing import Any, Dict
4+
35
from .const import HAP_REPR_CHARS
46
from .util import to_hap_json
57

@@ -10,13 +12,13 @@
1012
)
1113

1214

13-
def create_hap_event(data):
15+
def create_hap_event(data: Dict[str, Any]) -> bytes:
1416
"""Creates a HAP HTTP EVENT response for the given data.
1517
1618
@param data: Payload of the request.
1719
@type data: bytes
1820
"""
1921
bytesdata = to_hap_json({HAP_REPR_CHARS: data})
20-
return (
21-
EVENT_MSG_STUB + str(len(bytesdata)).encode("utf-8") + b"\r\n" * 2 + bytesdata
22+
return b"".join(
23+
(EVENT_MSG_STUB, str(len(bytesdata)).encode("utf-8"), b"\r\n" * 2, bytesdata)
2224
)

pyhap/hap_handler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def __init__(self):
5151
self.headers = []
5252
self.body = b""
5353
self.shared_key = None
54-
self.task = None
54+
self.task: Optional[asyncio.Future] = None
5555
self.pairing_changed = False
5656

5757
def __repr__(self):

pyhap/hap_protocol.py

Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import asyncio
66
import logging
77
import time
8+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple
89

910
from cryptography.exceptions import InvalidTag
1011
import h11
@@ -17,6 +18,9 @@
1718
from .hap_handler import HAPResponse, HAPServerHandler
1819
from .util import async_create_background_task
1920

21+
if TYPE_CHECKING:
22+
from .accessory_driver import AccessoryDriver
23+
2024
logger = logging.getLogger(__name__)
2125

2226
HIGH_WRITE_BUFFER_SIZE = 2**19
@@ -29,29 +33,35 @@
2933

3034
EVENT_COALESCE_TIME_WINDOW = 0.5
3135

36+
H11_END_OF_MESSAGE = h11.EndOfMessage()
37+
H11_CONNECTION_CLOSED = h11.ConnectionClosed()
38+
3239

3340
class HAPServerProtocol(asyncio.Protocol):
3441
"""A asyncio.Protocol implementing the HAP protocol."""
3542

36-
def __init__(self, loop, connections, accessory_driver) -> None:
37-
self.loop = loop
43+
def __init__(
44+
self,
45+
loop: asyncio.AbstractEventLoop,
46+
connections: Dict[str, "HAPServerProtocol"],
47+
accessory_driver: "AccessoryDriver",
48+
) -> None:
49+
self.loop: asyncio.AbstractEventLoop = loop
3850
self.conn = h11.Connection(h11.SERVER)
3951
self.connections = connections
4052
self.accessory_driver = accessory_driver
41-
self.handler = None
42-
self.peername = None
43-
self.transport = None
44-
45-
self.request = None
46-
self.request_body = None
47-
self.response = None
53+
self.handler: Optional[HAPServerHandler] = None
54+
self.peername: Optional[str] = None
55+
self.transport: Optional[asyncio.Transport] = None
4856

49-
self.last_activity = None
50-
self.hap_crypto = None
51-
self._event_timer = None
52-
self._event_queue = {}
57+
self.request: Optional[h11.Request] = None
58+
self.request_body: Optional[bytes] = None
59+
self.response: Optional[HAPResponse] = None
5360

54-
self.start_time = None
61+
self.last_activity: Optional[float] = None
62+
self.hap_crypto: Optional[HAPCrypto] = None
63+
self._event_timer: Optional[asyncio.TimerHandle] = None
64+
self._event_queue: Dict[Tuple[int, int], Dict[str, Any]] = {}
5565

5666
def connection_lost(self, exc: Exception) -> None:
5767
"""Handle connection lost."""
@@ -128,24 +138,29 @@ def send_response(self, response: HAPResponse) -> None:
128138
# Force Content-Length as iOS can sometimes
129139
# stall if it gets chunked encoding
130140
response.headers.append(("Content-Length", str(body_len)))
141+
send = self.conn.send
131142
self.write(
132-
self.conn.send(
133-
h11.Response(
134-
status_code=response.status_code,
135-
reason=response.reason,
136-
headers=response.headers,
143+
b"".join(
144+
(
145+
send(
146+
h11.Response(
147+
status_code=response.status_code,
148+
reason=response.reason,
149+
headers=response.headers,
150+
)
151+
),
152+
send(h11.Data(data=response.body)),
153+
send(H11_END_OF_MESSAGE),
137154
)
138155
)
139-
+ self.conn.send(h11.Data(data=response.body))
140-
+ self.conn.send(h11.EndOfMessage())
141156
)
142157

143-
def finish_and_close(self):
158+
def finish_and_close(self) F438 -> None:
144159
"""Cleanly finish and close the connection."""
145-
self.conn.send(h11.ConnectionClosed())
160+
self.conn.send(H11_CONNECTION_CLOSED)
146161
self.close()
147162

148-
def check_idle(self, now) -> None:
163+
def check_idle(self, now: float) -> None:
149164
"""Abort when do not get any data within the timeout."""
150165
if self.last_activity + IDLE_CONNECTION_TIMEOUT_SECONDS >= now:
151166
return
@@ -193,7 +208,7 @@ def data_received(self, data: bytes) -> None:
193208
)
194209
self._process_events()
195210

196-
def _process_events(self):
211+
def _process_events(self) -> None:
197212
"""Process pending events."""
198213
try:
199214
while self._process_one_event():
@@ -203,7 +218,7 @@ def _process_events(self):
203218
except h11.ProtocolError as protocol_ex:
204219
self._handle_invalid_conn_state(protocol_ex)
205220

206-
def _send_events(self):
221+
def _send_events(self) -> None:
207222
"""Send any pending events."""
208223
if self._event_timer:
209224
self._event_timer.cancel()
@@ -215,7 +230,7 @@ def _send_events(self):
215230
self.write(create_hap_event(subscribed_events))
216231
self._event_queue.clear()
217232

218-
def _event_queue_with_active_subscriptions(self):
233+
def _event_queue_with_active_subscriptions(self) -> List[Dict[str, Any]]:
219234
"""Remove any topics that have been unsubscribed after the event was generated."""
220235
topics = self.accessory_driver.topics
221236
return [
@@ -256,7 +271,7 @@ def _process_one_event(self) -> bool:
256271

257272
return self._handle_invalid_conn_state(f"Unexpected event: {event}")
258273

259-
def _process_response(self, response) -> None:
274+
def _process_response(self, response: HAPResponse) -> None:
260275
"""Process a response from the handler."""
261276
if response.task:
262277
# If there is a task pending we will schedule
@@ -298,7 +313,7 @@ def _handle_response_ready(self, task: asyncio.Task) -> None:
298313
return
299314
self.send_response(response)
300315

301-
def _handle_invalid_conn_state(self, message):
316+
def _handle_invalid_conn_state(self, message: Exception) -> bool:
302317
"""Log invalid state and close."""
303318
logger.debug(
304319
"%s (%s): Invalid state: %s: close the client socket",

0 commit comments

Comments
 (0)
0