diff --git a/homeassistant/components/api/__init__.py b/homeassistant/components/api/__init__.py index 144205b3b25..01d48a190fd 100644 --- a/homeassistant/components/api/__init__.py +++ b/homeassistant/components/api/__init__.py @@ -1,5 +1,6 @@ """Rest API for Home Assistant.""" import asyncio +from http import HTTPStatus import json import logging @@ -14,10 +15,6 @@ from homeassistant.components.http import HomeAssistantView from homeassistant.const import ( EVENT_HOMEASSISTANT_STOP, EVENT_TIME_CHANGED, - HTTP_BAD_REQUEST, - HTTP_CREATED, - HTTP_NOT_FOUND, - HTTP_OK, MATCH_ALL, URL_API, URL_API_COMPONENTS, @@ -231,7 +228,7 @@ class APIEntityStateView(HomeAssistantView): state = request.app["hass"].states.get(entity_id) if state: return self.json(state) - return self.json_message("Entity not found.", HTTP_NOT_FOUND) + return self.json_message("Entity not found.", HTTPStatus.NOT_FOUND) async def post(self, request, entity_id): """Update state of entity.""" @@ -241,12 +238,12 @@ class APIEntityStateView(HomeAssistantView): try: data = await request.json() except ValueError: - return self.json_message("Invalid JSON specified.", HTTP_BAD_REQUEST) + return self.json_message("Invalid JSON specified.", HTTPStatus.BAD_REQUEST) new_state = data.get("state") if new_state is None: - return self.json_message("No state specified.", HTTP_BAD_REQUEST) + return self.json_message("No state specified.", HTTPStatus.BAD_REQUEST) attributes = data.get("attributes") force_update = data.get("force_update", False) @@ -259,7 +256,7 @@ class APIEntityStateView(HomeAssistantView): ) # Read the state back for our response - status_code = HTTP_CREATED if is_new_state else HTTP_OK + status_code = HTTPStatus.CREATED if is_new_state else HTTPStatus.OK resp = self.json(hass.states.get(entity_id), status_code) resp.headers.add("Location", f"/api/states/{entity_id}") @@ -273,7 +270,7 @@ class APIEntityStateView(HomeAssistantView): raise Unauthorized(entity_id=entity_id) if request.app["hass"].states.async_remove(entity_id): return self.json_message("Entity removed.") - return self.json_message("Entity not found.", HTTP_NOT_FOUND) + return self.json_message("Entity not found.", HTTPStatus.NOT_FOUND) class APIEventListenersView(HomeAssistantView): @@ -303,12 +300,12 @@ class APIEventView(HomeAssistantView): event_data = json.loads(body) if body else None except ValueError: return self.json_message( - "Event data should be valid JSON.", HTTP_BAD_REQUEST + "Event data should be valid JSON.", HTTPStatus.BAD_REQUEST ) if event_data is not None and not isinstance(event_data, dict): return self.json_message( - "Event data should be a JSON object", HTTP_BAD_REQUEST + "Event data should be a JSON object", HTTPStatus.BAD_REQUEST ) # Special case handling for event STATE_CHANGED @@ -355,7 +352,9 @@ class APIDomainServicesView(HomeAssistantView): try: data = json.loads(body) if body else None except ValueError: - return self.json_message("Data should be valid JSON.", HTTP_BAD_REQUEST) + return self.json_message( + "Data should be valid JSON.", HTTPStatus.BAD_REQUEST + ) context = self.context(request) @@ -403,7 +402,7 @@ class APITemplateView(HomeAssistantView): return tpl.async_render(variables=data.get("variables"), parse_result=False) except (ValueError, TemplateError) as ex: return self.json_message( - f"Error rendering template: {ex}", HTTP_BAD_REQUEST + f"Error rendering template: {ex}", HTTPStatus.BAD_REQUEST ) diff --git a/homeassistant/components/auth/__init__.py b/homeassistant/components/auth/__init__.py index c4a48f7eda4..49c18b4737a 100644 --- a/homeassistant/components/auth/__init__.py +++ b/homeassistant/components/auth/__init__.py @@ -117,6 +117,7 @@ Result will be a long-lived access token: from __future__ import annotations from datetime import timedelta +from http import HTTPStatus import uuid from aiohttp import web @@ -133,7 +134,7 @@ from homeassistant.components.http.auth import async_sign_path from homeassistant.components.http.ban import log_invalid_auth from homeassistant.components.http.data_validator import RequestDataValidator from homeassistant.components.http.view import HomeAssistantView -from homeassistant.const import HTTP_BAD_REQUEST, HTTP_FORBIDDEN, HTTP_OK +from homeassistant.const import HTTP_OK from homeassistant.core import HomeAssistant, callback from homeassistant.loader import bind_hass from homeassistant.util import dt as dt_util @@ -259,7 +260,7 @@ class TokenView(HomeAssistantView): return await self._async_handle_refresh_token(hass, data, request.remote) return self.json( - {"error": "unsupported_grant_type"}, status_code=HTTP_BAD_REQUEST + {"error": "unsupported_grant_type"}, status_code=HTTPStatus.BAD_REQUEST ) async def _async_handle_revoke_token(self, hass, data): @@ -289,7 +290,7 @@ class TokenView(HomeAssistantView): if client_id is None or not indieauth.verify_client_id(client_id): return self.json( {"error": "invalid_request", "error_description": "Invalid client id"}, - status_code=HTTP_BAD_REQUEST, + status_code=HTTPStatus.BAD_REQUEST, ) code = data.get("code") @@ -297,7 +298,7 @@ class TokenView(HomeAssistantView): if code is None: return self.json( {"error": "invalid_request", "error_description": "Invalid code"}, - status_code=HTTP_BAD_REQUEST, + status_code=HTTPStatus.BAD_REQUEST, ) credential = self._retrieve_auth(client_id, RESULT_TYPE_CREDENTIALS, code) @@ -305,7 +306,7 @@ class TokenView(HomeAssistantView): if credential is None or not isinstance(credential, Credentials): return self.json( {"error": "invalid_request", "error_description": "Invalid code"}, - status_code=HTTP_BAD_REQUEST, + status_code=HTTPStatus.BAD_REQUEST, ) user = await hass.auth.async_get_or_create_user(credential) @@ -313,7 +314,7 @@ class TokenView(HomeAssistantView): if not user.is_active: return self.json( {"error": "access_denied", "error_description": "User is not active"}, - status_code=HTTP_FORBIDDEN, + status_code=HTTPStatus.FORBIDDEN, ) refresh_token = await hass.auth.async_create_refresh_token( @@ -326,7 +327,7 @@ class TokenView(HomeAssistantView): except InvalidAuthError as exc: return self.json( {"error": "access_denied", "error_description": str(exc)}, - status_code=HTTP_FORBIDDEN, + status_code=HTTPStatus.FORBIDDEN, ) return self.json( @@ -346,21 +347,27 @@ class TokenView(HomeAssistantView): if client_id is not None and not indieauth.verify_client_id(client_id): return self.json( {"error": "invalid_request", "error_description": "Invalid client id"}, - status_code=HTTP_BAD_REQUEST, + status_code=HTTPStatus.BAD_REQUEST, ) token = data.get("refresh_token") if token is None: - return self.json({"error": "invalid_request"}, status_code=HTTP_BAD_REQUEST) + return self.json( + {"error": "invalid_request"}, status_code=HTTPStatus.BAD_REQUEST + ) refresh_token = await hass.auth.async_get_refresh_token_by_token(token) if refresh_token is None: - return self.json({"error": "invalid_grant"}, status_code=HTTP_BAD_REQUEST) + return self.json( + {"error": "invalid_grant"}, status_code=HTTPStatus.BAD_REQUEST + ) if refresh_token.client_id != client_id: - return self.json({"error": "invalid_request"}, status_code=HTTP_BAD_REQUEST) + return self.json( + {"error": "invalid_request"}, status_code=HTTPStatus.BAD_REQUEST + ) try: access_token = hass.auth.async_create_access_token( @@ -369,7 +376,7 @@ class TokenView(HomeAssistantView): except InvalidAuthError as exc: return self.json( {"error": "access_denied", "error_description": str(exc)}, - status_code=HTTP_FORBIDDEN, + status_code=HTTPStatus.FORBIDDEN, ) return self.json( @@ -404,7 +411,7 @@ class LinkUserView(HomeAssistantView): ) if credentials is None: - return self.json_message("Invalid code", status_code=HTTP_BAD_REQUEST) + return self.json_message("Invalid code", status_code=HTTPStatus.BAD_REQUEST) await hass.auth.async_link_user(user, credentials) return self.json_message("User linked") diff --git a/homeassistant/components/auth/login_flow.py b/homeassistant/components/auth/login_flow.py index f948233b33b..f15eeee2f16 100644 --- a/homeassistant/components/auth/login_flow.py +++ b/homeassistant/components/auth/login_flow.py @@ -66,6 +66,7 @@ associate with an credential if "type" set to "link_user" in "version": 1 } """ +from http import HTTPStatus from ipaddress import ip_address from aiohttp import web @@ -80,11 +81,7 @@ from homeassistant.components.http.ban import ( ) from homeassistant.components.http.data_validator import RequestDataValidator from homeassistant.components.http.view import HomeAssistantView -from homeassistant.const import ( - HTTP_BAD_REQUEST, - HTTP_METHOD_NOT_ALLOWED, - HTTP_NOT_FOUND, -) +from homeassistant.const import HTTP_METHOD_NOT_ALLOWED from . import indieauth @@ -109,7 +106,7 @@ class AuthProvidersView(HomeAssistantView): if not hass.components.onboarding.async_is_user_onboarded(): return self.json_message( message="Onboarding not finished", - status_code=HTTP_BAD_REQUEST, + status_code=HTTPStatus.BAD_REQUEST, message_code="onboarding_required", ) @@ -177,7 +174,7 @@ class LoginFlowIndexView(HomeAssistantView): request.app["hass"], data["client_id"], data["redirect_uri"] ): return self.json_message( - "invalid client id or redirect uri", HTTP_BAD_REQUEST + "invalid client id or redirect uri", HTTPStatus.BAD_REQUEST ) if isinstance(data["handler"], list): @@ -194,9 +191,11 @@ class LoginFlowIndexView(HomeAssistantView): }, ) except data_entry_flow.UnknownHandler: - return self.json_message("Invalid handler specified", HTTP_NOT_FOUND) + return self.json_message("Invalid handler specified", HTTPStatus.NOT_FOUND) except data_entry_flow.UnknownStep: - return self.json_message("Handler does not support init", HTTP_BAD_REQUEST) + return self.json_message( + "Handler does not support init", HTTPStatus.BAD_REQUEST + ) if result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY: await process_success_login(request) @@ -221,7 +220,7 @@ class LoginFlowResourceView(HomeAssistantView): async def get(self, request): """Do not allow getting status of a flow in progress.""" - return self.json_message("Invalid flow specified", HTTP_NOT_FOUND) + return self.json_message("Invalid flow specified", HTTPStatus.NOT_FOUND) @RequestDataValidator(vol.Schema({"client_id": str}, extra=vol.ALLOW_EXTRA)) @log_invalid_auth @@ -230,7 +229,7 @@ class LoginFlowResourceView(HomeAssistantView): client_id = data.pop("client_id") if not indieauth.verify_client_id(client_id): - return self.json_message("Invalid client id", HTTP_BAD_REQUEST) + return self.json_message("Invalid client id", HTTPStatus.BAD_REQUEST) try: # do not allow change ip during login flow @@ -238,13 +237,15 @@ class LoginFlowResourceView(HomeAssistantView): if flow["flow_id"] == flow_id and flow["context"][ "ip_address" ] != ip_address(request.remote): - return self.json_message("IP address changed", HTTP_BAD_REQUEST) + return self.json_message( + "IP address changed", HTTPStatus.BAD_REQUEST + ) result = await self._flow_mgr.async_configure(flow_id, data) except data_entry_flow.UnknownFlow: - return self.json_message("Invalid flow specified", HTTP_NOT_FOUND) + return self.json_message("Invalid flow specified", HTTPStatus.NOT_FOUND) except vol.Invalid: - return self.json_message("User input malformed", HTTP_BAD_REQUEST) + return self.json_message("User input malformed", HTTPStatus.BAD_REQUEST) if result["type"] != data_entry_flow.RESULT_TYPE_CREATE_ENTRY: # @log_invalid_auth does not work here since it returns HTTP 200 @@ -266,6 +267,6 @@ class LoginFlowResourceView(HomeAssistantView): try: self._flow_mgr.async_abort(flow_id) except data_entry_flow.UnknownFlow: - return self.json_message("Invalid flow specified", HTTP_NOT_FOUND) + return self.json_message("Invalid flow specified", HTTPStatus.NOT_FOUND) return self.json_message("Flow aborted") diff --git a/homeassistant/components/config/__init__.py b/homeassistant/components/config/__init__.py index 7d07710a4d0..0815216ec79 100644 --- a/homeassistant/components/config/__init__.py +++ b/homeassistant/components/config/__init__.py @@ -1,17 +1,13 @@ """Component to configure Home Assistant via an API.""" import asyncio +from http import HTTPStatus import importlib import os import voluptuous as vol from homeassistant.components.http import HomeAssistantView -from homeassistant.const import ( - CONF_ID, - EVENT_COMPONENT_LOADED, - HTTP_BAD_REQUEST, - HTTP_NOT_FOUND, -) +from homeassistant.const import CONF_ID, EVENT_COMPONENT_LOADED from homeassistant.core import callback from homeassistant.exceptions import HomeAssistantError from homeassistant.setup import ATTR_COMPONENT @@ -125,7 +121,7 @@ class BaseEditConfigView(HomeAssistantView): value = self._get_value(hass, current, config_key) if value is None: - return self.json_message("Resource not found", HTTP_NOT_FOUND) + return self.json_message("Resource not found", HTTPStatus.NOT_FOUND) return self.json(value) @@ -134,12 +130,12 @@ class BaseEditConfigView(HomeAssistantView): try: data = await request.json() except ValueError: - return self.json_message("Invalid JSON specified", HTTP_BAD_REQUEST) + return self.json_message("Invalid JSON specified", HTTPStatus.BAD_REQUEST) try: self.key_schema(config_key) except vol.Invalid as err: - return self.json_message(f"Key malformed: {err}", HTTP_BAD_REQUEST) + return self.json_message(f"Key malformed: {err}", HTTPStatus.BAD_REQUEST) hass = request.app["hass"] @@ -151,7 +147,9 @@ class BaseEditConfigView(HomeAssistantView): else: self.data_schema(data) except (vol.Invalid, HomeAssistantError) as err: - return self.json_message(f"Message malformed: {err}", HTTP_BAD_REQUEST) + return self.json_message( + f"Message malformed: {err}", HTTPStatus.BAD_REQUEST + ) path = hass.config.path(self.path) @@ -177,7 +175,7 @@ class BaseEditConfigView(HomeAssistantView): path = hass.config.path(self.path) if value is None: - return self.json_message("Resource not found", HTTP_NOT_FOUND) + return self.json_message("Resource not found", HTTPStatus.BAD_REQUEST) self._delete_value(hass, current, config_key) await hass.async_add_executor_job(_write, path, current) diff --git a/homeassistant/components/config/config_entries.py b/homeassistant/components/config/config_entries.py index f842a240dc1..cf243137940 100644 --- a/homeassistant/components/config/config_entries.py +++ b/homeassistant/components/config/config_entries.py @@ -1,6 +1,8 @@ """Http views to control the config manager.""" from __future__ import annotations +from http import HTTPStatus + import aiohttp.web_exceptions import voluptuous as vol @@ -8,7 +10,6 @@ from homeassistant import config_entries, data_entry_flow from homeassistant.auth.permissions.const import CAT_CONFIG_ENTRIES, POLICY_EDIT from homeassistant.components import websocket_api from homeassistant.components.http import HomeAssistantView -from homeassistant.const import HTTP_FORBIDDEN, HTTP_NOT_FOUND from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import Unauthorized from homeassistant.helpers.data_entry_flow import ( @@ -69,7 +70,7 @@ class ConfigManagerEntryResourceView(HomeAssistantView): try: result = await hass.config_entries.async_remove(entry_id) except config_entries.UnknownEntry: - return self.json_message("Invalid entry specified", HTTP_NOT_FOUND) + return self.json_message("Invalid entry specified", HTTPStatus.NOT_FOUND) return self.json(result) @@ -90,9 +91,9 @@ class ConfigManagerEntryResourceReloadView(HomeAssistantView): try: result = await hass.config_entries.async_reload(entry_id) except config_entries.OperationNotAllowed: - return self.json_message("Entry cannot be reloaded", HTTP_FORBIDDEN) + return self.json_message("Entry cannot be reloaded", HTTPStatus.FORBIDDEN) except config_entries.UnknownEntry: - return self.json_message("Invalid entry specified", HTTP_NOT_FOUND) + return self.json_message("Invalid entry specified", HTTPStatus.NOT_FOUND) return self.json({"require_restart": not result}) diff --git a/homeassistant/components/config/zwave.py b/homeassistant/components/config/zwave.py index b0f6fca4817..f8a3ac0cd9f 100644 --- a/homeassistant/components/config/zwave.py +++ b/homeassistant/components/config/zwave.py @@ -1,12 +1,13 @@ """Provide configuration end points for Z-Wave.""" from collections import deque +from http import HTTPStatus import logging from aiohttp.web import Response from homeassistant.components.http import HomeAssistantView from homeassistant.components.zwave import DEVICE_CONFIG_SCHEMA_ENTRY, const -from homeassistant.const import HTTP_ACCEPTED, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, HTTP_OK +from homeassistant.const import HTTP_BAD_REQUEST import homeassistant.core as ha import homeassistant.helpers.config_validation as cv @@ -82,10 +83,12 @@ class ZWaveConfigWriteView(HomeAssistantView): hass = request.app["hass"] network = hass.data.get(const.DATA_NETWORK) if network is None: - return self.json_message("No Z-Wave network data found", HTTP_NOT_FOUND) + return self.json_message( + "No Z-Wave network data found", HTTPStatus.NOT_FOUND + ) _LOGGER.info("Z-Wave configuration written to file") network.write_config() - return self.json_message("Z-Wave configuration saved to file", HTTP_OK) + return self.json_message("Z-Wave configuration saved to file") class ZWaveNodeValueView(HomeAssistantView): @@ -131,7 +134,7 @@ class ZWaveNodeGroupView(HomeAssistantView): network = hass.data.get(const.DATA_NETWORK) node = network.nodes.get(nodeid) if node is None: - return self.json_message("Node not found", HTTP_NOT_FOUND) + return self.json_message("Node not found", HTTPStatus.NOT_FOUND) groupdata = node.groups groups = {} for key, value in groupdata.items(): @@ -158,7 +161,7 @@ class ZWaveNodeConfigView(HomeAssistantView): network = hass.data.get(const.DATA_NETWORK) node = network.nodes.get(nodeid) if node is None: - return self.json_message("Node not found", HTTP_NOT_FOUND) + return self.json_message("Node not found", HTTPStatus.NOT_FOUND) config = {} for value in node.get_values( class_id=const.COMMAND_CLASS_CONFIGURATION @@ -189,7 +192,7 @@ class ZWaveUserCodeView(HomeAssistantView): network = hass.data.get(const.DATA_NETWORK) node = network.nodes.get(nodeid) if node is None: - return self.json_message("Node not found", HTTP_NOT_FOUND) + return self.json_message("Node not found", HTTPStatus.NOT_FOUND) usercodes = {} if not node.has_command_class(const.COMMAND_CLASS_USER_CODE): return self.json(usercodes) @@ -220,7 +223,7 @@ class ZWaveProtectionView(HomeAssistantView): """Get protection data.""" node = network.nodes.get(nodeid) if node is None: - return self.json_message("Node not found", HTTP_NOT_FOUND) + return self.json_message("Node not found", HTTPStatus.NOT_FOUND) protection_options = {} if not node.has_command_class(const.COMMAND_CLASS_PROTECTION): return self.json(protection_options) @@ -247,16 +250,16 @@ class ZWaveProtectionView(HomeAssistantView): selection = protection_data["selection"] value_id = int(protection_data[const.ATTR_VALUE_ID]) if node is None: - return self.json_message("Node not found", HTTP_NOT_FOUND) + return self.json_message("Node not found", HTTPStatus.NOT_FOUND) if not node.has_command_class(const.COMMAND_CLASS_PROTECTION): return self.json_message( - "No protection commandclass on this node", HTTP_NOT_FOUND + "No protection commandclass on this node", HTTPStatus.NOT_FOUND ) state = node.set_protection(value_id, selection) if not state: return self.json_message( - "Protection setting did not complete", HTTP_ACCEPTED + "Protection setting did not complete", HTTPStatus.ACCEPTED ) - return self.json_message("Protection setting succsessfully set", HTTP_OK) + return self.json_message("Protection setting successfully set") return await hass.async_add_executor_job(_set_protection) diff --git a/homeassistant/components/conversation/__init__.py b/homeassistant/components/conversation/__init__.py index f8534d99935..4d3297d8c65 100644 --- a/homeassistant/components/conversation/__init__.py +++ b/homeassistant/components/conversation/__init__.py @@ -1,4 +1,5 @@ """Support for functionality to have conversations with Home Assistant.""" +from http import HTTPStatus import logging import re @@ -7,7 +8,6 @@ import voluptuous as vol from homeassistant import core from homeassistant.components import http, websocket_api from homeassistant.components.http.data_validator import RequestDataValidator -from homeassistant.const import HTTP_INTERNAL_SERVER_ERROR from homeassistant.helpers import config_validation as cv, intent from homeassistant.loader import bind_hass @@ -146,7 +146,7 @@ class ConversationProcessView(http.HomeAssistantView): "message": str(err), }, }, - status_code=HTTP_INTERNAL_SERVER_ERROR, + status_code=HTTPStatus.INTERNAL_SERVER_ERROR, ) return self.json(intent_result) diff --git a/homeassistant/components/emulated_hue/hue_api.py b/homeassistant/components/emulated_hue/hue_api.py index bbd899b559b..a7106f5105f 100644 --- a/homeassistant/components/emulated_hue/hue_api.py +++ b/homeassistant/components/emulated_hue/hue_api.py @@ -1,6 +1,7 @@ """Support for a Hue API to control Home Assistant.""" import asyncio import hashlib +from http import HTTPStatus from ipaddress import ip_address import logging import time @@ -55,9 +56,6 @@ from homeassistant.const import ( ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, ATTR_TEMPERATURE, - HTTP_BAD_REQUEST, - HTTP_NOT_FOUND, - HTTP_UNAUTHORIZED, SERVICE_CLOSE_COVER, SERVICE_OPEN_COVER, SERVICE_TURN_OFF, @@ -136,15 +134,15 @@ class HueUsernameView(HomeAssistantView): async def post(self, request): """Handle a POST request.""" if not is_local(ip_address(request.remote)): - return self.json_message("Only local IPs allowed", HTTP_UNAUTHORIZED) + return self.json_message("Only local IPs allowed", HTTPStatus.UNAUTHORIZED) try: data = await request.json() except ValueError: - return self.json_message("Invalid JSON", HTTP_BAD_REQUEST) + return self.json_message("Invalid JSON", HTTPStatus.BAD_REQUEST) if "devicetype" not in data: - return self.json_message("devicetype not specified", HTTP_BAD_REQUEST) + return self.json_message("devicetype not specified", HTTPStatus.BAD_REQUEST) return self.json([{"success": {"username": HUE_API_USERNAME}}]) @@ -164,7 +162,7 @@ class HueAllGroupsStateView(HomeAssistantView): def get(self, request, username): """Process a request to make the Brilliant Lightpad work.""" if not is_local(ip_address(request.remote)): - return self.json_message("Only local IPs allowed", HTTP_UNAUTHORIZED) + return self.json_message("Only local IPs allowed", HTTPStatus.UNAUTHORIZED) return self.json({}) @@ -184,7 +182,7 @@ class HueGroupView(HomeAssistantView): def put(self, request, username): """Process a request to make the Logitech Pop working.""" if not is_local(ip_address(request.remote)): - return self.json_message("Only local IPs allowed", HTTP_UNAUTHORIZED) + return self.json_message("Only local IPs allowed", HTTPStatus.UNAUTHORIZED) return self.json( [ @@ -214,7 +212,7 @@ class HueAllLightsStateView(HomeAssistantView): def get(self, request, username): """Process a request to get the list of available lights.""" if not is_local(ip_address(request.remote)): - return self.json_message("Only local IPs allowed", HTTP_UNAUTHORIZED) + return self.json_message("Only local IPs allowed", HTTPStatus.UNAUTHORIZED) return self.json(create_list_of_entities(self.config, request)) @@ -234,7 +232,7 @@ class HueFullStateView(HomeAssistantView): def get(self, request, username): """Process a request to get the list of available lights.""" if not is_local(ip_address(request.remote)): - return self.json_message("only local IPs allowed", HTTP_UNAUTHORIZED) + return self.json_message("only local IPs allowed", HTTPStatus.UNAUTHORIZED) if username != HUE_API_USERNAME: return self.json(UNAUTHORIZED_USER) @@ -262,7 +260,7 @@ class HueConfigView(HomeAssistantView): def get(self, request, username=""): """Process a request to get the configuration.""" if not is_local(ip_address(request.remote)): - return self.json_message("only local IPs allowed", HTTP_UNAUTHORIZED) + return self.json_message("only local IPs allowed", HTTPStatus.UNAUTHORIZED) json_response = create_config_model(self.config, request) @@ -284,7 +282,7 @@ class HueOneLightStateView(HomeAssistantView): def get(self, request, username, entity_id): """Process a request to get the state of an individual light.""" if not is_local(ip_address(request.remote)): - return self.json_message("Only local IPs allowed", HTTP_UNAUTHORIZED) + return self.json_message("Only local IPs allowed", HTTPStatus.UNAUTHORIZED) hass = request.app["hass"] hass_entity_id = self.config.number_to_entity_id(entity_id) @@ -294,17 +292,17 @@ class HueOneLightStateView(HomeAssistantView): "Unknown entity number: %s not found in emulated_hue_ids.json", entity_id, ) - return self.json_message("Entity not found", HTTP_NOT_FOUND) + return self.json_message("Entity not found", HTTPStatus.NOT_FOUND) entity = hass.states.get(hass_entity_id) if entity is None: _LOGGER.error("Entity not found: %s", hass_entity_id) - return self.json_message("Entity not found", HTTP_NOT_FOUND) + return self.json_message("Entity not found", HTTPStatus.NOT_FOUND) if not self.config.is_entity_exposed(entity): _LOGGER.error("Entity not exposed: %s", entity_id) - return self.json_message("Entity not exposed", HTTP_UNAUTHORIZED) + return self.json_message("Entity not exposed", HTTPStatus.UNAUTHORIZED) json_response = entity_to_json(self.config, entity) @@ -325,7 +323,7 @@ class HueOneLightChangeView(HomeAssistantView): async def put(self, request, username, entity_number): # noqa: C901 """Process a request to set the state of an individual light.""" if not is_local(ip_address(request.remote)): - return self.json_message("Only local IPs allowed", HTTP_UNAUTHORIZED) + return self.json_message("Only local IPs allowed", HTTPStatus.UNAUTHORIZED) config = self.config hass = request.app["hass"] @@ -333,23 +331,23 @@ class HueOneLightChangeView(HomeAssistantView): if entity_id is None: _LOGGER.error("Unknown entity number: %s", entity_number) - return self.json_message("Entity not found", HTTP_NOT_FOUND) + return self.json_message("Entity not found", HTTPStatus.NOT_FOUND) entity = hass.states.get(entity_id) if entity is None: _LOGGER.error("Entity not found: %s", entity_id) - return self.json_message("Entity not found", HTTP_NOT_FOUND) + return self.json_message("Entity not found", HTTPStatus.NOT_FOUND) if not config.is_entity_exposed(entity): _LOGGER.error("Entity not exposed: %s", entity_id) - return self.json_message("Entity not exposed", HTTP_UNAUTHORIZED) + return self.json_message("Entity not exposed", HTTPStatus.UNAUTHORIZED) try: request_json = await request.json() except ValueError: _LOGGER.error("Received invalid json") - return self.json_message("Invalid JSON", HTTP_BAD_REQUEST) + return self.json_message("Invalid JSON", HTTPStatus.BAD_REQUEST) # Get the entity's supported features entity_features = entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0) @@ -370,7 +368,7 @@ class HueOneLightChangeView(HomeAssistantView): if HUE_API_STATE_ON in request_json: if not isinstance(request_json[HUE_API_STATE_ON], bool): _LOGGER.error("Unable to parse data: %s", request_json) - return self.json_message("Bad request", HTTP_BAD_REQUEST) + return self.json_message("Bad request", HTTPStatus.BAD_REQUEST) parsed[STATE_ON] = request_json[HUE_API_STATE_ON] else: parsed[STATE_ON] = entity.state != STATE_OFF @@ -387,7 +385,7 @@ class HueOneLightChangeView(HomeAssistantView): parsed[attr] = int(request_json[key]) except ValueError: _LOGGER.error("Unable to parse data (2): %s", request_json) - return self.json_message("Bad request", HTTP_BAD_REQUEST) + return self.json_message("Bad request", HTTPStatus.BAD_REQUEST) if HUE_API_STATE_XY in request_json: try: parsed[STATE_XY] = ( @@ -396,7 +394,7 @@ class HueOneLightChangeView(HomeAssistantView): ) except ValueError: _LOGGER.error("Unable to parse data (2): %s", request_json) - return self.json_message("Bad request", HTTP_BAD_REQUEST) + return self.json_message("Bad request", HTTPStatus.BAD_REQUEST) if HUE_API_STATE_BRI in request_json: if entity.domain == light.DOMAIN: diff --git a/homeassistant/components/foursquare/__init__.py b/homeassistant/components/foursquare/__init__.py index 6f33c9ff591..6dc0d1c8228 100644 --- a/homeassistant/components/foursquare/__init__.py +++ b/homeassistant/components/foursquare/__init__.py @@ -1,16 +1,12 @@ """Support for the Foursquare (Swarm) API.""" +from http import HTTPStatus import logging import requests import voluptuous as vol from homeassistant.components.http import HomeAssistantView -from homeassistant.const import ( - CONF_ACCESS_TOKEN, - HTTP_BAD_REQUEST, - HTTP_CREATED, - HTTP_OK, -) +from homeassistant.const import CONF_ACCESS_TOKEN, HTTP_CREATED, HTTP_OK import homeassistant.helpers.config_validation as cv _LOGGER = logging.getLogger(__name__) @@ -95,7 +91,7 @@ class FoursquarePushReceiver(HomeAssistantView): try: data = await request.json() except ValueError: - return self.json_message("Invalid JSON", HTTP_BAD_REQUEST) + return self.json_message("Invalid JSON", HTTPStatus.BAD_REQUEST) secret = data.pop("secret", None) @@ -105,6 +101,6 @@ class FoursquarePushReceiver(HomeAssistantView): _LOGGER.error( "Received Foursquare push with invalid push secret: %s", secret ) - return self.json_message("Incorrect secret", HTTP_BAD_REQUEST) + return self.json_message("Incorrect secret", HTTPStatus.BAD_REQUEST) request.app["hass"].bus.async_fire(EVENT_PUSH, data) diff --git a/homeassistant/components/history/__init__.py b/homeassistant/components/history/__init__.py index 4f50a5e66be..3ae71602dc1 100644 --- a/homeassistant/components/history/__init__.py +++ b/homeassistant/components/history/__init__.py @@ -3,6 +3,7 @@ from __future__ import annotations from collections.abc import Iterable from datetime import datetime as dt, timedelta +from http import HTTPStatus import logging import time from typing import cast @@ -19,13 +20,7 @@ from homeassistant.components.recorder.statistics import ( statistics_during_period, ) from homeassistant.components.recorder.util import session_scope -from homeassistant.const import ( - CONF_DOMAINS, - CONF_ENTITIES, - CONF_EXCLUDE, - CONF_INCLUDE, - HTTP_BAD_REQUEST, -) +from homeassistant.const import CONF_DOMAINS, CONF_ENTITIES, CONF_EXCLUDE, CONF_INCLUDE from homeassistant.core import HomeAssistant import homeassistant.helpers.config_validation as cv from homeassistant.helpers.deprecation import deprecated_class, deprecated_function @@ -203,7 +198,7 @@ class HistoryPeriodView(HomeAssistantView): datetime_ = dt_util.parse_datetime(datetime) if datetime_ is None: - return self.json_message("Invalid datetime", HTTP_BAD_REQUEST) + return self.json_message("Invalid datetime", HTTPStatus.BAD_REQUEST) now = dt_util.utcnow() @@ -222,7 +217,7 @@ class HistoryPeriodView(HomeAssistantView): if end_time: end_time = dt_util.as_utc(end_time) else: - return self.json_message("Invalid end_time", HTTP_BAD_REQUEST) + return self.json_message("Invalid end_time", HTTPStatus.BAD_REQUEST) else: end_time = start_time + one_day entity_ids_str = request.query.get("filter_entity_id") diff --git a/homeassistant/components/html5/notify.py b/homeassistant/components/html5/notify.py index eceaa0b73b9..594d84a8068 100644 --- a/homeassistant/components/html5/notify.py +++ b/homeassistant/components/html5/notify.py @@ -2,6 +2,7 @@ from contextlib import suppress from datetime import datetime, timedelta from functools import partial +from http import HTTPStatus import json import logging import time @@ -26,13 +27,7 @@ from homeassistant.components.notify import ( PLATFORM_SCHEMA, BaseNotificationService, ) -from homeassistant.const import ( - ATTR_NAME, - HTTP_BAD_REQUEST, - HTTP_INTERNAL_SERVER_ERROR, - HTTP_UNAUTHORIZED, - URL_ROOT, -) +from homeassistant.const import ATTR_NAME, URL_ROOT from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import config_validation as cv from homeassistant.util import ensure_unique_string @@ -224,11 +219,11 @@ class HTML5PushRegistrationView(HomeAssistantView): try: data = await request.json() except ValueError: - return self.json_message("Invalid JSON", HTTP_BAD_REQUEST) + return self.json_message("Invalid JSON", HTTPStatus.BAD_REQUEST) try: data = REGISTER_SCHEMA(data) except vol.Invalid as ex: - return self.json_message(humanize_error(data, ex), HTTP_BAD_REQUEST) + return self.json_message(humanize_error(data, ex), HTTPStatus.BAD_REQUEST) devname = data.get(ATTR_NAME) data.pop(ATTR_NAME, None) @@ -252,7 +247,7 @@ class HTML5PushRegistrationView(HomeAssistantView): self.registrations.pop(name) return self.json_message( - "Error saving registration.", HTTP_INTERNAL_SERVER_ERROR + "Error saving registration.", HTTPStatus.INTERNAL_SERVER_ERROR ) def find_registration_name(self, data, suggested=None): @@ -269,7 +264,7 @@ class HTML5PushRegistrationView(HomeAssistantView): try: data = await request.json() except ValueError: - return self.json_message("Invalid JSON", HTTP_BAD_REQUEST) + return self.json_message("Invalid JSON", HTTPStatus.BAD_REQUEST) subscription = data.get(ATTR_SUBSCRIPTION) @@ -295,7 +290,7 @@ class HTML5PushRegistrationView(HomeAssistantView): except HomeAssistantError: self.registrations[found] = reg return self.json_message( - "Error saving registration.", HTTP_INTERNAL_SERVER_ERROR + "Error saving registration.", HTTPStatus.INTERNAL_SERVER_ERROR ) return self.json_message("Push notification subscriber unregistered.") @@ -330,7 +325,7 @@ class HTML5PushCallbackView(HomeAssistantView): return jwt.decode(token, key, algorithms=["ES256", "HS256"]) return self.json_message( - "No target found in JWT", status_code=HTTP_UNAUTHORIZED + "No target found in JWT", status_code=HTTPStatus.UNAUTHORIZED ) # The following is based on code from Auth0 @@ -341,7 +336,7 @@ class HTML5PushCallbackView(HomeAssistantView): auth = request.headers.get(AUTHORIZATION) if not auth: return self.json_message( - "Authorization header is expected", status_code=HTTP_UNAUTHORIZED + "Authorization header is expected", status_code=HTTPStatus.UNAUTHORIZED ) parts = auth.split() @@ -349,19 +344,21 @@ class HTML5PushCallbackView(HomeAssistantView): if parts[0].lower() != "bearer": return self.json_message( "Authorization header must start with Bearer", - status_code=HTTP_UNAUTHORIZED, + status_code=HTTPStatus.UNAUTHORIZED, ) if len(parts) != 2: return self.json_message( "Authorization header must be Bearer token", - status_code=HTTP_UNAUTHORIZED, + status_code=HTTPStatus.UNAUTHORIZED, ) token = parts[1] try: payload = self.decode_jwt(token) except jwt.exceptions.InvalidTokenError: - return self.json_message("token is invalid", status_code=HTTP_UNAUTHORIZED) + return self.json_message( + "token is invalid", status_code=HTTPStatus.UNAUTHORIZED + ) return payload async def post(self, request): @@ -373,7 +370,7 @@ class HTML5PushCallbackView(HomeAssistantView): try: data = await request.json() except ValueError: - return self.json_message("Invalid JSON", HTTP_BAD_REQUEST) + return self.json_message("Invalid JSON", HTTPStatus.BAD_REQUEST) event_payload = { ATTR_TAG: data.get(ATTR_TAG), diff --git a/homeassistant/components/http/data_validator.py b/homeassistant/components/http/data_validator.py index 2768350c183..f64a3c4830e 100644 --- a/homeassistant/components/http/data_validator.py +++ b/homeassistant/components/http/data_validator.py @@ -3,14 +3,13 @@ from __future__ import annotations from collections.abc import Awaitable from functools import wraps +from http import HTTPStatus import logging from typing import Any, Callable from aiohttp import web import voluptuous as vol -from homeassistant.const import HTTP_BAD_REQUEST - from .view import HomeAssistantView _LOGGER = logging.getLogger(__name__) @@ -49,7 +48,7 @@ class RequestDataValidator: except ValueError: if not self._allow_empty or (await request.content.read()) != b"": _LOGGER.error("Invalid JSON received") - return view.json_message("Invalid JSON.", HTTP_BAD_REQUEST) + return view.json_message("Invalid JSON.", HTTPStatus.BAD_REQUEST) data = {} try: @@ -57,7 +56,7 @@ class RequestDataValidator: except vol.Invalid as err: _LOGGER.error("Data does not match schema: %s", err) return view.json_message( - f"Message format incorrect: {err}", HTTP_BAD_REQUEST + f"Message format incorrect: {err}", HTTPStatus.BAD_REQUEST ) result = await method(view, request, *args, **kwargs) diff --git a/homeassistant/components/http/view.py b/homeassistant/components/http/view.py index 129c43600c4..39225c918e5 100644 --- a/homeassistant/components/http/view.py +++ b/homeassistant/components/http/view.py @@ -3,6 +3,7 @@ from __future__ import annotations import asyncio from collections.abc import Awaitable, Callable +from http import HTTPStatus import json import logging from typing import Any @@ -48,7 +49,7 @@ class HomeAssistantView: @staticmethod def json( result: Any, - status_code: int = HTTP_OK, + status_code: HTTPStatus | int = HTTPStatus.OK, headers: LooseHeaders | None = None, ) -> web.Response: """Return a JSON response.""" @@ -60,7 +61,7 @@ class HomeAssistantView: response = web.Response( body=msg, content_type=CONTENT_TYPE_JSON, - status=status_code, + status=int(status_code), headers=headers, ) response.enable_compression() @@ -69,7 +70,7 @@ class HomeAssistantView: def json_message( self, message: str, - status_code: int = HTTP_OK, + status_code: HTTPStatus | int = HTTPStatus.OK, message_code: str | None = None, headers: LooseHeaders | None = None, ) -> web.Response: diff --git a/homeassistant/components/ios/__init__.py b/homeassistant/components/ios/__init__.py index 6797da9d8a6..048107910d1 100644 --- a/homeassistant/components/ios/__init__.py +++ b/homeassistant/components/ios/__init__.py @@ -1,11 +1,11 @@ """Native Home Assistant iOS app component.""" import datetime +from http import HTTPStatus import voluptuous as vol from homeassistant import config_entries from homeassistant.components.http import HomeAssistantView -from homeassistant.const import HTTP_BAD_REQUEST, HTTP_INTERNAL_SERVER_ERROR from homeassistant.core import callback from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import config_validation as cv, discovery @@ -333,7 +333,7 @@ class iOSIdentifyDeviceView(HomeAssistantView): try: data = await request.json() except ValueError: - return self.json_message("Invalid JSON", HTTP_BAD_REQUEST) + return self.json_message("Invalid JSON", HTTPStatus.BAD_REQUEST) hass = request.app["hass"] @@ -348,6 +348,8 @@ class iOSIdentifyDeviceView(HomeAssistantView): try: save_json(self._config_path, hass.data[DOMAIN]) except HomeAssistantError: - return self.json_message("Error saving device.", HTTP_INTERNAL_SERVER_ERROR) + return self.json_message( + "Error saving device.", HTTPStatus.INTERNAL_SERVER_ERROR + ) return self.json({"status": "registered"}) diff --git a/homeassistant/components/konnected/__init__.py b/homeassistant/components/konnected/__init__.py index 6785e2e7124..29502f3878c 100644 --- a/homeassistant/components/konnected/__init__.py +++ b/homeassistant/components/konnected/__init__.py @@ -1,6 +1,7 @@ """Support for Konnected devices.""" import copy import hmac +from http import HTTPStatus import json import logging @@ -28,9 +29,6 @@ from homeassistant.const import ( CONF_SWITCHES, CONF_TYPE, CONF_ZONE, - HTTP_BAD_REQUEST, - HTTP_NOT_FOUND, - HTTP_UNAUTHORIZED, STATE_OFF, STATE_ON, ) @@ -325,7 +323,9 @@ class KonnectedView(HomeAssistantView): (True for token in tokens if hmac.compare_digest(f"Bearer {token}", auth)), False, ): - return self.json_message("unauthorized", status_code=HTTP_UNAUTHORIZED) + return self.json_message( + "unauthorized", status_code=HTTPStatus.UNAUTHORIZED + ) try: # Konnected 2.2.0 and above supports JSON payloads payload = await request.json() @@ -339,7 +339,7 @@ class KonnectedView(HomeAssistantView): device = data[CONF_DEVICES].get(device_id) if device is None: return self.json_message( - "unregistered device", status_code=HTTP_BAD_REQUEST + "unregistered device", status_code=HTTPStatus.BAD_REQUEST ) panel = device.get("panel") @@ -364,7 +364,7 @@ class KonnectedView(HomeAssistantView): if zone_data is None: return self.json_message( - "unregistered sensor/actuator", status_code=HTTP_BAD_REQUEST + "unregistered sensor/actuator", status_code=HTTPStatus.BAD_REQUEST ) zone_data["device_id"] = device_id @@ -385,7 +385,7 @@ class KonnectedView(HomeAssistantView): device = data[CONF_DEVICES].get(device_id) if not device: return self.json_message( - f"Device {device_id} not configured", status_code=HTTP_NOT_FOUND + f"Device {device_id} not configured", status_code=HTTPStatus.NOT_FOUND ) panel = device.get("panel") @@ -417,7 +417,7 @@ class KonnectedView(HomeAssistantView): ) return self.json_message( f"Switch on zone or pin {target} not configured", - status_code=HTTP_NOT_FOUND, + status_code=HTTPStatus.NOT_FOUND, ) resp = {} diff --git a/homeassistant/components/logbook/__init__.py b/homeassistant/components/logbook/__init__.py index 8bbfd08314d..91739aa5990 100644 --- a/homeassistant/components/logbook/__init__.py +++ b/homeassistant/components/logbook/__init__.py @@ -1,6 +1,7 @@ """Event parser and human readable log generator.""" from contextlib import suppress from datetime import timedelta +from http import HTTPStatus from itertools import groupby import json import re @@ -32,7 +33,6 @@ from homeassistant.const import ( EVENT_HOMEASSISTANT_STOP, EVENT_LOGBOOK_ENTRY, EVENT_STATE_CHANGED, - HTTP_BAD_REQUEST, ) from homeassistant.core import DOMAIN as HA_DOMAIN, callback, split_entity_id from homeassistant.exceptions import InvalidEntityFormatError @@ -198,7 +198,7 @@ class LogbookView(HomeAssistantView): datetime = dt_util.parse_datetime(datetime) if datetime is None: - return self.json_message("Invalid datetime", HTTP_BAD_REQUEST) + return self.json_message("Invalid datetime", HTTPStatus.BAD_REQUEST) else: datetime = dt_util.start_of_local_day() @@ -226,7 +226,7 @@ class LogbookView(HomeAssistantView): start_day = datetime end_day = dt_util.parse_datetime(end_time) if end_day is None: - return self.json_message("Invalid end_time", HTTP_BAD_REQUEST) + return self.json_message("Invalid end_time", HTTPStatus.BAD_REQUEST) hass = request.app["hass"] @@ -235,7 +235,7 @@ class LogbookView(HomeAssistantView): if entity_ids and context_id: return self.json_message( - "Can't combine entity with context_id", HTTP_BAD_REQUEST + "Can't combine entity with context_id", HTTPStatus.BAD_REQUEST ) def json_events(): diff --git a/homeassistant/components/logi_circle/config_flow.py b/homeassistant/components/logi_circle/config_flow.py index d61de1ea017..9054b476332 100644 --- a/homeassistant/components/logi_circle/config_flow.py +++ b/homeassistant/components/logi_circle/config_flow.py @@ -1,6 +1,7 @@ """Config flow to configure Logi Circle component.""" import asyncio from collections import OrderedDict +from http import HTTPStatus import async_timeout from logi_circle import LogiCircle @@ -14,7 +15,6 @@ from homeassistant.const import ( CONF_CLIENT_ID, CONF_CLIENT_SECRET, CONF_SENSORS, - HTTP_BAD_REQUEST, ) from homeassistant.core import callback @@ -201,5 +201,6 @@ class LogiCircleAuthCallbackView(HomeAssistantView): ) return self.json_message("Authorisation code saved") return self.json_message( - "Authorisation code missing from query string", status_code=HTTP_BAD_REQUEST + "Authorisation code missing from query string", + status_code=HTTPStatus.BAD_REQUEST, ) diff --git a/homeassistant/components/meraki/device_tracker.py b/homeassistant/components/meraki/device_tracker.py index 159083ecd23..28953a47213 100644 --- a/homeassistant/components/meraki/device_tracker.py +++ b/homeassistant/components/meraki/device_tracker.py @@ -1,4 +1,5 @@ """Support for the Meraki CMX location service.""" +from http import HTTPStatus import json import logging @@ -9,7 +10,6 @@ from homeassistant.components.device_tracker import ( SOURCE_TYPE_ROUTER, ) from homeassistant.components.http import HomeAssistantView -from homeassistant.const import HTTP_BAD_REQUEST, HTTP_UNPROCESSABLE_ENTITY from homeassistant.core import callback import homeassistant.helpers.config_validation as cv @@ -56,21 +56,23 @@ class MerakiView(HomeAssistantView): try: data = await request.json() except ValueError: - return self.json_message("Invalid JSON", HTTP_BAD_REQUEST) + return self.json_message("Invalid JSON", HTTPStatus.BAD_REQUEST) _LOGGER.debug("Meraki Data from Post: %s", json.dumps(data)) if not data.get("secret", False): _LOGGER.error("The secret is invalid") - return self.json_message("No secret", HTTP_UNPROCESSABLE_ENTITY) + return self.json_message("No secret", HTTPStatus.UNPROCESSABLE_ENTITY) if data["secret"] != self.secret: _LOGGER.error("Invalid Secret received from Meraki") - return self.json_message("Invalid secret", HTTP_UNPROCESSABLE_ENTITY) + return self.json_message("Invalid secret", HTTPStatus.UNPROCESSABLE_ENTITY) if data["version"] != VERSION: _LOGGER.error("Invalid API version: %s", data["version"]) - return self.json_message("Invalid version", HTTP_UNPROCESSABLE_ENTITY) + return self.json_message("Invalid version", HTTPStatus.UNPROCESSABLE_ENTITY) _LOGGER.debug("Valid Secret") if data["type"] not in ("DevicesSeen", "BluetoothDevicesSeen"): _LOGGER.error("Unknown Device %s", data["type"]) - return self.json_message("Invalid device type", HTTP_UNPROCESSABLE_ENTITY) + return self.json_message( + "Invalid device type", HTTPStatus.UNPROCESSABLE_ENTITY + ) _LOGGER.debug("Processing %s", data["type"]) if not data["data"]["observations"]: _LOGGER.debug("No observations found") diff --git a/homeassistant/components/mobile_app/http_api.py b/homeassistant/components/mobile_app/http_api.py index 63bf13bad5e..05b370c711d 100644 --- a/homeassistant/components/mobile_app/http_api.py +++ b/homeassistant/components/mobile_app/http_api.py @@ -2,6 +2,7 @@ from __future__ import annotations from contextlib import suppress +from http import HTTPStatus import secrets from aiohttp.web import Request, Response @@ -11,7 +12,7 @@ import voluptuous as vol from homeassistant.components.http import HomeAssistantView from homeassistant.components.http.data_validator import RequestDataValidator -from homeassistant.const import ATTR_DEVICE_ID, CONF_WEBHOOK_ID, HTTP_CREATED +from homeassistant.const import ATTR_DEVICE_ID, CONF_WEBHOOK_ID from homeassistant.helpers import config_validation as cv from homeassistant.util import slugify @@ -109,5 +110,5 @@ class RegistrationsView(HomeAssistantView): CONF_SECRET: data.get(CONF_SECRET), CONF_WEBHOOK_ID: data[CONF_WEBHOOK_ID], }, - status_code=HTTP_CREATED, + status_code=HTTPStatus.CREATED, ) diff --git a/homeassistant/components/onboarding/views.py b/homeassistant/components/onboarding/views.py index cedce0d1d51..61a99d345ff 100644 --- a/homeassistant/components/onboarding/views.py +++ b/homeassistant/components/onboarding/views.py @@ -1,5 +1,6 @@ """Onboarding views.""" import asyncio +from http import HTTPStatus from aiohttp.web_exceptions import HTTPUnauthorized import voluptuous as vol @@ -9,7 +10,6 @@ from homeassistant.components.auth import indieauth from homeassistant.components.http.const import KEY_HASS_REFRESH_TOKEN_ID from homeassistant.components.http.data_validator import RequestDataValidator from homeassistant.components.http.view import HomeAssistantView -from homeassistant.const import HTTP_BAD_REQUEST, HTTP_FORBIDDEN from homeassistant.core import callback from homeassistant.helpers.system_info import async_get_system_info @@ -124,7 +124,7 @@ class UserOnboardingView(_BaseOnboardingView): async with self._lock: if self._async_is_done(): - return self.json_message("User step already done", HTTP_FORBIDDEN) + return self.json_message("User step already done", HTTPStatus.FORBIDDEN) provider = _async_get_hass_provider(hass) await provider.async_initialize() @@ -179,7 +179,7 @@ class CoreConfigOnboardingView(_BaseOnboardingView): async with self._lock: if self._async_is_done(): return self.json_message( - "Core config step already done", HTTP_FORBIDDEN + "Core config step already done", HTTPStatus.FORBIDDEN ) await self._async_mark_done(hass) @@ -217,7 +217,7 @@ class IntegrationOnboardingView(_BaseOnboardingView): async with self._lock: if self._async_is_done(): return self.json_message( - "Integration step already done", HTTP_FORBIDDEN + "Integration step already done", HTTPStatus.FORBIDDEN ) await self._async_mark_done(hass) @@ -227,13 +227,13 @@ class IntegrationOnboardingView(_BaseOnboardingView): request.app["hass"], data["client_id"], data["redirect_uri"] ): return self.json_message( - "invalid client id or redirect uri", HTTP_BAD_REQUEST + "invalid client id or redirect uri", HTTPStatus.BAD_REQUEST ) refresh_token = await hass.auth.async_get_refresh_token(refresh_token_id) if refresh_token is None or refresh_token.credential is None: return self.json_message( - "Credentials for user not available", HTTP_FORBIDDEN + "Credentials for user not available", HTTPStatus.FORBIDDEN ) # Return authorization code so we can redirect user and log them in @@ -257,7 +257,7 @@ class AnalyticsOnboardingView(_BaseOnboardingView): async with self._lock: if self._async_is_done(): return self.json_message( - "Analytics config step already done", HTTP_FORBIDDEN + "Analytics config step already done", HTTPStatus.FORBIDDEN ) await self._async_mark_done(hass) diff --git a/homeassistant/components/shopping_list/__init__.py b/homeassistant/components/shopping_list/__init__.py index 49b4d8a5d91..a38720bef59 100644 --- a/homeassistant/components/shopping_list/__init__.py +++ b/homeassistant/components/shopping_list/__init__.py @@ -1,4 +1,5 @@ """Support to manage a shopping list.""" +from http import HTTPStatus import logging import uuid @@ -7,7 +8,7 @@ import voluptuous as vol from homeassistant import config_entries from homeassistant.components import http, websocket_api from homeassistant.components.http.data_validator import RequestDataValidator -from homeassistant.const import ATTR_NAME, HTTP_BAD_REQUEST, HTTP_NOT_FOUND +from homeassistant.const import ATTR_NAME from homeassistant.core import callback import homeassistant.helpers.config_validation as cv from homeassistant.util.json import load_json, save_json @@ -293,9 +294,9 @@ class UpdateShoppingListItemView(http.HomeAssistantView): request.app["hass"].bus.async_fire(EVENT) return self.json(item) except KeyError: - return self.json_message("Item not found", HTTP_NOT_FOUND) + return self.json_message("Item not found", HTTPStatus.NOT_FOUND) except vol.Invalid: - return self.json_message("Item not found", HTTP_BAD_REQUEST) + return self.json_message("Item not found", HTTPStatus.BAD_REQUEST) class CreateShoppingListItemView(http.HomeAssistantView): diff --git a/homeassistant/components/telegram_bot/webhooks.py b/homeassistant/components/telegram_bot/webhooks.py index bd0dde7c02c..c1e86129ebb 100644 --- a/homeassistant/components/telegram_bot/webhooks.py +++ b/homeassistant/components/telegram_bot/webhooks.py @@ -1,16 +1,13 @@ """Support for Telegram bots using webhooks.""" import datetime as dt +from http import HTTPStatus from ipaddress import ip_address import logging from telegram.error import TimedOut from homeassistant.components.http import HomeAssistantView -from homeassistant.const import ( - EVENT_HOMEASSISTANT_STOP, - HTTP_BAD_REQUEST, - HTTP_UNAUTHORIZED, -) +from homeassistant.const import EVENT_HOMEASSISTANT_STOP from homeassistant.helpers.network import get_url from . import ( @@ -98,13 +95,13 @@ class BotPushReceiver(HomeAssistantView, BaseTelegramBotEntity): real_ip = ip_address(request.remote) if not any(real_ip in net for net in self.trusted_networks): _LOGGER.warning("Access denied from %s", real_ip) - return self.json_message("Access denied", HTTP_UNAUTHORIZED) + return self.json_message("Access denied", HTTPStatus.UNAUTHORIZED) try: data = await request.json() except ValueError: - return self.json_message("Invalid JSON", HTTP_BAD_REQUEST) + return self.json_message("Invalid JSON", HTTPStatus.BAD_REQUEST) if not self.process_message(data): - return self.json_message("Invalid message", HTTP_BAD_REQUEST) + return self.json_message("Invalid message", HTTPStatus.BAD_REQUEST) return None diff --git a/homeassistant/components/tts/__init__.py b/homeassistant/components/tts/__init__.py index be38eb6ec09..59dfaf484b4 100644 --- a/homeassistant/components/tts/__init__.py +++ b/homeassistant/components/tts/__init__.py @@ -4,6 +4,7 @@ from __future__ import annotations import asyncio import functools as ft import hashlib +from http import HTTPStatus import io import logging import mimetypes @@ -29,7 +30,6 @@ from homeassistant.const import ( CONF_DESCRIPTION, CONF_NAME, CONF_PLATFORM, - HTTP_BAD_REQUEST, HTTP_NOT_FOUND, PLATFORM_FORMAT, ) @@ -598,10 +598,10 @@ class TextToSpeechUrlView(HomeAssistantView): try: data = await request.json() except ValueError: - return self.json_message("Invalid JSON specified", HTTP_BAD_REQUEST) + return self.json_message("Invalid JSON specified", HTTPStatus.BAD_REQUEST) if not data.get(ATTR_PLATFORM) and data.get(ATTR_MESSAGE): return self.json_message( - "Must specify platform and message", HTTP_BAD_REQUEST + "Must specify platform and message", HTTPStatus.BAD_REQUEST ) p_type = data[ATTR_PLATFORM] @@ -616,7 +616,7 @@ class TextToSpeechUrlView(HomeAssistantView): ) except HomeAssistantError as err: _LOGGER.error("Error on init tts: %s", err) - return self.json({"error": err}, HTTP_BAD_REQUEST) + return self.json({"error": err}, HTTPStatus.BAD_REQUEST) base = self.tts.base_url or get_url(self.tts.hass) url = base + path diff --git a/homeassistant/components/withings/common.py b/homeassistant/components/withings/common.py index 732197b7dcb..9d8d68c1927 100644 --- a/homeassistant/components/withings/common.py +++ b/homeassistant/components/withings/common.py @@ -507,7 +507,7 @@ class ConfigEntryWithingsApi(AbstractWithingsApi): def json_message_response(message: str, message_code: int) -> Response: """Produce common json output.""" - return HomeAssistantView.json({"message": message, "code": message_code}, 200) + return HomeAssistantView.json({"message": message, "code": message_code}) class WebhookAvailability(IntEnum): diff --git a/homeassistant/helpers/data_entry_flow.py b/homeassistant/helpers/data_entry_flow.py index 07f12a08262..7cdb1823ae0 100644 --- a/homeassistant/helpers/data_entry_flow.py +++ b/homeassistant/helpers/data_entry_flow.py @@ -1,6 +1,7 @@ """Helpers for the data entry flow.""" from __future__ import annotations +from http import HTTPStatus from typing import Any from aiohttp import web @@ -9,7 +10,6 @@ import voluptuous as vol from homeassistant import config_entries, data_entry_flow from homeassistant.components.http import HomeAssistantView from homeassistant.components.http.data_validator import RequestDataValidator -from homeassistant.const import HTTP_BAD_REQUEST, HTTP_NOT_FOUND import homeassistant.helpers.config_validation as cv @@ -77,9 +77,11 @@ class FlowManagerIndexView(_BaseFlowManagerView): }, ) except data_entry_flow.UnknownHandler: - return self.json_message("Invalid handler specified", HTTP_NOT_FOUND) + return self.json_message("Invalid handler specified", HTTPStatus.NOT_FOUND) except data_entry_flow.UnknownStep: - return self.json_message("Handler does not support user", HTTP_BAD_REQUEST) + return self.json_message( + "Handler does not support user", HTTPStatus.BAD_REQUEST + ) result = self._prepare_result_json(result) @@ -94,7 +96,7 @@ class FlowManagerResourceView(_BaseFlowManagerView): try: result = await self._flow_mgr.async_configure(flow_id) except data_entry_flow.UnknownFlow: - return self.json_message("Invalid flow specified", HTTP_NOT_FOUND) + return self.json_message("Invalid flow specified", HTTPStatus.NOT_FOUND) result = self._prepare_result_json(result) @@ -108,9 +110,9 @@ class FlowManagerResourceView(_BaseFlowManagerView): try: result = await self._flow_mgr.async_configure(flow_id, data) except data_entry_flow.UnknownFlow: - return self.json_message("Invalid flow specified", HTTP_NOT_FOUND) + return self.json_message("Invalid flow specified", HTTPStatus.NOT_FOUND) except vol.Invalid: - return self.json_message("User input malformed", HTTP_BAD_REQUEST) + return self.json_message("User input malformed", HTTPStatus.BAD_REQUEST) result = self._prepare_result_json(result) @@ -121,6 +123,6 @@ class FlowManagerResourceView(_BaseFlowManagerView): try: self._flow_mgr.async_abort(flow_id) except data_entry_flow.UnknownFlow: - return self.json_message("Invalid flow specified", HTTP_NOT_FOUND) + return self.json_message("Invalid flow specified", HTTPStatus.NOT_FOUND) return self.json_message("Flow aborted") diff --git a/tests/components/config/test_zwave.py b/tests/components/config/test_zwave.py index 2f15a167c92..06dd3434738 100644 --- a/tests/components/config/test_zwave.py +++ b/tests/components/config/test_zwave.py @@ -455,7 +455,7 @@ async def test_set_protection_value(hass, client): assert resp.status == 200 result = await resp.json() assert node.set_protection.called - assert result == {"message": "Protection setting succsessfully set"} + assert result == {"message": "Protection setting successfully set"} async def test_set_protection_value_failed(hass, client):