Improve type annotations for the Brother integration (#49771)

This commit is contained in:
Maciej Bieniek 2021-04-29 16:59:31 +02:00 committed by GitHub
parent f7cf82be6d
commit 3210c086ef
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 200 additions and 155 deletions

View file

@ -6,6 +6,7 @@ homeassistant.components
homeassistant.components.automation.*
homeassistant.components.binary_sensor.*
homeassistant.components.bond.*
homeassistant.components.brother.*
homeassistant.components.calendar.*
homeassistant.components.cover.*
homeassistant.components.device_automation.*

View file

@ -1,8 +1,11 @@
"""The Brother component."""
from __future__ import annotations
from datetime import timedelta
import logging
from brother import Brother, SnmpError, UnsupportedModel
from brother import Brother, DictToObj, SnmpError, UnsupportedModel
import pysnmp.hlapi.asyncio as SnmpEngine
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, CONF_TYPE
@ -19,7 +22,7 @@ SCAN_INTERVAL = timedelta(seconds=30)
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Brother from a config entry."""
host = entry.data[CONF_HOST]
kind = entry.data[CONF_TYPE]
@ -41,7 +44,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
return True
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
@ -57,7 +60,9 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
class BrotherDataUpdateCoordinator(DataUpdateCoordinator):
"""Class to manage fetching Brother data from the printer."""
def __init__(self, hass, host, kind, snmp_engine):
def __init__(
self, hass: HomeAssistant, host: str, kind: str, snmp_engine: SnmpEngine
) -> None:
"""Initialize."""
self.brother = Brother(host, kind=kind, snmp_engine=snmp_engine)
@ -68,7 +73,7 @@ class BrotherDataUpdateCoordinator(DataUpdateCoordinator):
update_interval=SCAN_INTERVAL,
)
async def _async_update_data(self):
async def _async_update_data(self) -> DictToObj:
"""Update data via library."""
try:
data = await self.brother.async_update()

View file

@ -1,12 +1,17 @@
"""Adds config flow for Brother Printer."""
from __future__ import annotations
import ipaddress
import re
from typing import Any
from brother import Brother, SnmpError, UnsupportedModel
import voluptuous as vol
from homeassistant import config_entries, exceptions
from homeassistant.const import CONF_HOST, CONF_TYPE
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers.typing import DiscoveryInfoType
from .const import DOMAIN, PRINTER_TYPES
from .utils import get_snmp_engine
@ -19,14 +24,15 @@ DATA_SCHEMA = vol.Schema(
)
def host_valid(host):
def host_valid(host: str) -> bool:
"""Return True if hostname or IP address is valid."""
try:
if ipaddress.ip_address(host).version == (4 or 6):
if ipaddress.ip_address(host).version in [4, 6]:
return True
except ValueError:
disallowed = re.compile(r"[^a-zA-Z\d\-]")
return all(x and not disallowed.search(x) for x in host.split("."))
return False
class BrotherConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
@ -35,12 +41,14 @@ class BrotherConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
VERSION = 1
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL
def __init__(self):
def __init__(self) -> None:
"""Initialize."""
self.brother = None
self.host = None
self.brother: Brother = None
self.host: str | None = None
async def async_step_user(self, user_input=None):
async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
"""Handle the initial step."""
errors = {}
@ -72,11 +80,10 @@ class BrotherConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
step_id="user", data_schema=DATA_SCHEMA, errors=errors
)
async def async_step_zeroconf(self, discovery_info):
async def async_step_zeroconf(
self, discovery_info: DiscoveryInfoType
) -> FlowResult:
"""Handle zeroconf discovery."""
if discovery_info is None:
return self.async_abort(reason="cannot_connect")
if not discovery_info.get("name") or not discovery_info["name"].startswith(
"Brother"
):
@ -107,7 +114,9 @@ class BrotherConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
)
return await self.async_step_zeroconf_confirm()
async def async_step_zeroconf_confirm(self, user_input=None):
async def async_step_zeroconf_confirm(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
"""Handle a flow initiated by zeroconf."""
if user_input is not None:
title = f"{self.brother.model} {self.brother.serial}"

View file

@ -1,5 +1,9 @@
"""Constants for Brother integration."""
from homeassistant.const import ATTR_ICON, PERCENTAGE
from __future__ import annotations
from typing import TypedDict
from homeassistant.const import PERCENTAGE
ATTR_BELT_UNIT_REMAINING_LIFE = "belt_unit_remaining_life"
ATTR_BLACK_DRUM_COUNTER = "black_drum_counter"
@ -18,9 +22,7 @@ ATTR_DRUM_COUNTER = "drum_counter"
ATTR_DRUM_REMAINING_LIFE = "drum_remaining_life"
ATTR_DRUM_REMAINING_PAGES = "drum_remaining_pages"
ATTR_DUPLEX_COUNTER = "duplex_unit_pages_counter"
ATTR_ENABLED = "enabled"
ATTR_FUSER_REMAINING_LIFE = "fuser_remaining_life"
ATTR_LABEL = "label"
ATTR_LASER_REMAINING_LIFE = "laser_remaining_life"
ATTR_MAGENTA_DRUM_COUNTER = "magenta_drum_counter"
ATTR_MAGENTA_DRUM_REMAINING_LIFE = "magenta_drum_remaining_life"
@ -32,7 +34,6 @@ ATTR_PAGE_COUNTER = "page_counter"
ATTR_PF_KIT_1_REMAINING_LIFE = "pf_kit_1_remaining_life"
ATTR_PF_KIT_MP_REMAINING_LIFE = "pf_kit_mp_remaining_life"
ATTR_STATUS = "status"
ATTR_UNIT = "unit"
ATTR_UPTIME = "uptime"
ATTR_YELLOW_DRUM_COUNTER = "yellow_drum_counter"
ATTR_YELLOW_DRUM_REMAINING_LIFE = "yellow_drum_remaining_life"
@ -50,7 +51,7 @@ PRINTER_TYPES = ["laser", "ink"]
SNMP = "snmp"
ATTRS_MAP = {
ATTRS_MAP: dict[str, tuple[str, str]] = {
ATTR_DRUM_REMAINING_LIFE: (ATTR_DRUM_REMAINING_PAGES, ATTR_DRUM_COUNTER),
ATTR_BLACK_DRUM_REMAINING_LIFE: (
ATTR_BLACK_DRUM_REMAINING_PAGES,
@ -70,149 +71,158 @@ ATTRS_MAP = {
),
}
SENSOR_TYPES = {
SENSOR_TYPES: dict[str, SensorDescription] = {
ATTR_STATUS: {
ATTR_ICON: "mdi:printer",
ATTR_LABEL: ATTR_STATUS.title(),
ATTR_UNIT: None,
ATTR_ENABLED: True,
"icon": "mdi:printer",
"label": ATTR_STATUS.title(),
"unit": None,
"enabled": True,
},
ATTR_PAGE_COUNTER: {
ATTR_ICON: "mdi:file-document-outline",
ATTR_LABEL: ATTR_PAGE_COUNTER.replace("_", " ").title(),
ATTR_UNIT: UNIT_PAGES,
ATTR_ENABLED: True,
"icon": "mdi:file-document-outline",
"label": ATTR_PAGE_COUNTER.replace("_", " ").title(),
"unit": UNIT_PAGES,
"enabled": True,
},
ATTR_BW_COUNTER: {
ATTR_ICON: "mdi:file-document-outline",
ATTR_LABEL: ATTR_BW_COUNTER.replace("_", " ").title(),
ATTR_UNIT: UNIT_PAGES,
ATTR_ENABLED: True,
"icon": "mdi:file-document-outline",
"label": ATTR_BW_COUNTER.replace("_", " ").title(),
"unit": UNIT_PAGES,
"enabled": True,
},
ATTR_COLOR_COUNTER: {
ATTR_ICON: "mdi:file-document-outline",
ATTR_LABEL: ATTR_COLOR_COUNTER.replace("_", " ").title(),
ATTR_UNIT: UNIT_PAGES,
ATTR_ENABLED: True,
"icon": "mdi:file-document-outline",
"label": ATTR_COLOR_COUNTER.replace("_", " ").title(),
"unit": UNIT_PAGES,
"enabled": True,
},
ATTR_DUPLEX_COUNTER: {
ATTR_ICON: "mdi:file-document-outline",
ATTR_LABEL: ATTR_DUPLEX_COUNTER.replace("_", " ").title(),
ATTR_UNIT: UNIT_PAGES,
ATTR_ENABLED: True,
"icon": "mdi:file-document-outline",
"label": ATTR_DUPLEX_COUNTER.replace("_", " ").title(),
"unit": UNIT_PAGES,
"enabled": True,
},
ATTR_DRUM_REMAINING_LIFE: {
ATTR_ICON: "mdi:chart-donut",
ATTR_LABEL: ATTR_DRUM_REMAINING_LIFE.replace("_", " ").title(),
ATTR_UNIT: PERCENTAGE,
ATTR_ENABLED: True,
"icon": "mdi:chart-donut",
"label": ATTR_DRUM_REMAINING_LIFE.replace("_", " ").title(),
"unit": PERCENTAGE,
"enabled": True,
},
ATTR_BLACK_DRUM_REMAINING_LIFE: {
ATTR_ICON: "mdi:chart-donut",
ATTR_LABEL: ATTR_BLACK_DRUM_REMAINING_LIFE.replace("_", " ").title(),
ATTR_UNIT: PERCENTAGE,
ATTR_ENABLED: True,
"icon": "mdi:chart-donut",
"label": ATTR_BLACK_DRUM_REMAINING_LIFE.replace("_", " ").title(),
"unit": PERCENTAGE,
"enabled": True,
},
ATTR_CYAN_DRUM_REMAINING_LIFE: {
ATTR_ICON: "mdi:chart-donut",
ATTR_LABEL: ATTR_CYAN_DRUM_REMAINING_LIFE.replace("_", " ").title(),
ATTR_UNIT: PERCENTAGE,
ATTR_ENABLED: True,
"icon": "mdi:chart-donut",
"label": ATTR_CYAN_DRUM_REMAINING_LIFE.replace("_", " ").title(),
"unit": PERCENTAGE,
"enabled": True,
},
ATTR_MAGENTA_DRUM_REMAINING_LIFE: {
ATTR_ICON: "mdi:chart-donut",
ATTR_LABEL: ATTR_MAGENTA_DRUM_REMAINING_LIFE.replace("_", " ").title(),
ATTR_UNIT: PERCENTAGE,
ATTR_ENABLED: True,
"icon": "mdi:chart-donut",
"label": ATTR_MAGENTA_DRUM_REMAINING_LIFE.replace("_", " ").title(),
"unit": PERCENTAGE,
"enabled": True,
},
ATTR_YELLOW_DRUM_REMAINING_LIFE: {
ATTR_ICON: "mdi:chart-donut",
ATTR_LABEL: ATTR_YELLOW_DRUM_REMAINING_LIFE.replace("_", " ").title(),
ATTR_UNIT: PERCENTAGE,
ATTR_ENABLED: True,
"icon": "mdi:chart-donut",
"label": ATTR_YELLOW_DRUM_REMAINING_LIFE.replace("_", " ").title(),
"unit": PERCENTAGE,
"enabled": True,
},
ATTR_BELT_UNIT_REMAINING_LIFE: {
ATTR_ICON: "mdi:current-ac",
ATTR_LABEL: ATTR_BELT_UNIT_REMAINING_LIFE.replace("_", " ").title(),
ATTR_UNIT: PERCENTAGE,
ATTR_ENABLED: True,
"icon": "mdi:current-ac",
"label": ATTR_BELT_UNIT_REMAINING_LIFE.replace("_", " ").title(),
"unit": PERCENTAGE,
"enabled": True,
},
ATTR_FUSER_REMAINING_LIFE: {
ATTR_ICON: "mdi:water-outline",
ATTR_LABEL: ATTR_FUSER_REMAINING_LIFE.replace("_", " ").title(),
ATTR_UNIT: PERCENTAGE,
ATTR_ENABLED: True,
"icon": "mdi:water-outline",
"label": ATTR_FUSER_REMAINING_LIFE.replace("_", " ").title(),
"unit": PERCENTAGE,
"enabled": True,
},
ATTR_LASER_REMAINING_LIFE: {
ATTR_ICON: "mdi:spotlight-beam",
ATTR_LABEL: ATTR_LASER_REMAINING_LIFE.replace("_", " ").title(),
ATTR_UNIT: PERCENTAGE,
ATTR_ENABLED: True,
"icon": "mdi:spotlight-beam",
"label": ATTR_LASER_REMAINING_LIFE.replace("_", " ").title(),
"unit": PERCENTAGE,
"enabled": True,
},
ATTR_PF_KIT_1_REMAINING_LIFE: {
ATTR_ICON: "mdi:printer-3d",
ATTR_LABEL: ATTR_PF_KIT_1_REMAINING_LIFE.replace("_", " ").title(),
ATTR_UNIT: PERCENTAGE,
ATTR_ENABLED: True,
"icon": "mdi:printer-3d",
"label": ATTR_PF_KIT_1_REMAINING_LIFE.replace("_", " ").title(),
"unit": PERCENTAGE,
"enabled": True,
},
ATTR_PF_KIT_MP_REMAINING_LIFE: {
ATTR_ICON: "mdi:printer-3d",
ATTR_LABEL: ATTR_PF_KIT_MP_REMAINING_LIFE.replace("_", " ").title(),
ATTR_UNIT: PERCENTAGE,
ATTR_ENABLED: True,
"icon": "mdi:printer-3d",
"label": ATTR_PF_KIT_MP_REMAINING_LIFE.replace("_", " ").title(),
"unit": PERCENTAGE,
"enabled": True,
},
ATTR_BLACK_TONER_REMAINING: {
ATTR_ICON: "mdi:printer-3d-nozzle",
ATTR_LABEL: ATTR_BLACK_TONER_REMAINING.replace("_", " ").title(),
ATTR_UNIT: PERCENTAGE,
ATTR_ENABLED: True,
"icon": "mdi:printer-3d-nozzle",
"label": ATTR_BLACK_TONER_REMAINING.replace("_", " ").title(),
"unit": PERCENTAGE,
"enabled": True,
},
ATTR_CYAN_TONER_REMAINING: {
ATTR_ICON: "mdi:printer-3d-nozzle",
ATTR_LABEL: ATTR_CYAN_TONER_REMAINING.replace("_", " ").title(),
ATTR_UNIT: PERCENTAGE,
ATTR_ENABLED: True,
"icon": "mdi:printer-3d-nozzle",
"label": ATTR_CYAN_TONER_REMAINING.replace("_", " ").title(),
"unit": PERCENTAGE,
"enabled": True,
},
ATTR_MAGENTA_TONER_REMAINING: {
ATTR_ICON: "mdi:printer-3d-nozzle",
ATTR_LABEL: ATTR_MAGENTA_TONER_REMAINING.replace("_", " ").title(),
ATTR_UNIT: PERCENTAGE,
ATTR_ENABLED: True,
"icon": "mdi:printer-3d-nozzle",
"label": ATTR_MAGENTA_TONER_REMAINING.replace("_", " ").title(),
"unit": PERCENTAGE,
"enabled": True,
},
ATTR_YELLOW_TONER_REMAINING: {
ATTR_ICON: "mdi:printer-3d-nozzle",
ATTR_LABEL: ATTR_YELLOW_TONER_REMAINING.replace("_", " ").title(),
ATTR_UNIT: PERCENTAGE,
ATTR_ENABLED: True,
"icon": "mdi:printer-3d-nozzle",
"label": ATTR_YELLOW_TONER_REMAINING.replace("_", " ").title(),
"unit": PERCENTAGE,
"enabled": True,
},
ATTR_BLACK_INK_REMAINING: {
ATTR_ICON: "mdi:printer-3d-nozzle",
ATTR_LABEL: ATTR_BLACK_INK_REMAINING.replace("_", " ").title(),
ATTR_UNIT: PERCENTAGE,
ATTR_ENABLED: True,
"icon": "mdi:printer-3d-nozzle",
"label": ATTR_BLACK_INK_REMAINING.replace("_", " ").title(),
"unit": PERCENTAGE,
"enabled": True,
},
ATTR_CYAN_INK_REMAINING: {
ATTR_ICON: "mdi:printer-3d-nozzle",
ATTR_LABEL: ATTR_CYAN_INK_REMAINING.replace("_", " ").title(),
ATTR_UNIT: PERCENTAGE,
ATTR_ENABLED: True,
"icon": "mdi:printer-3d-nozzle",
"label": ATTR_CYAN_INK_REMAINING.replace("_", " ").title(),
"unit": PERCENTAGE,
"enabled": True,
},
ATTR_MAGENTA_INK_REMAINING: {
ATTR_ICON: "mdi:printer-3d-nozzle",
ATTR_LABEL: ATTR_MAGENTA_INK_REMAINING.replace("_", " ").title(),
ATTR_UNIT: PERCENTAGE,
ATTR_ENABLED: True,
"icon": "mdi:printer-3d-nozzle",
"label": ATTR_MAGENTA_INK_REMAINING.replace("_", " ").title(),
"unit": PERCENTAGE,
"enabled": True,
},
ATTR_YELLOW_INK_REMAINING: {
ATTR_ICON: "mdi:printer-3d-nozzle",
ATTR_LABEL: ATTR_YELLOW_INK_REMAINING.replace("_", " ").title(),
ATTR_UNIT: PERCENTAGE,
ATTR_ENABLED: True,
"icon": "mdi:printer-3d-nozzle",
"label": ATTR_YELLOW_INK_REMAINING.replace("_", " ").title(),
"unit": PERCENTAGE,
"enabled": True,
},
ATTR_UPTIME: {
ATTR_ICON: None,
ATTR_LABEL: ATTR_UPTIME.title(),
ATTR_UNIT: None,
ATTR_ENABLED: False,
"icon": None,
"label": ATTR_UPTIME.title(),
"unit": None,
"enabled": False,
},
}
class SensorDescription(TypedDict):
"""Sensor description class."""
icon: str | None
label: str
unit: str | None
enabled: bool

View file

@ -1,14 +1,18 @@
"""Support for the Brother service."""
from __future__ import annotations
from typing import Any
from homeassistant.components.sensor import SensorEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import DEVICE_CLASS_TIMESTAMP
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import BrotherDataUpdateCoordinator
from .const import (
ATTR_ENABLED,
ATTR_ICON,
ATTR_LABEL,
ATTR_MANUFACTURER,
ATTR_UNIT,
ATTR_UPTIME,
ATTRS_MAP,
DATA_CONFIG_ENTRY,
@ -20,9 +24,11 @@ ATTR_COUNTER = "counter"
ATTR_REMAINING_PAGES = "remaining_pages"
async def async_setup_entry(hass, config_entry, async_add_entities):
async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Add Brother entities from a config_entry."""
coordinator = hass.data[DOMAIN][DATA_CONFIG_ENTRY][config_entry.entry_id]
coordinator = hass.data[DOMAIN][DATA_CONFIG_ENTRY][entry.entry_id]
sensors = []
@ -43,36 +49,42 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
class BrotherPrinterSensor(CoordinatorEntity, SensorEntity):
"""Define an Brother Printer sensor."""
def __init__(self, coordinator, kind, device_info):
def __init__(
self,
coordinator: BrotherDataUpdateCoordinator,
kind: str,
device_info: dict[str, Any],
) -> None:
"""Initialize."""
super().__init__(coordinator)
self._name = f"{coordinator.data.model} {SENSOR_TYPES[kind][ATTR_LABEL]}"
self._description = SENSOR_TYPES[kind]
self._name = f"{coordinator.data.model} {self._description['label']}"
self._unique_id = f"{coordinator.data.serial.lower()}_{kind}"
self._device_info = device_info
self.kind = kind
self._attrs = {}
self._attrs: dict[str, Any] = {}
@property
def name(self):
def name(self) -> str:
"""Return the name."""
return self._name
@property
def state(self):
def state(self) -> Any:
"""Return the state."""
if self.kind == ATTR_UPTIME:
return getattr(self.coordinator.data, self.kind).isoformat()
return getattr(self.coordinator.data, self.kind)
@property
def device_class(self):
def device_class(self) -> str | None:
"""Return the class of this sensor."""
if self.kind == ATTR_UPTIME:
return DEVICE_CLASS_TIMESTAMP
return None
@property
def extra_state_attributes(self):
def extra_state_attributes(self) -> dict[str, Any]:
"""Return the state attributes."""
remaining_pages, drum_counter = ATTRS_MAP.get(self.kind, (None, None))
if remaining_pages and drum_counter:
@ -83,26 +95,26 @@ class BrotherPrinterSensor(CoordinatorEntity, SensorEntity):
return self._attrs
@property
def icon(self):
def icon(self) -> str | None:
"""Return the icon."""
return SENSOR_TYPES[self.kind][ATTR_ICON]
return self._description["icon"]
@property
def unique_id(self):
def unique_id(self) -> str:
"""Return a unique_id for this entity."""
return self._unique_id
@property
def unit_of_measurement(self):
def unit_of_measurement(self) -> str | None:
"""Return the unit the value is expressed in."""
return SENSOR_TYPES[self.kind][ATTR_UNIT]
return self._description["unit"]
@property
def device_info(self):
def device_info(self) -> dict[str, Any]:
"""Return the device info."""
return self._device_info
@property
def entity_registry_enabled_default(self):
def entity_registry_enabled_default(self) -> bool:
"""Return if the entity should be enabled when first added to the entity registry."""
return SENSOR_TYPES[self.kind][ATTR_ENABLED]
return self._description["enabled"]

View file

@ -5,7 +5,7 @@ import pysnmp.hlapi.asyncio as hlapi
from pysnmp.hlapi.asyncio.cmdgen import lcd
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
from homeassistant.core import callback
from homeassistant.core import Event, HomeAssistant, callback
from homeassistant.helpers import singleton
from .const import DOMAIN, SNMP
@ -14,13 +14,13 @@ _LOGGER = logging.getLogger(__name__)
@singleton.singleton("snmp_engine")
def get_snmp_engine(hass):
def get_snmp_engine(hass: HomeAssistant) -> hlapi.SnmpEngine:
"""Get SNMP engine."""
_LOGGER.debug("Creating SNMP engine")
snmp_engine = hlapi.SnmpEngine()
@callback
def shutdown_listener(ev):
def shutdown_listener(ev: Event) -> None:
if hass.data.get(DOMAIN):
_LOGGER.debug("Unconfiguring SNMP engine")
lcd.unconfigure(hass.data[DOMAIN][SNMP], None)

View file

@ -35,7 +35,7 @@ warn_return_any = false
warn_unreachable = false
warn_unused_ignores = false
[mypy-homeassistant.components,homeassistant.components.automation.*,homeassistant.components.binary_sensor.*,homeassistant.components.bond.*,homeassistant.components.calendar.*,homeassistant.components.cover.*,homeassistant.components.device_automation.*,homeassistant.components.frontend.*,homeassistant.components.geo_location.*,homeassistant.components.group.*,homeassistant.components.history.*,homeassistant.components.http.*,homeassistant.components.huawei_lte.*,homeassistant.components.hyperion.*,homeassistant.components.image_processing.*,homeassistant.components.integration.*,homeassistant.components.knx.*,homeassistant.components.light.*,homeassistant.components.lock.*,homeassistant.components.mailbox.*,homeassistant.components.media_player.*,homeassistant.components.notify.*,homeassistant.components.number.*,homeassistant.components.persistent_notification.*,homeassistant.components.proximity.*,homeassistant.components.recorder.purge,homeassistant.components.recorder.repack,homeassistant.components.remote.*,homeassistant.components.scene.*,homeassistant.components.sensor.*,homeassistant.components.slack.*,homeassistant.components.sonos.media_player,homeassistant.components.sun.*,homeassistant.components.switch.*,homeassistant.components.systemmonitor.*,homeassistant.components.tts.*,homeassistant.components.vacuum.*,homeassistant.components.water_heater.*,homeassistant.components.weather.*,homeassistant.components.websocket_api.*,homeassistant.components.zeroconf.*,homeassistant.components.zone.*,homeassistant.components.zwave_js.*]
[mypy-homeassistant.components,homeassistant.components.automation.*,homeassistant.components.binary_sensor.*,homeassistant.components.bond.*,homeassistant.components.brother.*,homeassistant.components.calendar.*,homeassistant.components.cover.*,homeassistant.components.device_automation.*,homeassistant.components.frontend.*,homeassistant.components.geo_location.*,homeassistant.components.group.*,homeassistant.components.history.*,homeassistant.components.http.*,homeassistant.components.huawei_lte.*,homeassistant.components.hyperion.*,homeassistant.components.image_processing.*,homeassistant.components.integration.*,homeassistant.components.knx.*,homeassistant.components.light.*,homeassistant.components.lock.*,homeassistant.components.mailbox.*,homeassistant.components.media_player.*,homeassistant.components.notify.*,homeassistant.components.number.*,homeassistant.components.persistent_notification.*,homeassistant.components.proximity.*,homeassistant.components.recorder.purge,homeassistant.components.recorder.repack,homeassistant.components.remote.*,homeassistant.components.scene.*,homeassistant.components.sensor.*,homeassistant.components.slack.*,homeassistant.components.sonos.media_player,homeassistant.components.sun.*,homeassistant.components.switch.*,homeassistant.components.systemmonitor.*,homeassistant.components.tts.*,homeassistant.components.vacuum.*,homeassistant.components.water_heater.*,homeassistant.components.weather.*,homeassistant.components.websocket_api.*,homeassistant.components.zeroconf.*,homeassistant.components.zone.*,homeassistant.components.zwave_js.*]
check_untyped_defs = true
disallow_incomplete_defs = true
disallow_subclassing_any = true

View file

@ -40,8 +40,8 @@ async def test_create_entry_with_hostname(hass):
assert result["data"][CONF_TYPE] == CONFIG[CONF_TYPE]
async def test_create_entry_with_ip_address(hass):
"""Test that the user step works with printer IP address."""
async def test_create_entry_with_ipv4_address(hass):
"""Test that the user step works with printer IPv4 address."""
with patch(
"brother.Brother._get_data",
return_value=json.loads(load_fixture("brother_printer_data.json")),
@ -58,6 +58,24 @@ async def test_create_entry_with_ip_address(hass):
assert result["data"][CONF_TYPE] == "laser"
async def test_create_entry_with_ipv6_address(hass):
"""Test that the user step works with printer IPv6 address."""
with patch(
"brother.Brother._get_data",
return_value=json.loads(load_fixture("brother_printer_data.json")),
):
result = await hass.config_entries.flow.async_init(
DOMAIN,
context={"source": SOURCE_USER},
data={CONF_HOST: "2001:db8::1428:57ab", CONF_TYPE: "laser"},
)
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
assert result["title"] == "HL-L2340DW 0123456789"
assert result["data"][CONF_HOST] == "2001:db8::1428:57ab"
assert result["data"][CONF_TYPE] == "laser"
async def test_invalid_hostname(hass):
"""Test invalid hostname in user_input."""
result = await hass.config_entries.flow.async_init(
@ -118,16 +136,6 @@ async def test_device_exists_abort(hass):
assert result["reason"] == "already_configured"
async def test_zeroconf_no_data(hass):
"""Test we abort if zeroconf provides no data."""
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_ZEROCONF}
)
assert result["type"] == data_entry_flow.RESULT_TYPE_ABORT
assert result["reason"] == "cannot_connect"
async def test_zeroconf_not_brother_printer_error(hass):
"""Test we abort zeroconf flow if printer isn't Brother."""
with patch(