mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 20:57:21 +00:00
Add strict typing for input_text (#103095)
This commit is contained in:
parent
8e2c2e5cc5
commit
8668f47543
@ -180,6 +180,7 @@ homeassistant.components.image_upload.*
|
|||||||
homeassistant.components.imap.*
|
homeassistant.components.imap.*
|
||||||
homeassistant.components.input_button.*
|
homeassistant.components.input_button.*
|
||||||
homeassistant.components.input_select.*
|
homeassistant.components.input_select.*
|
||||||
|
homeassistant.components.input_text.*
|
||||||
homeassistant.components.integration.*
|
homeassistant.components.integration.*
|
||||||
homeassistant.components.ipp.*
|
homeassistant.components.ipp.*
|
||||||
homeassistant.components.iqvia.*
|
homeassistant.components.iqvia.*
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Self
|
from typing import Any, Self
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
@ -61,20 +61,20 @@ STORAGE_FIELDS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def _cv_input_text(cfg):
|
def _cv_input_text(config: dict[str, Any]) -> dict[str, Any]:
|
||||||
"""Configure validation helper for input box (voluptuous)."""
|
"""Configure validation helper for input box (voluptuous)."""
|
||||||
minimum = cfg.get(CONF_MIN)
|
minimum: int = config[CONF_MIN]
|
||||||
maximum = cfg.get(CONF_MAX)
|
maximum: int = config[CONF_MAX]
|
||||||
if minimum > maximum:
|
if minimum > maximum:
|
||||||
raise vol.Invalid(
|
raise vol.Invalid(
|
||||||
f"Max len ({minimum}) is not greater than min len ({maximum})"
|
f"Max len ({minimum}) is not greater than min len ({maximum})"
|
||||||
)
|
)
|
||||||
state = cfg.get(CONF_INITIAL)
|
state: str | None = config.get(CONF_INITIAL)
|
||||||
if state is not None and (len(state) < minimum or len(state) > maximum):
|
if state is not None and (len(state) < minimum or len(state) > maximum):
|
||||||
raise vol.Invalid(
|
raise vol.Invalid(
|
||||||
f"Initial value {state} length not in range {minimum}-{maximum}"
|
f"Initial value {state} length not in range {minimum}-{maximum}"
|
||||||
)
|
)
|
||||||
return cfg
|
return config
|
||||||
|
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema(
|
CONFIG_SCHEMA = vol.Schema(
|
||||||
@ -86,7 +86,7 @@ CONFIG_SCHEMA = vol.Schema(
|
|||||||
vol.Optional(CONF_NAME): cv.string,
|
vol.Optional(CONF_NAME): cv.string,
|
||||||
vol.Optional(CONF_MIN, default=CONF_MIN_VALUE): vol.Coerce(int),
|
vol.Optional(CONF_MIN, default=CONF_MIN_VALUE): vol.Coerce(int),
|
||||||
vol.Optional(CONF_MAX, default=CONF_MAX_VALUE): vol.Coerce(int),
|
vol.Optional(CONF_MAX, default=CONF_MAX_VALUE): vol.Coerce(int),
|
||||||
vol.Optional(CONF_INITIAL, ""): cv.string,
|
vol.Optional(CONF_INITIAL): cv.string,
|
||||||
vol.Optional(CONF_ICON): cv.icon,
|
vol.Optional(CONF_ICON): cv.icon,
|
||||||
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
|
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
|
||||||
vol.Optional(CONF_PATTERN): cv.string,
|
vol.Optional(CONF_PATTERN): cv.string,
|
||||||
@ -162,16 +162,18 @@ class InputTextStorageCollection(collection.DictStorageCollection):
|
|||||||
|
|
||||||
CREATE_UPDATE_SCHEMA = vol.Schema(vol.All(STORAGE_FIELDS, _cv_input_text))
|
CREATE_UPDATE_SCHEMA = vol.Schema(vol.All(STORAGE_FIELDS, _cv_input_text))
|
||||||
|
|
||||||
async def _process_create_data(self, data: dict) -> dict:
|
async def _process_create_data(self, data: dict[str, Any]) -> vol.Schema:
|
||||||
"""Validate the config is valid."""
|
"""Validate the config is valid."""
|
||||||
return self.CREATE_UPDATE_SCHEMA(data)
|
return self.CREATE_UPDATE_SCHEMA(data)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _get_suggested_id(self, info: dict) -> str:
|
def _get_suggested_id(self, info: dict[str, Any]) -> str:
|
||||||
"""Suggest an ID based on the config."""
|
"""Suggest an ID based on the config."""
|
||||||
return info[CONF_NAME]
|
return info[CONF_NAME] # type: ignore[no-any-return]
|
||||||
|
|
||||||
async def _update_data(self, item: dict, update_data: dict) -> dict:
|
async def _update_data(
|
||||||
|
self, item: dict[str, Any], update_data: dict[str, Any]
|
||||||
|
) -> dict[str, Any]:
|
||||||
"""Return a new updated data object."""
|
"""Return a new updated data object."""
|
||||||
update_data = self.CREATE_UPDATE_SCHEMA(update_data)
|
update_data = self.CREATE_UPDATE_SCHEMA(update_data)
|
||||||
return {CONF_ID: item[CONF_ID]} | update_data
|
return {CONF_ID: item[CONF_ID]} | update_data
|
||||||
@ -185,6 +187,7 @@ class InputText(collection.CollectionEntity, RestoreEntity):
|
|||||||
)
|
)
|
||||||
|
|
||||||
_attr_should_poll = False
|
_attr_should_poll = False
|
||||||
|
_current_value: str | None
|
||||||
editable: bool
|
editable: bool
|
||||||
|
|
||||||
def __init__(self, config: ConfigType) -> None:
|
def __init__(self, config: ConfigType) -> None:
|
||||||
@ -195,55 +198,55 @@ class InputText(collection.CollectionEntity, RestoreEntity):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def from_storage(cls, config: ConfigType) -> Self:
|
def from_storage(cls, config: ConfigType) -> Self:
|
||||||
"""Return entity instance initialized from storage."""
|
"""Return entity instance initialized from storage."""
|
||||||
input_text = cls(config)
|
input_text: Self = cls(config)
|
||||||
input_text.editable = True
|
input_text.editable = True
|
||||||
return input_text
|
return input_text
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_yaml(cls, config: ConfigType) -> Self:
|
def from_yaml(cls, config: ConfigType) -> Self:
|
||||||
"""Return entity instance initialized from yaml."""
|
"""Return entity instance initialized from yaml."""
|
||||||
input_text = cls(config)
|
input_text: Self = cls(config)
|
||||||
input_text.entity_id = f"{DOMAIN}.{config[CONF_ID]}"
|
input_text.entity_id = f"{DOMAIN}.{config[CONF_ID]}"
|
||||||
input_text.editable = False
|
input_text.editable = False
|
||||||
return input_text
|
return input_text
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self) -> str | None:
|
||||||
"""Return the name of the text input entity."""
|
"""Return the name of the text input entity."""
|
||||||
return self._config.get(CONF_NAME)
|
return self._config.get(CONF_NAME)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def icon(self):
|
def icon(self) -> str | None:
|
||||||
"""Return the icon to be used for this entity."""
|
"""Return the icon to be used for this entity."""
|
||||||
return self._config.get(CONF_ICON)
|
return self._config.get(CONF_ICON)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _maximum(self) -> int:
|
def _maximum(self) -> int:
|
||||||
"""Return max len of the text."""
|
"""Return max len of the text."""
|
||||||
return self._config[CONF_MAX]
|
return self._config[CONF_MAX] # type: ignore[no-any-return]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _minimum(self) -> int:
|
def _minimum(self) -> int:
|
||||||
"""Return min len of the text."""
|
"""Return min len of the text."""
|
||||||
return self._config[CONF_MIN]
|
return self._config[CONF_MIN] # type: ignore[no-any-return]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state(self):
|
def state(self) -> str | None:
|
||||||
"""Return the state of the component."""
|
"""Return the state of the component."""
|
||||||
return self._current_value
|
return self._current_value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def unit_of_measurement(self):
|
def unit_of_measurement(self) -> str | None:
|
||||||
"""Return the unit the value is expressed in."""
|
"""Return the unit the value is expressed in."""
|
||||||
return self._config.get(CONF_UNIT_OF_MEASUREMENT)
|
return self._config.get(CONF_UNIT_OF_MEASUREMENT)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def unique_id(self) -> str | None:
|
def unique_id(self) -> str:
|
||||||
"""Return unique id for the entity."""
|
"""Return unique id for the entity."""
|
||||||
return self._config[CONF_ID]
|
return self._config[CONF_ID] # type: ignore[no-any-return]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_state_attributes(self):
|
def extra_state_attributes(self) -> dict[str, Any]:
|
||||||
"""Return the state attributes."""
|
"""Return the state attributes."""
|
||||||
return {
|
return {
|
||||||
ATTR_EDITABLE: self.editable,
|
ATTR_EDITABLE: self.editable,
|
||||||
@ -253,20 +256,20 @@ class InputText(collection.CollectionEntity, RestoreEntity):
|
|||||||
ATTR_MODE: self._config[CONF_MODE],
|
ATTR_MODE: self._config[CONF_MODE],
|
||||||
}
|
}
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self) -> None:
|
||||||
"""Run when entity about to be added to hass."""
|
"""Run when entity about to be added to hass."""
|
||||||
await super().async_added_to_hass()
|
await super().async_added_to_hass()
|
||||||
if self._current_value is not None:
|
if self._current_value is not None:
|
||||||
return
|
return
|
||||||
|
|
||||||
state = await self.async_get_last_state()
|
state = await self.async_get_last_state()
|
||||||
value = state and state.state
|
value: str | None = state and state.state # type: ignore[assignment]
|
||||||
|
|
||||||
# Check against None because value can be 0
|
# Check against None because value can be 0
|
||||||
if value is not None and self._minimum <= len(value) <= self._maximum:
|
if value is not None and self._minimum <= len(value) <= self._maximum:
|
||||||
self._current_value = value
|
self._current_value = value
|
||||||
|
|
||||||
async def async_set_value(self, value):
|
async def async_set_value(self, value: str) -> None:
|
||||||
"""Select new value."""
|
"""Select new value."""
|
||||||
if len(value) < self._minimum or len(value) > self._maximum:
|
if len(value) < self._minimum or len(value) > self._maximum:
|
||||||
_LOGGER.warning(
|
_LOGGER.warning(
|
||||||
|
10
mypy.ini
10
mypy.ini
@ -1561,6 +1561,16 @@ disallow_untyped_defs = true
|
|||||||
warn_return_any = true
|
warn_return_any = true
|
||||||
warn_unreachable = true
|
warn_unreachable = true
|
||||||
|
|
||||||
|
[mypy-homeassistant.components.input_text.*]
|
||||||
|
check_untyped_defs = true
|
||||||
|
disallow_incomplete_defs = true
|
||||||
|
disallow_subclassing_any = true
|
||||||
|
disallow_untyped_calls = true
|
||||||
|
disallow_untyped_decorators = true
|
||||||
|
disallow_untyped_defs = true
|
||||||
|
warn_return_any = true
|
||||||
|
warn_unreachable = true
|
||||||
|
|
||||||
[mypy-homeassistant.components.integration.*]
|
[mypy-homeassistant.components.integration.*]
|
||||||
check_untyped_defs = true
|
check_untyped_defs = true
|
||||||
disallow_incomplete_defs = true
|
disallow_incomplete_defs = true
|
||||||
|
Loading…
x
Reference in New Issue
Block a user