diff --git a/homeassistant/auth/mfa_modules/notify.py b/homeassistant/auth/mfa_modules/notify.py index 978758bebb1c3e..fffee79da66fa8 100644 --- a/homeassistant/auth/mfa_modules/notify.py +++ b/homeassistant/auth/mfa_modules/notify.py @@ -27,7 +27,7 @@ SetupFlow, ) -REQUIREMENTS = ["pyotp==2.8.0"] +REQUIREMENTS = ["pyotp==2.9.0"] CONF_MESSAGE = "message" diff --git a/homeassistant/auth/mfa_modules/totp.py b/homeassistant/auth/mfa_modules/totp.py index b344043b832028..2128d874390f83 100644 --- a/homeassistant/auth/mfa_modules/totp.py +++ b/homeassistant/auth/mfa_modules/totp.py @@ -20,7 +20,7 @@ SetupFlow, ) -REQUIREMENTS = ["pyotp==2.8.0", "PyQRCode==1.2.1"] +REQUIREMENTS = ["pyotp==2.9.0", "PyQRCode==1.2.1"] CONFIG_SCHEMA = MULTI_FACTOR_AUTH_MODULE_SCHEMA.extend({}, extra=vol.PREVENT_EXTRA) diff --git a/homeassistant/components/bluesound/manifest.json b/homeassistant/components/bluesound/manifest.json index 54fb061676d610..f4e49e00175feb 100644 --- a/homeassistant/components/bluesound/manifest.json +++ b/homeassistant/components/bluesound/manifest.json @@ -6,7 +6,7 @@ "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/bluesound", "iot_class": "local_polling", - "requirements": ["pyblu==2.0.4"], + "requirements": ["pyblu==2.0.5"], "zeroconf": [ { "type": "_musc._tcp.local." diff --git a/homeassistant/components/bluesound/media_player.py b/homeassistant/components/bluesound/media_player.py index 2662562f575eef..115c6d054af211 100644 --- a/homeassistant/components/bluesound/media_player.py +++ b/homeassistant/components/bluesound/media_player.py @@ -321,8 +321,14 @@ def source_list(self) -> list[str] | None: if self.available is False or (self.is_grouped and not self.is_leader): return None - sources = [x.text for x in self._inputs] - sources += [x.name for x in self._presets] + sources = [x.name for x in self._presets] + + # ignore if both id and text are None + for input_ in self._inputs: + if input_.text is not None: + sources.append(input_.text) + elif input_.id is not None: + sources.append(input_.id) return sources @@ -340,7 +346,7 @@ def source(self) -> str | None: input_.id == self._status.input_id or input_.url == self._status.stream_url ): - return input_.text + return input_.text if input_.text is not None else input_.id for preset in self._presets: if preset.url == self._status.stream_url: @@ -537,7 +543,7 @@ async def async_select_source(self, source: str) -> None: # presets and inputs might have the same name; presets have priority for input_ in self._inputs: - if input_.text == source: + if source in (input_.text, input_.id): await self._player.play_url(input_.url) return for preset in self._presets: diff --git a/homeassistant/components/habitica/manifest.json b/homeassistant/components/habitica/manifest.json index 86002107a68734..30443f1d1da821 100644 --- a/homeassistant/components/habitica/manifest.json +++ b/homeassistant/components/habitica/manifest.json @@ -7,5 +7,5 @@ "iot_class": "cloud_polling", "loggers": ["habiticalib"], "quality_scale": "platinum", - "requirements": ["habiticalib==0.4.4"] + "requirements": ["habiticalib==0.4.5"] } diff --git a/homeassistant/components/mill/manifest.json b/homeassistant/components/mill/manifest.json index c5cc94ead3055a..4ae2ac8bbbfb62 100644 --- a/homeassistant/components/mill/manifest.json +++ b/homeassistant/components/mill/manifest.json @@ -7,5 +7,5 @@ "documentation": "https://www.home-assistant.io/integrations/mill", "iot_class": "local_polling", "loggers": ["mill", "mill_local"], - "requirements": ["millheater==0.12.5", "mill-local==0.3.0"] + "requirements": ["millheater==0.13.1", "mill-local==0.3.0"] } diff --git a/homeassistant/components/ohme/manifest.json b/homeassistant/components/ohme/manifest.json index 786c615d68a3cc..14612fff6eb899 100644 --- a/homeassistant/components/ohme/manifest.json +++ b/homeassistant/components/ohme/manifest.json @@ -7,5 +7,5 @@ "integration_type": "device", "iot_class": "cloud_polling", "quality_scale": "platinum", - "requirements": ["ohme==1.5.1"] + "requirements": ["ohme==1.5.2"] } diff --git a/homeassistant/components/otp/manifest.json b/homeassistant/components/otp/manifest.json index f62f89cff405e5..f6adbb20427efa 100644 --- a/homeassistant/components/otp/manifest.json +++ b/homeassistant/components/otp/manifest.json @@ -7,5 +7,5 @@ "iot_class": "local_polling", "loggers": ["pyotp"], "quality_scale": "internal", - "requirements": ["pyotp==2.8.0"] + "requirements": ["pyotp==2.9.0"] } diff --git a/homeassistant/components/schlage/manifest.json b/homeassistant/components/schlage/manifest.json index b71afe01e5609a..eadf5585f3074a 100644 --- a/homeassistant/components/schlage/manifest.json +++ b/homeassistant/components/schlage/manifest.json @@ -5,5 +5,5 @@ "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/schlage", "iot_class": "cloud_polling", - "requirements": ["pyschlage==2025.7.3"] + "requirements": ["pyschlage==2025.9.0"] } diff --git a/requirements_all.txt b/requirements_all.txt index c0d8e4770d4b38..fcce1a87dbf909 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1131,7 +1131,7 @@ ha-philipsjs==3.2.2 ha-silabs-firmware-client==0.2.0 # homeassistant.components.habitica -habiticalib==0.4.4 +habiticalib==0.4.5 # homeassistant.components.bluetooth habluetooth==5.3.0 @@ -1444,7 +1444,7 @@ microBeesPy==0.3.5 mill-local==0.3.0 # homeassistant.components.mill -millheater==0.12.5 +millheater==0.13.1 # homeassistant.components.minio minio==7.1.12 @@ -1583,7 +1583,7 @@ odp-amsterdam==6.1.2 oemthermostat==1.1.1 # homeassistant.components.ohme -ohme==1.5.1 +ohme==1.5.2 # homeassistant.components.ollama ollama==0.5.1 @@ -1871,7 +1871,7 @@ pybbox==0.0.5-alpha pyblackbird==0.6 # homeassistant.components.bluesound -pyblu==2.0.4 +pyblu==2.0.5 # homeassistant.components.neato pybotvac==0.0.28 @@ -2228,7 +2228,7 @@ pyotgw==2.2.2 # homeassistant.auth.mfa_modules.notify # homeassistant.auth.mfa_modules.totp # homeassistant.components.otp -pyotp==2.8.0 +pyotp==2.9.0 # homeassistant.components.overkiz pyoverkiz==1.17.2 @@ -2315,7 +2315,7 @@ pysabnzbd==1.1.1 pysaj==0.0.16 # homeassistant.components.schlage -pyschlage==2025.7.3 +pyschlage==2025.9.0 # homeassistant.components.sensibo pysensibo==1.2.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 600e7c79ffd2ce..d9adddc1969438 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -992,7 +992,7 @@ ha-philipsjs==3.2.2 ha-silabs-firmware-client==0.2.0 # homeassistant.components.habitica -habiticalib==0.4.4 +habiticalib==0.4.5 # homeassistant.components.bluetooth habluetooth==5.3.0 @@ -1236,7 +1236,7 @@ microBeesPy==0.3.5 mill-local==0.3.0 # homeassistant.components.mill -millheater==0.12.5 +millheater==0.13.1 # homeassistant.components.minio minio==7.1.12 @@ -1351,7 +1351,7 @@ objgraph==3.5.0 odp-amsterdam==6.1.2 # homeassistant.components.ohme -ohme==1.5.1 +ohme==1.5.2 # homeassistant.components.ollama ollama==0.5.1 @@ -1573,7 +1573,7 @@ pybalboa==1.1.3 pyblackbird==0.6 # homeassistant.components.bluesound -pyblu==2.0.4 +pyblu==2.0.5 # homeassistant.components.neato pybotvac==0.0.28 @@ -1855,7 +1855,7 @@ pyotgw==2.2.2 # homeassistant.auth.mfa_modules.notify # homeassistant.auth.mfa_modules.totp # homeassistant.components.otp -pyotp==2.8.0 +pyotp==2.9.0 # homeassistant.components.overkiz pyoverkiz==1.17.2 @@ -1927,7 +1927,7 @@ pyrympro==0.0.9 pysabnzbd==1.1.1 # homeassistant.components.schlage -pyschlage==2025.7.3 +pyschlage==2025.9.0 # homeassistant.components.sensibo pysensibo==1.2.1 diff --git a/tests/components/bluesound/conftest.py b/tests/components/bluesound/conftest.py index 63597ed05321d6..4a793967645398 100644 --- a/tests/components/bluesound/conftest.py +++ b/tests/components/bluesound/conftest.py @@ -98,6 +98,9 @@ async def generate(host: str) -> "PlayerMockData": return_value=[ Input("1", "input1", "image1", "url1"), Input("2", "input2", "image2", "url2"), + Input(None, "input3", "image3", "url3"), + Input("4", None, "image4", "url4"), + Input(None, None, "image5", "url5"), ] ) player.presets = AsyncMock( diff --git a/tests/components/bluesound/snapshots/test_media_player.ambr b/tests/components/bluesound/snapshots/test_media_player.ambr index f71302f286d43c..24e04160e90c9e 100644 --- a/tests/components/bluesound/snapshots/test_media_player.ambr +++ b/tests/components/bluesound/snapshots/test_media_player.ambr @@ -12,10 +12,12 @@ 'media_title': 'song', 'shuffle': False, 'source_list': list([ - 'input1', - 'input2', 'preset1', 'preset2', + 'input1', + 'input2', + 'input3', + '4', ]), 'supported_features': , 'volume_level': 0.1, diff --git a/tests/components/bluesound/test_media_player.py b/tests/components/bluesound/test_media_player.py index d2a72200423a38..b534c7aafb0834 100644 --- a/tests/components/bluesound/test_media_player.py +++ b/tests/components/bluesound/test_media_player.py @@ -121,17 +121,30 @@ async def test_volume_down( player_mocks.player_data.player.volume.assert_called_once_with(level=9) +@pytest.mark.parametrize( + ("input", "url"), + [ + ("input1", "url1"), + ("input2", "url2"), + ("input3", "url3"), + ("4", "url4"), + ], +) async def test_select_input_source( - hass: HomeAssistant, setup_config_entry: None, player_mocks: PlayerMocks + hass: HomeAssistant, + setup_config_entry: None, + player_mocks: PlayerMocks, + input: str, + url: str, ) -> None: """Test the media player select input source.""" await hass.services.async_call( MEDIA_PLAYER_DOMAIN, SERVICE_SELECT_SOURCE, - {ATTR_ENTITY_ID: "media_player.player_name1111", ATTR_INPUT_SOURCE: "input1"}, + {ATTR_ENTITY_ID: "media_player.player_name1111", ATTR_INPUT_SOURCE: input}, ) - player_mocks.player_data.player.play_url.assert_called_once_with("url1") + player_mocks.player_data.player.play_url.assert_called_once_with(url) async def test_select_preset_source(