Add IntelliDwell Sprinkler Controller core integration and tests - #177408
Add IntelliDwell Sprinkler Controller core integration and tests#177408TannerNelson16 wants to merge 4 commits into
Conversation
There was a problem hiding this comment.
It seems you haven't yet signed a CLA. Please do so here.
Once you do that we will be able to review and accept this pull request.
Thanks!
|
Please take a look at the requested changes, and use the Ready for review button when you are done, thanks 👍 |
There was a problem hiding this comment.
Pull request overview
Adds a core integration for locally polling and controlling IntelliDwell sprinkler controllers.
Changes:
- Adds config-entry setup, polling coordinator, and config flow.
- Exposes ten sprinkler zones as switches.
- Adds config-flow and switch tests.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 15 comments.
Show a summary per file
| File | Description |
|---|---|
homeassistant/components/intellidwell/__init__.py |
Adds client and coordinator lifecycle. |
homeassistant/components/intellidwell/config_flow.py |
Adds host-based configuration. |
homeassistant/components/intellidwell/const.py |
Defines integration constants. |
homeassistant/components/intellidwell/manifest.json |
Declares integration metadata. |
homeassistant/components/intellidwell/switch.py |
Implements zone switches. |
tests/components/intellidwell/__init__.py |
Initializes the test package. |
tests/components/intellidwell/conftest.py |
Enables custom integrations during tests. |
tests/components/intellidwell/test_config_flow.py |
Tests configuration flows. |
tests/components/intellidwell/test_switch.py |
Tests switch setup and commands. |
Comments suppressed due to low confidence (4)
homeassistant/components/intellidwell/switch.py:80
- Propagate a Home Assistant service error when turning a zone off fails. Logging and swallowing every exception makes the service call report success even though the controller rejected or never received the command.
try:
await self.coordinator.client.set_relay(self.zone_index, "off")
except Exception as err:
_LOGGER.error("Error turning off zone %s: %s", self.zone_index + 1, err)
tests/components/intellidwell/test_config_flow.py:29
- Patch setup through the core integration package. The current nonexistent target prevents the successful config-flow test from running.
"homeassistant_integration.intellidwell.async_setup_entry",
tests/components/intellidwell/test_switch.py:48
- Patch
set_relaythrough the core integration module. The current target does not exist, so this turn-on test errors before calling the service.
"homeassistant_integration.intellidwell.IntelliDwellClient.set_relay"
tests/components/intellidwell/test_switch.py:62
- Keep
get_statusmocked while invoking the turn-off service. The coordinator refresh afterset_relayotherwise performs another real request to1.1.1.1.
await hass.services.async_call(
| "name": "IntelliDwell Sprinkler Controller", | ||
| "codeowners": ["@TannerNelson16"], | ||
| "config_flow": true, | ||
| "documentation": "https://docs.intellidwell.net/sprinkler/", |
| "domain": "intellidwell", | ||
| "name": "IntelliDwell Sprinkler Controller", | ||
| "codeowners": ["@TannerNelson16"], | ||
| "config_flow": true, |
| "config_flow": true, | ||
| "documentation": "https://docs.intellidwell.net/sprinkler/", | ||
| "iot_class": "local_polling", | ||
| "requirements": ["aiohttp>=3.9.0"], |
| "documentation": "https://docs.intellidwell.net/sprinkler/", | ||
| "iot_class": "local_polling", | ||
| "requirements": ["aiohttp>=3.9.0"], | ||
| "version": "2.1.0" |
| @@ -0,0 +1,10 @@ | |||
| { | |||
| "domain": "intellidwell", | |||
| "name": "IntelliDwell Sprinkler Controller", | |||
| ) | ||
|
|
||
| with patch( | ||
| "homeassistant_integration.intellidwell.config_flow.IntelliDwellClient.get_status", |
| from homeassistant.core import HomeAssistant | ||
| from homeassistant.helpers import entity_registry as er | ||
|
|
||
| from homeassistant_integration.intellidwell.const import DOMAIN |
| } | ||
|
|
||
| with patch( | ||
| "homeassistant_integration.intellidwell.IntelliDwellClient.get_status", |
|
|
||
| # Test turn off switch 2 | ||
| with patch( | ||
| "homeassistant_integration.intellidwell.IntelliDwellClient.set_relay" |
| with patch( | ||
| "homeassistant_integration.intellidwell.IntelliDwellClient.set_relay" | ||
| ) as mock_set_relay: | ||
| await hass.services.async_call( |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (16)
homeassistant/components/intellidwell/init.py:60
- Handle invalid responses as update failures too.
validate_inputestablishes thatget_status()can raiseIntelliDwellInvalidResponseError; allowing it to escape here bypasses coordinator retry/unavailable handling during later polls and initial setup.
except IntelliDwellConnectionError as err:
raise UpdateFailed(f"Error communicating with API: {err}") from err
homeassistant/components/intellidwell/switch.py:72
- Let command failures propagate to the service caller. Catching every exception and only logging it reports a successful turn-on even though the controller rejected or never received the command.
try:
await self.coordinator.client.set_relay(self.zone_index, "on")
except Exception as err:
_LOGGER.error("Error turning on zone %s: %s", self.zone_index + 1, err)
homeassistant/components/intellidwell/switch.py:80
- Let command failures propagate to the service caller. Catching every exception and only logging it reports a successful turn-off even though the controller rejected or never received the command.
try:
await self.coordinator.client.set_relay(self.zone_index, "off")
except Exception as err:
_LOGGER.error("Error turning off zone %s: %s", self.zone_index + 1, err)
homeassistant/components/intellidwell/manifest.json:6
- Use the Home Assistant integration documentation URL. Core manifest validation requires documentation links to begin with
https://www.home-assistant.io/integrations/, so hassfest rejects this external vendor URL.
"documentation": "https://docs.intellidwell.net/sprinkler/",
homeassistant/components/intellidwell/manifest.json:8
- Declare and exactly pin the package that provides
pyintellidwell. The integration imports that package but it is absent from the manifest andrequirements_all.txt, while this looseaiohttppin is rejected for core requirements; the integration therefore cannot import in a clean installation.
"requirements": ["aiohttp>=3.9.0"],
homeassistant/components/intellidwell/manifest.json:3
- Complete the PR template before review. The proposed-change section is blank, no change type is selected, and all applicable checklist items remain unchecked, so the description does not document or attest to this new integration.
"name": "IntelliDwell Sprinkler Controller",
tests/components/intellidwell/test_config_flow.py:9
- Import the core integration namespace so this test can be collected.
homeassistant_integrationdoes not exist in this repository and would test an external/custom package rather than the code in this PR.
from homeassistant_integration.intellidwell.const import DOMAIN
tests/components/intellidwell/test_config_flow.py:26
- Patch the core integration module. This target points at the nonexistent
homeassistant_integrationnamespace, sopatch()fails before the flow is exercised.
"homeassistant_integration.intellidwell.config_flow.IntelliDwellClient.get_status",
tests/components/intellidwell/test_config_flow.py:29
- Patch the core integration setup function. This nonexistent namespace causes the success-flow test to fail before configuration completes.
"homeassistant_integration.intellidwell.async_setup_entry",
tests/components/intellidwell/test_config_flow.py:50
- Patch the core integration module. This target points at the nonexistent
homeassistant_integrationnamespace, so the connection-error test never reaches validation.
"homeassistant_integration.intellidwell.config_flow.IntelliDwellClient.get_status",
tests/components/intellidwell/test_switch.py:9
- Import the core integration namespace so this test can be collected.
homeassistant_integrationdoes not exist in this repository and would test an external/custom package rather than the code in this PR.
from homeassistant_integration.intellidwell.const import DOMAIN
tests/components/intellidwell/test_switch.py:28
- Patch the core integration module. This target points at the nonexistent
homeassistant_integrationnamespace, so setup is not isolated from the real client.
"homeassistant_integration.intellidwell.IntelliDwellClient.get_status",
tests/components/intellidwell/test_switch.py:48
- Patch the core integration module. This nonexistent target prevents the turn-on assertion from running.
"homeassistant_integration.intellidwell.IntelliDwellClient.set_relay"
tests/components/intellidwell/test_switch.py:60
- Patch the core integration module. This nonexistent target prevents the turn-off assertion from running.
"homeassistant_integration.intellidwell.IntelliDwellClient.set_relay"
tests/components/intellidwell/test_switch.py:30
- Keep
get_statusmocked through the service calls. This context ends immediately after setup, but both switch methods request a coordinator refresh, causing the test to make real network requests to1.1.1.1.
with patch(
"homeassistant_integration.intellidwell.IntelliDwellClient.get_status",
return_value=status_data,
):
homeassistant/components/intellidwell/manifest.json:9
- Remove the custom-integration version field.
versionis only accepted byCUSTOM_INTEGRATION_MANIFEST_SCHEMA; the core manifest schema rejects it as an extra key.
"version": "2.1.0"
| super().__init__( | ||
| hass, | ||
| _LOGGER, | ||
| name=f"IntelliDwell Sprinkler Coordinator ({client.host})", | ||
| update_interval=timedelta(seconds=5), |
| self._attr_device_info = DeviceInfo( | ||
| identifiers={(DOMAIN, config_entry.entry_id)}, | ||
| name="IntelliDwell Sprinkler Controller", | ||
| manufacturer="Intellidwell", |
| }, | ||
| "error": { | ||
| "cannot_connect": "Failed to connect, please check your network connection and try again.", | ||
| "unknown": "Unexpected error occurred." |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (17)
homeassistant/components/intellidwell/manifest.json:3
- Complete the PR description before requesting review. The Proposed change is empty, no Type of change is selected, and every checklist item remains unchecked, so the description does not identify or attest to this new integration.
"name": "IntelliDwell Sprinkler Controller",
homeassistant/components/intellidwell/manifest.json:6
- Point this core manifest at its Home Assistant integration documentation. Core manifests are rejected unless the URL begins with
https://www.home-assistant.io/integrations/(script/hassfest/manifest.py:138-145), so the current vendor URL fails hassfest.
"documentation": "https://docs.intellidwell.net/sprinkler/",
homeassistant/components/intellidwell/manifest.json:7
- Declare this config-flow integration as a hub. New core config-flow integrations not in the legacy allowlist must include
integration_type, otherwise hassfest reports an error (script/hassfest/integration_type.py:74-97).
"iot_class": "local_polling",
homeassistant/components/intellidwell/manifest.json:8
- Declare the imported
pyintellidwelldistribution with an exact version pin and regenerate the requirement files.aiohttp>=3.9.0neither installs the module imported by this integration nor satisfies the core==pin requirement (script/hassfest/requirements.py:407-411), so imports and hassfest will fail.
"requirements": ["aiohttp>=3.9.0"],
homeassistant/components/intellidwell/manifest.json:9
- Remove the
versionkey from this core manifest.versionis accepted only by the custom-integration schema (script/hassfest/manifest.py:322-328), so this extra key makes the core manifest invalid.
"version": "2.1.0"
homeassistant/components/intellidwell/switch.py:71
- Propagate a failed turn-on operation to the service caller. This catch currently logs every client failure and then returns successfully, falsely reporting that the zone was turned on; re-raise the error (ideally as a translated HomeAssistantError) instead.
try:
await self.coordinator.client.set_relay(self.zone_index, "on")
except Exception as err:
_LOGGER.error("Error turning on zone %s: %s", self.zone_index + 1, err)
homeassistant/components/intellidwell/switch.py:80
- Propagate a failed turn-off operation to the service caller. Swallowing the exception makes the service call succeed even though the controller rejected or never received the command.
try:
await self.coordinator.client.set_relay(self.zone_index, "off")
except Exception as err:
_LOGGER.error("Error turning off zone %s: %s", self.zone_index + 1, err)
tests/components/intellidwell/test_config_flow.py:9
- Import the integration from its actual core package.
homeassistant_integrationdoes not exist in this repository, so test collection fails before any config-flow test runs.
from homeassistant_integration.intellidwell.const import DOMAIN
tests/components/intellidwell/test_config_flow.py:29
- Patch the actual core integration modules. Both
homeassistant_integration...targets are nonexistent, so entering this context raisesModuleNotFoundErrorinstead of exercising successful configuration.
"homeassistant_integration.intellidwell.config_flow.IntelliDwellClient.get_status",
return_value={"relay_states": [0] * 10},
), patch(
"homeassistant_integration.intellidwell.async_setup_entry",
tests/components/intellidwell/test_config_flow.py:50
- Patch the connection method under the core integration namespace. The current nonexistent target prevents the cannot-connect test from reaching the flow.
"homeassistant_integration.intellidwell.config_flow.IntelliDwellClient.get_status",
tests/components/intellidwell/test_switch.py:9
- Import the integration from its actual core package. The nonexistent
homeassistant_integrationnamespace makes this test module fail during collection.
from homeassistant_integration.intellidwell.const import DOMAIN
tests/components/intellidwell/test_switch.py:28
- Patch
get_statusunder the core integration namespace. This target cannot be resolved, so switch setup is never tested.
"homeassistant_integration.intellidwell.IntelliDwellClient.get_status",
tests/components/intellidwell/test_switch.py:30
- Keep the status mock active while exercising the switch services. Each service method awaits
async_request_refresh(), but this mock ends after setup, causing the test to call the real1.1.1.1controller during turn-on and turn-off.
with patch(
"homeassistant_integration.intellidwell.IntelliDwellClient.get_status",
return_value=status_data,
):
tests/components/intellidwell/test_switch.py:48
- Patch
set_relayunder the core integration namespace. The current target does not exist and prevents the turn-on assertion from running.
"homeassistant_integration.intellidwell.IntelliDwellClient.set_relay"
tests/components/intellidwell/test_switch.py:60
- Patch
set_relayunder the core integration namespace. The current target does not exist and prevents the turn-off assertion from running.
"homeassistant_integration.intellidwell.IntelliDwellClient.set_relay"
homeassistant/components/intellidwell/init.py:60
- Treat invalid controller responses as an expected coordinator update failure. The config flow explicitly recognizes
IntelliDwellInvalidResponseError, but polling does not, so the same device response is logged as an unexpected traceback instead of a normalUpdateFailed.
except IntelliDwellConnectionError as err:
raise UpdateFailed(f"Error communicating with API: {err}") from err
homeassistant/components/intellidwell/switch.py:53
- Use the product's established
IntelliDwellcapitalization in device metadata.
manufacturer="Intellidwell",
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated 7 comments.
Comments suppressed due to low confidence (17)
homeassistant/components/intellidwell/manifest.json:3
- Complete the pull request description before further review. The Proposed change is empty, no change type is selected, and all checklist items remain unchecked, so the required template has not been filled in for this new integration.
"name": "IntelliDwell Sprinkler Controller",
homeassistant/components/intellidwell/manifest.json:5
- Declare this as a device integration. Hassfest rejects new core config-flow integrations without an
integration_type(script/hassfest/integration_type.py:74-97).
"config_flow": true,
homeassistant/components/intellidwell/manifest.json:6
- Use the Home Assistant integration documentation URL. Core manifest validation requires URLs under
https://www.home-assistant.io/integrations/, so the vendor URL makes hassfest fail.
"documentation": "https://docs.intellidwell.net/sprinkler/",
homeassistant/components/intellidwell/manifest.json:8
- Declare the library that the integration imports. Installing this integration currently installs only aiohttp, so
from pyintellidwell import ...fails on a normal Home Assistant installation even though the generated requirements file lists pyintellidwell.
"requirements": ["aiohttp>=3.9.0"],
homeassistant/components/intellidwell/manifest.json:9
- Remove the custom-integration
versionfield. The core integration manifest schema does not allow this key, so hassfest rejects this manifest.
"version": "2.1.0"
tests/components/intellidwell/test_switch.py:9
- Import the core integration namespace.
homeassistant_integrationis not a package in this repository, so this import prevents the switch test module from being collected.
from homeassistant_integration.intellidwell.const import DOMAIN
tests/components/intellidwell/test_switch.py:28
- Patch the core integration namespace. The current target cannot be resolved because
homeassistant_integrationdoes not exist.
"homeassistant_integration.intellidwell.IntelliDwellClient.get_status",
tests/components/intellidwell/test_switch.py:49
- Patch both the core client command and the refresh request. After
set_relay, the entity requests a coordinator refresh, so correcting only the namespace would make this test perform a real request to1.1.1.1.
with patch(
"homeassistant_integration.intellidwell.IntelliDwellClient.set_relay"
) as mock_set_relay:
tests/components/intellidwell/test_switch.py:61
- Patch both the core client command and the refresh request. After
set_relay, the entity requests a coordinator refresh, so correcting only the namespace would make this test perform a real request to1.1.1.1.
with patch(
"homeassistant_integration.intellidwell.IntelliDwellClient.set_relay"
) as mock_set_relay:
tests/components/intellidwell/test_config_flow.py:9
- Import the core integration namespace.
homeassistant_integrationis not a package in this repository, so this import prevents the config-flow test module from being collected.
from homeassistant_integration.intellidwell.const import DOMAIN
tests/components/intellidwell/test_config_flow.py:29
- Patch the core integration modules in the success test. Both current targets use the nonexistent
homeassistant_integrationnamespace, so the context manager fails before the flow is configured.
"homeassistant_integration.intellidwell.config_flow.IntelliDwellClient.get_status",
return_value={"relay_states": [0] * 10},
), patch(
"homeassistant_integration.intellidwell.async_setup_entry",
tests/components/intellidwell/test_config_flow.py:50
- Patch the core config-flow module. The current target uses the nonexistent
homeassistant_integrationnamespace, so this error-path test cannot run.
"homeassistant_integration.intellidwell.config_flow.IntelliDwellClient.get_status",
homeassistant/components/intellidwell/switch.py:71
- Let turn-on failures propagate to the service caller. Catching every exception and only logging it reports a successful service call even when the sprinkler command failed; translate known client errors to
HomeAssistantErroror allow them to propagate.
try:
await self.coordinator.client.set_relay(self.zone_index, "on")
except Exception as err:
_LOGGER.error("Error turning on zone %s: %s", self.zone_index + 1, err)
homeassistant/components/intellidwell/switch.py:80
- Let turn-off failures propagate to the service caller. Catching every exception and only logging it reports a successful service call even when the sprinkler command failed; translate known client errors to
HomeAssistantErroror allow them to propagate.
try:
await self.coordinator.client.set_relay(self.zone_index, "off")
except Exception as err:
_LOGGER.error("Error turning off zone %s: %s", self.zone_index + 1, err)
tests/components/intellidwell/test_switch.py:39
- Remove this narration comment. The state lookups and assertions immediately below already make the intent clear.
# Verify states
tests/components/intellidwell/test_switch.py:46
- Remove this narration comment. The service name and entity ID immediately below already describe the turn-on case.
# Test turn on switch 1
tests/components/intellidwell/test_switch.py:58
- Remove this narration comment. The service name and entity ID immediately below already describe the turn-off case.
# Test turn off switch 2
| "codeowners": ["@TannerNelson16"], | ||
| "config_flow": true, | ||
| "documentation": "https://docs.intellidwell.net/sprinkler/", | ||
| "iot_class": "local_polling", |
| "domain": "intellidwell", | ||
| "name": "IntelliDwell Sprinkler Controller", | ||
| "codeowners": ["@TannerNelson16"], | ||
| "config_flow": true, |
| coordinator = IntelliDwellCoordinator(hass, client) | ||
| await coordinator.async_config_entry_first_refresh() | ||
|
|
||
| hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator |
| errors: dict[str, str] = {} | ||
| if user_input is not None: | ||
| host = user_input[CONF_HOST] | ||
| self._async_abort_entries_match({CONF_HOST: host}) |
| except Exception: # pylint: disable=broad-except | ||
| _LOGGER.exception("Unexpected exception") | ||
| errors["base"] = "unknown" |
| client = IntelliDwellClient(host, session=session) | ||
|
|
||
| coordinator = IntelliDwellCoordinator(hass, client) | ||
| await coordinator.async_config_entry_first_refresh() |
| assert await hass.config_entries.async_setup(entry.entry_id) | ||
| await hass.async_block_till_done() | ||
|
|
||
| # Verify switches were created |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (12)
homeassistant/components/intellidwell/manifest.json:6
- Point this core integration at its Home Assistant documentation URL; the core manifest validator rejects vendor documentation URLs (
script/hassfest/manifest.py:138-145).
"documentation": "https://docs.intellidwell.net/sprinkler/",
homeassistant/components/intellidwell/manifest.json:8
- Add a Bronze quality-scale declaration and
quality_scale.yaml; hassfest requires every new core integration to reach Bronze (script/hassfest/quality_scale.py:2120-2138).
"iot_class": "local_polling",
"requirements": ["pyintellidwell==1.0.0"],
homeassistant/components/intellidwell/manifest.json:9
- Remove the custom-integration version key; it is not accepted by the core manifest schema (
script/hassfest/manifest.py:204-299,342-348).
"version": "2.1.0"
homeassistant/components/intellidwell/manifest.json:5
- Regenerate and include the config-flow metadata files;
config_flow: truecurrently has no IntelliDwell entry inhomeassistant/generated/config_flows.pyorintegrations.json, which hassfest reports as stale (script/hassfest/config_flow.py:210-230).
"config_flow": true,
homeassistant/components/intellidwell/init.py:52
- Pass the config entry explicitly into the coordinator and then to
DataUpdateCoordinator; omitting it is reported as an error for core integrations (homeassistant/helpers/update_coordinator.py:95-108).
super().__init__(
hass,
_LOGGER,
name=f"IntelliDwell Sprinkler Coordinator ({client.host})",
update_interval=timedelta(seconds=5),
homeassistant/components/intellidwell/init.py:31
- Store the coordinator in a typed
entry.runtime_dataand read it from there in the platform; new Bronze integrations must implement the runtime-data rule.
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator
homeassistant/components/intellidwell/switch.py:71
- Let relay-command failures propagate so the service call reports failure instead of logging an error and returning success.
try:
await self.coordinator.client.set_relay(self.zone_index, "on")
except Exception as err:
_LOGGER.error("Error turning on zone %s: %s", self.zone_index + 1, err)
homeassistant/components/intellidwell/switch.py:80
- Let relay-command failures propagate so the service call reports failure instead of logging an error and returning success.
try:
await self.coordinator.client.set_relay(self.zone_index, "off")
except Exception as err:
_LOGGER.error("Error turning off zone %s: %s", self.zone_index + 1, err)
homeassistant/components/intellidwell/switch.py:53
- Use the product's established
IntelliDwellcapitalization in the user-visible manufacturer name.
manufacturer="Intellidwell",
tests/components/intellidwell/test_config_flow.py:9
- Replace this import and every patch target in this file with
homeassistant.components.intellidwell;homeassistant_integrationis not a package in core, so the test fails during collection.
from homeassistant_integration.intellidwell.const import DOMAIN
tests/components/intellidwell/test_switch.py:9
- Replace this import and every patch target in this file with
homeassistant.components.intellidwell;homeassistant_integrationis not a package in core, so the test fails during collection.
from homeassistant_integration.intellidwell.const import DOMAIN
tests/components/intellidwell/test_switch.py:30
- Keep
get_statusmocked while exercising both switch services; each command requests a coordinator refresh after this context exits, so the test otherwise contacts1.1.1.1.
with patch(
"homeassistant_integration.intellidwell.IntelliDwellClient.get_status",
return_value=status_data,
):
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (11)
tests/components/intellidwell/test_config_flow.py:72
- Remove this narrative comment because the successful response patch and create-entry assertions already describe the second attempt.
# Second attempt: connection succeeds — entry should be created.
tests/components/intellidwell/test_switch.py:152
- Mock all coordinator endpoints in this setup-failure test.
_async_update_data()startsget_status(),get_rain_delay(), andget_schedules()concurrently, so the two unpatched calls can perform real network I/O and make the test flaky or fail under socket blocking.
with patch(
"homeassistant.components.intellidwell.IntelliDwellClient.get_status",
side_effect=IntelliDwellConnectionError,
):
homeassistant/util/init.py:65
- Remove this unrelated syntax-only change from the IntelliDwell integration PR. Python 3.14 supports the existing exception syntax, and this edit does not contribute to the integration or its tests.
except (ValueError, TypeError):
homeassistant/components/intellidwell/coordinator.py:51
- Mark failed auxiliary fetches unavailable instead of returning fabricated defaults. If rain-delay or schedule parsing raises one of these exceptions, the fallback status lacks those keys, yet the number reports
0and every schedule switch reports enabled, which can misrepresent the controller state.
except (ValueError, KeyError, TypeError) as err:
_LOGGER.debug("Error fetching extra data: %s", err)
return await self.client.get_status()
homeassistant/components/intellidwell/quality_scale.yaml:71
- Mark
entity-device-classas todo until the applicable duration metadata is implemented. The rain-delay number has a day unit but noNumberDeviceClass.DURATION, so this Gold rule is not currently complete.
entity-device-class: done
homeassistant/components/intellidwell/quality_scale.yaml:78
- Mark
icon-translationsas todo until entity icons are moved toicons.json. The integration currently hardcodes icons innumber.py:41andswitch.py:111, so this Gold rule is not complete.
icon-translations: done
homeassistant/components/intellidwell/quality_scale.yaml:9
- Move the repeated controller entity setup into a shared base entity before marking
common-modulesdone. The identicalDeviceInfoconstruction is duplicated atswitch.py:63-69,switch.py:126-132, andnumber.py:58-64, so metadata changes can easily drift across platforms.
common-modules: done
homeassistant/components/intellidwell/quality_scale.yaml:75
- Correct this exemption reason to include the rain-delay number entity. The integration creates both switch and number entities, so the current quality-scale declaration is factually inaccurate.
entity-disabled-by-default:
status: exempt
comment: |
Only switch entities are created.
homeassistant/components/intellidwell/manifest.json:3
- Complete and correct the PR description before merging this integration. The Proposed change section is empty, two mutually exclusive Type of change boxes are selected, and the checked dependency-release comparison item has no corresponding link.
"name": "IntelliDwell Sprinkler Controller",
tests/components/intellidwell/test_config_flow.py:58
- Remove this narrative comment because the exception patch and following assertions already make the failed first attempt explicit.
This issue also appears on line 72 of the same file.
# First attempt: connection fails — form should re-display with an error.
homeassistant/components/intellidwell/switch.py:148
- Add coverage for dictionary-shaped schedule responses. The existing switch test only supplies a list, leaving this alternate key-lookup path entirely unverified.
elif isinstance(schedules, dict):
zone_info = schedules.get(str(self.zone_index)) or schedules.get(
self.zone_index
)
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (11)
homeassistant/components/intellidwell/quality_scale.yaml:75
- Correct this exemption rationale because the integration also creates a rain-delay number entity in
number.py.
entity-disabled-by-default:
status: exempt
comment: |
Only switch entities are created.
homeassistant/components/intellidwell/quality_scale.yaml:78
- Change this rule to
todountil the hard-coded number and schedule-switch icons are moved to anicons.jsontranslation file; integrations that mark it done provide that file (for example,homeassistant/components/huum/icons.json).
icon-translations: done
homeassistant/components/intellidwell/quality_scale.yaml:69
- Mark this rule exempt because each config entry always represents one fixed controller; single-device integrations use an exemption (for example,
homeassistant/components/airgradient/quality_scale.yaml:65-68).
dynamic-devices: done
homeassistant/components/intellidwell/quality_scale.yaml:71
- Change this rule to
todoor assign the rain-delay number the available duration device class.NumberDeviceClass.DURATIONsupports days (homeassistant/components/number/const.py:545-552), whilenumber.py:46currently only sets the unit.
entity-device-class: done
homeassistant/components/intellidwell/quality_scale.yaml:81
- Mark this rule exempt because a fixed single-device config entry cannot accumulate stale discovered devices; this matches integrations such as
homeassistant/components/airgradient/quality_scale.yaml:80-83.
stale-devices: done
tests/components/intellidwell/test_switch.py:152
- Mock the other two coordinator requests in this failure test as well.
_async_update_datastartsget_status,get_rain_delay, andget_schedulestogether, so the latter two currently make real requests to1.1.1.1and can continue afterget_statusraises, making this test flaky and network-dependent.
with patch(
"homeassistant.components.intellidwell.IntelliDwellClient.get_status",
side_effect=IntelliDwellConnectionError,
):
homeassistant/util/init.py:65
- Remove this unrelated syntax-only change from the IntelliDwell integration PR so the change set remains scoped to the new integration.
except (ValueError, TypeError):
homeassistant/components/intellidwell/coordinator.py:51
- Treat extra-endpoint parse failures as an unsuccessful update, or explicitly mark the missing rain-delay and schedule data unknown. Returning status-only data keeps the coordinator successful, so the number reports
0and every missing schedule reportsoneven though those values were not fetched.
except (ValueError, KeyError, TypeError) as err:
_LOGGER.debug("Error fetching extra data: %s", err)
return await self.client.get_status()
homeassistant/components/intellidwell/quality_scale.yaml:26
- Mark this rule exempt because this is a polling-only integration with no event subscriptions; polling integrations use that status consistently (for example,
homeassistant/components/rainbird/quality_scale.yaml:27-29andhomeassistant/components/freshr/quality_scale.yaml:24-26).
This issue also appears in the following locations of the same file:
- line 69
- line 71
- line 72
- line 78
- line 81
entity-event-setup: done
homeassistant/components/intellidwell/switch.py:130
- Reuse one shared IntelliDwell device-info definition instead of repeating this block for the schedule entity; it duplicates the zone entity metadata at
switch.py:63-69, so future model or URL changes can diverge.
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, config_entry.entry_id)},
name="IntelliDwell Sprinkler Controller",
manufacturer="IntelliDwell",
model="Sprinkler Controller V2",
homeassistant/components/intellidwell/number.py:62
- Reuse shared IntelliDwell device metadata here instead of maintaining a third copy of the same
DeviceInfoblock fromswitch.py:63-69andswitch.py:126-132.
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, config_entry.entry_id)},
name="IntelliDwell Sprinkler Controller",
manufacturer="IntelliDwell",
model="Sprinkler Controller V2",
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (15)
tests/components/intellidwell/test_switch.py:152
- Mock every request started by the coordinator in this setup-failure test.
_async_update_data()starts all three calls withasyncio.gather, so the unpatched rain-delay and schedules methods can perform real network I/O against 1.1.1.1 even thoughget_status()raises.
with patch(
"homeassistant.components.intellidwell.IntelliDwellClient.get_status",
side_effect=IntelliDwellConnectionError,
):
homeassistant/components/intellidwell/coordinator.py:51
- Treat an auxiliary API failure as an update failure instead of publishing incomplete coordinator data. Returning only
get_status()marks the refresh successful while the rain-delay entity falls back to 0 and schedule switches fall back to enabled, exposing incorrect device state.
except (ValueError, KeyError, TypeError) as err:
_LOGGER.debug("Error fetching extra data: %s", err)
return await self.client.get_status()
homeassistant/util/init.py:65
- Remove this unrelated syntax-only edit from the IntelliDwell integration PR. Python 3.14 supports the original form, and this change is not required by the new integration or its dependency.
except (ValueError, TypeError):
homeassistant/components/intellidwell/config_flow.py:32
- Validate every API endpoint required by the initial coordinator refresh before creating the entry. A controller can pass
get_status()but failget_rain_delay()orget_schedules(), after which setup enters retry even though the config flow reported success.
await client.get_status()
homeassistant/components/intellidwell/switch.py:149
- Move schedule-response normalization into
pyintellidwelland consume one typed representation here. Supporting list/dict payloads plus string/integer keys in the integration is protocol parsing and a library workaround, which Home Assistant integrations should not own.
elif isinstance(schedules, dict):
zone_info = schedules.get(str(self.zone_index)) or schedules.get(
self.zone_index
)
if isinstance(zone_info, dict):
homeassistant/components/intellidwell/quality_scale.yaml:9
- Extract the shared entity metadata before marking
common-modulescomplete. The sameDeviceInfoconstruction is duplicated in both switch classes and the number class, so this Bronze rule is not yet satisfied; a common coordinator property or base entity should own it.
common-modules: done
homeassistant/components/intellidwell/quality_scale.yaml:26
- Mark
entity-event-setupexempt because this integration registers no entity events.doneclaims an event setup implementation that is absent from the integration.
entity-event-setup: done
homeassistant/components/intellidwell/quality_scale.yaml:50
- Mark test coverage as pending or add coverage for the untested runtime branches. The tests never exercise unloading, invalid/partial coordinator responses, or the dictionary schedule representation, so
test-coverage: doneis not supported.
test-coverage: done
homeassistant/components/intellidwell/quality_scale.yaml:75
- Correct this exemption rationale to include the rain-delay number entity. The integration does not create only switches, so the stated reason is factually inaccurate and does not establish why every entity should remain enabled by default.
Only switch entities are created.
homeassistant/components/intellidwell/quality_scale.yaml:78
- Mark icon translations pending until the hard-coded entity icons are moved to
icons.json. This integration has noicons.json, whilenumber.pyandswitch.pyset_attr_icondirectly, so the rule is not implemented.
icon-translations: done
tests/components/intellidwell/test_config_flow.py:58
- Remove this narrative comment because the patch and following assertions already make the failed first attempt explicit. It restates straightforward test code without explaining a non-obvious constraint.
# First attempt: connection fails — form should re-display with an error.
tests/components/intellidwell/test_config_flow.py:72
- Remove this narrative comment because the successful retry and entry assertions directly describe the second attempt. It restates straightforward test code without adding rationale.
# Second attempt: connection succeeds — entry should be created.
homeassistant/components/intellidwell/number.py:46
- Declare this number as a duration using Home Assistant's device-class and unit enums. Duration number entities use
NumberDeviceClass.DURATIONwithUnitOfTime.DAYS(for example,homeassistant/components/renson/number.py:24-34); the raw unit also contradicts the claimedentity-device-classcompletion.
_attr_native_unit_of_measurement = "d"
homeassistant/components/intellidwell/quality_scale.yaml:69
- Mark
dynamic-devicesexempt because this integration creates one fixed controller device per config entry. There is no runtime device-discovery path implementing this rule.
dynamic-devices: done
homeassistant/components/intellidwell/quality_scale.yaml:81
- Mark
stale-devicesexempt because this integration has no dynamically discovered child devices to remove.donecurrently claims stale-device cleanup behavior that is not implemented.
stale-devices: done
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (15)
tests/components/intellidwell/test_switch.py:152
- Mock every coordinator request in this setup-failure test.
_async_update_data()startsget_rain_delay()andget_schedules()alongsideget_status(), so leaving those methods unpatched performs real network I/O against1.1.1.1and makes the test nondeterministic.
with patch(
"homeassistant.components.intellidwell.IntelliDwellClient.get_status",
side_effect=IntelliDwellConnectionError,
):
homeassistant/components/intellidwell/quality_scale.yaml:69
- Mark the dynamic-device rule exempt for this single-controller integration. The integration creates one fixed device and has no discovery path for adding devices dynamically; the established single-device exemption is shown in
homeassistant/components/peblar/quality_scale.yaml:62-65.
dynamic-devices: done
homeassistant/components/intellidwell/quality_scale.yaml:71
- Do not claim the entity-device-class rule until the duration metadata is implemented. The rain-delay number uses a day unit but omits
NumberDeviceClass.DURATION; the corresponding established implementation ishomeassistant/components/renson/number.py:24-33.
entity-device-class: done
homeassistant/components/intellidwell/quality_scale.yaml:75
- Correct this exemption rationale to include the rain-delay number.
number.pycreates a number entity, so the current statement that only switches are created is factually incorrect.
entity-disabled-by-default:
status: exempt
comment: |
Only switch entities are created.
homeassistant/components/intellidwell/quality_scale.yaml:78
- Mark icon translations as incomplete or add an
icons.json. The number and schedule switch icons are hardcoded in Python, while integrations satisfying this rule define translation-key icons as inhomeassistant/components/peblar/icons.json.
icon-translations: done
homeassistant/components/intellidwell/quality_scale.yaml:81
- Mark stale-device handling exempt for this single-controller integration. There is no dynamic device inventory from which stale devices could be removed;
homeassistant/components/peblar/quality_scale.yaml:77-80uses the applicable exemption.
stale-devices: done
homeassistant/util/init.py:65
- Revert this unrelated syntax-only change. The original exception syntax is valid on Home Assistant's Python 3.14 baseline, and changing shared utility code is not required to add IntelliDwell or its dependency.
except (ValueError, TypeError):
homeassistant/components/intellidwell/coordinator.py:51
- Fail the coordinator update instead of returning an incomplete payload. If either auxiliary endpoint raises one of these parsing errors, this branch omits
rain_delayandscheduleswhile reporting a successful update; the number then shows zero and missing schedule switches show enabled rather than preserving the last valid state.
except (ValueError, KeyError, TypeError) as err:
_LOGGER.debug("Error fetching extra data: %s", err)
return await self.client.get_status()
homeassistant/components/intellidwell/quality_scale.yaml:26
- Mark this rule exempt because the integration does not explicitly subscribe to events. Polling integrations use this exemption pattern in
homeassistant/components/peblar/quality_scale.yaml:25-28andhomeassistant/components/rainbird/quality_scale.yaml:27-29;CoordinatorEntityhandles its own listener lifecycle.
This issue also appears in the following locations of the same file:
- line 69
- line 71
- line 72
- line 78
- line 81
entity-event-setup: done
homeassistant/components/intellidwell/switch.py:151
- Return an unknown state when schedule data is absent or malformed. Ten schedule switches are always created, so a shorter response—such as the two-item fixture in
test_switches—currently makes every remaining zone report enabled without anenabledvalue.
if not isinstance(self.coordinator.data, dict):
return True
schedules = self.coordinator.data.get("schedules", [])
homeassistant/components/intellidwell/number.py:75
- Reject fractional rain-delay values instead of silently truncating them. The
number.set_valueservice accepts any float and only clamps its range (homeassistant/components/number/__init__.py:99,122-127), so requesting2.9currently sends2days despite the caller's value.
"""Set rain delay days (0 to 5)."""
days = int(value)
homeassistant/components/intellidwell/switch.py:130
- Extract a shared IntelliDwell coordinator entity for the common device metadata. This identical
DeviceInfoblock is repeated in both switch classes andnumber.py:58-64, so model, manufacturer, identifiers, and URL can drift; the claimedcommon-modulesrule should keep this single-sourced.
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, config_entry.entry_id)},
name="IntelliDwell Sprinkler Controller",
manufacturer="IntelliDwell",
model="Sprinkler Controller V2",
requirements_all.txt:2273
- Add a pyintellidwell 1.0.0 release or source-comparison link to the PR description. The dependency checklist item is checked as completed, but the description contains no release, changelog, or comparison link for this newly added requirement.
pyintellidwell==1.0.0
homeassistant/components/intellidwell/manifest.json:10
- Select only “New integration” in the PR description’s type checklist.
pyintellidwellis a required part of this new integration, not a separate dependency-upgrade change, and the template explicitly permits only one selected type.
"quality_scale": "bronze",
"requirements": ["pyintellidwell==1.0.0"]
homeassistant/components/intellidwell/init.py:42
- Add a test that unloads the config entry and verifies its entities are removed. This new lifecycle path is currently never exercised even though the quality-scale file claims both config-entry unloading and test coverage are complete.
async def async_unload_entry(
hass: HomeAssistant, entry: IntelliDwellConfigEntry
) -> bool:
"""Unload a config entry."""
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (9)
tests/components/intellidwell/test_switch.py:152
- Mock all three coordinator requests during this failure test.
_async_update_data()startsget_rain_delay()andget_schedules()alongsideget_status(), so these unpatched calls still perform real network I/O against1.1.1.1and can leak pending requests or make the test flaky.
with patch(
"homeassistant.components.intellidwell.IntelliDwellClient.get_status",
side_effect=IntelliDwellConnectionError,
):
homeassistant/components/intellidwell/coordinator.py:51
- Raise
UpdateFailedinstead of treating an incomplete refresh as successful. If either auxiliary endpoint raises one of these exceptions, this returns status withoutrain_delayorschedules, so the coordinator stays available while entities publish fabricated defaults.
except (ValueError, KeyError, TypeError) as err:
_LOGGER.debug("Error fetching extra data: %s", err)
return await self.client.get_status()
homeassistant/components/intellidwell/switch.py:151
- Return an unknown state when schedule data is absent instead of reporting it as enabled. Missing, short, or malformed schedule responses all reach this fallback, causing affected switches to appear
onwithout an enabled value.
return True
homeassistant/components/intellidwell/number.py:62
- Move the shared device metadata into the coordinator or a common entity base. This identical
DeviceInfoblock is repeated here and twice inswitch.py:63-69,126-132, so device identity changes must be kept synchronized across three implementations.
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, config_entry.entry_id)},
name="IntelliDwell Sprinkler Controller",
manufacturer="IntelliDwell",
model="Sprinkler Controller V2",
homeassistant/components/intellidwell/quality_scale.yaml:26
- Mark
entity-event-setupas exempt for this polling integration. Polling coordinators do not register entity event subscriptions; established entries use this exemption, for examplefreshr/quality_scale.yaml:24-26andrainbird/quality_scale.yaml:27-29.
entity-event-setup: done
homeassistant/components/intellidwell/quality_scale.yaml:78
- Mark
icon-translationsastodountil translated icons are implemented. There is noicons.json, andnumber.py:41andswitch.py:111still hard-code entity icons, so the rule is not currently complete.
icon-translations: done
homeassistant/components/intellidwell/quality_scale.yaml:75
- Correct this exemption rationale to account for the number entity. The integration creates
IntelliDwellRainDelayNumber, so the current claim that only switches are created is factually incorrect.
Only switch entities are created.
homeassistant/util/init.py:65
- Revert this unrelated syntax-only change. The PR is scoped to adding IntelliDwell, while this alters a global utility that the integration does not depend on and changes syntax that is valid on Home Assistant's minimum Python 3.14.
except (ValueError, TypeError):
homeassistant/components/intellidwell/manifest.json:10
- Complete the PR description for this new dependency and select only the New integration type. The Proposed change section is empty, both Dependency upgrade and New integration are checked, and the checked release/compare-link requirement has no corresponding link.
"requirements": ["pyintellidwell==1.0.0"]
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (6)
homeassistant/components/intellidwell/quality_scale.yaml:75
- Mark this rule as
todoor provide an exemption that matches the entities created; the integration also creates a rain-delay number, so “Only switch entities are created” is factually incorrect and cannot justify this exemption.
entity-disabled-by-default:
status: exempt
comment: |
Only switch entities are created.
tests/components/intellidwell/test_switch.py:152
- Mock all three coordinator requests in this failure test.
_async_update_datastartsget_rain_delay()andget_schedules()concurrently withget_status(), andasyncio.gatherdoes not cancel them when the status mock raises, so these unpatched calls can perform real network I/O against 1.1.1.1.
with patch(
"homeassistant.components.intellidwell.IntelliDwellClient.get_status",
side_effect=IntelliDwellConnectionError,
):
homeassistant/components/intellidwell/quality_scale.yaml:78
- Mark icon translations as
todountil the entity icons are moved toicons.json. The integration has noicons.jsonand instead hard-codes icons innumber.py:41andswitch.py:111, so this rule is not implemented.
icon-translations: done
homeassistant/components/intellidwell/coordinator.py:51
- Treat malformed extra data as a failed update, or explicitly track per-field availability. Returning only
get_status()marks the coordinator successful withoutrain_delayorschedules, so the number reports a fabricated zero and every schedule switch reports enabled instead of becoming unavailable.
except (ValueError, KeyError, TypeError) as err:
_LOGGER.debug("Error fetching extra data: %s", err)
return await self.client.get_status()
homeassistant/components/intellidwell/quality_scale.yaml:9
- Mark
common-modulesastodountil the shared entity setup is extracted. The sameDeviceInfoconstruction is duplicated innumber.py:58-64and twice inswitch.py:63-69,126-132; a common entity base or coordinator property is needed to keep this metadata single-source.
This issue also appears in the following locations of the same file:
- line 72
- line 78
common-modules: done
homeassistant/components/intellidwell/quality_scale.yaml:50
- Mark
test-coverageastodountil the untested branches are covered. The suite never executes the coordinator’s malformed-extra-data fallback (coordinator.py:49-51), the schedule dictionary/non-dictionary handling (switch.py:138-150), or config-entry unloading, so the Silver rule is not yet demonstrated.
test-coverage: done
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (7)
homeassistant/components/intellidwell/quality_scale.yaml:75
- Correct this exemption because the integration also creates a rain-delay number entity in
number.py; the stated reason is factually false, so this rule should remaintodounless all entities are evaluated and a valid exemption is documented.
entity-disabled-by-default:
status: exempt
comment: |
Only switch entities are created.
tests/components/intellidwell/test_switch.py:152
- Mock all coordinator requests in this failure test.
_async_update_datastartsget_status,get_rain_delay, andget_schedulesconcurrently, so leaving the latter two unpatched allows real requests to1.1.1.1to continue afterget_statusraises, making the test perform external I/O and potentially hang or fail nondeterministically.
with patch(
"homeassistant.components.intellidwell.IntelliDwellClient.get_status",
side_effect=IntelliDwellConnectionError,
):
homeassistant/components/intellidwell/coordinator.py:51
- Wrap failures from the fallback
get_status()call asUpdateFailed. Exceptions raised inside anexceptblock are not handled by the preceding handlers, so a connection/invalid-response/parsing failure here reachesDataUpdateCoordinatoras an unexpected exception and can emit a traceback on every five-second poll instead of using its normal unavailable/recovery logging.
except (ValueError, KeyError, TypeError) as err:
_LOGGER.debug("Error fetching extra data: %s", err)
return await self.client.get_status()
homeassistant/components/intellidwell/quality_scale.yaml:78
- Mark icon translations as
todountil the entity icons are moved toicons.json. Both platforms currently set_attr_iconin Python and this integration has noicons.json, so the Gold rule is not implemented.
icon-translations: done
homeassistant/components/intellidwell/quality_scale.yaml:71
- Mark the device-class rule as
todoor addNumberDeviceClass.DURATIONto the rain-delay number. That entity represents a duration in days but defines no device class, so this Gold rule is not yet complete.
entity-device-class: done
homeassistant/components/intellidwell/coordinator.py:51
- Avoid publishing status-only data as a successful full update. When either extra request raises one of these parsing errors, this return omits
rain_delayandschedules; the coordinator remains available, sonumber.pyreports a false zero-day delay andswitch.pyreports every schedule as enabled, overwriting previously valid states. Preserve the prior extra values, model their availability separately, or fail the update instead.
except (ValueError, KeyError, TypeError) as err:
_LOGGER.debug("Error fetching extra data: %s", err)
return await self.client.get_status()
homeassistant/components/intellidwell/quality_scale.yaml:9
- Move the shared entity setup into a common entity base before marking this Bronze rule done. The identical
DeviceInfoblock is currently duplicated inswitch.py:63-69,switch.py:126-132, andnumber.py:58-64, so metadata changes must be kept synchronized across three classes; established integrations such asrainbird/number.py:52-54expose shared device info from their coordinator/base entity.
common-modules: done
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (9)
homeassistant/components/intellidwell/quality_scale.yaml:66
- Mark the unimplemented documentation rules
todoor expand the linked documentation PR. That page has no data-update, example, limitation, troubleshooting, or use-case sections, and its supported-function list omits both the rain-delay number and schedule switches.
docs-data-update: done
docs-examples: done
docs-known-limitations: done
docs-supported-devices: done
docs-supported-functions: done
tests/components/intellidwell/test_config_flow.py:72
- Remove this narrating comment; the success mock and create-entry assertions immediately below already describe the recovery attempt.
# Second attempt: connection succeeds — entry should be created.
homeassistant/components/intellidwell/switch.py:21
- Serialize all client calls through one shared coordinator lock.
PARALLEL_UPDATES = 1only protects switch actions from other switch actions; number actions and scheduled refreshes can still overlap them, despite the firmware warning that concurrent HTTP requests can exhaust sockets and crash the ESP32.
PARALLEL_UPDATES = 1
homeassistant/components/intellidwell/coordinator.py:51
- Fail the refresh instead of returning incomplete coordinator data. This path omits
rain_delayandschedules, so the number reports a false zero and every schedule switch reports enabled while all entities remain available.
except (ValueError, KeyError, TypeError) as err:
_LOGGER.debug("Error fetching extra data: %s", err)
return await self.client.get_status()
homeassistant/components/intellidwell/quality_scale.yaml:75
- Correct this exemption rationale or the entity behavior.
number.pycreates a rain-delay number, so “Only switch entities are created” is factually incorrect and cannot justify this exemption.
entity-disabled-by-default:
status: exempt
comment: |
Only switch entities are created.
homeassistant/components/intellidwell/quality_scale.yaml:9
- Extract the shared entity setup before marking
common-modulescomplete. The identicalDeviceInfoconstruction is currently repeated innumber.pyand both switch classes, while this Bronze rule requires common entity behavior to live inentity.py.
common-modules: done
homeassistant/components/intellidwell/quality_scale.yaml:71
- Do not mark the device-class rule complete while the rain-delay entity lacks a duration device class.
number.pyexposes a value measured in days but does not setNumberDeviceClass.DURATION.
entity-device-class: done
homeassistant/components/intellidwell/quality_scale.yaml:78
- Do not mark icon translations complete while icons remain hardcoded. Both platforms set
_attr_icon, and the integration has noicons.json, whereas this rule requires icons to be defined by translation key.
icon-translations: done
tests/components/intellidwell/test_config_flow.py:58
- Remove this narrating comment; the mock and assertions immediately below already express the failed first attempt and expected form error.
This issue also appears on line 72 of the same file.
# First attempt: connection fails — form should re-display with an error.
| status_data, rain_delay_data, schedules_data = await asyncio.gather( | ||
| self.client.get_status(), | ||
| self.client.get_rain_delay(), | ||
| self.client.get_schedules(), | ||
| return_exceptions=False, | ||
| ) |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (11)
tests/components/intellidwell/test_switch.py:152
- Mock all coordinator requests in this failure test. The coordinator starts
get_status,get_rain_delay, andget_schedulesconcurrently, so the two unpatched methods perform real network I/O and can make this test slow or flaky.
with patch(
"homeassistant.components.intellidwell.IntelliDwellClient.get_status",
side_effect=IntelliDwellConnectionError,
):
homeassistant/components/intellidwell/quality_scale.yaml:8
- Complete the
brandsrule before declaring Bronze quality. A Bronze integration cannot leave one of its Bronze rules astodo, so the manifest currently overstates the integration's achieved tier.
appropriate-polling: done
brands: todo
homeassistant/components/intellidwell/coordinator.py:51
- Treat malformed auxiliary responses as a failed coordinator update. Returning status-only data drops
rain_delayandschedules, while the entities publish those missing values as 0/enabled and remain available, producing false states.
except (ValueError, KeyError, TypeError) as err:
_LOGGER.debug("Error fetching extra data: %s", err)
return await self.client.get_status()
homeassistant/components/intellidwell/number.py:75
- Reject non-integral rain-delay values instead of silently truncating them. The number service validates only the 0–5 range, so a call with
4.9reaches this method and is unexpectedly sent to the controller as 4 days.
async def async_set_native_value(self, value: float) -> None:
"""Set rain delay days (0 to 5)."""
days = int(value)
homeassistant/components/intellidwell/quality_scale.yaml:9
- Move the shared entity metadata into an
entity.pybase class before markingcommon-modulesdone. The sameCoordinatorEntitysetup andDeviceInfoblock is duplicated across both switch classes and the number class;homeassistant/components/prana/entity.py:13-37demonstrates the established pattern.
common-modules: done
homeassistant/components/intellidwell/quality_scale.yaml:64
- Mark these documentation rules
todountil the linked documentation implements them. The linked page contains no data-update interval, automation example, or known-limitations section, so thesedonestatuses are inaccurate.
docs-data-update: done
docs-examples: done
docs-known-limitations: done
homeassistant/components/intellidwell/quality_scale.yaml:67
- Mark these documentation rules
todountil the linked page is completed. It documents only relay zone switches, omitting the rain-delay number and schedule switches, and it has no troubleshooting guidance.
docs-supported-functions: done
docs-troubleshooting: done
homeassistant/components/intellidwell/quality_scale.yaml:75
- Remove this invalid exemption or mark the rule
todo. The rule has no exemption and the explanation is also factually incorrect becausenumber.pycreates a rain-delay number entity.
entity-disabled-by-default:
status: exempt
comment: |
Only switch entities are created.
homeassistant/components/intellidwell/quality_scale.yaml:78
- Mark
icon-translationstodountil the icons are moved toicons.json. The number and schedule switch currently set_attr_icondirectly, and this integration has noicons.json, which does not satisfy the icon-translations rule.
icon-translations: done
homeassistant/components/intellidwell/quality_scale.yaml:71
- Mark
entity-device-classtodoor add the applicable duration device class. The rain-delay number exposes a day unit but does not setNumberDeviceClass.DURATION, unlike the established duration-number pattern inhomeassistant/components/renson/number.py:32-33.
entity-device-class: done
homeassistant/components/intellidwell/init.py:42
- Add a config-entry unload test for this new integration. Both nearby new integrations test the loaded-to-unloaded transition (
tests/components/prana/test_init.py:19-25andtests/components/aidot/test_init.py:20-26), while this implementation and itsconfig-entry-unloading: doneclaim are currently uncovered.
async def async_unload_entry(
hass: HomeAssistant, entry: IntelliDwellConfigEntry
) -> bool:
"""Unload a config entry."""
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (11)
tests/components/intellidwell/test_switch.py:152
- Mock every coordinator request in this failure test.
_async_update_data()startsget_status(),get_rain_delay(), andget_schedules()concurrently, so leaving the latter two unpatched can perform real network I/O and make the test flaky.
with (
patch(
"homeassistant.components.intellidwell.IntelliDwellClient.get_status",
side_effect=IntelliDwellConnectionError,
homeassistant/components/intellidwell/quality_scale.yaml:8
- Complete the required branding work before declaring Bronze.
manifest.jsonclaims Bronze while this mandatory Bronze rule remainstodo; the linked documentation PR also confirms that no Brands PR has been opened.
brands: todo
homeassistant/components/intellidwell/switch.py:35
- Build entities from the controller's configured relay roles instead of treating all ten relays as zones. IntelliDwell supports a configured master-valve relay; exposing it as a normal zone lets users bypass its automatic sequencing, and its schedule control has no effect because firmware skips scheduling that relay.
entities: list[SwitchEntity] = [
IntelliDwellZoneSwitch(coordinator, config_entry, zone_index)
for zone_index in range(10)
]
homeassistant/components/intellidwell/quality_scale.yaml:38
- Remove the invalid
action-exceptionsexemption. The rule explicitly includes platform actions, and this integration implements number and switch actions even though it has no custom services.
action-exceptions:
status: exempt
comment: |
Integration does not provide custom services.
homeassistant/components/intellidwell/coordinator.py:51
- Treat malformed auxiliary responses as update failures instead of returning status-only data. This fallback marks the coordinator successful while omitting
rain_delayandschedules, so the entities publish fabricated defaults (0 days and enabled schedules) rather than becoming unavailable.
except (ValueError, KeyError, TypeError) as err:
_LOGGER.debug("Error fetching extra data: %s", err)
return await self.client.get_status()
homeassistant/components/intellidwell/quality_scale.yaml:9
- Add a shared base entity before marking
common-modulesdone.DeviceInfoand coordinator setup are duplicated acrossnumber.pyand both switch classes, while this Bronze rule requires common entity behavior to live inentity.py.
common-modules: done
homeassistant/components/intellidwell/quality_scale.yaml:78
- Do not mark icon translations done while icons are hardcoded.
number.py:41andswitch.py:111use_attr_icon, and the integration has noicons.json, so this rule is not implemented.
icon-translations: done
homeassistant/components/intellidwell/quality_scale.yaml:67
- Mark unsupported documentation rules
todountil the linked docs are completed. PR 47101 contains no examples, known-limitations, or troubleshooting content and its supported-functions section omits both the rain-delay number and schedule switches.
docs-examples: done
docs-known-limitations: done
docs-supported-devices: done
docs-supported-functions: done
docs-troubleshooting: done
homeassistant/components/intellidwell/quality_scale.yaml:75
- Correct this exemption to account for the number entity. The integration creates
IntelliDwellRainDelayNumber, so the stated reason that only switches are created is factually incorrect and does not establish whether non-primary entities should be disabled by default.
entity-disabled-by-default:
status: exempt
comment: |
Only switch entities are created.
requirements_all.txt:2273
- Correct and complete the PR template for this dependency addition. This line introduces
pyintellidwellrather than upgrading it, but the description checks both “Dependency upgrade” and “New integration,” leaves Proposed change empty, and claims a release/changelog link that is not provided.
pyintellidwell==1.0.0
homeassistant/components/intellidwell/config_flow.py:34
- Validate every endpoint required by the first coordinator refresh before creating the entry. The flow currently succeeds after only
get_status(), but setup immediately requires rain-delay and schedule requests too, so a controller missing either endpoint is accepted and then remains inSETUP_RETRY.
try:
await client.get_status()
except (IntelliDwellConnectionError, IntelliDwellInvalidResponseError) as err:
raise CannotConnect from err
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (12)
homeassistant/components/intellidwell/quality_scale.yaml:8
- Complete the branding rule before declaring Bronze.
brands: todois a required Bronze rule, soscript/hassfest/quality_scale.py:2232-2249rejects the manifest’s Bronze tier and the current hassfest check fails.
brands: todo
homeassistant/components/intellidwell/coordinator.py:51
- Keep failed auxiliary fetches as failed/partial data instead of returning a successful status-only update. This path drops
rain_delayandschedules, so the coordinator remains available while the number falsely becomes 0 and every schedule switch falsely becomes enabled.
except (ValueError, KeyError, TypeError) as err:
_LOGGER.debug("Error fetching extra data: %s", err)
return await self.client.get_status()
requirements_all.txt:2273
- Update the PR description to select only “New integration” and describe the proposed change. This line adds a new package, while the description also selects “Dependency upgrade,” leaves Proposed change empty, and claims a version comparison was supplied when none is present.
# homeassistant.components.intellidwell
pyintellidwell==1.0.0
homeassistant/components/intellidwell/quality_scale.yaml:9
- Add a shared base entity before marking
common-modulesdone. The identicalDeviceInfoand entity-name setup is currently repeated in both switch classes and the number class; the rule specifically establishesentity.pyfor this shared logic.
common-modules: done
homeassistant/components/intellidwell/number.py:76
- Raise
ServiceValidationErrorfor this invalid action input. The number platform only validates the range, so fractional values reach this branch; exposing a rawValueErrorturns user input into an internal service failure instead of a user-facing validation error.
if not value.is_integer():
raise ValueError("Rain delay value must be a whole number of days")
homeassistant/components/intellidwell/number.py:47
- Declare this rain-delay number as
NumberDeviceClass.DURATION. Days are a supported duration unit (homeassistant/components/number/const.py:545-552), and the current implementation contradicts theentity-device-class: doneclaim.
_attr_native_min_value = 0
_attr_native_max_value = 5
_attr_native_step = 1
_attr_native_unit_of_measurement = "d"
_attr_mode = NumberMode.BOX
homeassistant/components/intellidwell/switch.py:112
- Classify schedule-enable switches as
EntityCategory.CONFIG. These entities change persistent schedule configuration rather than operating a zone; the analogous RainMachine enable switch uses this category (homeassistant/components/rainmachine/switch.py:352-356).
"""Representation of an IntelliDwell Zone Schedule Enable switch."""
_attr_has_entity_name = True
_attr_icon = "mdi:calendar-clock"
homeassistant/components/intellidwell/quality_scale.yaml:66
- Update the linked documentation before marking supported functions done. The documentation PR lists only ten zone switches and only the switch platform, while this integration also adds ten schedule-enable switches and a rain-delay number.
docs-known-limitations: done
docs-supported-devices: done
docs-supported-functions: done
homeassistant/components/intellidwell/quality_scale.yaml:78
- Implement icon translations before marking this rule done. The entities still set
_attr_icondirectly and the integration has noicons.json, which is the mechanism required by the icon-translations rule.
icon-translations: done
homeassistant/components/intellidwell/quality_scale.yaml:64
- Mark these documentation rules incomplete or add the required sections. The linked documentation has no polling/data-update description, automation example or blueprint, or known-limitations section, so these three
donestatuses are not substantiated.
docs-data-update: done
docs-examples: done
docs-known-limitations: done
homeassistant/components/intellidwell/quality_scale.yaml:75
- Correct this exemption and status. The rule has no exemption for integrations that only expose switches, and this integration also creates a number entity, so the stated justification is factually incorrect.
entity-disabled-by-default:
status: exempt
comment: |
Only switch entities are created.
homeassistant/components/intellidwell/quality_scale.yaml:68
- Mark these documentation rules todo or add the required content. The linked documentation contains neither troubleshooting guidance nor concrete use-case examples, despite both rules being marked done.
docs-troubleshooting: done
docs-use-cases: done
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (17)
homeassistant/components/intellidwell/quality_scale.yaml:8
- Complete the branding requirement before declaring Bronze.
brandsis a mandatory Bronze rule with no exceptions, but it remainstodo, so the manifest'squality_scale: bronzeclaim is not yet satisfied.
brands: todo
homeassistant/components/intellidwell/quality_scale.yaml:38
- Do not exempt
action-exceptionsfor these platform actions. The rule explicitly includes switch and number platform actions, which this integration provides, so the absence of custom services is not a valid exemption; mark it done only after all library action failures are translated to Home Assistant exceptions.
action-exceptions:
status: exempt
comment: |
Integration does not provide custom services.
homeassistant/components/intellidwell/quality_scale.yaml:63
- Mark these documentation rules
todountil the linked documentation implements them. The linked docs PR contains no data-update explanation or usage examples, so thesedonestatuses are inaccurate.
docs-data-update: done
docs-examples: done
homeassistant/components/intellidwell/quality_scale.yaml:68
- Update the linked documentation or mark the unimplemented rules
todo. It has no known-limitations, troubleshooting, or use-case sections, and its supported-functions section omits both the rain-delay number and schedule switches.
docs-known-limitations: done
docs-supported-devices: done
docs-supported-functions: done
docs-troubleshooting: done
docs-use-cases: done
homeassistant/components/intellidwell/switch.py:36
- Exclude the configured master-valve relay from zone switch creation. The controller allows one of these relay indices to be designated as the master valve; exposing it as a normal zone lets a user turn it off directly while another zone remains active, cutting off watering and bypassing the controller's automatic master-valve handling.
entities: list[SwitchEntity] = [
IntelliDwellZoneSwitch(coordinator, config_entry, zone_index)
for zone_index in range(10)
]
homeassistant/components/intellidwell/switch.py:41
- Do not create a schedule switch for the configured master-valve relay. The controller's scheduler explicitly skips that relay, so this entity can accept enable/disable commands while having no scheduling effect.
IntelliDwellScheduleSwitch(coordinator, config_entry, zone_index)
for zone_index in range(10)
]
homeassistant/components/intellidwell/manifest.json:10
- Correct and complete the PR description for this new integration. It currently leaves
Proposed changeempty and checks bothDependency upgradeandNew integration, even though this requirement is being introduced rather than upgraded; the template requires exactly one type and a substantive description.
"requirements": ["pyintellidwell==1.0.0"]
homeassistant/components/intellidwell/quality_scale.yaml:12
- Publish and link the
pyintellidwellclient source before marking dependency transparency done. No public client source, tagged1.0.0release, or public publishing pipeline is linked or discoverable; the available controller firmware is a different project and carries a non-commercial restriction, so this mandatory Bronze rule is not met.
dependency-transparency: done
homeassistant/components/intellidwell/coordinator.py:46
- Fetch the controller endpoints serially instead of opening three requests together. The IntelliDwell firmware documents serialized HTTP handling as necessary to avoid ESP32 socket exhaustion, but this five-second polling path starts all three requests concurrently.
status_data, rain_delay_data, schedules_data = await asyncio.gather(
self.client.get_status(),
self.client.get_rain_delay(),
self.client.get_schedules(),
return_exceptions=False,
)
homeassistant/components/intellidwell/switch.py:46
- Model irrigation zones as water valves rather than generic switches. The established sprinkler implementation uses
ValveEntitywithValveDeviceClass.WATER(homeassistant/components/hydrawise/valve.py:22-26,54-59), preserving valve semantics and the corresponding UI and voice behavior that these new switch entities lose.
class IntelliDwellZoneSwitch(CoordinatorEntity[IntelliDwellCoordinator], SwitchEntity):
homeassistant/components/intellidwell/manifest.json:5
- Regenerate and commit the Home Assistant metadata for this new config flow.
homeassistant/generated/config_flows.pyandhomeassistant/generated/integrations.jsonstill omitintellidwell, and hassfest validates both generated files against this manifest declaration (script/hassfest/config_flow.py:210-236).
"config_flow": true,
homeassistant/components/intellidwell/quality_scale.yaml:9
- Add a shared IntelliDwell entity base before marking
common-modulesdone. The sameDeviceInfoconstruction is duplicated inswitch.py:64,switch.py:128, andnumber.py:58, while this rule calls for shared entity behavior to live inentity.py.
common-modules: done
homeassistant/components/intellidwell/number.py:46
- Set
NumberDeviceClass.DURATIONon the rain-delay entity. This number uses a duration unit and the quality file marksentity-device-classdone, but without the duration device class Home Assistant lacks the corresponding duration semantics and unit conversion.
_attr_native_unit_of_measurement = "d"
homeassistant/components/intellidwell/quality_scale.yaml:75
- Correct this exemption reason to cover the entities actually created. The integration also creates a rain-delay number, so “Only switch entities are created” is factually incorrect.
entity-disabled-by-default:
status: exempt
comment: |
Only switch entities are created.
homeassistant/components/intellidwell/quality_scale.yaml:78
- Use
icons.jsonbefore marking icon translations done. No icon translation file is added, while the schedule and rain-delay entities still set_attr_icondirectly, so this Gold rule is not implemented.
icon-translations: done
tests/components/intellidwell/test_number.py:124
- Describe the exception asserted by this test. The test expects
ServiceValidationError, notValueError, so the current docstring misstates the behavior under test.
"""Test ValueError raised when setting float value for rain delay."""
tests/components/intellidwell/test_number.py:129
- Extract the repeated config-entry setup into a shared fixture. This block duplicates the setup in the two preceding tests and similar setup in
test_switch.py, while the newly addedconftest.pyis otherwise empty.
entry = MockConfigEntry(
domain=DOMAIN,
data={CONF_HOST: "1.1.1.1"},
entry_id="mock_entry_num_invalid",
)
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (14)
homeassistant/components/intellidwell/quality_scale.yaml:8
- Complete the
brandsrule before declaring this integration Bronze. AtodoBronze rule means the integration does not yet qualify for thequality_scale: bronzelevel declared inmanifest.json.
brands: todo
homeassistant/components/intellidwell/quality_scale.yaml:64
- Mark these documentation rules
todountil the linked documentation PR implements them. PR 47101 contains no data-update/polling section, blueprint example, or known-limitations section, despite these three rules being marked complete.
docs-data-update: done
docs-examples: done
docs-known-limitations: done
homeassistant/components/intellidwell/coordinator.py:45
- Serialize the three controller requests instead of starting them concurrently. IntelliDwell’s own web client queues
safeFetchcalls one at a time to prevent ESP32 socket exhaustion, but this coordinator opens three requests together every five seconds, risking controller instability and failed updates.
status_data, rain_delay_data, schedules_data = await asyncio.gather(
self.client.get_status(),
self.client.get_rain_delay(),
self.client.get_schedules(),
return_exceptions=False,
homeassistant/components/intellidwell/switch.py:46
- Model sprinkler zones as water valves rather than generic switches. These entities open and close irrigation valves, so
SwitchEntityloses the water-valve semantics, supported open/close features, and UI/voice behavior established byhomeassistant/components/hydrawise/valve.py:22-26,54-59.
class IntelliDwellZoneSwitch(CoordinatorEntity[IntelliDwellCoordinator], SwitchEntity):
homeassistant/components/intellidwell/switch.py:35
- Exclude the configured master-valve relay from the zone entity list. IntelliDwell designates one of these ten indexes as the master valve, so exposing it as a normal zone lets users operate it independently of the firmware’s automatic master-valve control.
IntelliDwellZoneSwitch(coordinator, config_entry, zone_index)
for zone_index in range(10)
homeassistant/components/intellidwell/quality_scale.yaml:9
- Move the shared coordinator and device setup into an
IntelliDwellEntitybase class, or mark this ruletodo. The identicalDeviceInfoinitialization is currently duplicated inswitch.py:64-70,switch.py:128-134, andnumber.py:58-64, socommon-modulesis not yet complete.
common-modules: done
homeassistant/components/intellidwell/quality_scale.yaml:66
- Document every exposed entity before marking
docs-supported-functionscomplete. The linked documentation describes only the ten zone relay switches and omits the rain-delay number and ten schedule switches created by this integration.
docs-supported-functions: done
homeassistant/components/intellidwell/quality_scale.yaml:67
- Mark
docs-troubleshootingtodountil troubleshooting guidance is added. The linked documentation PR has no troubleshooting section or resolution for a common setup/runtime issue.
docs-troubleshooting: done
homeassistant/components/intellidwell/quality_scale.yaml:78
- Add icon translations or mark this rule
todo. The entities currently hard-code_attr_iconinnumber.pyandswitch.py, and the integration provides noicons.json, so the icon-translations rule is not implemented.
icon-translations: done
homeassistant/components/intellidwell/quality_scale.yaml:71
- Add
NumberDeviceClass.DURATIONto the rain-delay number or mark this ruletodo. The entity represents a duration in days but currently has no device class, soentity-device-classis not complete.
entity-device-class: done
homeassistant/components/intellidwell/quality_scale.yaml:75
- Correct the exemption reason to describe why no entity should be disabled by default. The current reason says the integration creates only switches, but
number.pyalso creates the rain-delay number entity.
entity-disabled-by-default:
status: exempt
comment: |
Only switch entities are created.
homeassistant/components/intellidwell/switch.py:151
- Add coverage for dictionary-shaped schedule data or remove this unsupported branch. All schedule tests supply a list, leaving this branch (along with other fallback/error paths) uncovered, so the integration does not substantiate the
test-coverage: doneclaim requiring over 95% module coverage.
elif isinstance(schedules, dict):
zone_info = schedules.get(str(self.zone_index)) or schedules.get(
self.zone_index
)
if isinstance(zone_info, dict):
homeassistant/components/intellidwell/coordinator.py:50
- Add a coordinator test for malformed-response exceptions. The existing setup-failure test covers only
IntelliDwellConnectionError, so this distinctValueError/KeyError/TypeErrorpath and itsUpdateFailedconversion are unverified despitetest-coveragebeing marked complete.
except (ValueError, KeyError, TypeError) as err:
raise UpdateFailed(f"Invalid response from API: {err}") from err
homeassistant/components/intellidwell/switch.py:40
- Exclude the configured master-valve relay from the schedule-switch list. The controller firmware rejects schedule operations for the master-valve index, so this entity is created but every enable/disable command fails.
IntelliDwellScheduleSwitch(coordinator, config_entry, zone_index)
for zone_index in range(10)
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (10)
homeassistant/components/intellidwell/quality_scale.yaml:9
- Centralize the shared device metadata before marking
common-modulesdone. The sameDeviceInfoconstruction is duplicated in both switch classes and the number class; established integrations such as Rain Bird expose it once from the coordinator (homeassistant/components/rainbird/coordinator.py:105).
common-modules: done
homeassistant/components/intellidwell/quality_scale.yaml:75
- Mark this rule
todoor provide a valid exemption. The stated reason is factually incorrect becausenumber.pycreates a rain-delay number entity in addition to the switch entities.
entity-disabled-by-default:
status: exempt
comment: |
Only switch entities are created.
homeassistant/components/intellidwell/quality_scale.yaml:78
- Do not mark icon translations done without an
icons.json. Both custom icons are currently hard-coded with_attr_icon; integrations satisfying this rule, such asprana, define translation-key icons inhomeassistant/components/prana/icons.json.
icon-translations: done
homeassistant/components/intellidwell/config_flow.py:51
- Normalize the host before checking for an existing entry. DNS hostnames are case-insensitive, so values such as
SPRINKLER.LOCALandsprinkler.localcurrently bypass this exact-string match and create duplicate entries.
host = user_input[CONF_HOST]
self._async_abort_entries_match({CONF_HOST: host})
homeassistant/components/intellidwell/quality_scale.yaml:8
- Complete the Bronze
brandsrequirement before declaring this integration Bronze. This is the only integration currently markingbrandsastodo, while existing Bronze integrations such aspranamark every Bronze requirement done or exempt.
This issue also appears in the following locations of the same file:
- line 9
- line 72
- line 78
brands: todo
homeassistant/components/intellidwell/manifest.json:2
- Complete the PR description and select only the New integration change type. The Proposed change section is empty and both Dependency upgrade and New integration are checked, contrary to the PR template's exactly-one requirement.
"domain": "intellidwell",
homeassistant/components/intellidwell/coordinator.py:54
- Keep response assembly inside the guarded block. These lines run in the
else, so malformedstatus_dataorrain_delay_dataraises an uncaughtTypeError/AttributeErrorinstead ofUpdateFailed, causing initial setup to fail rather than retry.
status_data["rain_delay"] = rain_delay_data.get("days_remaining", 0)
status_data["schedules"] = schedules_data
tests/components/intellidwell/test_config_flow.py:72
- Remove this narrating comment. The following mock and assertions already make the successful retry and expected entry creation explicit.
# Second attempt: connection succeeds — entry should be created.
tests/components/intellidwell/test_config_flow.py:58
- Remove this narrating comment. The following mock and assertions already make both the failed attempt and expected form error explicit.
# First attempt: connection fails — form should re-display with an error.
tests/components/intellidwell/conftest.py:1
- Use this
conftest.pyfor shared config-entry and client-response fixtures. The same entry creation and three-method patch block is repeated across the switch, number, and unload tests, so every response-shape change currently requires synchronized edits in several files.
"""Fixtures for IntelliDwell Sprinkler Controller tests."""
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (5)
homeassistant/components/intellidwell/quality_scale.yaml:8
- Complete the
brandsrule before declaring Bronze.script/hassfest/quality_scale.py:2237-2250rejects a declared tier when any rule at or below that tier remainstodo, so the currentquality_scale: bronzemanifest will fail hassfest while this Bronze rule is unmet.
brands: todo
homeassistant/components/intellidwell/quality_scale.yaml:9
- Introduce a shared IntelliDwell entity base before marking
common-modulesdone. The identicalDeviceInfosetup is repeated inswitch.py:64-70,switch.py:128-134, andnumber.py:58-64; the established pattern is a common coordinator entity such ashomeassistant/components/intelliclima/entity.py:19-38, which prevents device metadata from diverging across platforms.
common-modules: done
homeassistant/components/intellidwell/quality_scale.yaml:75
- Correct this exemption or mark the rule
todo. The integration also createsIntelliDwellRainDelayNumber, so the stated rationale that only switch entities are created is factually incorrect.
entity-disabled-by-default:
status: exempt
comment: |
Only switch entities are created.
homeassistant/components/intellidwell/quality_scale.yaml:78
- Move the custom entity icons to
icons.jsonbefore marking icon translations done. Bothnumber.py:41andswitch.py:113hard-code_attr_icon, whereas integrations satisfying this rule define translation-key icons inicons.json(for example,homeassistant/components/prana/icons.json:1-56).
icon-translations: done
homeassistant/components/intellidwell/manifest.json:10
- Correct the PR template to select only “New integration.” This requirement is introduced with a new domain rather than replacing an existing dependency version, so checking both “Dependency upgrade” and “New integration” violates the template’s exactly-one-type requirement.
"requirements": ["pyintellidwell==1.0.0"]
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (4)
homeassistant/components/intellidwell/quality_scale.yaml:8
- Complete the
brandsrule before declaring Bronze quality. Bronze requires every Bronze rule to bedoneor validlyexempt, so leaving this astodomakes the manifest's"quality_scale": "bronze"claim inaccurate.
brands: done
homeassistant/components/intellidwell/quality_scale.yaml:9
- Move the shared device metadata into a common entity base or coordinator property before marking
common-modulescomplete. The sameDeviceInfoconstruction is duplicated inswitch.py:64,switch.py:128, andnumber.py:58, so model or URL changes must currently be kept in sync across three implementations.
common-modules: done
homeassistant/components/intellidwell/quality_scale.yaml:75
- Correct this exemption to account for the rain-delay number entity.
number.pycreatesIntelliDwellRainDelayNumber, so “Only switch entities are created” is false; either give a valid reason that no entity should be disabled by default or mark/implement the rule appropriately.
entity-disabled-by-default: done
entity-translations: done
exception-translations: todo
icon-translations: done
homeassistant/components/intellidwell/switch.py:153
- Report an unknown state when schedule data for this zone is absent or malformed. The platform always creates 10 schedule switches, but the added test supplies only two schedule records; zones 3–10 therefore become available and incorrectly show
onbecause this fallback returnsTrue. ReturnNonefor missing data (and update the return annotation) instead of asserting that the schedule is enabled.
return True
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (8)
homeassistant/components/intellidwell/manifest.json:9
- Declare the integration's Bronze quality tier in the manifest. New integrations with
quality_scale.yamlmust set a manifest quality scale; otherwise hassfest reports “New integrations are required to at least reach the Bronze tier” (script/hassfest/quality_scale.py:2184-2197).
"iot_class": "local_polling",
"requirements": ["pyintellidwell==1.0.0"]
homeassistant/components/intellidwell/quality_scale.yaml:75
- Mark
icon-translationsas todo or add translated icons. Noicons.jsonis included, while the icons remain hardcoded innumber.py:41andswitch.py:113, so this rule is not done.
icon-translations: done
homeassistant/components/intellidwell/quality_scale.yaml:69
- Mark
dynamic-devicesexempt because this integration creates one static controller device. This matches the quality-scale representation used by static device integrations such asrainbird/quality_scale.yaml:52-54.
dynamic-devices: done
homeassistant/components/intellidwell/quality_scale.yaml:78
- Mark
stale-devicesexempt because the integration has only the config-entry controller device and cannot accumulate stale devices. Static-device integrations represent this as an exemption, for examplerainbird/quality_scale.yaml:63-65.
stale-devices: done
homeassistant/components/intellidwell/manifest.json:9
- Update the PR description to describe the proposed integration and include the dependency release/compare link. This line adds a new dependency, but the description leaves “Proposed change” empty and checks that a dependency diff/link was supplied without providing one; it also selects both “Dependency upgrade” and “New integration” despite the template requiring exactly one type.
"requirements": ["pyintellidwell==1.0.0"]
homeassistant/components/intellidwell/quality_scale.yaml:9
- Move the shared entity/device metadata into a common entity module.
DeviceInfoconstruction and identifiers are duplicated innumber.py:58-64and twice inswitch.py:64-70,128-134, so the integration does not currently satisfy thecommon-modulesrule marked done here.
common-modules: done
homeassistant/components/intellidwell/number.py:46
- Add
NumberDeviceClass.DURATIONand useUnitOfTime.DAYSfor this duration entity. The core number contract explicitly supports days for duration values (homeassistant/components/number/const.py:545-552), and established duration numbers use this pair (for example,renson/number.py:24-34); without it, theentity-device-class: doneclaim is not met.
_attr_native_min_value = 0
_attr_native_max_value = 5
_attr_native_step = 1
_attr_native_unit_of_measurement = "d"
homeassistant/components/intellidwell/quality_scale.yaml:26
- Mark this rule exempt because the polling integration does not subscribe to entity events. The established quality-scale representation for this case is an exemption (for example,
rainbird/quality_scale.yaml:27-29), notdone.
This issue also appears in the following locations of the same file:
- line 69
- line 75
- line 78
entity-event-setup: done
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (7)
homeassistant/components/intellidwell/manifest.json:9
- Declare the integration's Bronze quality tier in the manifest. With this new
quality_scale.yamlpresent but no manifest tier, hassfest rejects the integration as not reaching Bronze (script/hassfest/quality_scale.py:2183-2197).
"iot_class": "local_polling",
"requirements": ["pyintellidwell==1.0.0"]
tests/components/intellidwell/test_config_flow.py:72
- Remove this comment because it only narrates the immediately following test setup and assertions.
# Second attempt: connection succeeds — entry should be created.
homeassistant/components/intellidwell/quality_scale.yaml:9
- Deduplicate the shared entity/device setup before marking
common-modulescomplete. The sameDeviceInfoconstruction is repeated in both switch classes and the number class, so model or URL changes can easily drift; place it on the coordinator or a shared entity base instead.
common-modules: done
homeassistant/components/intellidwell/quality_scale.yaml:75
- Mark icon translations as incomplete until the entity icons are moved to
icons.json. The number and schedule switch still set_attr_icondirectly, so this Gold rule is not currently implemented.
icon-translations: done
homeassistant/components/intellidwell/switch.py:151
- Add coverage for mapping-shaped schedule data or remove this unsupported branch. Every schedule fixture currently returns a list, leaving the alternate key lookup and enabled-state behavior unverified despite
test-coveragebeing marked complete.
elif isinstance(schedules, dict):
zone_info = schedules.get(str(self.zone_index)) or schedules.get(
self.zone_index
)
if isinstance(zone_info, dict):
tests/components/intellidwell/test_number.py:124
- Update the docstring to name the exception this test actually verifies.
ServiceValidationErrorinherits fromHomeAssistantError, notValueError, so the current description is inaccurate.
"""Test ValueError raised when setting float value for rain delay."""
tests/components/intellidwell/test_config_flow.py:58
- Remove this comment because it only narrates the immediately following test setup and assertions.
This issue also appears on line 72 of the same file.
# First attempt: connection fails — form should re-display with an error.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (9)
tests/components/intellidwell/test_config_flow.py:72
- Remove this narrating comment; the mock and following assertions already make the successful retry explicit.
# Second attempt: connection succeeds — entry should be created.
homeassistant/components/intellidwell/coordinator.py:54
- Move response normalization into the
tryblock so malformed payloads are converted toUpdateFailed. The assignments in thiselserun after the exception handlers, so the listedTypeError/KeyErrorhandling cannot catch failures they raise; an invalid payload instead reaches the coordinator's generic handler and emits an unexpected traceback on every poll.
else:
status_data["rain_delay"] = rain_delay_data.get("days_remaining", 0)
status_data["schedules"] = schedules_data
return status_data
homeassistant/components/intellidwell/switch.py:153
- Report an absent schedule as disabled or unknown instead of enabled. Empty and short schedule responses are accepted during setup (and are used by the new tests), but these defaults make every missing schedule entity misleadingly appear on.
return True
homeassistant/components/intellidwell/quality_scale.yaml:9
- Move the shared entity/device setup into a common module or mark this rule
todo. The identicalDeviceInfoconstruction is currently repeated innumber.py:58-64and twice inswitch.py:64-70,128-134, so the Bronzecommon-modulesrule is not yet satisfied.
common-modules: done
tests/components/intellidwell/test_config_flow.py:58
- Remove this narrating comment; the mock and following assertions already make the failed first attempt explicit.
This issue also appears on line 72 of the same file.
# First attempt: connection fails — form should re-display with an error.
tests/components/intellidwell/test_switch.py:220
- Parameterize this case with
test_turn_on_connection_error; the two tests duplicate setup, patching, service invocation, and assertions while varying only the service and expected message.
async def test_turn_off_connection_error(hass: HomeAssistant) -> None:
"""Test that turn_off raises HomeAssistantError on IntelliDwellConnectionError."""
homeassistant/components/intellidwell/quality_scale.yaml:38
- Mark this rule
todo(or verify it asdone) instead of exempting it. The integration exposes standard number and switch actions innumber.py:73andswitch.py:82,94,156,168; the action-exceptions rule applies to standard entity actions, not only custom services.
action-exceptions:
status: exempt
comment: |
Integration does not provide custom services.
homeassistant/components/intellidwell/quality_scale.yaml:71
- Mark this rule
todoor addNumberDeviceClass.DURATIONto the rain-delay entity. The entity represents a duration in days but currently declares only a raw unit (number.py:46), unlike duration numbers such asrenson/number.py:32-33.
entity-device-class: done
homeassistant/components/intellidwell/quality_scale.yaml:75
- Mark this rule
todoor move the hard-coded entity icons intoicons.json. No icon translation file is added, while both platforms set_attr_icondirectly (number.py:41andswitch.py:113), so the claimed rule is not implemented.
icon-translations: done
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (4)
homeassistant/components/intellidwell/manifest.json:2
- Correct the PR description to classify this solely as a new integration and fill in the Proposed change section. It currently selects both Dependency upgrade and New integration even though this manifest introduces a new domain and its initial requirement; the PR template requires exactly one type.
"domain": "intellidwell",
homeassistant/components/intellidwell/quality_scale.yaml:72
- Move the hard-coded entity icons to
icons.json, or leave this rule as todo. Both platforms assign_attr_iconin Python and this integration has no icon translation file, soicon-translationsis not implemented.
icon-translations: done
homeassistant/components/intellidwell/switch.py:153
- Do not report a missing schedule entry as enabled. The platform always creates ten switches, while valid update data can contain fewer schedule records (including the empty and two-item responses used by these tests), so zones absent from the payload currently appear
onand can trigger automations incorrectly; expose them as unavailable/off or only create backed entities.
return True
homeassistant/components/intellidwell/quality_scale.yaml:9
- Move the shared entity setup into a common entity module before marking this Bronze rule done. The identical
DeviceInfoand entity-name setup is repeated in both platforms and twice inswitch.py, whereas the rule requires shared platform code to be centralized.
common-modules: done
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (6)
homeassistant/components/intellidwell/quality_scale.yaml:66
- Mark this rule exempt for a single-device integration rather than done; the integration always represents one controller and has no dynamically discovered devices to add.
dynamic-devices: done
homeassistant/components/intellidwell/quality_scale.yaml:75
- Mark this rule exempt for a single-device integration rather than done; a config entry cannot accumulate stale child devices, so there is no stale-device removal behavior here.
stale-devices: done
homeassistant/components/intellidwell/quality_scale.yaml:72
- Mark this rule
todoor move the custom icons intoicons.json; both entity platforms currently hard-code_attr_icon, so the integration does not implement icon translations.
icon-translations: done
tests/components/intellidwell/test_number.py:124
- Update the docstring to name the exception the test actually verifies; the implementation and assertion use
ServiceValidationError, notValueError.
"""Test ValueError raised when setting float value for rain delay."""
homeassistant/components/intellidwell/switch.py:132
- Centralize this repeated
DeviceInfo; the identical controller metadata is copied in both switch classes and the number entity, so a model, identifier, or URL change can leave entities attached to inconsistent devices. Comparable coordinator integrations expose shared device metadata once (for example,homeassistant/components/rainbird/coordinator.py:105-120).
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, config_entry.entry_id)},
name="IntelliDwell Sprinkler Controller",
manufacturer="IntelliDwell",
model="Sprinkler Controller V2",
homeassistant/components/intellidwell/switch.py:153
- Return an unknown state when schedule data is absent instead of reporting the schedule as enabled; a successful response can contain fewer entries (the added tests use both partial and empty schedule lists), so zones without a record currently appear
onwith no supporting device data.
return True
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (3)
homeassistant/components/intellidwell/coordinator.py:54
- Keep response normalization inside the protected block and handle invalid mappings there. As written, the
elseruns outside thetry, so a malformedstatus_dataorrain_delay_dataraises an uncaughtTypeError/AttributeErrorinstead ofUpdateFailed, bypassing coordinator availability handling.
except (ValueError, KeyError, TypeError) as err:
raise UpdateFailed(f"Invalid response from API: {err}") from err
else:
status_data["rain_delay"] = rain_delay_data.get("days_remaining", 0)
status_data["schedules"] = schedules_data
tests/components/intellidwell/test_number.py:124
- Update the docstring to name the exception the test actually verifies; this test expects
ServiceValidationError, notValueError.
"""Test ValueError raised when setting float value for rain delay."""
homeassistant/components/intellidwell/switch.py:152
- Add coverage for dictionary-shaped schedule payloads or remove this unsupported branch. The switch tests only exercise list payloads, so string/integer key lookup and enabled-state handling here can regress despite
test-coveragebeing marked done.
elif isinstance(schedules, dict):
zone_info = schedules.get(str(self.zone_index)) or schedules.get(
self.zone_index
)
if isinstance(zone_info, dict):
return zone_info.get("enabled", True)
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (6)
homeassistant/components/intellidwell/manifest.json:10
- Select only “New integration” in the PR description. This requirement is newly introduced for the integration rather than upgraded from an existing version, while the template currently has both “Dependency upgrade” and “New integration” selected despite requiring exactly one type.
"requirements": ["pyintellidwell==1.0.0"]
homeassistant/components/intellidwell/coordinator.py:54
- Keep response processing inside the
tryblock. Theelsesuite is outside these handlers, so malformed status or rain-delay data can raiseTypeError/AttributeErrordirectly instead ofUpdateFailed, bypassing coordinator unavailable/retry handling.
else:
status_data["rain_delay"] = rain_delay_data.get("days_remaining", 0)
status_data["schedules"] = schedules_data
homeassistant/components/intellidwell/quality_scale.yaml:9
- Introduce a shared IntelliDwell entity base before marking this rule done.
switch.pycontains the sameDeviceInfoblock twice andnumber.pyrepeats it again; the Bronzecommon-modulesrule requires this cross-platform entity logic to be centralized (for example inentity.py).
common-modules: done
homeassistant/components/intellidwell/quality_scale.yaml:72
- Mark this rule
todoor move the entity icons intoicons.json.number.py:42andswitch.py:113hard-code MDI icons, soicon-translations: doneis currently inaccurate.
icon-translations: done
homeassistant/components/intellidwell/manifest.json:3
- Fill in the PR’s “Proposed change” section with a description of this integration. The section is currently empty, so the required PR template does not describe the new domain or its purpose.
This issue also appears on line 10 of the same file.
"domain": "intellidwell",
"name": "IntelliDwell Sprinkler Controller",
tests/components/intellidwell/test_switch.py:220
- Parameterize the relay connection-error cases instead of duplicating the test body. This test and
test_turn_on_connection_errordiffer only by service name and expected message, so keeping separate copies makes future action-test changes easy to apply inconsistently.
async def test_turn_off_connection_error(hass: HomeAssistant) -> None:
"""Test that turn_off raises HomeAssistantError on IntelliDwellConnectionError."""
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (3)
homeassistant/components/intellidwell/quality_scale.yaml:9
- Move the shared entity/device setup into a common entity module before marking this rule done.
DeviceInfoconstruction is duplicated innumber.py:59-65andswitch.py:64-70,128-134, so this Bronze rule is not currently satisfied and the copies can drift.
common-modules: done
homeassistant/components/intellidwell/quality_scale.yaml:26
- Mark this rule exempt because these polling entities do not explicitly subscribe to events. Coordinator-based integrations with the same behavior use an exemption, for example
homewizard/quality_scale.yaml:26-29andairgradient/quality_scale.yaml:26-29;doneinaccurately claims an event-subscription implementation.
entity-event-setup: done
homeassistant/components/intellidwell/coordinator.py:54
- Keep response assembly inside its own guarded block so malformed payloads are converted to
UpdateFailed. Exceptions from these lines occur in theelseblock after the handlers have finished; for example, a non-mapping rain-delay response raisesAttributeErrorand is logged as an unexpected coordinator error instead of the intended invalid-response failure.
else:
status_data["rain_delay"] = rain_delay_data.get("days_remaining", 0)
status_data["schedules"] = schedules_data
return status_data
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (8)
homeassistant/components/intellidwell/quality_scale.yaml:75
- Mark stale-device removal exempt for this single-controller integration. Since the integration never discovers child devices, it has no stale devices to remove;
homeassistant/components/peblar/quality_scale.yaml:77-80uses this exemption for the same topology.
stale-devices: done
homeassistant/components/intellidwell/quality_scale.yaml:66
- Mark dynamic device handling exempt for this single, statically configured controller. No runtime device discovery is implemented;
homeassistant/components/peblar/quality_scale.yaml:62-65establishes the exemption used for this case.
dynamic-devices: done
homeassistant/components/intellidwell/config_flow.py:63
- Normalize the host before duplicate detection and storage. DNS hostnames are case-insensitive, so entries such as
Controller.localandcontroller.localcurrently bypass_async_abort_entries_matchand create duplicate polling entities for the same controller.
host = user_input[CONF_HOST]
self._async_abort_entries_match({CONF_HOST: host})
homeassistant/components/intellidwell/quality_scale.yaml:35
- Wrap invalid-response failures from every setter in
HomeAssistantError. The coordinator recognizesIntelliDwellInvalidResponseError, but the relay, schedule, and rain-delay actions catch only connection errors, so an invalid controller response escapes as a raw dependency exception and makes thisdoneclaim inaccurate.
This issue also appears in the following locations of the same file:
- line 66
- line 75
action-exceptions: done
homeassistant/components/intellidwell/quality_scale.yaml:26
- Mark this rule exempt because these polling entities do not subscribe to entity-specific events. This follows the established polling-integration pattern in
homeassistant/components/rainbird/quality_scale.yaml:27-29; claimingdoneimplies event setup/teardown behavior that is not implemented.
entity-event-setup: done
homeassistant/components/intellidwell/switch.py:152
- Add coverage for dictionary-shaped schedule responses. The separate string-key and integer-key lookup is new behavior, but every schedule fixture uses a list, so key/index regressions in this branch are undetected.
elif isinstance(schedules, dict):
zone_info = schedules.get(str(self.zone_index)) or schedules.get(
self.zone_index
)
if isinstance(zone_info, dict):
return zone_info.get("enabled", False)
homeassistant/components/intellidwell/manifest.json:10
- Correct the PR type to select only “New integration.” This requirement is being added for the new integration rather than upgraded from an existing version, while the PR description currently selects both “Dependency upgrade” and “New integration” despite the template allowing only one.
"requirements": ["pyintellidwell==1.0.0"]
homeassistant/components/intellidwell/switch.py:69
- Centralize the shared
DeviceInfoand reuse it from every entity. This identical block is repeated in both switch classes and the number class, so any model, identifier, or URL correction must stay synchronized across three places;homeassistant/components/rainbird/coordinator.py:105-120and its entities show the established shared-coordinator pattern.
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, config_entry.entry_id)},
name="IntelliDwell Sprinkler Controller",
manufacturer="IntelliDwell",
model="Sprinkler Controller V2",
configuration_url=f"http://{coordinator.client.host}",
… switch connection error tests, and mark icon-translations todo
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (4)
homeassistant/components/intellidwell/manifest.json:10
- Select only “New integration” in the PR’s Type of change section. Both “Dependency upgrade” and “New integration” are checked, but this line adds a new dependency rather than upgrading an existing one, and the PR template requires exactly one selection.
"requirements": ["pyintellidwell==1.0.0"]
homeassistant/components/intellidwell/manifest.json:3
- Fill in the PR’s Proposed change section with a concise description of this integration. That required template section is currently empty, so reviewers cannot verify the intended behavior and scope of the new integration represented by this manifest.
"domain": "intellidwell",
"name": "IntelliDwell Sprinkler Controller",
tests/components/intellidwell/conftest.py:1
- Add shared config-entry and API-mock fixtures here instead of repeating the setup blocks. The same
MockConfigEntryplus three client-method patches are copied acrosstest_switch.py,test_number.py, andtest_init.py, so a setup or response-shape change currently requires edits in at least six places.
"""Fixtures for IntelliDwell Sprinkler Controller tests."""
homeassistant/components/intellidwell/switch.py:152
- Cover or remove the dictionary schedule-response path. Every
get_schedulesmock returns a list, so this branch is never exercised even thoughtest-coverageis marked done; a regression in dictionary-key handling would therefore pass the integration tests.
elif isinstance(schedules, dict):
zone_info = schedules.get(str(self.zone_index)) or schedules.get(
self.zone_index
)
if isinstance(zone_info, dict):
return zone_info.get("enabled", False)
Breaking change
Proposed change
Type of change
Additional information
Checklist
ruff format homeassistant tests)If user exposed functionality or configuration variables are added/changed:
If the code communicates with devices, web services, or third-party tools:
Updated and included derived files by running:
python3 -m script.hassfest.requirements_all.txt.Updated by running
python3 -m script.gen_requirements_all.To help with the load of incoming pull requests: