Skip to content

Commit

Permalink
Add a helpful message to the config_entries.OperationNotAllowed excep…
Browse files Browse the repository at this point in the history
…tion (#78631)

We only expect this exception to be raised as a result of an
implementation problem. When it is raised during production
it is currently hard to trace down why its happening

See #75835
  • Loading branch information
bdraco authored and balloob committed Sep 18, 2022
1 parent 7eb98ff commit a2aa0e6
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 7 deletions.
10 changes: 8 additions & 2 deletions homeassistant/config_entries.py
Original file line number Diff line number Diff line change
Expand Up @@ -1024,7 +1024,10 @@ async def async_setup(self, entry_id: str) -> bool:
raise UnknownEntry

if entry.state is not ConfigEntryState.NOT_LOADED:
raise OperationNotAllowed
raise OperationNotAllowed(
f"The config entry {entry.title} ({entry.domain}) with entry_id {entry.entry_id}"
f" cannot be setup because is already loaded in the {entry.state} state"
)

# Setup Component if not set up yet
if entry.domain in self.hass.config.components:
Expand All @@ -1046,7 +1049,10 @@ async def async_unload(self, entry_id: str) -> bool:
raise UnknownEntry

if not entry.state.recoverable:
raise OperationNotAllowed
raise OperationNotAllowed(
f"The config entry {entry.title} ({entry.domain}) with entry_id "
f"{entry.entry_id} cannot be unloaded because it is not in a recoverable state ({entry.state})"
)

return await entry.async_unload(self.hass)

Expand Down
16 changes: 11 additions & 5 deletions tests/test_config_entries.py
Original file line number Diff line number Diff line change
Expand Up @@ -1141,7 +1141,7 @@ async def test_entry_setup_invalid_state(hass, manager, state):
MockModule("comp", async_setup=mock_setup, async_setup_entry=mock_setup_entry),
)

with pytest.raises(config_entries.OperationNotAllowed):
with pytest.raises(config_entries.OperationNotAllowed, match=str(state)):
assert await manager.async_setup(entry.entry_id)

assert len(mock_setup.mock_calls) == 0
Expand Down Expand Up @@ -1201,7 +1201,7 @@ async def test_entry_unload_invalid_state(hass, manager, state):

mock_integration(hass, MockModule("comp", async_unload_entry=async_unload_entry))

with pytest.raises(config_entries.OperationNotAllowed):
with pytest.raises(config_entries.OperationNotAllowed, match=str(state)):
assert await manager.async_unload(entry.entry_id)

assert len(async_unload_entry.mock_calls) == 0
Expand Down Expand Up @@ -1296,7 +1296,7 @@ async def test_entry_reload_error(hass, manager, state):
),
)

with pytest.raises(config_entries.OperationNotAllowed):
with pytest.raises(config_entries.OperationNotAllowed, match=str(state)):
assert await manager.async_reload(entry.entry_id)

assert len(async_unload_entry.mock_calls) == 0
Expand Down Expand Up @@ -1370,7 +1370,10 @@ async def test_entry_disable_without_reload_support(hass, manager):
assert entry.state is config_entries.ConfigEntryState.FAILED_UNLOAD

# Enable
with pytest.raises(config_entries.OperationNotAllowed):
with pytest.raises(
config_entries.OperationNotAllowed,
match=str(config_entries.ConfigEntryState.FAILED_UNLOAD),
):
await manager.async_set_disabled_by(entry.entry_id, None)
assert len(async_setup.mock_calls) == 0
assert len(async_setup_entry.mock_calls) == 0
Expand Down Expand Up @@ -3270,7 +3273,10 @@ async def test_disallow_entry_reload_with_setup_in_progresss(hass, manager):
)
entry.add_to_hass(hass)

with pytest.raises(config_entries.OperationNotAllowed):
with pytest.raises(
config_entries.OperationNotAllowed,
match=str(config_entries.ConfigEntryState.SETUP_IN_PROGRESS),
):
assert await manager.async_reload(entry.entry_id)
assert entry.state is config_entries.ConfigEntryState.SETUP_IN_PROGRESS

Expand Down

0 comments on commit a2aa0e6

Please sign in to comment.