mirror of
https://github.com/home-assistant/core.git
synced 2026-08-06 21:35:13 +01:00
Add pylint checker to check for using registries as fixture (#172455)
Co-authored-by: Markus Tuominen <3738613+Markus98@users.noreply.github.com>
This commit is contained in:
co-authored by
Markus Tuominen
parent
149fca4900
commit
8e7deee967
@@ -104,6 +104,7 @@ Every check has a code following the
|
||||
| `R7401` | [`home-assistant-consider-usefixtures-decorator`](#r7401-home-assistant-consider-usefixtures-decorator) | Use `@pytest.mark.usefixtures` for unused fixtures |
|
||||
| `R7402` | [`home-assistant-unused-test-fixture-argument`](#r7402-home-assistant-unused-test-fixture-argument) | Unused test function argument should use `@pytest.mark.usefixtures` |
|
||||
| `R7403` | [`home-assistant-tests-redundant-usefixtures`](#r7403-home-assistant-tests-redundant-usefixtures) | `@pytest.mark.usefixtures` redundant when `pytestmark` already applies it |
|
||||
| `R7404` | [`home-assistant-tests-registry-fixtures`](#r7404-home-assistant-tests-registry-fixtures) | Use the registry fixture instead of calling `<registry>.async_get(hass)` directly in tests |
|
||||
| `W7401` | [`home-assistant-deprecated-import`](#w7401-home-assistant-deprecated-import) | Import uses a deprecated path |
|
||||
| `W7402` | [`home-assistant-async-callback-decorator`](#w7402-home-assistant-async-callback-decorator) | Coroutine should not be decorated with `@callback` |
|
||||
| `W7403` | [`home-assistant-pytest-fixture-decorator`](#w7403-home-assistant-pytest-fixture-decorator) | Pytest fixture has invalid scope or autouse config |
|
||||
@@ -744,6 +745,34 @@ Drop the redundant `@pytest.mark.usefixtures` decorator; the fixture is
|
||||
already applied to every test in the module.
|
||||
|
||||
|
||||
## `home_assistant_tests_registry_fixtures` checker
|
||||
|
||||
Detects test functions and pytest fixtures that call a registry helper's
|
||||
`async_get(hass)` directly instead of using the registry fixtures defined
|
||||
in `tests/conftest.py` (`area_registry`, `category_registry`,
|
||||
`device_registry`, `entity_registry`, `floor_registry`, `issue_registry`,
|
||||
`label_registry`).
|
||||
|
||||
### `R7404`: `home-assistant-tests-registry-fixtures`
|
||||
|
||||
A `test_*` function or `@pytest.fixture`-decorated function calls
|
||||
`<registry>.async_get(hass)` directly (e.g. `er.async_get(hass)`) where
|
||||
`<registry>` resolves via a module-level
|
||||
`from homeassistant.helpers import ...` statement to one of the seven
|
||||
registry helper modules. Request the corresponding registry fixture as a
|
||||
test/fixture argument instead:
|
||||
|
||||
```python
|
||||
async def test_entities(hass: HomeAssistant, entity_registry: er.EntityRegistry) -> None:
|
||||
entry = entity_registry.async_get(entity_id)
|
||||
```
|
||||
|
||||
Only aliases imported from `homeassistant.helpers` are tracked. The
|
||||
checker is scoped to test modules; `conftest.py` files (where the
|
||||
fixtures themselves are defined) and `tests.helpers` (which exercises the
|
||||
registry helpers directly) are exempt.
|
||||
|
||||
|
||||
## `home_assistant_test_determinism` checker
|
||||
|
||||
`if` and `match` statements inside test functions create non-deterministic
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
"""Checker for direct registry ``async_get`` calls in tests.
|
||||
|
||||
Test functions and pytest fixtures should use the standard registry
|
||||
fixtures defined in ``tests/conftest.py``
|
||||
(``area_registry``, ``category_registry``, ``device_registry``,
|
||||
``entity_registry``, ``floor_registry``, ``issue_registry``,
|
||||
``label_registry``) instead of calling ``<registry>.async_get(hass)``
|
||||
directly.
|
||||
|
||||
This checker flags calls of the form ``<alias>.async_get(...)`` where
|
||||
``<alias>`` resolves (via a module-level ``from homeassistant.helpers
|
||||
import ...`` statement) to one of the seven registry helper modules,
|
||||
when the call is located inside a ``test_*`` function or a
|
||||
``@pytest.fixture``-decorated function.
|
||||
|
||||
Files literally named ``conftest.py`` are exempt — these are where the
|
||||
registry fixtures themselves are typically defined.
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from astroid import nodes
|
||||
from pylint.checkers import BaseChecker
|
||||
from pylint.lint import PyLinter
|
||||
|
||||
from pylint_home_assistant.helpers.module_info import is_test_module
|
||||
|
||||
_REGISTRY_HELPERS: frozenset[str] = frozenset(
|
||||
{
|
||||
"area_registry",
|
||||
"category_registry",
|
||||
"device_registry",
|
||||
"entity_registry",
|
||||
"floor_registry",
|
||||
"issue_registry",
|
||||
"label_registry",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def _build_alias_map(module: nodes.Module) -> dict[str, str]:
|
||||
"""Map module-level alias -> registry helper module name.
|
||||
|
||||
Walks top-level ``from homeassistant.helpers import ...`` statements
|
||||
and records each imported registry helper, keyed by its alias (or
|
||||
its own name when no alias is provided).
|
||||
"""
|
||||
alias_map: dict[str, str] = {}
|
||||
for node in module.body:
|
||||
if not isinstance(node, nodes.ImportFrom):
|
||||
continue
|
||||
if node.modname != "homeassistant.helpers":
|
||||
continue
|
||||
for name, asname in node.names:
|
||||
if name not in _REGISTRY_HELPERS:
|
||||
continue
|
||||
alias_map[asname or name] = name
|
||||
return alias_map
|
||||
|
||||
|
||||
def _binds_to_import(name_node: nodes.Name) -> bool:
|
||||
"""Return True when *name_node* resolves to a module-level import.
|
||||
|
||||
Uses Astroid scope lookup to find the binding for the name at the call
|
||||
site. Returns True only when every binding is an ``ImportFrom`` (i.e.
|
||||
the name was not shadowed by a parameter, assignment, or other local
|
||||
definition such as a fixture instance).
|
||||
"""
|
||||
try:
|
||||
_, assignments = name_node.lookup(name_node.name)
|
||||
except Exception: # noqa: BLE001 - defensive: lookup can raise on odd ASTs
|
||||
return False
|
||||
if not assignments:
|
||||
return False
|
||||
return all(isinstance(assignment, nodes.ImportFrom) for assignment in assignments)
|
||||
|
||||
|
||||
def _in_test_or_fixture(node: nodes.NodeNG) -> bool:
|
||||
"""Return True when *node* executes inside a test or pytest fixture.
|
||||
|
||||
Walks the full ancestor chain so calls in nested helpers/callbacks
|
||||
defined inside a ``test_*`` function or a ``@pytest.fixture`` function
|
||||
are recognized, not just those in the nearest enclosing function.
|
||||
"""
|
||||
parent = node.parent
|
||||
while parent is not None and not isinstance(parent, nodes.Module):
|
||||
if isinstance(parent, (nodes.FunctionDef, nodes.AsyncFunctionDef)) and (
|
||||
parent.name.startswith("test_") or _is_pytest_fixture(parent)
|
||||
):
|
||||
return True
|
||||
parent = parent.parent
|
||||
return False
|
||||
|
||||
|
||||
def _is_pytest_fixture(
|
||||
func: nodes.FunctionDef | nodes.AsyncFunctionDef,
|
||||
) -> bool:
|
||||
"""Return True when *func* is decorated with ``@pytest.fixture``."""
|
||||
if not func.decorators:
|
||||
return False
|
||||
for decorator in func.decorators.nodes:
|
||||
# ``@pytest.fixture(...)`` — a Call whose func is an Attribute
|
||||
target = decorator.func if isinstance(decorator, nodes.Call) else decorator
|
||||
if not isinstance(target, nodes.Attribute):
|
||||
continue
|
||||
if target.attrname != "fixture":
|
||||
continue
|
||||
expr = target.expr
|
||||
if isinstance(expr, nodes.Name) and expr.name == "pytest":
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class RegistryFixturesChecker(BaseChecker):
|
||||
"""Checker that enforces use of registry fixtures in tests."""
|
||||
|
||||
name = "home_assistant_tests_registry_fixtures"
|
||||
priority = -1
|
||||
msgs = {
|
||||
"R7404": (
|
||||
"Use the '%s' fixture instead of calling '%s.async_get(...)' "
|
||||
"directly in tests",
|
||||
"home-assistant-tests-registry-fixtures",
|
||||
"Used when a test function or pytest fixture calls "
|
||||
"``<registry>.async_get(hass)`` directly instead of relying "
|
||||
"on the corresponding registry fixture defined in "
|
||||
"``tests/conftest.py``.",
|
||||
),
|
||||
}
|
||||
options = ()
|
||||
|
||||
_active: bool
|
||||
_alias_map: dict[str, str]
|
||||
|
||||
def visit_module(self, node: nodes.Module) -> None:
|
||||
"""Record module state and build the alias map."""
|
||||
self._active = False
|
||||
self._alias_map = {}
|
||||
if not is_test_module(node.name):
|
||||
return
|
||||
# ``tests.helpers`` tests cover the registry helpers themselves and
|
||||
# are expected to call ``async_get`` directly.
|
||||
if node.name == "tests.helpers" or node.name.startswith("tests.helpers."):
|
||||
return
|
||||
# Exempt ``conftest.py`` files entirely — registry fixtures live there.
|
||||
if node.file and Path(node.file).name == "conftest.py":
|
||||
return
|
||||
self._active = True
|
||||
self._alias_map = _build_alias_map(node)
|
||||
|
||||
def visit_call(self, node: nodes.Call) -> None:
|
||||
"""Flag direct registry ``async_get`` calls inside tests/fixtures."""
|
||||
if not self._active or not self._alias_map:
|
||||
return
|
||||
|
||||
func = node.func
|
||||
if not isinstance(func, nodes.Attribute):
|
||||
return
|
||||
if func.attrname != "async_get":
|
||||
return
|
||||
if not isinstance(func.expr, nodes.Name):
|
||||
return
|
||||
|
||||
helper = self._alias_map.get(func.expr.name)
|
||||
if helper is None:
|
||||
return
|
||||
|
||||
# The alias map only records the module-level spelling. A parameter
|
||||
# or local (e.g. the ``entity_registry`` fixture instance) can shadow
|
||||
# a non-aliased import, so confirm the name still binds to the
|
||||
# recorded ``from homeassistant.helpers import ...`` statement before
|
||||
# flagging.
|
||||
if not _binds_to_import(func.expr):
|
||||
return
|
||||
|
||||
if _in_test_or_fixture(node):
|
||||
self.add_message(
|
||||
"home-assistant-tests-registry-fixtures",
|
||||
node=node,
|
||||
args=(helper, helper),
|
||||
)
|
||||
|
||||
|
||||
def register(linter: PyLinter) -> None:
|
||||
"""Register the checker."""
|
||||
linter.register_checker(RegistryFixturesChecker(linter))
|
||||
@@ -188,7 +188,7 @@ async def test_uid_migrate_entry(
|
||||
mock_async_get_firmware_data: AsyncMock,
|
||||
) -> None:
|
||||
"""Test migrate entry unique id."""
|
||||
entity_registry = er.async_get(hass)
|
||||
entity_registry = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
MOCK_MAC = dr.format_mac("01:23:45:67:89:AB")
|
||||
MOCK_ID = "device_id_12345"
|
||||
|
||||
@@ -266,7 +266,7 @@ async def test_brand_migration_issue(hass: HomeAssistant) -> None:
|
||||
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
issue_reg = ir.async_get(hass)
|
||||
issue_reg = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
await hass.config_entries.async_remove(config_entry.entry_id)
|
||||
assert not issue_reg.async_get_issue(DOMAIN, "yale_brand_migration")
|
||||
|
||||
@@ -197,7 +197,7 @@ async def test_vehicle_name_update(
|
||||
"""Test device name updates in device registry when vehicle is renamed."""
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
device_registry = dr.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
device_entry = device_registry.async_get_device(identifiers={(DOMAIN, "12345")})
|
||||
assert device_entry is not None
|
||||
assert device_entry.name == "Test Vehicle"
|
||||
|
||||
@@ -42,7 +42,7 @@ async def test_unauthorized_triggers_reauth(
|
||||
await async_check_for_repair_issues(hass, mock_entry)
|
||||
|
||||
mock_reauth.assert_called_once_with(hass)
|
||||
assert len(ir.async_get(hass).issues) == 0
|
||||
assert len(ir.async_get(hass).issues) == 0 # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@@ -65,7 +65,7 @@ async def test_repair_issue_creation(
|
||||
await async_check_for_repair_issues(hass, mock_entry)
|
||||
|
||||
mock_reauth.assert_not_called()
|
||||
assert len(ir.async_get(hass).issues) == expected_issues
|
||||
assert len(ir.async_get(hass).issues) == expected_issues # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
|
||||
async def test_async_create_fix_flow(hass: HomeAssistant) -> None:
|
||||
|
||||
@@ -982,7 +982,7 @@ async def test_create_backup_success_clears_issue(
|
||||
|
||||
await hass.async_block_till_done()
|
||||
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert set(issue_registry.issues) == issues_after_create_backup
|
||||
|
||||
|
||||
@@ -1344,7 +1344,7 @@ async def test_create_backup_failure_raises_issue(
|
||||
assert result["success"] == create_backup_result
|
||||
await hass.async_block_till_done()
|
||||
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert set(issue_registry.issues) == set(issues_after_create_backup)
|
||||
for issue_id, issue_data in issues_after_create_backup.items():
|
||||
issue = issue_registry.issues[issue_id]
|
||||
|
||||
@@ -1807,7 +1807,7 @@ async def test_repair_issue_created_for_degraded_scanner_in_docker(
|
||||
manager.on_scanner_start(scanner)
|
||||
|
||||
issue_id = f"bluetooth_adapter_missing_permissions_{scanner.source}"
|
||||
registry = ir.async_get(hass)
|
||||
registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
issue = registry.async_get_issue(bluetooth.DOMAIN, issue_id)
|
||||
assert issue is not None
|
||||
assert issue.severity == ir.IssueSeverity.WARNING
|
||||
@@ -1824,7 +1824,7 @@ async def test_repair_issue_deleted_when_scanner_not_degraded(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
manager = _get_manager()
|
||||
registry = ir.async_get(hass)
|
||||
registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
scanner = HaScanner(
|
||||
mode=BluetoothScanningMode.ACTIVE,
|
||||
@@ -1900,7 +1900,7 @@ async def test_no_repair_issue_when_not_docker(
|
||||
manager.on_scanner_start(scanner)
|
||||
|
||||
issue_id = f"bluetooth_adapter_missing_permissions_{scanner.source}"
|
||||
registry = ir.async_get(hass)
|
||||
registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert registry.async_get_issue(bluetooth.DOMAIN, issue_id) is None
|
||||
|
||||
|
||||
@@ -1926,7 +1926,7 @@ async def test_no_repair_issue_for_remote_scanner(
|
||||
):
|
||||
manager.on_scanner_start(scanner)
|
||||
|
||||
registry = ir.async_get(hass)
|
||||
registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
issues = [
|
||||
issue
|
||||
for issue in registry.issues.values()
|
||||
@@ -1963,7 +1963,7 @@ async def test_repair_issue_created_for_passive_mode_fallback(
|
||||
|
||||
# Check repair issue is created
|
||||
issue_id = f"bluetooth_adapter_passive_mode_{scanner.source}"
|
||||
registry = ir.async_get(hass)
|
||||
registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
issue = registry.async_get_issue(bluetooth.DOMAIN, issue_id)
|
||||
assert issue is not None
|
||||
assert issue.severity == ir.IssueSeverity.WARNING
|
||||
@@ -2014,7 +2014,7 @@ async def test_repair_issue_created_for_passive_mode_fallback_uart(
|
||||
|
||||
# Check repair issue is created with UART-specific translation key
|
||||
issue_id = f"bluetooth_adapter_passive_mode_{scanner.source}"
|
||||
registry = ir.async_get(hass)
|
||||
registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
issue = registry.async_get_issue(bluetooth.DOMAIN, issue_id)
|
||||
assert issue is not None
|
||||
assert issue.severity == ir.IssueSeverity.WARNING
|
||||
@@ -2051,7 +2051,7 @@ async def test_repair_issue_deleted_when_passive_mode_resolved(
|
||||
|
||||
# Check repair issue is created
|
||||
issue_id = f"bluetooth_adapter_passive_mode_{scanner.source}"
|
||||
registry = ir.async_get(hass)
|
||||
registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
issue = registry.async_get_issue(bluetooth.DOMAIN, issue_id)
|
||||
assert issue is not None
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ async def test_setup_multiple_systems_zones(
|
||||
assert state.attributes["current_temperature"] == zone
|
||||
|
||||
# Check that the created devices are wired to each other as expected.
|
||||
device_registry = dr.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
def find_device(name):
|
||||
return next(filter(lambda x: x.name == name, device_registry.devices.values()))
|
||||
|
||||
@@ -24,7 +24,7 @@ async def test_async_setup_and_unload_entry(
|
||||
assert mock_config_entry.state is ConfigEntryState.LOADED
|
||||
assert mock_config_entry.runtime_data is not None
|
||||
|
||||
entity_reg = er.async_get(hass)
|
||||
entity_reg = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
entities = [
|
||||
e
|
||||
for e in entity_reg.entities.values()
|
||||
|
||||
@@ -178,7 +178,7 @@ async def test_set_temperature(
|
||||
# Put areas on different floors:
|
||||
# first floor => living room and office
|
||||
# upstairs => bedroom
|
||||
floor_registry = fr.async_get(hass)
|
||||
floor_registry = fr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
first_floor = floor_registry.async_create("First floor")
|
||||
living_room_area = area_registry.async_update(
|
||||
living_room_area.id, floor_id=first_floor.floor_id
|
||||
|
||||
@@ -36,7 +36,7 @@ async def test_registry_cleanup(
|
||||
) -> None:
|
||||
"""Test being able to remove a disconnected device."""
|
||||
entry_id = load_int.entry_id
|
||||
device_registry = dr.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
live_id = "L1.100"
|
||||
dead_id = "L2.200"
|
||||
|
||||
|
||||
@@ -1814,8 +1814,8 @@ async def test_device_automation_resolves_legacy_id(
|
||||
await dr.async_load(hass)
|
||||
await er.async_load(hass)
|
||||
await ar.async_load(hass)
|
||||
device_registry = dr.async_get(hass)
|
||||
entity_registry = er.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
entity_registry = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
by_entry = {
|
||||
d.config_entry_id: d.id
|
||||
for d in device_registry.async_get_devices_for_composite_device_id(COMPOSITE_ID)
|
||||
|
||||
@@ -24,7 +24,7 @@ async def test_change_schedule_fails(
|
||||
favorites_side_effect=mock_not_found_exception()
|
||||
)
|
||||
assert doorbird_entry.entry.state is ConfigEntryState.SETUP_RETRY
|
||||
issue_reg = ir.async_get(hass)
|
||||
issue_reg = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert len(issue_reg.issues) == 1
|
||||
issue = list(issue_reg.issues.values())[0]
|
||||
issue_id = issue.issue_id
|
||||
|
||||
@@ -463,7 +463,7 @@ async def test_remote_sensor_devices(
|
||||
freezer.tick(100)
|
||||
async_fire_time_changed(hass)
|
||||
state = hass.states.get(ENTITY_ID)
|
||||
device_registry = dr.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
for device in device_registry.devices.values():
|
||||
if device.name == "Remote Sensor 1":
|
||||
remote_sensor_1_id = device.id
|
||||
@@ -551,7 +551,7 @@ async def test_remote_sensors_ignore_non_ecobee_devices(hass: HomeAssistant) ->
|
||||
an ecobee sensor's name was wrongly reported as a participating sensor.
|
||||
"""
|
||||
await setup_platform(hass, [const.Platform.CLIMATE, const.Platform.SENSOR])
|
||||
device_registry = dr.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
# A device from another integration that shares the ecobee sensor's name.
|
||||
other_entry = MockConfigEntry(domain="other")
|
||||
@@ -581,7 +581,7 @@ async def test_set_sensors_used_in_climate(hass: HomeAssistant) -> None:
|
||||
"""Test set sensors used in climate."""
|
||||
# Get device_id of remote sensor from the device registry.
|
||||
await setup_platform(hass, [const.Platform.CLIMATE, const.Platform.SENSOR])
|
||||
device_registry = dr.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
for device in device_registry.devices.values():
|
||||
if device.name == "Remote Sensor 1":
|
||||
remote_sensor_1_id = device.id
|
||||
|
||||
@@ -390,7 +390,7 @@ async def test_raise_segment_changed_issue(
|
||||
|
||||
entity_entry = entity_registry.async_get(entity_id)
|
||||
issue_id = f"{vacuum.ISSUE_SEGMENTS_CHANGED}_{entity_entry.id}"
|
||||
issue = ir.async_get(hass).async_get_issue(vacuum.DOMAIN, issue_id)
|
||||
issue = ir.async_get(hass).async_get_issue(vacuum.DOMAIN, issue_id) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert issue is not None
|
||||
|
||||
|
||||
|
||||
@@ -707,7 +707,7 @@ async def test_entity_assignment_to_sub_device(
|
||||
mock_esphome_device: MockESPHomeDeviceType,
|
||||
) -> None:
|
||||
"""Test entities are assigned to correct sub devices."""
|
||||
device_registry = dr.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
# Define sub devices
|
||||
sub_devices = [
|
||||
|
||||
@@ -1920,7 +1920,7 @@ async def test_device_adds_friendly_name(
|
||||
device_info={"name": "nofriendlyname", "friendly_name": ""},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
dev_reg = dr.async_get(hass)
|
||||
dev_reg = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
dev = dev_reg.async_get_device(
|
||||
connections={(dr.CONNECTION_NETWORK_MAC, device.entry.unique_id)}
|
||||
)
|
||||
@@ -2006,7 +2006,7 @@ async def test_sub_device_creation(
|
||||
mock_esphome_device: MockESPHomeDeviceType,
|
||||
) -> None:
|
||||
"""Test sub devices are created in device registry."""
|
||||
device_registry = dr.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
# Define areas
|
||||
areas = [
|
||||
@@ -2076,7 +2076,7 @@ async def test_sub_device_cleanup(
|
||||
mock_esphome_device: MockESPHomeDeviceType,
|
||||
) -> None:
|
||||
"""Test sub devices are removed when they no longer exist."""
|
||||
device_registry = dr.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
# Initial sub devices
|
||||
sub_devices_initial = [
|
||||
@@ -2167,7 +2167,7 @@ async def test_sub_device_with_empty_name(
|
||||
mock_esphome_device: MockESPHomeDeviceType,
|
||||
) -> None:
|
||||
"""Test sub devices with empty names are handled correctly."""
|
||||
device_registry = dr.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
# Define sub devices with empty names
|
||||
sub_devices = [
|
||||
@@ -2211,7 +2211,7 @@ async def test_sub_device_references_main_device_area(
|
||||
mock_esphome_device: MockESPHomeDeviceType,
|
||||
) -> None:
|
||||
"""Test sub devices can reference the main device's area."""
|
||||
device_registry = dr.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
# Define areas - note we don't include area_id=0 in the areas list
|
||||
areas = [
|
||||
|
||||
@@ -115,7 +115,7 @@ async def test_last_alarm_pic_sensor_not_created(
|
||||
assert last_alarm_pic_state is None
|
||||
|
||||
# But other sensors should be created
|
||||
registry = er.async_get(hass)
|
||||
registry = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
battery_entity = registry.async_get("sensor.camera_1_battery")
|
||||
assert battery_entity is not None
|
||||
|
||||
|
||||
@@ -283,7 +283,7 @@ async def test_cleanup_button_deprecation_issue(
|
||||
await hass.async_block_till_done()
|
||||
assert entry.state is ConfigEntryState.LOADED
|
||||
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert issue_registry.async_get_issue(DOMAIN, "deprecated_cleanup_button")
|
||||
|
||||
|
||||
@@ -303,5 +303,5 @@ async def test_firmware_update_button_deprecation_issue(
|
||||
await hass.async_block_till_done()
|
||||
assert entry.state is ConfigEntryState.LOADED
|
||||
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert issue_registry.async_get_issue(DOMAIN, "deprecated_firmware_update_button")
|
||||
|
||||
@@ -29,7 +29,7 @@ async def test_get_forecast_service(
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test fetching a forecast for a subentry."""
|
||||
device = dr.async_get(hass).async_get_device(
|
||||
device = dr.async_get(hass).async_get_device( # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
identifiers={(DOMAIN, f"{mock_config_entry.entry_id}_home-subentry-id")}
|
||||
)
|
||||
assert device is not None
|
||||
|
||||
@@ -869,7 +869,7 @@ async def test_dynamic_device_added(
|
||||
# Verify multiple entity types to confirm end-to-end dynamic device support
|
||||
assert hass.states.get("switch.new456789_charge_from_grid") is not None
|
||||
# Additional check: verify entities exist in the entity registry
|
||||
entity_registry = er.async_get(hass)
|
||||
entity_registry = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
new_device_entry = device_registry.async_get_device(
|
||||
identifiers={(DOMAIN, "NEW456789")}
|
||||
)
|
||||
|
||||
@@ -72,7 +72,7 @@ async def test_unique_id_migration(
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
ent_reg = er.async_get(hass)
|
||||
ent_reg = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
switch_tv = ent_reg.async_get(ENTITY_WATCH_TV)
|
||||
assert switch_tv.unique_id == f"activity_{WATCH_TV_ACTIVITY_ID}"
|
||||
|
||||
@@ -1146,7 +1146,7 @@ async def test_reader_writer_create_addon_folder_error(
|
||||
),
|
||||
]
|
||||
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert not issue_registry.issues
|
||||
|
||||
await client.send_json_auto_id({"type": "backup/subscribe_events"})
|
||||
|
||||
@@ -875,7 +875,7 @@ async def test_partial_backup_legacy_homeassistant_folder(
|
||||
folders={Folder.SSL},
|
||||
)
|
||||
)
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert (
|
||||
issue_registry.async_get_issue("hassio", "legacy_homeassistant_folder")
|
||||
is not None
|
||||
|
||||
@@ -71,7 +71,7 @@ async def test_device_diagnostics(
|
||||
"""Test generating diagnostics for a config entry."""
|
||||
config_entry.add_to_hass(hass)
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
device_registry = dr.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
device = device_registry.async_get_device({(DOMAIN, "1")})
|
||||
assert device is not None
|
||||
diagnostics = await get_diagnostics_for_device(
|
||||
|
||||
@@ -204,7 +204,7 @@ async def test_switch_restore_state(
|
||||
]
|
||||
|
||||
# Verify entity registry attributes
|
||||
entity_registry = er.async_get(hass)
|
||||
entity_registry = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
entity_entry = entity_registry.async_get(TEST_SWITCH_ENTITY_ID)
|
||||
assert entity_entry is not None
|
||||
assert entity_entry.entity_category == EntityCategory.CONFIG
|
||||
|
||||
@@ -261,7 +261,7 @@ async def test_ble_device_populates_connections(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert config_entry.state is ConfigEntryState.LOADED
|
||||
dev_reg = dr.async_get(hass)
|
||||
dev_reg = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert (
|
||||
dev_reg.async_get_device(
|
||||
identifiers={}, connections={("bluetooth", "AA:BB:CC:DD:EE:FF")}
|
||||
|
||||
@@ -930,7 +930,7 @@ async def test_hmip_smoke_detector_dirt_level(
|
||||
device_model = "HmIP-SWSD"
|
||||
|
||||
# Pre-register the entity as enabled before platform loads
|
||||
entity_registry = er.async_get(hass)
|
||||
entity_registry = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
entity_registry.async_get_or_create(
|
||||
"sensor",
|
||||
DOMAIN,
|
||||
|
||||
@@ -142,7 +142,7 @@ async def test_load_creates_repair_issue(
|
||||
|
||||
await hass.async_block_till_done()
|
||||
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
issue = issue_registry.async_get_issue(
|
||||
domain=DOMAIN, issue_id=f"migrate_to_v2_api_{mock_config_entry.entry_id}"
|
||||
@@ -168,7 +168,7 @@ async def test_load_creates_repair_issue_when_name_is_updated(
|
||||
|
||||
await hass.async_block_till_done()
|
||||
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
issue_id = f"migrate_to_v2_api_{mock_config_entry.entry_id}"
|
||||
|
||||
issue = issue_registry.async_get_issue(domain=DOMAIN, issue_id=issue_id)
|
||||
@@ -178,7 +178,7 @@ async def test_load_creates_repair_issue_when_name_is_updated(
|
||||
assert issue.translation_placeholders["title"] == "Device"
|
||||
|
||||
# Update the device name
|
||||
device_registry = dr.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
device = get_main_device(hass, mock_config_entry)
|
||||
|
||||
# Update device name
|
||||
@@ -318,9 +318,9 @@ async def test_battery_cloud_issue_stale_issue_cleared_on_reload(
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert ir.async_get(hass).async_get_issue(DOMAIN, issue_id) is not None
|
||||
assert ir.async_get(hass).async_get_issue(DOMAIN, issue_id) is not None # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
combined_data.system.cloud_enabled = True
|
||||
await hass.config_entries.async_reload(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
assert ir.async_get(hass).async_get_issue(DOMAIN, issue_id) is None
|
||||
assert ir.async_get(hass).async_get_issue(DOMAIN, issue_id) is None # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
@@ -46,7 +46,7 @@ async def test_device_manufacturer_uses_oem(
|
||||
with patch("homeassistant.components.hypontech._PLATFORMS", [Platform.SENSOR]):
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
device_registry = dr.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
overview_device = device_registry.async_get_device(
|
||||
identifiers={(DOMAIN, mock_config_entry.unique_id)}
|
||||
)
|
||||
|
||||
@@ -58,7 +58,7 @@ async def test_setup_ignores_unknown_button_types(
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Unknown button keys from the API are not turned into entities."""
|
||||
registry = er.async_get(hass)
|
||||
registry = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
entries = er.async_entries_for_config_entry(registry, mock_config_entry.entry_id)
|
||||
assert len(entries) == 1
|
||||
assert entries[0].translation_key == PARAM_MUTE
|
||||
|
||||
@@ -96,7 +96,7 @@ async def test_no_camera_without_channel(
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Devices without a channel do not get a camera entity."""
|
||||
registry = er.async_get(hass)
|
||||
registry = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
entries = er.async_entries_for_config_entry(registry, mock_config_entry.entry_id)
|
||||
assert not any(entry.domain == "camera" for entry in entries)
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ async def test_device_registry_identifiers(
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Device registry uses channel-aware identifiers from the default mock devices."""
|
||||
registry = dr.async_get(hass)
|
||||
registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
devices = dr.async_entries_for_config_entry(registry, mock_config_entry.entry_id)
|
||||
assert len(devices) == 1
|
||||
assert (DOMAIN, "d1") in devices[0].identifiers
|
||||
|
||||
@@ -85,7 +85,7 @@ async def test_setup_ignores_unknown_switch_types(
|
||||
mock_config_entry: MockConfigEntry,
|
||||
) -> None:
|
||||
"""Unknown switch keys from the API are not turned into entities."""
|
||||
registry = er.async_get(hass)
|
||||
registry = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
entries = er.async_entries_for_config_entry(registry, mock_config_entry.entry_id)
|
||||
switch_entries = [entry for entry in entries if entry.domain == SWITCH_DOMAIN]
|
||||
assert len(switch_entries) == 1
|
||||
|
||||
@@ -151,8 +151,8 @@ async def test_setup_and_remove_config_entry(
|
||||
async def test_entry_changed(hass: HomeAssistant, platform) -> None:
|
||||
"""Test reconfiguring."""
|
||||
|
||||
device_registry = dr.async_get(hass)
|
||||
entity_registry = er.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
entity_registry = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
def _create_mock_entity(domain: str, name: str) -> er.RegistryEntry:
|
||||
config_entry = MockConfigEntry(
|
||||
|
||||
@@ -183,7 +183,7 @@ async def test_get_temperature(
|
||||
# first floor => living room and office
|
||||
# 2nd floor => bedroom
|
||||
# 3rd floor => attic
|
||||
floor_registry = fr.async_get(hass)
|
||||
floor_registry = fr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
first_floor = floor_registry.async_create("First floor")
|
||||
living_room_area = area_registry.async_update(
|
||||
living_room_area.id, floor_id=first_floor.floor_id
|
||||
|
||||
@@ -59,13 +59,13 @@ async def test_sensor_device_info(
|
||||
hass: HomeAssistant, init_integration: MockConfigEntry
|
||||
) -> None:
|
||||
"""Test sensor has correct device info."""
|
||||
entity_registry = er.async_get(hass)
|
||||
entity_registry = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
entity = entity_registry.async_get("sensor.iss")
|
||||
|
||||
assert entity is not None
|
||||
assert entity.unique_id == f"{init_integration.entry_id}_people"
|
||||
|
||||
device_registry = dr.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
device = device_registry.async_get(entity.device_id)
|
||||
|
||||
assert device is not None
|
||||
|
||||
@@ -50,7 +50,7 @@ async def test_data_secure_group_key_issue_only_for_configured_group_address(
|
||||
}
|
||||
)
|
||||
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert bool(issue_registry.issues) is False
|
||||
# An issue should only be created if this address is configured.
|
||||
knx.receive_data_secure_issue("1/2/5")
|
||||
@@ -76,7 +76,7 @@ async def test_data_secure_group_key_issue_repair_flow(
|
||||
knx.receive_data_secure_issue("11/0/0", source="1.0.1")
|
||||
knx.receive_data_secure_issue("1/2/5", source="1.0.10")
|
||||
knx.receive_data_secure_issue("1/2/5", source="1.0.1")
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
issue = issue_registry.async_get_issue(DOMAIN, REPAIR_ISSUE_DATA_SECURE_GROUP_KEY)
|
||||
assert issue is not None
|
||||
assert issue.translation_placeholders == {
|
||||
|
||||
@@ -155,7 +155,7 @@ async def test_store_telegram_history_error_handling(
|
||||
assert telegrams_module.store is None
|
||||
|
||||
# Check that the repair issue was created
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
issue = issue_registry.async_get_issue(DOMAIN, REPAIR_ISSUE_TELEGRAM_BACKEND_ERROR)
|
||||
assert issue is not None
|
||||
|
||||
@@ -183,7 +183,7 @@ async def test_store_telegram_history_needs_migration_timeout(
|
||||
assert telegrams_module.store is None
|
||||
|
||||
# Check that the repair issue was created
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
issue = issue_registry.async_get_issue(DOMAIN, REPAIR_ISSUE_TELEGRAM_BACKEND_ERROR)
|
||||
assert issue is not None
|
||||
|
||||
@@ -546,7 +546,7 @@ async def test_postgres_backend_init_error(
|
||||
telegrams_module = hass.data[KNX_MODULE_KEY].telegrams
|
||||
assert telegrams_module.store is None
|
||||
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert (
|
||||
issue_registry.async_get_issue(DOMAIN, REPAIR_ISSUE_TELEGRAM_BACKEND_ERROR)
|
||||
is not None
|
||||
|
||||
@@ -22,7 +22,7 @@ async def test_migrate_entry(
|
||||
|
||||
mock_config_entry_v1.add_to_hass(hass)
|
||||
|
||||
dev_reg = dr.async_get(hass)
|
||||
dev_reg = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
# Create device registry entries for old integration
|
||||
dev_reg.async_get_or_create(
|
||||
config_entry_id=mock_config_entry_v1.entry_id,
|
||||
|
||||
@@ -232,7 +232,7 @@ async def test_gateway_version_issue(
|
||||
|
||||
await async_init_integration(hass, mock_config_entry)
|
||||
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
issue = issue_registry.async_get_issue(DOMAIN, "unsupported_gateway_firmware")
|
||||
assert (issue is not None) == issue_exists
|
||||
|
||||
|
||||
@@ -187,7 +187,7 @@ async def test_filter_sensor(
|
||||
) -> None:
|
||||
"""Test numeric sensors are filtered."""
|
||||
|
||||
registry = er.async_get(hass_)
|
||||
registry = er.async_get(hass_) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
# Unregistered sensor without a unit of measurement - should be in logbook
|
||||
entity_id1 = "sensor.bla"
|
||||
@@ -3225,7 +3225,7 @@ async def test_context_user_ids_lru_eviction(
|
||||
for_live_stream=True,
|
||||
)
|
||||
context_augmenter = logbook.processor.ContextAugmenter(logbook_run)
|
||||
ent_reg = er.async_get(hass)
|
||||
ent_reg = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
processor = logbook.processor.EventProcessor.__new__(
|
||||
logbook.processor.EventProcessor
|
||||
@@ -3353,7 +3353,7 @@ async def test_parent_user_attribution_does_not_use_origin_event_fallback(
|
||||
memoize_new_contexts=False,
|
||||
)
|
||||
context_augmenter = logbook.processor.ContextAugmenter(logbook_run)
|
||||
ent_reg = er.async_get(hass)
|
||||
ent_reg = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
processor = logbook.processor.EventProcessor.__new__(
|
||||
logbook.processor.EventProcessor
|
||||
|
||||
@@ -372,7 +372,7 @@ async def test_lovelace_from_yaml_creates_repair_issue(
|
||||
assert hass.data[frontend.DATA_PANELS]["lovelace"].config == {"mode": "yaml"}
|
||||
|
||||
# Repair issue should be created
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
issue = issue_registry.async_get_issue("lovelace", "yaml_mode_deprecated")
|
||||
assert issue is not None
|
||||
assert issue.severity == ir.IssueSeverity.WARNING
|
||||
|
||||
@@ -29,7 +29,7 @@ async def test_setup_entry(
|
||||
|
||||
# Verify that the unique ID is generated correctly.
|
||||
# This prevents regression in unique ID generation which would be a breaking change.
|
||||
entity_registry = er.async_get(hass)
|
||||
entity_registry = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
# The light from mock_lutron has uuid="light_uuid" and guid="12345678901"
|
||||
expected_unique_id = "12345678901_light_uuid"
|
||||
entry = entity_registry.async_get("light.test_area_test_light")
|
||||
@@ -81,8 +81,8 @@ async def test_unique_id_migration(
|
||||
|
||||
# Setup registries with an entry using the "legacy" unique ID format.
|
||||
# This simulates a user who had configured the integration in an older version.
|
||||
entity_registry = er.async_get(hass)
|
||||
device_registry = dr.async_get(hass)
|
||||
entity_registry = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
legacy_unique_id = "12345678901_light_legacy_uuid"
|
||||
new_unique_id = "12345678901_light_uuid"
|
||||
|
||||
@@ -506,7 +506,7 @@ async def test_vacuum_no_issue_on_transient_empty_segments(
|
||||
set_node_attribute(matter_node, 1, 336, 0, [])
|
||||
await trigger_subscription_callback(hass, matter_client)
|
||||
|
||||
issue_reg = ir.async_get(hass)
|
||||
issue_reg = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
issue = issue_reg.async_get_issue(
|
||||
VACUUM_DOMAIN, f"segments_changed_{entity_entry.id}"
|
||||
)
|
||||
@@ -542,7 +542,7 @@ async def test_vacuum_raise_segments_changed_issue(
|
||||
set_node_attribute(matter_node, 1, 97, 4, 0x02)
|
||||
await trigger_subscription_callback(hass, matter_client)
|
||||
|
||||
issue_reg = ir.async_get(hass)
|
||||
issue_reg = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
issue = issue_reg.async_get_issue(
|
||||
VACUUM_DOMAIN, f"segments_changed_{entity_entry.id}"
|
||||
)
|
||||
|
||||
@@ -2593,7 +2593,7 @@ async def test_mqtt_protocol_failed_migration_to_v5(
|
||||
assert len(events) == 1
|
||||
assert events[0].data["issue_id"] == "protocol_5_migration"
|
||||
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert len(issue_registry.issues) == 1
|
||||
issue = issue_registry.async_get_issue(DOMAIN, "protocol_5_migration")
|
||||
assert issue is not None
|
||||
|
||||
@@ -140,7 +140,7 @@ async def test_subentry_reconfigure_export_settings(
|
||||
# The subentry ID is used as device identifier
|
||||
assert len(events) == 1
|
||||
issue_id = events[0].data["issue_id"]
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
repair_issue = issue_registry.async_get_issue(DOMAIN, issue_id)
|
||||
assert repair_issue.translation_key == translation_key
|
||||
|
||||
|
||||
@@ -355,7 +355,7 @@ async def test_clean_segments_initial_setup_without_repair_issue(
|
||||
state.attributes.get(ATTR_SUPPORTED_FEATURES)
|
||||
& vacuum.VacuumEntityFeature.CLEAN_AREA
|
||||
)
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert len(issue_registry.issues) == 0
|
||||
|
||||
|
||||
@@ -405,7 +405,7 @@ async def test_clean_segments_command(
|
||||
& vacuum.VacuumEntityFeature.CLEAN_AREA
|
||||
)
|
||||
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
# We do not expect a repair flow as the segments did not change
|
||||
assert len(issue_registry.issues) == 0
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ async def test_authentication_required_triggers_reauth(
|
||||
|
||||
assert config_entry.state is ConfigEntryState.SETUP_ERROR
|
||||
|
||||
issue_reg = ir.async_get(hass)
|
||||
issue_reg = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
issue_id = f"config_entry_reauth_{DOMAIN}_{config_entry.entry_id}"
|
||||
assert issue_reg.async_get_issue("homeassistant", issue_id)
|
||||
|
||||
@@ -208,6 +208,6 @@ async def test_authentication_required_addon_no_reauth(
|
||||
|
||||
assert config_entry.state is ConfigEntryState.SETUP_ERROR
|
||||
|
||||
issue_reg = ir.async_get(hass)
|
||||
issue_reg = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
issue_id = f"config_entry_reauth_{DOMAIN}_{config_entry.entry_id}"
|
||||
assert issue_reg.async_get_issue("homeassistant", issue_id) is None
|
||||
|
||||
@@ -63,7 +63,8 @@ async def test_updating(
|
||||
|
||||
# Resolve the created scene entity dynamically
|
||||
entity_entries = er.async_entries_for_config_entry(
|
||||
er.async_get(hass), mock_config_entry.entry_id
|
||||
er.async_get(hass), # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
mock_config_entry.entry_id,
|
||||
)
|
||||
scene_entities = [e for e in entity_entries if e.domain == SCENE_DOMAIN]
|
||||
assert scene_entities, "No scene entities registered"
|
||||
|
||||
@@ -104,7 +104,7 @@ async def test_remove_device_valid(
|
||||
list_commands_return_value=[],
|
||||
)
|
||||
|
||||
device_registry = dr.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert device_registry is not None
|
||||
|
||||
device_entry = device_registry.async_get_device(
|
||||
@@ -137,7 +137,7 @@ async def test_remove_device_stale(
|
||||
list_commands_return_value=[],
|
||||
)
|
||||
|
||||
device_registry = dr.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert device_registry is not None
|
||||
|
||||
device_entry = device_registry.async_get_or_create(
|
||||
|
||||
@@ -221,7 +221,7 @@ async def test_data_cap_issues(
|
||||
|
||||
await setup_integration(hass, mock_config_entry)
|
||||
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
issue = issue_registry.async_get_issue(DOMAIN, issue_key)
|
||||
assert (issue is not None) == issue_exists
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ async def test_migrate_camera_entities_unique_ids(hass: HomeAssistant) -> None:
|
||||
config_entry = MockConfigEntry(domain=DOMAIN, unique_id=MAC)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
entity_registry = er.async_get(hass)
|
||||
entity_registry = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
entity_with_only_mac = entity_registry.async_get_or_create(
|
||||
domain="camera",
|
||||
|
||||
@@ -48,7 +48,7 @@ async def test_remove_config_entry_device_server(
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
device_registry = dr.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
server_device = device_registry.async_get_device(
|
||||
identifiers={(DOMAIN, mock_config_entry.entry_id)}
|
||||
)
|
||||
@@ -74,7 +74,7 @@ async def test_remove_config_entry_device_still_connected(
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
device_registry = dr.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
# Get a device that's in coordinator.data (still connected)
|
||||
devices = dr.async_entries_for_config_entry(
|
||||
|
||||
@@ -238,7 +238,7 @@ async def test_coordinator_migration(
|
||||
assert stats == snapshot
|
||||
|
||||
# Check that an issue was created
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
issue = issue_registry.async_get_issue(DOMAIN, "return_to_grid_migration_111111")
|
||||
assert issue is not None
|
||||
assert issue.severity == ir.IssueSeverity.WARNING
|
||||
@@ -412,7 +412,7 @@ async def test_coordinator_migration_empty_source_stats(
|
||||
# no individual stats were found
|
||||
assert migrated is False
|
||||
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
issue = issue_registry.async_get_issue(DOMAIN, "return_to_grid_migration_111111")
|
||||
assert issue is None
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ async def test_sensors(
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
entity_registry = er.async_get(hass)
|
||||
entity_registry = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
# Check electric sensors
|
||||
entry = entity_registry.async_get(
|
||||
|
||||
@@ -92,7 +92,7 @@ async def test_unique_id_migration(hass: HomeAssistant) -> None:
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
ent_reg = er.async_get(hass)
|
||||
ent_reg = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
unique_id_map = {
|
||||
ENTITY_SENSOR_DISCRETE_RSSI_LEVEL: "io://1234-5678-1234/3541212-core:DiscreteRSSILevelState",
|
||||
|
||||
@@ -585,7 +585,7 @@ class TestPicnicSensor(unittest.IsolatedAsyncioTestCase):
|
||||
# Setup platform and default mock responses
|
||||
await self._setup_platform(use_default_responses=True)
|
||||
|
||||
device_registry = dr.async_get(self.hass)
|
||||
device_registry = dr.async_get(self.hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
picnic_service = device_registry.async_get_device(
|
||||
identifiers={(const.DOMAIN, DEFAULT_USER_RESPONSE["user_id"])}
|
||||
)
|
||||
|
||||
@@ -143,8 +143,8 @@ async def test_migration_v1_to_v3(
|
||||
entry.add_to_hass(hass)
|
||||
assert entry.version == 1
|
||||
|
||||
device_registry = dr.async_get(hass)
|
||||
entity_registry = er.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
entity_registry = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
vm_device = device_registry.async_get_or_create(
|
||||
config_entry_id=entry.entry_id,
|
||||
|
||||
@@ -452,7 +452,7 @@ async def test_cloud_api_repair(
|
||||
await hass.config_entries.async_setup(mock_roborock_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert len(issue_registry.issues) == 1
|
||||
# Check that both expected device names are present, regardless of order
|
||||
assert all(
|
||||
@@ -495,7 +495,7 @@ async def test_cloud_api_repair_cleared_on_update(
|
||||
await hass.async_block_till_done()
|
||||
assert mock_roborock_entry.state is ConfigEntryState.LOADED
|
||||
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert len(issue_registry.issues) == 1
|
||||
|
||||
# Fake that the device is reachable locally again.
|
||||
@@ -513,7 +513,7 @@ async def test_cloud_api_repair_cleared_on_update(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Verify that the repair issue is cleared
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert len(issue_registry.issues) == 0
|
||||
|
||||
# Fake the device is cloud only again. Refreshing the coordinator
|
||||
@@ -529,7 +529,7 @@ async def test_cloud_api_repair_cleared_on_update(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Verify that the repair issue still does not exist
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert len(issue_registry.issues) == 0
|
||||
|
||||
|
||||
|
||||
@@ -588,7 +588,7 @@ async def test_segments_changed_issue(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
issue_id = f"segments_changed_{entity_entry.id}"
|
||||
issue = ir.async_get(hass).async_get_issue(VACUUM_DOMAIN, issue_id)
|
||||
issue = ir.async_get(hass).async_get_issue(VACUUM_DOMAIN, issue_id) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert issue is not None
|
||||
assert issue.severity == ir.IssueSeverity.WARNING
|
||||
assert issue.translation_key == "segments_changed"
|
||||
@@ -621,7 +621,7 @@ async def test_segments_changed_issue_no_map_info(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
issue_id = f"segments_changed_{entity_entry.id}"
|
||||
issue = ir.async_get(hass).async_get_issue(VACUUM_DOMAIN, issue_id)
|
||||
issue = ir.async_get(hass).async_get_issue(VACUUM_DOMAIN, issue_id) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert issue is None
|
||||
|
||||
|
||||
|
||||
@@ -6744,7 +6744,7 @@ async def test_clean_up_repairs(
|
||||
) -> None:
|
||||
"""Test cleaning up repairs."""
|
||||
await async_setup_component(hass, DOMAIN, {})
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
client = await hass_ws_client()
|
||||
|
||||
# Create some issues
|
||||
|
||||
@@ -126,7 +126,7 @@ async def test_unique_id_migration(hass: HomeAssistant, mock_asyncsleepiq) -> No
|
||||
assert await async_setup_component(hass, DOMAIN, {})
|
||||
await hass.async_block_till_done()
|
||||
|
||||
ent_reg = er.async_get(hass)
|
||||
ent_reg = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
sensor_is_in_bed = ent_reg.async_get(ENTITY_IS_IN_BED)
|
||||
assert sensor_is_in_bed.unique_id == f"{SLEEPER_L_ID}_{IS_IN_BED}"
|
||||
|
||||
@@ -115,7 +115,7 @@ async def test_upnp_disabled_discovery(
|
||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert (
|
||||
issue_registry.async_get_issue(
|
||||
sonos.DOMAIN, f"{UPNP_ISSUE_ID}_{soco.ip_address}"
|
||||
@@ -144,7 +144,7 @@ async def test_upnp_disabled_manual_hosts(
|
||||
):
|
||||
await _setup_hass(hass)
|
||||
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
issue = issue_registry.async_get_issue(
|
||||
sonos.DOMAIN, f"{UPNP_ISSUE_ID}_{soco.ip_address}"
|
||||
)
|
||||
|
||||
@@ -334,7 +334,7 @@ async def test_yaml_filter_only_no_deprecation_issue(
|
||||
assert len(entries) == 0
|
||||
|
||||
# Verify no deprecation issue was created
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
issues = issue_registry.issues
|
||||
assert not any(
|
||||
issue_id[0] == DOMAIN and "deprecated" in issue_id[1] for issue_id in issues
|
||||
@@ -370,7 +370,7 @@ async def test_yaml_with_connection_creates_deprecation_issue(
|
||||
assert entries[0].source == SOURCE_IMPORT
|
||||
|
||||
# Verify deprecation issue was created in homeassistant domain
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert (HOMEASSISTANT_DOMAIN, f"deprecated_yaml_{DOMAIN}") in issue_registry.issues
|
||||
|
||||
|
||||
@@ -400,7 +400,7 @@ async def test_yaml_import_error_creates_specific_issue(
|
||||
assert len(entries) == 0
|
||||
|
||||
# Verify error-specific issue was created
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert (
|
||||
DOMAIN,
|
||||
"deprecated_yaml_import_issue_cannot_connect",
|
||||
@@ -432,5 +432,5 @@ async def test_yaml_import_already_configured_creates_deprecation_issue(
|
||||
await hass.async_block_till_done()
|
||||
|
||||
# Verify deprecation issue was still created (single_instance_allowed is ok)
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert (HOMEASSISTANT_DOMAIN, f"deprecated_yaml_{DOMAIN}") in issue_registry.issues
|
||||
|
||||
@@ -501,7 +501,7 @@ async def test_dhcp_known_player(
|
||||
"""Test DHCP discovery aborts if player is already registered."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
entity_registry = er.async_get(hass)
|
||||
entity_registry = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
entity_registry.async_get_or_create(
|
||||
MP_DOMAIN, DOMAIN, "aa:bb:cc:dd:ee:ff", config_entry=mock_config_entry
|
||||
)
|
||||
|
||||
@@ -74,7 +74,7 @@ async def test_setup_g4(hass: HomeAssistant, subaru_config_entry) -> None:
|
||||
assert check_entry.state is ConfigEntryState.LOADED
|
||||
# Gen4 must receive both Gen2+ and Gen3+ sensor sets; without this, only
|
||||
# the odometer was created on 2026 model year vehicles.
|
||||
entity_registry = er.async_get(hass)
|
||||
entity_registry = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert entity_registry.async_get_entity_id(
|
||||
"sensor", DOMAIN, f"{TEST_VIN_4_G4}_AVG_FUEL_CONSUMPTION"
|
||||
)
|
||||
|
||||
@@ -399,7 +399,7 @@ async def test_hub_device_info_mac_connections(
|
||||
setup_dsm_with_usb: MagicMock,
|
||||
) -> None:
|
||||
"""Test that the hub DeviceInfo includes MAC address connections."""
|
||||
dev_reg = dr.async_get(hass)
|
||||
dev_reg = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
device = dev_reg.async_get_device(identifiers={(DOMAIN, SERIAL)})
|
||||
assert device is not None
|
||||
assert device.connections == {
|
||||
|
||||
@@ -41,7 +41,7 @@ def storage_setup_named_tag(
|
||||
}
|
||||
else:
|
||||
hass_storage[DOMAIN] = items
|
||||
entity_registry = er.async_get(hass)
|
||||
entity_registry = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
entry = entity_registry.async_get_or_create(DOMAIN, DOMAIN, TEST_TAG_ID)
|
||||
entity_registry.async_update_entity(entry.entity_id, name=TEST_TAG_NAME)
|
||||
config = {DOMAIN: {}}
|
||||
|
||||
@@ -44,7 +44,7 @@ def storage_setup(hass: HomeAssistant, hass_storage: dict[str, Any]):
|
||||
}
|
||||
else:
|
||||
hass_storage[DOMAIN] = items
|
||||
entity_registry = er.async_get(hass)
|
||||
entity_registry = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
_create_entry(entity_registry, TEST_TAG_ID, TEST_TAG_NAME)
|
||||
_create_entry(entity_registry, TEST_TAG_ID_2, TEST_TAG_NAME_2)
|
||||
config = {DOMAIN: {}}
|
||||
|
||||
@@ -1149,7 +1149,7 @@ async def test_raise_segments_changed_issue(
|
||||
hass.states.async_set(TEST_ATTRIBUTE_ENTITY_ID, "Bathroom")
|
||||
await hass.async_block_till_done()
|
||||
|
||||
issue_registry = ir.async_get(hass)
|
||||
issue_registry = ir.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert len(issue_registry.issues) != 0
|
||||
|
||||
|
||||
|
||||
@@ -149,8 +149,8 @@ async def test_setup_and_remove_config_entry(
|
||||
async def test_entry_changed(hass: HomeAssistant, platform) -> None:
|
||||
"""Test reconfiguring."""
|
||||
|
||||
device_registry = dr.async_get(hass)
|
||||
entity_registry = er.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
entity_registry = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
def _create_mock_entity(domain: str, name: str) -> er.RegistryEntry:
|
||||
config_entry = MockConfigEntry(
|
||||
|
||||
@@ -639,7 +639,7 @@ async def test_time_remaining_trigger_entity_removed_from_target(
|
||||
now = dt_util.utcnow()
|
||||
calls: list[dict[str, Any]] = []
|
||||
|
||||
label_reg = lr.async_get(hass)
|
||||
label_reg = lr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
label = label_reg.async_create("Test Time Remaining")
|
||||
|
||||
entry = entity_registry.async_get_or_create(
|
||||
@@ -688,7 +688,7 @@ async def test_time_remaining_trigger_entity_added_to_target(
|
||||
now = dt_util.utcnow()
|
||||
calls: list[dict[str, Any]] = []
|
||||
|
||||
label_reg = lr.async_get(hass)
|
||||
label_reg = lr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
label = label_reg.async_create("Test Time Remaining Add")
|
||||
|
||||
entry = entity_registry.async_get_or_create(
|
||||
|
||||
@@ -35,7 +35,7 @@ async def test_restore_state(hass: HomeAssistant) -> None:
|
||||
|
||||
entry = MockConfigEntry(domain=DOMAIN, data={CONF_WEBHOOK_ID: "webhook_id"})
|
||||
entry.add_to_hass(hass)
|
||||
dr.async_get(hass).async_get_or_create(
|
||||
dr.async_get(hass).async_get_or_create( # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
config_entry_id=entry.entry_id,
|
||||
identifiers={(DOMAIN, DEVICE_ID)},
|
||||
)
|
||||
|
||||
@@ -202,7 +202,7 @@ async def test_get_tuya_device_error_non_tuya_device(
|
||||
"""Test service error when target device is not a Tuya device."""
|
||||
await initialize_entry(hass, mock_manager, mock_config_entry, mock_device)
|
||||
|
||||
device_registry = dr.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
non_tuya_device = device_registry.async_get_or_create(
|
||||
config_entry_id=mock_config_entry.entry_id,
|
||||
identifiers={("other_domain", "some_id")},
|
||||
@@ -231,7 +231,7 @@ async def test_get_tuya_device_error_unknown_tuya_device(
|
||||
"""Test service error when Tuya identifier is not present in manager map."""
|
||||
await initialize_entry(hass, mock_manager, mock_config_entry, mock_device)
|
||||
|
||||
device_registry = dr.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
tuya_device = device_registry.async_get_or_create(
|
||||
config_entry_id=mock_config_entry.entry_id,
|
||||
identifiers={(DOMAIN, "unknown_tuya_id")},
|
||||
|
||||
@@ -988,7 +988,7 @@ async def test_aiport_no_binary_sensor_entities(
|
||||
# AI Port should not create any camera-specific binary sensors
|
||||
# (motion, smart detection, etc.)
|
||||
# NVR HDD sensors will still be created, but no AI Port-specific entities
|
||||
entity_registry = er.async_get(hass)
|
||||
entity_registry = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
entities = er.async_entries_for_config_entry(entity_registry, ufp.entry.entry_id)
|
||||
|
||||
for entity in entities:
|
||||
|
||||
@@ -150,7 +150,7 @@ async def test_first_active_quality_is_default(
|
||||
== camera_all.channels[1].rtsps_no_srtp_url
|
||||
)
|
||||
|
||||
entity_registry = er.async_get(hass)
|
||||
entity_registry = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert entity_registry.async_get(_channel_entity_id(camera_all, 0)) is None
|
||||
assert entity_registry.async_get(_channel_entity_id(camera_all, 2)) is None
|
||||
assert (
|
||||
@@ -424,7 +424,7 @@ async def test_public_only_camera(
|
||||
|
||||
# device identity degrades to name-only; the NVR link is omitted (resolving
|
||||
# the NVR identity publicly is wired with the config-mode setup)
|
||||
device_registry = dr.async_get(hass)
|
||||
device_registry = dr.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
device = device_registry.async_get_device(
|
||||
connections={(dr.CONNECTION_NETWORK_MAC, public.mac)}
|
||||
)
|
||||
|
||||
@@ -140,7 +140,7 @@ async def test_multiple_entities_in_one_call(hass: HomeAssistant) -> None:
|
||||
"""Test handling of service calls with multiple entity IDs."""
|
||||
user_id = str(uuid.uuid4())
|
||||
|
||||
ent_reg = er.async_get(hass)
|
||||
ent_reg = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
ent_reg.async_get_or_create(
|
||||
"light",
|
||||
"test",
|
||||
|
||||
@@ -533,7 +533,7 @@ async def test_segments_changed_issue(
|
||||
mock_vacuum.async_create_segments_issue()
|
||||
|
||||
issue_id = f"segments_changed_{entity_entry.id}"
|
||||
issue = ir.async_get(hass).async_get_issue(DOMAIN, issue_id)
|
||||
issue = ir.async_get(hass).async_get_issue(DOMAIN, issue_id) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert issue is not None
|
||||
assert issue.severity == ir.IssueSeverity.WARNING
|
||||
assert issue.translation_key == "segments_changed"
|
||||
@@ -551,7 +551,7 @@ async def test_segments_changed_issue(
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert ir.async_get(hass).async_get_issue(DOMAIN, issue_id) is None
|
||||
assert ir.async_get(hass).async_get_issue(DOMAIN, issue_id) is None # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
|
||||
@pytest.mark.parametrize(("is_built_in", "log_warnings"), [(True, 0), (False, 3)])
|
||||
|
||||
@@ -125,7 +125,7 @@ async def test_clean_area(hass: HomeAssistant) -> None:
|
||||
"""Test HassVacuumCleanArea intent."""
|
||||
await vacuum_intent.async_setup_intents(hass)
|
||||
|
||||
area_reg = ar.async_get(hass)
|
||||
area_reg = ar.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
kitchen = area_reg.async_create("Kitchen")
|
||||
|
||||
vacuum_1 = f"{DOMAIN}.vacuum_1"
|
||||
@@ -183,7 +183,7 @@ async def test_clean_area_no_matching_vacuum(hass: HomeAssistant) -> None:
|
||||
"""Test HassVacuumCleanArea intent with no matching vacuum."""
|
||||
await vacuum_intent.async_setup_intents(hass)
|
||||
|
||||
area_reg = ar.async_get(hass)
|
||||
area_reg = ar.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
area_reg.async_create("Kitchen")
|
||||
|
||||
# No vacuums at all
|
||||
@@ -238,7 +238,7 @@ async def test_clean_area_service_failure(hass: HomeAssistant) -> None:
|
||||
"""Test HassVacuumCleanArea intent when the service call fails."""
|
||||
await vacuum_intent.async_setup_intents(hass)
|
||||
|
||||
area_reg = ar.async_get(hass)
|
||||
area_reg = ar.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
area_reg.async_create("Kitchen")
|
||||
|
||||
entity_id = f"{DOMAIN}.test_vacuum"
|
||||
|
||||
@@ -167,7 +167,7 @@ async def test_migrate_entry_creates_repair_issue(hass: HomeAssistant) -> None:
|
||||
await hass.config_entries.async_setup(config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
issue = ir.async_get(hass).async_get_issue(DOMAIN, "update_redirect_uri")
|
||||
issue = ir.async_get(hass).async_get_issue(DOMAIN, "update_redirect_uri") # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert issue is not None
|
||||
assert issue.severity == ir.IssueSeverity.WARNING
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ async def test_is_valid_call(
|
||||
protocol = HassVoipDatagramProtocol(hass, voip_devices)
|
||||
assert not protocol.is_valid_call(call_info)
|
||||
|
||||
ent_reg = er.async_get(hass)
|
||||
ent_reg = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
allowed_call_entity_id = ent_reg.async_get_entity_id(
|
||||
"switch", voip.DOMAIN, f"{voip_device.voip_id}-allow_call"
|
||||
)
|
||||
|
||||
@@ -311,7 +311,7 @@ async def target_entities(
|
||||
}
|
||||
assert set(label_registry.labels) == {"label_1", "label_2", "label_3"}
|
||||
assert set(area_registry.areas) == {"kitchen", "living_room", "bathroom", "garage"}
|
||||
assert set(dr.async_get(hass).devices) == {
|
||||
assert set(dr.async_get(hass).devices) == { # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
"device1",
|
||||
"device2",
|
||||
"area_device",
|
||||
|
||||
@@ -132,7 +132,7 @@ async def test_dynamic_entity_lifecycle(
|
||||
),
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
registry = er.async_get(hass)
|
||||
registry = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
assert registry.async_get(entity_id) is None
|
||||
assert hass.states.get(entity_id) is None
|
||||
# The binary_sensor with the same unique_id is untouched.
|
||||
@@ -201,7 +201,7 @@ async def test_unknown_unique_id_is_noop(
|
||||
assert entity_id is not None
|
||||
|
||||
ha_zha_data = get_zha_data(hass)
|
||||
registry = er.async_get(hass)
|
||||
registry = er.async_get(hass) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
|
||||
# Added: nothing queued, no dispatcher signal fired.
|
||||
with patch(
|
||||
@@ -255,7 +255,7 @@ async def test_remove_entity_reference_when_ieee_already_cleared(
|
||||
ieee = zha_device_proxy.device.ieee
|
||||
gateway_proxy._ha_entity_refs.pop(ieee, None)
|
||||
|
||||
er.async_get(hass).async_remove(entity_id)
|
||||
er.async_get(hass).async_remove(entity_id) # pylint: disable=home-assistant-tests-registry-fixtures
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert ieee not in gateway_proxy._ha_entity_refs
|
||||
|
||||
@@ -0,0 +1,340 @@
|
||||
"""Tests for the registry fixtures checker."""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import astroid
|
||||
from astroid import nodes
|
||||
from pylint.testutils import MessageTest, UnittestLinter
|
||||
from pylint_home_assistant.checkers.tests.registry_fixtures import (
|
||||
RegistryFixturesChecker,
|
||||
)
|
||||
import pytest
|
||||
|
||||
from tests.pylint import assert_adds_messages, assert_no_messages, walk_checker
|
||||
|
||||
|
||||
@pytest.fixture(name="registry_fixtures_checker")
|
||||
def registry_fixtures_checker_fixture(
|
||||
linter: UnittestLinter,
|
||||
) -> RegistryFixturesChecker:
|
||||
"""Fixture to provide a registry fixtures checker."""
|
||||
return RegistryFixturesChecker(linter)
|
||||
|
||||
|
||||
def _find_async_get_call(root_node: nodes.Module) -> nodes.Call:
|
||||
"""Find the first ``<alias>.async_get(...)`` call node."""
|
||||
for call in root_node.nodes_of_class(nodes.Call):
|
||||
func = call.func
|
||||
if isinstance(func, nodes.Attribute) and func.attrname == "async_get":
|
||||
return call
|
||||
raise AssertionError("no async_get call found")
|
||||
|
||||
|
||||
def _expect_registry_fixture(node: nodes.Call, helper: str) -> MessageTest:
|
||||
"""Build the expected MessageTest for a registry fixture violation."""
|
||||
return MessageTest(
|
||||
msg_id="home-assistant-tests-registry-fixtures",
|
||||
node=node,
|
||||
args=(helper, helper),
|
||||
line=node.lineno,
|
||||
col_offset=node.col_offset,
|
||||
end_line=node.end_lineno,
|
||||
end_col_offset=node.end_col_offset,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("helper", "alias"),
|
||||
[
|
||||
("area_registry", "ar"),
|
||||
("category_registry", "cr"),
|
||||
("device_registry", "dr"),
|
||||
("entity_registry", "er"),
|
||||
("floor_registry", "fr"),
|
||||
("issue_registry", "ir"),
|
||||
("label_registry", "lr"),
|
||||
],
|
||||
)
|
||||
def test_aliased_import_in_test_function_flagged(
|
||||
linter: UnittestLinter,
|
||||
registry_fixtures_checker: RegistryFixturesChecker,
|
||||
helper: str,
|
||||
alias: str,
|
||||
) -> None:
|
||||
"""Aliased registry import called inside a test function is flagged."""
|
||||
root_node = astroid.parse(
|
||||
f"""
|
||||
from homeassistant.helpers import {helper} as {alias}
|
||||
|
||||
|
||||
async def test_something(hass) -> None:
|
||||
registry = {alias}.async_get(hass)
|
||||
""",
|
||||
"tests.components.test_integration.test_init",
|
||||
)
|
||||
call_node = _find_async_get_call(root_node)
|
||||
|
||||
with assert_adds_messages(linter, _expect_registry_fixture(call_node, helper)):
|
||||
walk_checker(linter, registry_fixtures_checker, root_node)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"helper",
|
||||
[
|
||||
"area_registry",
|
||||
"category_registry",
|
||||
"device_registry",
|
||||
"entity_registry",
|
||||
"floor_registry",
|
||||
"issue_registry",
|
||||
"label_registry",
|
||||
],
|
||||
)
|
||||
def test_non_aliased_import_in_test_function_flagged(
|
||||
linter: UnittestLinter,
|
||||
registry_fixtures_checker: RegistryFixturesChecker,
|
||||
helper: str,
|
||||
) -> None:
|
||||
"""Non-aliased registry import called inside a test is flagged."""
|
||||
root_node = astroid.parse(
|
||||
f"""
|
||||
from homeassistant.helpers import {helper}
|
||||
|
||||
|
||||
async def test_something(hass) -> None:
|
||||
registry = {helper}.async_get(hass)
|
||||
""",
|
||||
"tests.components.test_integration.test_init",
|
||||
)
|
||||
call_node = _find_async_get_call(root_node)
|
||||
|
||||
with assert_adds_messages(linter, _expect_registry_fixture(call_node, helper)):
|
||||
walk_checker(linter, registry_fixtures_checker, root_node)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"fixture_decorator",
|
||||
[
|
||||
"@pytest.fixture",
|
||||
"@pytest.fixture()",
|
||||
'@pytest.fixture(name="my_fixture")',
|
||||
],
|
||||
ids=["bare", "call", "named"],
|
||||
)
|
||||
def test_pytest_fixture_flagged(
|
||||
linter: UnittestLinter,
|
||||
registry_fixtures_checker: RegistryFixturesChecker,
|
||||
fixture_decorator: str,
|
||||
) -> None:
|
||||
"""Calls inside a @pytest.fixture function are flagged."""
|
||||
root_node = astroid.parse(
|
||||
f"""
|
||||
import pytest
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
|
||||
|
||||
{fixture_decorator}
|
||||
def my_helper(hass):
|
||||
return dr.async_get(hass)
|
||||
""",
|
||||
"tests.components.test_integration.test_init",
|
||||
)
|
||||
call_node = _find_async_get_call(root_node)
|
||||
|
||||
with assert_adds_messages(
|
||||
linter, _expect_registry_fixture(call_node, "device_registry")
|
||||
):
|
||||
walk_checker(linter, registry_fixtures_checker, root_node)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("code", "helper"),
|
||||
[
|
||||
pytest.param(
|
||||
"""
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
|
||||
async def test_something(hass) -> None:
|
||||
def _helper():
|
||||
return er.async_get(hass)
|
||||
|
||||
_helper()
|
||||
""",
|
||||
"entity_registry",
|
||||
id="nested_helper_in_test",
|
||||
),
|
||||
pytest.param(
|
||||
"""
|
||||
import pytest
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def storage_setup(hass):
|
||||
async def _storage(items=None):
|
||||
entity_registry = er.async_get(hass)
|
||||
return entity_registry
|
||||
|
||||
return _storage
|
||||
""",
|
||||
"entity_registry",
|
||||
id="nested_helper_in_fixture",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_nested_helper_flagged(
|
||||
linter: UnittestLinter,
|
||||
registry_fixtures_checker: RegistryFixturesChecker,
|
||||
code: str,
|
||||
helper: str,
|
||||
) -> None:
|
||||
"""Calls in nested helpers inside tests/fixtures are flagged."""
|
||||
root_node = astroid.parse(code, "tests.components.test_integration.test_init")
|
||||
call_node = _find_async_get_call(root_node)
|
||||
|
||||
with assert_adds_messages(linter, _expect_registry_fixture(call_node, helper)):
|
||||
walk_checker(linter, registry_fixtures_checker, root_node)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("code", "module_name"),
|
||||
[
|
||||
pytest.param(
|
||||
"""
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
|
||||
def helper(hass):
|
||||
return er.async_get(hass)
|
||||
""",
|
||||
"tests.components.test_integration.test_init",
|
||||
id="non_test_non_fixture_helper",
|
||||
),
|
||||
pytest.param(
|
||||
"""
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
registry = er.async_get(None)
|
||||
""",
|
||||
"tests.components.test_integration.test_init",
|
||||
id="module_top_level",
|
||||
),
|
||||
pytest.param(
|
||||
"""
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
|
||||
async def test_something(hass) -> None:
|
||||
registry = er.async_get(hass)
|
||||
""",
|
||||
"homeassistant.components.test_integration",
|
||||
id="not_a_test_module",
|
||||
),
|
||||
pytest.param(
|
||||
"""
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
|
||||
async def test_something(hass) -> None:
|
||||
registry = er.async_get(hass)
|
||||
""",
|
||||
"tests.helpers.test_entity_registry",
|
||||
id="tests_helpers_excluded",
|
||||
),
|
||||
pytest.param(
|
||||
"""
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
|
||||
async def test_something(hass) -> None:
|
||||
something = other.async_get(hass)
|
||||
""",
|
||||
"tests.components.test_integration.test_init",
|
||||
id="unrelated_attribute_target",
|
||||
),
|
||||
pytest.param(
|
||||
"""
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
|
||||
async def test_something(hass) -> None:
|
||||
entry = er.async_get_or_create(hass)
|
||||
""",
|
||||
"tests.components.test_integration.test_init",
|
||||
id="different_method_name",
|
||||
),
|
||||
pytest.param(
|
||||
"""
|
||||
async def test_something(hass) -> None:
|
||||
# No import of any registry helper at module scope.
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
registry = er.async_get(hass)
|
||||
""",
|
||||
"tests.components.test_integration.test_init",
|
||||
id="local_import_not_tracked",
|
||||
),
|
||||
pytest.param(
|
||||
"""
|
||||
from homeassistant.helpers import entity_registry
|
||||
|
||||
|
||||
async def test_something(hass, entity_registry) -> None:
|
||||
entry = entity_registry.async_get("sensor.test")
|
||||
""",
|
||||
"tests.components.test_integration.test_init",
|
||||
id="fixture_parameter_shadows_import",
|
||||
),
|
||||
pytest.param(
|
||||
"""
|
||||
from homeassistant.helpers import entity_registry
|
||||
|
||||
|
||||
async def test_something(hass) -> None:
|
||||
entity_registry = get_registry()
|
||||
entry = entity_registry.async_get("sensor.test")
|
||||
""",
|
||||
"tests.components.test_integration.test_init",
|
||||
id="local_assignment_shadows_import",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_no_warning(
|
||||
linter: UnittestLinter,
|
||||
registry_fixtures_checker: RegistryFixturesChecker,
|
||||
code: str,
|
||||
module_name: str,
|
||||
) -> None:
|
||||
"""Cases that should not produce a warning."""
|
||||
root_node = astroid.parse(code, module_name)
|
||||
|
||||
with assert_no_messages(linter):
|
||||
walk_checker(linter, registry_fixtures_checker, root_node)
|
||||
|
||||
|
||||
def test_conftest_file_exempt(
|
||||
linter: UnittestLinter,
|
||||
registry_fixtures_checker: RegistryFixturesChecker,
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
"""Calls inside ``conftest.py`` files are not flagged."""
|
||||
conftest_path = tmp_path / "conftest.py"
|
||||
conftest_path.write_text("")
|
||||
|
||||
root_node = astroid.parse(
|
||||
"""
|
||||
import pytest
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def entity_registry(hass):
|
||||
return er.async_get(hass)
|
||||
""",
|
||||
"tests.components.test_integration.conftest",
|
||||
)
|
||||
root_node.file = str(conftest_path)
|
||||
|
||||
with assert_no_messages(linter):
|
||||
walk_checker(linter, registry_fixtures_checker, root_node)
|
||||
Reference in New Issue
Block a user