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 b14de63268..53cb921860 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 afa6116ff4..ba2b362af7 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 2603ee613a..c6a6327046 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 cdffe860f7..3fcf96ccb5 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 c8f2b57a76..7061c3bf62 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 fd77b5e234..89aac6bed6 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 a1b194284c..ff126a2260 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 fd9252aaa1..dbee01c4e7 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 9a19f61eb4..48b8de2060 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 3fcf96ccb5..27eb15772e 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 7061c3bf62..2168b2b42f 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 0aed6ce43a..a389d74643 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 dedfc9127a..eba6e2c1b3 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 e34ace05e1..e793fe2728 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 27eb15772e..debc7d480c 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 2168b2b42f..09afa5970b 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 eba6e2c1b3..213f0237e1 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 e793fe2728..6bb58752a0 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 debc7d480c..e763e3037a 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 09afa5970b..73feda7628 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 6b88dd84c8..fc0a4fd773 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 e763e3037a..ba96fabc1a 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 73feda7628..0331bdf76e 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 fc0a4fd773..0954269628 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 ba96fabc1a..f282e59eeb 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 0331bdf76e..6200c913d3 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 37b043e543..a1071cc0a1 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 f282e59eeb..fe86666d9c 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 6200c913d3..87663416f0 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 2637f578b8..ada24bcee5 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 fe86666d9c..9b63f54a60 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 87663416f0..e71f661b4e 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 5213cd1b07..d10bd677e4 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 fb00640cdc..246572e64f 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 f8e7859bf4..ed959488dd 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 a9c70089c7..6702915a85 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"