Improve type hints in image-processing (#78351)

This commit is contained in:
epenet 2022-09-13 14:39:39 +02:00 committed by GitHub
parent 6256d07255
commit 458ddb6f4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 15 deletions

View File

@ -1,11 +1,14 @@
"""Provides functionality to interact with image processing services.""" """Provides functionality to interact with image processing services."""
from __future__ import annotations
import asyncio import asyncio
from datetime import timedelta from datetime import timedelta
import logging import logging
from typing import Final, TypedDict, final from typing import Any, Final, TypedDict, final
import voluptuous as vol import voluptuous as vol
from homeassistant.components.camera import Image
from homeassistant.const import ( from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_ENTITY_ID,
ATTR_NAME, ATTR_NAME,
@ -22,8 +25,6 @@ from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from homeassistant.util.async_ import run_callback_threadsafe from homeassistant.util.async_ import run_callback_threadsafe
# mypy: allow-untyped-defs, no-check-untyped-defs
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
DOMAIN = "image_processing" DOMAIN = "image_processing"
@ -44,7 +45,7 @@ ATTR_CONFIDENCE: Final = "confidence"
ATTR_FACES = "faces" ATTR_FACES = "faces"
ATTR_GENDER = "gender" ATTR_GENDER = "gender"
ATTR_GLASSES = "glasses" ATTR_GLASSES = "glasses"
ATTR_MOTION = "motion" ATTR_MOTION: Final = "motion"
ATTR_TOTAL_FACES = "total_faces" ATTR_TOTAL_FACES = "total_faces"
CONF_CONFIDENCE = "confidence" CONF_CONFIDENCE = "confidence"
@ -113,24 +114,24 @@ class ImageProcessingEntity(Entity):
timeout = DEFAULT_TIMEOUT timeout = DEFAULT_TIMEOUT
@property @property
def camera_entity(self): def camera_entity(self) -> str | None:
"""Return camera entity id from process pictures.""" """Return camera entity id from process pictures."""
return None return None
@property @property
def confidence(self): def confidence(self) -> float | None:
"""Return minimum confidence for do some things.""" """Return minimum confidence for do some things."""
return None return None
def process_image(self, image): def process_image(self, image: Image) -> None:
"""Process image.""" """Process image."""
raise NotImplementedError() raise NotImplementedError()
async def async_process_image(self, image): async def async_process_image(self, image: Image) -> None:
"""Process image.""" """Process image."""
return await self.hass.async_add_executor_job(self.process_image, image) return await self.hass.async_add_executor_job(self.process_image, image)
async def async_update(self): async def async_update(self) -> None:
"""Update image and process it. """Update image and process it.
This method is a coroutine. This method is a coroutine.
@ -160,9 +161,9 @@ class ImageProcessingFaceEntity(ImageProcessingEntity):
self.total_faces = 0 self.total_faces = 0
@property @property
def state(self): def state(self) -> str | int | None:
"""Return the state of the entity.""" """Return the state of the entity."""
confidence = 0 confidence: float = 0
state = None state = None
# No confidence support # No confidence support
@ -178,19 +179,19 @@ class ImageProcessingFaceEntity(ImageProcessingEntity):
confidence = f_co confidence = f_co
for attr in (ATTR_NAME, ATTR_MOTION): for attr in (ATTR_NAME, ATTR_MOTION):
if attr in face: if attr in face:
state = face[attr] state = face[attr] # type: ignore[literal-required]
break break
return state return state
@property @property
def device_class(self): def device_class(self) -> str:
"""Return the class of this device, from component DEVICE_CLASSES.""" """Return the class of this device, from component DEVICE_CLASSES."""
return "face" return "face"
@final @final
@property @property
def state_attributes(self): def state_attributes(self) -> dict[str, Any]:
"""Return device specific state attributes.""" """Return device specific state attributes."""
return {ATTR_FACES: self.faces, ATTR_TOTAL_FACES: self.total_faces} return {ATTR_FACES: self.faces, ATTR_TOTAL_FACES: self.total_faces}

View File

@ -148,7 +148,7 @@ class ImageProcessingAlprEntity(ImageProcessingEntity):
plates = { plates = {
plate: confidence plate: confidence
for plate, confidence in plates.items() for plate, confidence in plates.items()
if confidence >= self.confidence if self.confidence is None or confidence >= self.confidence
} }
new_plates = set(plates) - set(self.plates) new_plates = set(plates) - set(self.plates)

View File

@ -1348,6 +1348,45 @@ _INHERITANCE_MATCH: dict[str, list[ClassTypeHintMatch]] = {
], ],
), ),
], ],
"image_processing": [
ClassTypeHintMatch(
base_class="Entity",
matches=_ENTITY_MATCH,
),
ClassTypeHintMatch(
base_class="ImageProcessingEntity",
matches=[
TypeHintMatch(
function_name="camera_entity",
return_type=["str", None],
),
TypeHintMatch(
function_name="confidence",
return_type=["float", None],
),
TypeHintMatch(
function_name="process_image",
arg_types={1: "Image"},
return_type=None,
has_async_counterpart=True,
),
],
),
ClassTypeHintMatch(
base_class="ImageProcessingFaceEntity",
matches=[
TypeHintMatch(
function_name="process_faces",
arg_types={
1: "list[FaceInformation]",
2: "int",
},
return_type=None,
has_async_counterpart=True,
),
],
),
],
"light": [ "light": [
ClassTypeHintMatch( ClassTypeHintMatch(
base_class="Entity", base_class="Entity",