<commit_before>"""Config flow for Network UPS Tools (NUT) integration."""
import logging

import voluptuous as vol

from homeassistant import config_entries, core, exceptions
from homeassistant.components import zeroconf
from homeassistant.const import (
    CONF_ALIAS,
    CONF_BASE,
    CONF_HOST,
    CONF_PASSWORD,
    CONF_PORT,
    CONF_SCAN_INTERVAL,
    CONF_USERNAME,
)
from homeassistant.core import callback
from homeassistant.data_entry_flow import FlowResult

from . import PyNUTData
from .const import DEFAULT_HOST, DEFAULT_PORT, DEFAULT_SCAN_INTERVAL, DOMAIN

_LOGGER = logging.getLogger(__name__)


def _base_schema(discovery_info):
    """Generate base schema."""
    base_schema = {}
    if not discovery_info:
        base_schema.update(
            {
                vol.Optional(CONF_HOST, default=DEFAULT_HOST): str,
                vol.Optional(CONF_PORT, default=DEFAULT_PORT): int,
            }
        )
    base_schema.update(
        {vol.Optional(CONF_USERNAME): str, vol.Optional(CONF_PASSWORD): str}
    )

    return vol.Schema(base_schema)


def _ups_schema(ups_list):
    """UPS selection schema."""
    return vol.Schema({vol.Required(CONF_ALIAS): vol.In(ups_list)})


async def validate_input(hass: core.HomeAssistant, data):
    """Validate the user input allows us to connect.

    Data has the keys from _base_schema with values provided by the user.
    """

    host = data[CONF_HOST]
    port = data[CONF_PORT]
    alias = data.get(CONF_ALIAS)
    username = data.get(CONF_USERNAME)
    password = data.get(CONF_PASSWORD)

    data = PyNUTData(host, port, alias, username, password)
    await hass.async_add_executor_job(data.update)
    if not (status := data.status):
        raise CannotConnect

    return {"ups_list": data.ups_list, "available_resources": status}


def _format_host_port_alias(user_input):
    """Format a host, port, and alias so it can be used for comparison or display."""
    host = user_input[CONF_HOST]
    port = user_input[CONF_PORT]
    alias = user_input.get(CONF_ALIAS)
    if alias:
        return f"{alias}@{host}:{port}"
    return f"{host}:{port}"


class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
    """Handle a config flow for Network UPS Tools (NUT)."""

    VERSION = 1

    def __init__(self):
        """Initialize the nut config flow."""
        self.nut_config = {}
        self.discovery_info = {}
        self.ups_list = None
        self.title = None

    async def async_step_zeroconf(
        self, discovery_info: zeroconf.ZeroconfServiceInfo
    ) -> FlowResult:
        """Prepare configuration for a discovered nut device."""
        self.discovery_info = discovery_info
        await self._async_handle_discovery_without_unique_id()
        self.context["title_placeholders"] = {
            CONF_PORT: discovery_info[zeroconf.ATTR_PORT] or DEFAULT_PORT,
            CONF_HOST: discovery_info[zeroconf.ATTR_HOST],
        }
        return await self.async_step_user()

    async def async_step_user(self, user_input=None):
        """Handle the user input."""
        errors = {}
        if user_input is not None:
            if self.discovery_info:
                user_input.update(
                    {
                        CONF_HOST: self.discovery_info[CONF_HOST],
                        CONF_PORT: self.discovery_info.port or DEFAULT_PORT,<commit_msg>Use dataclass properties in nut discovery (#60603)<commit_after>"""Config flow for Network UPS Tools (NUT) integration."""
from __future__ import annotations

import logging

import voluptuous as vol

from homeassistant import config_entries, core, exceptions
from homeassistant.components import zeroconf
from homeassistant.const import (
    CONF_ALIAS,
    CONF_BASE,
    CONF_HOST,
    CONF_PASSWORD,
    CONF_PORT,
    CONF_SCAN_INTERVAL,
    CONF_USERNAME,
)
from homeassistant.core import callback
from homeassistant.data_entry_flow import FlowResult

from . import PyNUTData
from .const import DEFAULT_HOST, DEFAULT_PORT, DEFAULT_SCAN_INTERVAL, DOMAIN

_LOGGER = logging.getLogger(__name__)


def _base_schema(discovery_info: zeroconf.ZeroconfServiceInfo | None) -> vol.Schema:
    """Generate base schema."""
    base_schema = {}
    if not discovery_info:
        base_schema.update(
            {
                vol.Optional(CONF_HOST, default=DEFAULT_HOST): str,
                vol.Optional(CONF_PORT, default=DEFAULT_PORT): int,
            }
        )
    base_schema.update(
        {vol.Optional(CONF_USERNAME): str, vol.Optional(CONF_PASSWORD): str}
    )

    return vol.Schema(base_schema)


def _ups_schema(ups_list):
    """UPS selection schema."""
    return vol.Schema({vol.Required(CONF_ALIAS): vol.In(ups_list)})


async def validate_input(hass: core.HomeAssistant, data):
    """Validate the user input allows us to connect.

    Data has the keys from _base_schema with values provided by the user.
    """

    host = data[CONF_HOST]
    port = data[CONF_PORT]
    alias = data.get(CONF_ALIAS)
    username = data.get(CONF_USERNAME)
    password = data.get(CONF_PASSWORD)

    data = PyNUTData(host, port, alias, username, password)
    await hass.async_add_executor_job(data.update)
    if not (status := data.status):
        raise CannotConnect

    return {"ups_list": data.ups_list, "available_resources": status}


def _format_host_port_alias(user_input):
    """Format a host, port, and alias so it can be used for comparison or display."""
    host = user_input[CONF_HOST]
    port = user_input[CONF_PORT]
    alias = user_input.get(CONF_ALIAS)
    if alias:
        return f"{alias}@{host}:{port}"
    return f"{host}:{port}"


class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
    """Handle a config flow for Network UPS Tools (NUT)."""

    VERSION = 1

    def __init__(self):
        """Initialize the nut config flow."""
        self.nut_config = {}
        self.discovery_info: zeroconf.ZeroconfServiceInfo | None = None
        self.ups_list = None
        self.title = None

    async def async_step_zeroconf(
        self, discovery_info: zeroconf.ZeroconfServiceInfo
    ) -> FlowResult:
        """Prepare configuration for a discovered nut device."""
        self.discovery_info = discovery_info
        await self._async_handle_discovery_without_unique_id()
        self.context["title_placeholders"] = {
            CONF_PORT: discovery_info.port or DEFAULT_PORT,
            CONF_HOST: discovery_info.host,
        }
        return await self.async_step_user()

    async def async_step_user(self, user_input=None):
        """Handle the user input."""
        errors = {}
        if user_input is not None:
            if self.discovery_info:
                user_input.update(
                    {
                        CONF_HOST: self.discovery_info.host,
                        CONF_PORT: self.discovery_info.port or DEFAULT_PORT,
{'fraction_non_alphanumeric': 0.09262759924385633, 'fraction_numerical': 0.0010178857059764432, 'mean_word_length': 2.982628836132021, 'pattern_counts': {'":': 4, '<': 3, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7547459', 'n_tokens_mistral': 2109, 'n_tokens_neox': 2028, 'n_words': 507}