From a5aa5c0c012b73a454948a4faa9174ff40488367 Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Mon, 20 Mar 2023 04:35:45 +0100 Subject: [PATCH 01/15] Fix imap_email_content unknown status and replaying stale states (#89563) --- .../components/imap_email_content/sensor.py | 74 ++++++++++++------- .../imap_email_content/test_sensor.py | 26 +++++-- 2 files changed, 70 insertions(+), 30 deletions(-) diff --git a/homeassistant/components/imap_email_content/sensor.py b/homeassistant/components/imap_email_content/sensor.py index b14de632687..53cb921860c 100644 --- a/homeassistant/components/imap_email_content/sensor.py +++ b/homeassistant/components/imap_email_content/sensor.py @@ -95,9 +95,25 @@ class EmailReader: self._folder = folder self._verify_ssl = verify_ssl self._last_id = None + self._last_message = None self._unread_ids = deque([]) self.connection = None + @property + def last_id(self) -> int | None: + """Return last email uid that was processed.""" + return self._last_id + + @property + def last_unread_id(self) -> int | None: + """Return last email uid received.""" + # We assume the last id in the list is the last unread id + # We cannot know if that is the newest one, because it could arrive later + # https://stackoverflow.com/questions/12409862/python-imap-the-order-of-uids + if self._unread_ids: + return int(self._unread_ids[-1]) + return self._last_id + def connect(self): """Login and setup the connection.""" ssl_context = client_context() if self._verify_ssl else None @@ -128,21 +144,21 @@ class EmailReader: try: self.connection.select(self._folder, readonly=True) - if not self._unread_ids: - search = f"SINCE {datetime.date.today():%d-%b-%Y}" - if self._last_id is not None: - search = f"UID {self._last_id}:*" - - _, data = self.connection.uid("search", None, search) - self._unread_ids = deque(data[0].split()) + if self._last_id is None: + # search for today and yesterday + time_from = datetime.datetime.now() - datetime.timedelta(days=1) + search = f"SINCE {time_from:%d-%b-%Y}" + else: + search = f"UID {self._last_id}:*" + _, data = self.connection.uid("search", None, search) + self._unread_ids = deque(data[0].split()) while self._unread_ids: message_uid = self._unread_ids.popleft() if self._last_id is None or int(message_uid) > self._last_id: self._last_id = int(message_uid) - return self._fetch_message(message_uid) - - return self._fetch_message(str(self._last_id)) + self._last_message = self._fetch_message(message_uid) + return self._last_message except imaplib.IMAP4.error: _LOGGER.info("Connection to %s lost, attempting to reconnect", self._server) @@ -254,22 +270,30 @@ class EmailContentSensor(SensorEntity): def update(self) -> None: """Read emails and publish state change.""" email_message = self._email_reader.read_next() + while ( + self._last_id is None or self._last_id != self._email_reader.last_unread_id + ): + if email_message is None: + self._message = None + self._state_attributes = {} + return - if email_message is None: - self._message = None - self._state_attributes = {} - return + self._last_id = self._email_reader.last_id - if self.sender_allowed(email_message): - message = EmailContentSensor.get_msg_subject(email_message) + if self.sender_allowed(email_message): + message = EmailContentSensor.get_msg_subject(email_message) - if self._value_template is not None: - message = self.render_template(email_message) + if self._value_template is not None: + message = self.render_template(email_message) - self._message = message - self._state_attributes = { - ATTR_FROM: EmailContentSensor.get_msg_sender(email_message), - ATTR_SUBJECT: EmailContentSensor.get_msg_subject(email_message), - ATTR_DATE: email_message["Date"], - ATTR_BODY: EmailContentSensor.get_msg_text(email_message), - } + self._message = message + self._state_attributes = { + ATTR_FROM: EmailContentSensor.get_msg_sender(email_message), + ATTR_SUBJECT: EmailContentSensor.get_msg_subject(email_message), + ATTR_DATE: email_message["Date"], + ATTR_BODY: EmailContentSensor.get_msg_text(email_message), + } + + if self._last_id == self._email_reader.last_unread_id: + break + email_message = self._email_reader.read_next() diff --git a/tests/components/imap_email_content/test_sensor.py b/tests/components/imap_email_content/test_sensor.py index afa6116ff42..ba2b362af73 100644 --- a/tests/components/imap_email_content/test_sensor.py +++ b/tests/components/imap_email_content/test_sensor.py @@ -14,9 +14,16 @@ from homeassistant.helpers.template import Template class FakeEMailReader: """A test class for sending test emails.""" - def __init__(self, messages): + def __init__(self, messages) -> None: """Set up the fake email reader.""" self._messages = messages + self.last_id = 0 + self.last_unread_id = len(messages) + + def add_test_message(self, message): + """Add a new message.""" + self.last_unread_id += 1 + self._messages.append(message) def connect(self): """Stay always Connected.""" @@ -26,6 +33,7 @@ class FakeEMailReader: """Get the next email.""" if len(self._messages) == 0: return None + self.last_id += 1 return self._messages.popleft() @@ -146,7 +154,7 @@ async def test_multi_part_only_other_text(hass: HomeAssistant) -> None: async def test_multiple_emails(hass: HomeAssistant) -> None: - """Test multiple emails.""" + """Test multiple emails, discarding stale states.""" states = [] test_message1 = email.message.Message() @@ -158,9 +166,15 @@ async def test_multiple_emails(hass: HomeAssistant) -> None: test_message2 = email.message.Message() test_message2["From"] = "sender@test.com" test_message2["Subject"] = "Test 2" - test_message2["Date"] = datetime.datetime(2016, 1, 1, 12, 44, 57) + test_message2["Date"] = datetime.datetime(2016, 1, 1, 12, 44, 58) test_message2.set_payload("Test Message 2") + test_message3 = email.message.Message() + test_message3["From"] = "sender@test.com" + test_message3["Subject"] = "Test 3" + test_message3["Date"] = datetime.datetime(2016, 1, 1, 12, 50, 1) + test_message3.set_payload("Test Message 2") + def state_changed_listener(entity_id, from_s, to_s): states.append(to_s) @@ -178,11 +192,13 @@ async def test_multiple_emails(hass: HomeAssistant) -> None: sensor.async_schedule_update_ha_state(True) await hass.async_block_till_done() + # Fake a new received message + sensor._email_reader.add_test_message(test_message3) sensor.async_schedule_update_ha_state(True) await hass.async_block_till_done() - assert states[0].state == "Test" - assert states[1].state == "Test 2" + assert states[0].state == "Test 2" + assert states[1].state == "Test 3" assert sensor.extra_state_attributes["body"] == "Test Message 2" From 1e03ff68a2604b78db53092cabd30f47b753c753 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 16 Mar 2023 16:44:49 -1000 Subject: [PATCH 02/15] Bump aioharmony to 0.2.10 (#89831) fixes #89823 --- homeassistant/components/harmony/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/harmony/manifest.json b/homeassistant/components/harmony/manifest.json index 2603ee613ae..c6a6327046d 100644 --- a/homeassistant/components/harmony/manifest.json +++ b/homeassistant/components/harmony/manifest.json @@ -13,7 +13,7 @@ "documentation": "https://www.home-assistant.io/integrations/harmony", "iot_class": "local_push", "loggers": ["aioharmony", "slixmpp"], - "requirements": ["aioharmony==0.2.9"], + "requirements": ["aioharmony==0.2.10"], "ssdp": [ { "manufacturer": "Logitech", diff --git a/requirements_all.txt b/requirements_all.txt index cdffe860f75..3fcf96ccb5e 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -171,7 +171,7 @@ aiogithubapi==22.10.1 aioguardian==2022.07.0 # homeassistant.components.harmony -aioharmony==0.2.9 +aioharmony==0.2.10 # homeassistant.components.homekit_controller aiohomekit==2.6.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index c8f2b57a764..7061c3bf624 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -155,7 +155,7 @@ aiogithubapi==22.10.1 aioguardian==2022.07.0 # homeassistant.components.harmony -aioharmony==0.2.9 +aioharmony==0.2.10 # homeassistant.components.homekit_controller aiohomekit==2.6.1 From 713d3025f20b8649d823804bd669b778723f72ea Mon Sep 17 00:00:00 2001 From: Joakim Plate Date: Mon, 20 Mar 2023 12:08:27 +0100 Subject: [PATCH 03/15] Correct missing wordswap for S series nibe (#89866) Correct missing wordswap for nibe --- homeassistant/components/nibe_heatpump/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/nibe_heatpump/__init__.py b/homeassistant/components/nibe_heatpump/__init__.py index fd77b5e2344..89aac6bed61 100644 --- a/homeassistant/components/nibe_heatpump/__init__.py +++ b/homeassistant/components/nibe_heatpump/__init__.py @@ -62,13 +62,13 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up Nibe Heat Pump from a config entry.""" heatpump = HeatPump(Model[entry.data[CONF_MODEL]]) + heatpump.word_swap = entry.data.get(CONF_WORD_SWAP, True) await heatpump.initialize() connection: Connection connection_type = entry.data[CONF_CONNECTION_TYPE] if connection_type == CONF_CONNECTION_TYPE_NIBEGW: - heatpump.word_swap = entry.data[CONF_WORD_SWAP] connection = NibeGW( heatpump, entry.data[CONF_IP_ADDRESS], From de6f55dcfb994929753d419bedee5056676d7f7d Mon Sep 17 00:00:00 2001 From: Jan Bouwhuis Date: Sun, 19 Mar 2023 01:57:40 +0100 Subject: [PATCH 04/15] Fix blocking MQTT entry unload (#89922) * Remove unneeded async_block_till_done * use await asyncio.sleep(0) instead --- homeassistant/components/mqtt/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/mqtt/__init__.py b/homeassistant/components/mqtt/__init__.py index a1b194284c7..ff126a22603 100644 --- a/homeassistant/components/mqtt/__init__.py +++ b/homeassistant/components/mqtt/__init__.py @@ -706,7 +706,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: for component in PLATFORMS ) ) - await hass.async_block_till_done() + await asyncio.sleep(0) # Unsubscribe reload dispatchers while reload_dispatchers := mqtt_data.reload_dispatchers: reload_dispatchers.pop()() From 127f2289a1af45ac123e733947f11b7ba40df3f1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 18 Mar 2023 20:59:05 -1000 Subject: [PATCH 05/15] Remove async_block_till_done in freebox (#89928) async_block_till_done() is not meant to be called in integrations --- homeassistant/components/freebox/config_flow.py | 1 - 1 file changed, 1 deletion(-) diff --git a/homeassistant/components/freebox/config_flow.py b/homeassistant/components/freebox/config_flow.py index fd9252aaa17..dbee01c4e7d 100644 --- a/homeassistant/components/freebox/config_flow.py +++ b/homeassistant/components/freebox/config_flow.py @@ -77,7 +77,6 @@ class FreeboxFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): # Check permissions await fbx.system.get_config() await fbx.lan.get_hosts_list() - await self.hass.async_block_till_done() # Close connection await fbx.close() From 92fb978a0377e6cea5c848c6a7265ab2f62a5657 Mon Sep 17 00:00:00 2001 From: micha91 Date: Mon, 20 Mar 2023 11:59:27 +0100 Subject: [PATCH 06/15] Bump aiomusiccast to 0.14.8 (#89978) --- homeassistant/components/yamaha_musiccast/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/yamaha_musiccast/manifest.json b/homeassistant/components/yamaha_musiccast/manifest.json index 9a19f61eb44..48b8de20608 100644 --- a/homeassistant/components/yamaha_musiccast/manifest.json +++ b/homeassistant/components/yamaha_musiccast/manifest.json @@ -7,7 +7,7 @@ "documentation": "https://www.home-assistant.io/integrations/yamaha_musiccast", "iot_class": "local_push", "loggers": ["aiomusiccast"], - "requirements": ["aiomusiccast==0.14.7"], + "requirements": ["aiomusiccast==0.14.8"], "ssdp": [ { "manufacturer": "Yamaha Corporation" diff --git a/requirements_all.txt b/requirements_all.txt index 3fcf96ccb5e..27eb15772e6 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -214,7 +214,7 @@ aiolyric==1.0.9 aiomodernforms==0.1.8 # homeassistant.components.yamaha_musiccast -aiomusiccast==0.14.7 +aiomusiccast==0.14.8 # homeassistant.components.nanoleaf aionanoleaf==0.2.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 7061c3bf624..2168b2b42f7 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -195,7 +195,7 @@ aiolyric==1.0.9 aiomodernforms==0.1.8 # homeassistant.components.yamaha_musiccast -aiomusiccast==0.14.7 +aiomusiccast==0.14.8 # homeassistant.components.nanoleaf aionanoleaf==0.2.1 From 1f71068740a6947acaa485af86b2acb2bad36b46 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 20 Mar 2023 17:49:59 -1000 Subject: [PATCH 07/15] Handle cancelation of wait_for_ble_connections_free in esphome bluetooth (#90014) Handle cancelation in wait_for_ble_connections_free If `wait_for_ble_connections_free` was canceled due to timeout or the esp disconnecting from Home Assistant the future would get canceled. When we reconnect and get the next callback we need to handle it being done. fixes ``` 2023-03-21 02:34:36.876 ERROR (MainThread) [homeassistant] Error doing job: Fatal error: protocol.data_received() call failed. Traceback (most recent call last): File "/usr/local/lib/python3.10/asyncio/selector_events.py", line 868, in _read_ready__data_received self._protocol.data_received(data) File "/usr/local/lib/python3.10/site-packages/aioesphomeapi/_frame_helper.py", line 195, in data_received self._callback_packet(msg_type_int, bytes(packet_data)) File "/usr/local/lib/python3.10/site-packages/aioesphomeapi/_frame_helper.py", line 110, in _callback_packet self._on_pkt(Packet(type_, data)) File "/usr/local/lib/python3.10/site-packages/aioesphomeapi/connection.py", line 688, in _process_packet handler(msg) File "/usr/local/lib/python3.10/site-packages/aioesphomeapi/client.py", line 482, in on_msg on_bluetooth_connections_free_update(resp.free, resp.limit) File "/usr/src/homeassistant/homeassistant/components/esphome/entry_data.py", line 136, in async_update_ble_connection_limits fut.set_result(free) asyncio.exceptions.InvalidStateError: invalid state ``` --- homeassistant/components/esphome/entry_data.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/esphome/entry_data.py b/homeassistant/components/esphome/entry_data.py index 0aed6ce43a7..a389d746435 100644 --- a/homeassistant/components/esphome/entry_data.py +++ b/homeassistant/components/esphome/entry_data.py @@ -130,10 +130,15 @@ class RuntimeEntryData: ) self.ble_connections_free = free self.ble_connections_limit = limit - if free: - for fut in self._ble_connection_free_futures: + if not free: + return + for fut in self._ble_connection_free_futures: + # If wait_for_ble_connections_free gets cancelled, it will + # leave a future in the list. We need to check if it's done + # before setting the result. + if not fut.done(): fut.set_result(free) - self._ble_connection_free_futures.clear() + self._ble_connection_free_futures.clear() async def wait_for_ble_connections_free(self) -> int: """Wait until there are free BLE connections.""" From 2a18261efb4b476b38e774740d59d04f09f9c8fc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 15 Mar 2023 17:47:26 -1000 Subject: [PATCH 08/15] Bump yalexs_ble to 2.1.0 (#89772) switches to using cryptography to reduce the number of deps changelog: https://github.com/bdraco/yalexs-ble/compare/v2.0.4...v2.1.0 --- homeassistant/components/august/manifest.json | 2 +- homeassistant/components/yalexs_ble/manifest.json | 2 +- requirements_all.txt | 4 ++-- requirements_test_all.txt | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/august/manifest.json b/homeassistant/components/august/manifest.json index dedfc9127a3..eba6e2c1b39 100644 --- a/homeassistant/components/august/manifest.json +++ b/homeassistant/components/august/manifest.json @@ -28,5 +28,5 @@ "documentation": "https://www.home-assistant.io/integrations/august", "iot_class": "cloud_push", "loggers": ["pubnub", "yalexs"], - "requirements": ["yalexs==1.2.7", "yalexs_ble==2.0.4"] + "requirements": ["yalexs==1.2.7", "yalexs_ble==2.1.0"] } diff --git a/homeassistant/components/yalexs_ble/manifest.json b/homeassistant/components/yalexs_ble/manifest.json index e34ace05e15..e793fe27286 100644 --- a/homeassistant/components/yalexs_ble/manifest.json +++ b/homeassistant/components/yalexs_ble/manifest.json @@ -12,5 +12,5 @@ "dependencies": ["bluetooth_adapters"], "documentation": "https://www.home-assistant.io/integrations/yalexs_ble", "iot_class": "local_push", - "requirements": ["yalexs-ble==2.0.4"] + "requirements": ["yalexs-ble==2.1.0"] } diff --git a/requirements_all.txt b/requirements_all.txt index 27eb15772e6..debc7d480cc 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2670,13 +2670,13 @@ xs1-api-client==3.0.0 yalesmartalarmclient==0.3.9 # homeassistant.components.yalexs_ble -yalexs-ble==2.0.4 +yalexs-ble==2.1.0 # homeassistant.components.august yalexs==1.2.7 # homeassistant.components.august -yalexs_ble==2.0.4 +yalexs_ble==2.1.0 # homeassistant.components.yeelight yeelight==0.7.10 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 2168b2b42f7..09afa5970ba 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1895,13 +1895,13 @@ xmltodict==0.13.0 yalesmartalarmclient==0.3.9 # homeassistant.components.yalexs_ble -yalexs-ble==2.0.4 +yalexs-ble==2.1.0 # homeassistant.components.august yalexs==1.2.7 # homeassistant.components.august -yalexs_ble==2.0.4 +yalexs_ble==2.1.0 # homeassistant.components.yeelight yeelight==0.7.10 From 53d400ca9679650f24bafac61f3e3fa8f2102fc3 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 20 Mar 2023 17:49:30 -1000 Subject: [PATCH 09/15] Bump yalexs-ble to 2.1.1 (#90015) * Bump yalexs-ble to 2.1.1 There was another task that could be prematurely GCed changelog: https://github.com/bdraco/yalexs-ble/compare/v2.1.0...v2.1.1 * fixes --- homeassistant/components/august/manifest.json | 2 +- homeassistant/components/yalexs_ble/manifest.json | 2 +- requirements_all.txt | 6 ++---- requirements_test_all.txt | 6 ++---- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/homeassistant/components/august/manifest.json b/homeassistant/components/august/manifest.json index eba6e2c1b39..213f0237e12 100644 --- a/homeassistant/components/august/manifest.json +++ b/homeassistant/components/august/manifest.json @@ -28,5 +28,5 @@ "documentation": "https://www.home-assistant.io/integrations/august", "iot_class": "cloud_push", "loggers": ["pubnub", "yalexs"], - "requirements": ["yalexs==1.2.7", "yalexs_ble==2.1.0"] + "requirements": ["yalexs==1.2.7", "yalexs-ble==2.1.1"] } diff --git a/homeassistant/components/yalexs_ble/manifest.json b/homeassistant/components/yalexs_ble/manifest.json index e793fe27286..6bb58752a00 100644 --- a/homeassistant/components/yalexs_ble/manifest.json +++ b/homeassistant/components/yalexs_ble/manifest.json @@ -12,5 +12,5 @@ "dependencies": ["bluetooth_adapters"], "documentation": "https://www.home-assistant.io/integrations/yalexs_ble", "iot_class": "local_push", - "requirements": ["yalexs-ble==2.1.0"] + "requirements": ["yalexs-ble==2.1.1"] } diff --git a/requirements_all.txt b/requirements_all.txt index debc7d480cc..e763e3037ab 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2669,15 +2669,13 @@ xs1-api-client==3.0.0 # homeassistant.components.yale_smart_alarm yalesmartalarmclient==0.3.9 +# homeassistant.components.august # homeassistant.components.yalexs_ble -yalexs-ble==2.1.0 +yalexs-ble==2.1.1 # homeassistant.components.august yalexs==1.2.7 -# homeassistant.components.august -yalexs_ble==2.1.0 - # homeassistant.components.yeelight yeelight==0.7.10 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 09afa5970ba..73feda7628e 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1894,15 +1894,13 @@ xmltodict==0.13.0 # homeassistant.components.yale_smart_alarm yalesmartalarmclient==0.3.9 +# homeassistant.components.august # homeassistant.components.yalexs_ble -yalexs-ble==2.1.0 +yalexs-ble==2.1.1 # homeassistant.components.august yalexs==1.2.7 -# homeassistant.components.august -yalexs_ble==2.1.0 - # homeassistant.components.yeelight yeelight==0.7.10 From 3747fd5dcb74842b6eab31630238bceccc54fc0d Mon Sep 17 00:00:00 2001 From: Klaas Schoute Date: Mon, 13 Mar 2023 15:00:50 +0100 Subject: [PATCH 10/15] Bump easyEnergy to v0.2.1 (#89630) --- homeassistant/components/easyenergy/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/easyenergy/manifest.json b/homeassistant/components/easyenergy/manifest.json index 6b88dd84c89..fc0a4fd7739 100644 --- a/homeassistant/components/easyenergy/manifest.json +++ b/homeassistant/components/easyenergy/manifest.json @@ -6,5 +6,5 @@ "documentation": "https://www.home-assistant.io/integrations/easyenergy", "iot_class": "cloud_polling", "quality_scale": "platinum", - "requirements": ["easyenergy==0.1.2"] + "requirements": ["easyenergy==0.2.1"] } diff --git a/requirements_all.txt b/requirements_all.txt index e763e3037ab..ba96fabc1a8 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -625,7 +625,7 @@ dynalite_devices==0.1.47 eagle100==0.1.1 # homeassistant.components.easyenergy -easyenergy==0.1.2 +easyenergy==0.2.1 # homeassistant.components.ebusd ebusdpy==0.0.17 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 73feda7628e..0331bdf76e7 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -490,7 +490,7 @@ dynalite_devices==0.1.47 eagle100==0.1.1 # homeassistant.components.easyenergy -easyenergy==0.1.2 +easyenergy==0.2.1 # homeassistant.components.elgato elgato==4.0.1 From 146347e31aba16345f2ecc51496601e80d24d7c1 Mon Sep 17 00:00:00 2001 From: Klaas Schoute Date: Wed, 22 Mar 2023 10:46:17 +0100 Subject: [PATCH 11/15] Bump easyEnergy to v0.2.2 (#90080) --- homeassistant/components/easyenergy/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/easyenergy/manifest.json b/homeassistant/components/easyenergy/manifest.json index fc0a4fd7739..0954269628a 100644 --- a/homeassistant/components/easyenergy/manifest.json +++ b/homeassistant/components/easyenergy/manifest.json @@ -6,5 +6,5 @@ "documentation": "https://www.home-assistant.io/integrations/easyenergy", "iot_class": "cloud_polling", "quality_scale": "platinum", - "requirements": ["easyenergy==0.2.1"] + "requirements": ["easyenergy==0.2.2"] } diff --git a/requirements_all.txt b/requirements_all.txt index ba96fabc1a8..f282e59eebf 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -625,7 +625,7 @@ dynalite_devices==0.1.47 eagle100==0.1.1 # homeassistant.components.easyenergy -easyenergy==0.2.1 +easyenergy==0.2.2 # homeassistant.components.ebusd ebusdpy==0.0.17 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 0331bdf76e7..6200c913d38 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -490,7 +490,7 @@ dynalite_devices==0.1.47 eagle100==0.1.1 # homeassistant.components.easyenergy -easyenergy==0.2.1 +easyenergy==0.2.2 # homeassistant.components.elgato elgato==4.0.1 From 406e92511bb489cf8dbd80e7c37090a2721ab942 Mon Sep 17 00:00:00 2001 From: Luke Date: Tue, 21 Mar 2023 23:09:38 -0400 Subject: [PATCH 12/15] Bump to oralb-ble 0.17.6 (#90081) --- homeassistant/components/oralb/manifest.json | 3 ++- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/oralb/manifest.json b/homeassistant/components/oralb/manifest.json index 37b043e5436..a1071cc0a11 100644 --- a/homeassistant/components/oralb/manifest.json +++ b/homeassistant/components/oralb/manifest.json @@ -11,5 +11,6 @@ "dependencies": ["bluetooth_adapters"], "documentation": "https://www.home-assistant.io/integrations/oralb", "iot_class": "local_push", - "requirements": ["oralb-ble==0.17.5"] + "loggers": ["oralb-ble"], + "requirements": ["oralb-ble==0.17.6"] } diff --git a/requirements_all.txt b/requirements_all.txt index f282e59eebf..fe86666d9c4 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1299,7 +1299,7 @@ openwrt-luci-rpc==1.1.11 openwrt-ubus-rpc==0.0.2 # homeassistant.components.oralb -oralb-ble==0.17.5 +oralb-ble==0.17.6 # homeassistant.components.oru oru==0.1.11 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 6200c913d38..87663416f00 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -947,7 +947,7 @@ openai==0.26.2 openerz-api==0.2.0 # homeassistant.components.oralb -oralb-ble==0.17.5 +oralb-ble==0.17.6 # homeassistant.components.ovo_energy ovoenergy==1.2.0 From a7b5a0297ef913ab305b22d2ebaf0cbdf0f0c4b9 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 22 Mar 2023 16:10:47 -1000 Subject: [PATCH 13/15] Bump PySwitchbot to 0.37.4 (#90146) fixes #90090 fixes #89061 changelog: https://github.com/Danielhiversen/pySwitchbot/compare/0.37.3...0.37.4 --- homeassistant/components/switchbot/manifest.json | 2 +- requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/switchbot/manifest.json b/homeassistant/components/switchbot/manifest.json index 2637f578b8f..ada24bcee57 100644 --- a/homeassistant/components/switchbot/manifest.json +++ b/homeassistant/components/switchbot/manifest.json @@ -40,5 +40,5 @@ "documentation": "https://www.home-assistant.io/integrations/switchbot", "iot_class": "local_push", "loggers": ["switchbot"], - "requirements": ["PySwitchbot==0.37.3"] + "requirements": ["PySwitchbot==0.37.4"] } diff --git a/requirements_all.txt b/requirements_all.txt index fe86666d9c4..9b63f54a60e 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -40,7 +40,7 @@ PyRMVtransport==0.3.3 PySocks==1.7.1 # homeassistant.components.switchbot -PySwitchbot==0.37.3 +PySwitchbot==0.37.4 # homeassistant.components.transport_nsw PyTransportNSW==0.1.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 87663416f00..e71f661b4ea 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -36,7 +36,7 @@ PyRMVtransport==0.3.3 PySocks==1.7.1 # homeassistant.components.switchbot -PySwitchbot==0.37.3 +PySwitchbot==0.37.4 # homeassistant.components.transport_nsw PyTransportNSW==0.1.1 From 174342860b828040b7018210861d98d1ae503de9 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 22 Mar 2023 22:54:09 -0400 Subject: [PATCH 14/15] Always enforce URL param ordering for signed URLs (#90148) Always enforce URL param ordering --- homeassistant/components/http/auth.py | 15 +++++++------- tests/components/http/test_auth.py | 28 ++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/homeassistant/components/http/auth.py b/homeassistant/components/http/auth.py index 5213cd1b072..d10bd677e41 100644 --- a/homeassistant/components/http/auth.py +++ b/homeassistant/components/http/auth.py @@ -60,9 +60,7 @@ def async_sign_path( url = URL(path) now = dt_util.utcnow() - params = dict(sorted(url.query.items())) - for param in SAFE_QUERY_PARAMS: - params.pop(param, None) + params = [itm for itm in url.query.items() if itm[0] not in SAFE_QUERY_PARAMS] encoded = jwt.encode( { "iss": refresh_token_id, @@ -75,7 +73,7 @@ def async_sign_path( algorithm="HS256", ) - params[SIGN_QUERY_PARAM] = encoded + params.append((SIGN_QUERY_PARAM, encoded)) url = url.with_query(params) return f"{url.path}?{url.query_string}" @@ -184,10 +182,11 @@ async def async_setup_auth(hass: HomeAssistant, app: Application) -> None: if claims["path"] != request.path: return False - params = dict(sorted(request.query.items())) - del params[SIGN_QUERY_PARAM] - for param in SAFE_QUERY_PARAMS: - params.pop(param, None) + params = [ + list(itm) # claims stores tuples as lists + for itm in request.query.items() + if itm[0] not in SAFE_QUERY_PARAMS and itm[0] != SIGN_QUERY_PARAM + ] if claims["params"] != params: return False diff --git a/tests/components/http/test_auth.py b/tests/components/http/test_auth.py index fb00640cdc5..246572e64f8 100644 --- a/tests/components/http/test_auth.py +++ b/tests/components/http/test_auth.py @@ -352,6 +352,12 @@ async def test_auth_access_signed_path_with_query_param( data = await req.json() assert data["user_id"] == refresh_token.user.id + # Without query params not allowed + url = yarl.URL(signed_path) + signed_path = f"{url.path}?{SIGN_QUERY_PARAM}={url.query.get(SIGN_QUERY_PARAM)}" + req = await client.get(signed_path) + assert req.status == HTTPStatus.UNAUTHORIZED + async def test_auth_access_signed_path_with_query_param_order( hass: HomeAssistant, @@ -374,12 +380,24 @@ async def test_auth_access_signed_path_with_query_param_order( refresh_token_id=refresh_token.id, ) url = yarl.URL(signed_path) - signed_path = f"{url.path}?{SIGN_QUERY_PARAM}={url.query.get(SIGN_QUERY_PARAM)}&foo=bar&test=test" - req = await client.get(signed_path) - assert req.status == HTTPStatus.OK - data = await req.json() - assert data["user_id"] == refresh_token.user.id + # Change order + req = await client.get( + f"{url.path}?{SIGN_QUERY_PARAM}={url.query.get(SIGN_QUERY_PARAM)}&foo=bar&test=test" + ) + assert req.status == HTTPStatus.UNAUTHORIZED + + # Duplicate a param + req = await client.get( + f"{url.path}?{SIGN_QUERY_PARAM}={url.query.get(SIGN_QUERY_PARAM)}&test=test&foo=aaa&foo=bar" + ) + assert req.status == HTTPStatus.UNAUTHORIZED + + # Remove a param + req = await client.get( + f"{url.path}?{SIGN_QUERY_PARAM}={url.query.get(SIGN_QUERY_PARAM)}&test=test" + ) + assert req.status == HTTPStatus.UNAUTHORIZED async def test_auth_access_signed_path_with_query_param_safe_param( From 117113cdfc4c81f6df6a1ef71d53ac3e58ade025 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Wed, 22 Mar 2023 22:59:47 -0400 Subject: [PATCH 15/15] Bumped version to 2023.3.6 --- homeassistant/const.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index f8e7859bf40..ed959488ddb 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -8,7 +8,7 @@ from .backports.enum import StrEnum APPLICATION_NAME: Final = "HomeAssistant" MAJOR_VERSION: Final = 2023 MINOR_VERSION: Final = 3 -PATCH_VERSION: Final = "5" +PATCH_VERSION: Final = "6" __short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__: Final = f"{__short_version__}.{PATCH_VERSION}" REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 10, 0) diff --git a/pyproject.toml b/pyproject.toml index a9c70089c7d..6702915a85b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "homeassistant" -version = "2023.3.5" +version = "2023.3.6" license = {text = "Apache-2.0"} description = "Open-source home automation platform running on Python 3." readme = "README.rst"