Repository: home-assistant/core
File: homeassistant/exceptions.py (Python)

Code before:

class IntegrationError(HomeAssistantError):
    """Base class for platform and config entry exceptions."""

    def __str__(self) -> str:
        """Return a human readable error."""
        return super().__str__() or str(self.__cause__)


class PlatformNotReady(IntegrationError):
    """Error to indicate that platform is not ready."""


class ConfigEntryError(IntegrationError):
    """Error to indicate that config entry setup has failed."""


class ConfigEntryNotReady(IntegrationError):
    """Error to indicate that config entry is not ready."""


class ConfigEntryAuthFailed(IntegrationError):
    """Error to indicate that config entry could not authenticate."""


class ConfigEntryRefreshTokenFailed(IntegrationError):
    """Error to indicate that config entry could not refresh token."""


class InvalidStateError(HomeAssistantError):
    """When an invalid state is encountered."""


class Unauthorized(HomeAssistantError):
    """When an action is unauthorized."""

    def __init__(
        self,
        context: Context | None = None,
        user_id: str | None = None,
        entity_id: str | None = None,
        config_entry_id: str | None = None,
        perm_category: str | None = None,
        permission: str | None = None,
    ) -> None:
        """Unauthorized error."""
        super().__init__(self.__class__.__name__)
        self.context = context

        if user_id is None and context is not None:
            user_id = context.user_id

Review comment (bug):
I don't think this exception should be prefixed with `ConfigEntry`. This is an exception that the oauth2 implementation raises when refreshing the token fails. It's not related specifically to the config entry. Maybe prefix it with `Oauth2`?

Code after:
        for item in self.errors:
            yield from item.output(indent)


class IntegrationError(HomeAssistantError):
    """Base class for platform and config entry exceptions."""

    def __str__(self) -> str:
        """Return a human readable error."""
        return super().__str__() or str(self.__cause__)


class PlatformNotReady(IntegrationError):
    """Error to indicate that platform is not ready."""


class ConfigEntryError(IntegrationError):
    """Error to indicate that config entry setup has failed."""


class ConfigEntryNotReady(IntegrationError):
    """Error to indicate that config entry is not ready."""


class ConfigEntryAuthFailed(IntegrationError):
    """Error to indicate that config entry could not authenticate."""


class OAuth2TokenRequestError(ClientResponseError, HomeAssistantError):
    """Error to indicate that the OAuth 2.0 flow could not refresh token."""

    def __init__(
        self,
        *,
        request_info: RequestInfo,
        history: tuple[ClientResponse, ...] = (),
        status: int = 0,
        message: str = "OAuth 2.0 token refresh failed",
        headers: MultiMapping[str] | None = None,
        domain: str,
    ) -> None:
        """Initialize OAuth2RefreshTokenFailed."""
        ClientResponseError.__init__(
            self,
            request_info=request_info,
            history=history,
            status=status,
            message=message,
            headers=headers,
        )
        HomeAssistantError.__init__(self)