diff --git a/homeassistant/components/frontend/manifest.json b/homeassistant/components/frontend/manifest.json index 09461a3543a0d..706940f5da7a2 100644 --- a/homeassistant/components/frontend/manifest.json +++ b/homeassistant/components/frontend/manifest.json @@ -20,5 +20,5 @@ "documentation": "https://www.home-assistant.io/integrations/frontend", "integration_type": "system", "quality_scale": "internal", - "requirements": ["home-assistant-frontend==20250730.0"] + "requirements": ["home-assistant-frontend==20250731.0"] } diff --git a/homeassistant/components/kitchen_sink/config_flow.py b/homeassistant/components/kitchen_sink/config_flow.py index 059fd11999f8c..056ace7011cf1 100644 --- a/homeassistant/components/kitchen_sink/config_flow.py +++ b/homeassistant/components/kitchen_sink/config_flow.py @@ -99,7 +99,7 @@ async def async_step_options_1( ), } ) - self.add_suggested_values_to_schema( + data_schema = self.add_suggested_values_to_schema( data_schema, {"section_1": {"int": self.config_entry.options.get(CONF_INT, 10)}}, ) diff --git a/homeassistant/components/litterrobot/manifest.json b/homeassistant/components/litterrobot/manifest.json index 33addd85ba2ec..e67c681ac5360 100644 --- a/homeassistant/components/litterrobot/manifest.json +++ b/homeassistant/components/litterrobot/manifest.json @@ -13,5 +13,5 @@ "iot_class": "cloud_push", "loggers": ["pylitterbot"], "quality_scale": "bronze", - "requirements": ["pylitterbot==2024.2.2"] + "requirements": ["pylitterbot==2024.2.3"] } diff --git a/homeassistant/components/zha/update.py b/homeassistant/components/zha/update.py index 062581fd25992..867e4ff2dd36c 100644 --- a/homeassistant/components/zha/update.py +++ b/homeassistant/components/zha/update.py @@ -58,7 +58,7 @@ async def async_setup_entry( zha_data = get_zha_data(hass) if zha_data.update_coordinator is None: zha_data.update_coordinator = ZHAFirmwareUpdateCoordinator( - hass, get_zha_gateway(hass).application_controller + hass, config_entry, get_zha_gateway(hass).application_controller ) entities_to_create = zha_data.platforms[Platform.UPDATE] @@ -79,12 +79,16 @@ class ZHAFirmwareUpdateCoordinator(DataUpdateCoordinator[None]): # pylint: disa """Firmware update coordinator that broadcasts updates network-wide.""" def __init__( - self, hass: HomeAssistant, controller_application: ControllerApplication + self, + hass: HomeAssistant, + config_entry: ConfigEntry, + controller_application: ControllerApplication, ) -> None: """Initialize the coordinator.""" super().__init__( hass, _LOGGER, + config_entry=config_entry, name="ZHA firmware update coordinator", update_method=self.async_update_data, ) diff --git a/homeassistant/data_entry_flow.py b/homeassistant/data_entry_flow.py index 7408993cc47eb..5023d291ad520 100644 --- a/homeassistant/data_entry_flow.py +++ b/homeassistant/data_entry_flow.py @@ -676,9 +676,10 @@ def add_suggested_values_to_schema( and key in suggested_values ): new_section_key = copy.copy(key) - schema[new_section_key] = val - val.schema = self.add_suggested_values_to_schema( - val.schema, suggested_values[key] + new_val = copy.copy(val) + schema[new_section_key] = new_val + new_val.schema = self.add_suggested_values_to_schema( + new_val.schema, suggested_values[key] ) continue diff --git a/homeassistant/package_constraints.txt b/homeassistant/package_constraints.txt index 704fb282784e6..ac91084c4f14f 100644 --- a/homeassistant/package_constraints.txt +++ b/homeassistant/package_constraints.txt @@ -38,7 +38,7 @@ habluetooth==4.0.1 hass-nabucasa==0.110.0 hassil==2.2.3 home-assistant-bluetooth==1.13.1 -home-assistant-frontend==20250730.0 +home-assistant-frontend==20250731.0 home-assistant-intents==2025.7.30 httpx==0.28.1 ifaddr==0.2.0 @@ -209,7 +209,6 @@ aiofiles>=24.1.0 # https://github.com/aio-libs/multidict/issues/1131 multidict>=6.4.2 -# rpds-py > 0.25.0 requires cargo 1.84.0 -# Stable Alpine current only ships cargo 1.83.0 +# rpds-py frequently updates cargo causing build failures # No wheels upstream available for armhf & armv7 -rpds-py==0.24.0 +rpds-py==0.26.0 diff --git a/requirements_all.txt b/requirements_all.txt index 49a50982f3200..446d7117588c0 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1174,7 +1174,7 @@ hole==0.9.0 holidays==0.77 # homeassistant.components.frontend -home-assistant-frontend==20250730.0 +home-assistant-frontend==20250731.0 # homeassistant.components.conversation home-assistant-intents==2025.7.30 @@ -2122,7 +2122,7 @@ pylibrespot-java==0.1.1 pylitejet==0.6.3 # homeassistant.components.litterrobot -pylitterbot==2024.2.2 +pylitterbot==2024.2.3 # homeassistant.components.lutron_caseta pylutron-caseta==0.24.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 8b992f2630cff..a4bf8743a524c 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1023,7 +1023,7 @@ hole==0.9.0 holidays==0.77 # homeassistant.components.frontend -home-assistant-frontend==20250730.0 +home-assistant-frontend==20250731.0 # homeassistant.components.conversation home-assistant-intents==2025.7.30 @@ -1767,7 +1767,7 @@ pylibrespot-java==0.1.1 pylitejet==0.6.3 # homeassistant.components.litterrobot -pylitterbot==2024.2.2 +pylitterbot==2024.2.3 # homeassistant.components.lutron_caseta pylutron-caseta==0.24.0 diff --git a/script/gen_requirements_all.py b/script/gen_requirements_all.py index 13bb33842588a..b13f586439d4d 100755 --- a/script/gen_requirements_all.py +++ b/script/gen_requirements_all.py @@ -235,10 +235,9 @@ # https://github.com/aio-libs/multidict/issues/1131 multidict>=6.4.2 -# rpds-py > 0.25.0 requires cargo 1.84.0 -# Stable Alpine current only ships cargo 1.83.0 +# rpds-py frequently updates cargo causing build failures # No wheels upstream available for armhf & armv7 -rpds-py==0.24.0 +rpds-py==0.26.0 """ GENERATED_MESSAGE = ( diff --git a/tests/test_data_entry_flow.py b/tests/test_data_entry_flow.py index a5908f0feabf6..0faa4dd1a80aa 100644 --- a/tests/test_data_entry_flow.py +++ b/tests/test_data_entry_flow.py @@ -135,6 +135,19 @@ async def async_step_init(self, user_input=None): async def test_form_shows_with_added_suggested_values(manager: MockFlowManager) -> None: """Test that we can show a form with suggested values.""" + + def compare_schemas(schema: vol.Schema, expected_schema: vol.Schema) -> None: + """Compare two schemas.""" + assert schema.schema is not expected_schema.schema + + assert list(schema.schema) == list(expected_schema.schema) + + for key, validator in schema.schema.items(): + if isinstance(validator, data_entry_flow.section): + assert validator.schema == expected_schema.schema[key].schema + continue + assert validator == expected_schema.schema[key] + schema = vol.Schema( { vol.Required("username"): str, @@ -155,20 +168,25 @@ class TestFlow(data_entry_flow.FlowHandler): async def async_step_init(self, user_input=None): data_schema = self.add_suggested_values_to_schema( schema, - { - "username": "doej", - "password": "verySecret1", - "section_1": {"full_name": "John Doe"}, - }, + user_input, ) return self.async_show_form( step_id="init", data_schema=data_schema, ) - form = await manager.async_init("test") + form = await manager.async_init( + "test", + data={ + "username": "doej", + "password": "verySecret1", + "section_1": {"full_name": "John Doe"}, + }, + ) assert form["type"] == data_entry_flow.FlowResultType.FORM - assert form["data_schema"].schema == schema.schema + assert form["data_schema"].schema is not schema.schema + assert form["data_schema"].schema != schema.schema + compare_schemas(form["data_schema"], schema) markers = list(form["data_schema"].schema) assert len(markers) == 3 assert markers[0] == "username" @@ -178,14 +196,40 @@ async def async_step_init(self, user_input=None): assert markers[2] == "section_1" section_validator = form["data_schema"].schema["section_1"] assert isinstance(section_validator, data_entry_flow.section) - # The section class was not replaced + # The section instance was copied + assert section_validator is not schema.schema["section_1"] + # The section schema instance was copied + assert section_validator.schema is not schema.schema["section_1"].schema + assert section_validator.schema == schema.schema["section_1"].schema + section_markers = list(section_validator.schema.schema) + assert len(section_markers) == 1 + assert section_markers[0] == "full_name" + assert section_markers[0].description == {"suggested_value": "John Doe"} + + # Test again without suggested values to make sure we're not mutating the schema + form = await manager.async_init( + "test", + ) + assert form["type"] == data_entry_flow.FlowResultType.FORM + assert form["data_schema"].schema is not schema.schema + assert form["data_schema"].schema == schema.schema + markers = list(form["data_schema"].schema) + assert len(markers) == 3 + assert markers[0] == "username" + assert markers[0].description is None + assert markers[1] == "password" + assert markers[1].description is None + assert markers[2] == "section_1" + section_validator = form["data_schema"].schema["section_1"] + assert isinstance(section_validator, data_entry_flow.section) + # The section class is not replaced if there is no suggested value for the section assert section_validator is schema.schema["section_1"] - # The section schema was not replaced + # The section schema is not replaced if there is no suggested value for the section assert section_validator.schema is schema.schema["section_1"].schema section_markers = list(section_validator.schema.schema) assert len(section_markers) == 1 assert section_markers[0] == "full_name" - assert section_markers[0].description == {"suggested_value": "John Doe"} + assert section_markers[0].description is None async def test_abort_removes_instance(manager: MockFlowManager) -> None: