Skip to content

Commit

Permalink
refactor: adjust configuration validation in config flow (moralmunky#880
Browse files Browse the repository at this point in the history
)

* fix: adjust configuration validation in config flow

* adjust defaults, adjust amazon foward email list validation

* update en.json

* formatting

* linting

* update tests

* add "" to list of inputs to clear

* formatting
  • Loading branch information
firstof9 authored Mar 13, 2024
1 parent 6a684ae commit 2a3e000
Show file tree
Hide file tree
Showing 11 changed files with 304 additions and 60 deletions.
45 changes: 19 additions & 26 deletions custom_components/mail_and_packages/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
CONF_SCAN_INTERVAL,
COORDINATOR,
DEFAULT_AMAZON_DAYS,
DEFAULT_AMAZON_FWDS,
DEFAULT_IMAP_TIMEOUT,
DOMAIN,
ISSUE_URL,
Expand Down Expand Up @@ -69,16 +70,6 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
# Sort the resources
updated_config[CONF_RESOURCES] = sorted(updated_config[CONF_RESOURCES])

# Make sure amazon forwarding emails are not a string
if isinstance(updated_config[CONF_AMAZON_FWDS], str):
tmp = updated_config[CONF_AMAZON_FWDS]
tmp_list = []
if "," in tmp:
tmp_list = tmp.split(",")
else:
tmp_list.append(tmp)
updated_config[CONF_AMAZON_FWDS] = tmp_list

if updated_config != config_entry.data:
hass.config_entries.async_update_entry(config_entry, data=updated_config)

Expand Down Expand Up @@ -156,6 +147,7 @@ async def update_listener(hass: HomeAssistant, config_entry: ConfigEntry) -> Non
async def async_migrate_entry(hass, config_entry):
"""Migrate an old config entry."""
version = config_entry.version
new_version = 5

# 1 -> 4: Migrate format
if version == 1:
Expand All @@ -182,11 +174,6 @@ async def async_migrate_entry(hass, config_entry):
# Add default Amazon Days configuration
updated_config[CONF_AMAZON_DAYS] = DEFAULT_AMAZON_DAYS

if updated_config != config_entry.data:
hass.config_entries.async_update_entry(
config_entry, data=updated_config, version=4
)

# 2 -> 4
if version == 2:
_LOGGER.debug("Migrating from version %s", version)
Expand All @@ -202,24 +189,26 @@ async def async_migrate_entry(hass, config_entry):
# Add default Amazon Days configuration
updated_config[CONF_AMAZON_DAYS] = DEFAULT_AMAZON_DAYS

if updated_config != config_entry.data:
hass.config_entries.async_update_entry(
config_entry, data=updated_config, version=4
)

if version == 3:
_LOGGER.debug("Migrating from version %s", version)
updated_config = config_entry.data.copy()

# Add default Amazon Days configuration
updated_config[CONF_AMAZON_DAYS] = DEFAULT_AMAZON_DAYS

if updated_config != config_entry.data:
hass.config_entries.async_update_entry(
config_entry, data=updated_config, version=4
)
if version == 4:
_LOGGER.debug("Migrating from version %s", version)
updated_config = config_entry.data.copy()

_LOGGER.debug("Migration complete")
if updated_config[CONF_AMAZON_FWDS] == ['""']:
updated_config[CONF_AMAZON_FWDS] = DEFAULT_AMAZON_FWDS

if updated_config != config_entry.data:
hass.config_entries.async_update_entry(
config_entry, data=updated_config, version=new_version
)

_LOGGER.debug("Migration complete to version %s", new_version)

return True

Expand All @@ -234,6 +223,7 @@ def __init__(self, hass, host, the_timeout, interval, config):
self.timeout = the_timeout
self.config = config
self.hass = hass
self._data = {}

_LOGGER.debug("Data will be update every %s", self.interval)

Expand All @@ -249,4 +239,7 @@ async def _async_update_data(self):
except Exception as error:
_LOGGER.error("Problem updating sensors: %s", error)
raise UpdateFailed(error) from error
return data

if data:
self._data = data
return self._data
26 changes: 15 additions & 11 deletions custom_components/mail_and_packages/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ async def _check_amazon_forwards(forwards: str) -> tuple:
amazon_forwards_list = forwards.split(",")

# No forwards
elif forwards in ["", "(none)", ""]:
elif forwards in ["", "(none)", '""']:
amazon_forwards_list = []

# If only one address append it to the list
Expand Down Expand Up @@ -159,10 +159,10 @@ def _get_default(key: str, fallback_default: Any = None) -> None:

return vol.Schema(
{
vol.Required(CONF_HOST, default=_get_default(CONF_HOST)): str,
vol.Required(CONF_PORT, default=_get_default(CONF_PORT)): vol.Coerce(int),
vol.Required(CONF_USERNAME, default=_get_default(CONF_USERNAME)): str,
vol.Required(CONF_PASSWORD, default=_get_default(CONF_PASSWORD)): str,
vol.Required(CONF_HOST, default=_get_default(CONF_HOST)): cv.string,
vol.Required(CONF_PORT, default=_get_default(CONF_PORT, 993)): cv.port,
vol.Required(CONF_USERNAME, default=_get_default(CONF_USERNAME)): cv.string,
vol.Required(CONF_PASSWORD, default=_get_default(CONF_PASSWORD)): cv.string,
}
)

Expand All @@ -189,7 +189,9 @@ def _get_default(key: str, fallback_default: Any = None) -> None:
vol.Required(
CONF_RESOURCES, default=_get_default(CONF_RESOURCES)
): cv.multi_select(get_resources()),
vol.Optional(CONF_AMAZON_FWDS, default=_get_default(CONF_AMAZON_FWDS)): str,
vol.Optional(
CONF_AMAZON_FWDS, default=_get_default(CONF_AMAZON_FWDS)
): cv.string,
vol.Optional(CONF_AMAZON_DAYS, default=_get_default(CONF_AMAZON_DAYS)): int,
vol.Optional(
CONF_SCAN_INTERVAL, default=_get_default(CONF_SCAN_INTERVAL)
Expand All @@ -202,11 +204,13 @@ def _get_default(key: str, fallback_default: Any = None) -> None:
): vol.Coerce(int),
vol.Optional(
CONF_GENERATE_MP4, default=_get_default(CONF_GENERATE_MP4)
): bool,
): cv.boolean,
vol.Optional(
CONF_ALLOW_EXTERNAL, default=_get_default(CONF_ALLOW_EXTERNAL)
): bool,
vol.Optional(CONF_CUSTOM_IMG, default=_get_default(CONF_CUSTOM_IMG)): bool,
): cv.boolean,
vol.Optional(
CONF_CUSTOM_IMG, default=_get_default(CONF_CUSTOM_IMG)
): cv.boolean,
}
)

Expand All @@ -225,7 +229,7 @@ def _get_default(key: str, fallback_default: Any = None) -> None:
vol.Optional(
CONF_CUSTOM_IMG_FILE,
default=_get_default(CONF_CUSTOM_IMG_FILE, DEFAULT_CUSTOM_IMG_FILE),
): str,
): cv.string,
}
)

Expand All @@ -234,7 +238,7 @@ def _get_default(key: str, fallback_default: Any = None) -> None:
class MailAndPackagesFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
"""Config flow for Mail and Packages."""

VERSION = 4
VERSION = 5
CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_POLL

def __init__(self):
Expand Down
6 changes: 3 additions & 3 deletions custom_components/mail_and_packages/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@
DEFAULT_FOLDER = '"INBOX"'
DEFAULT_PATH = "custom_components/mail_and_packages/images/"
DEFAULT_IMAGE_SECURITY = True
DEFAULT_IMAP_TIMEOUT = 30
DEFAULT_IMAP_TIMEOUT = 60
DEFAULT_GIF_DURATION = 5
DEFAULT_SCAN_INTERVAL = 5
DEFAULT_SCAN_INTERVAL = 30
DEFAULT_GIF_FILE_NAME = "mail_today.gif"
DEFAULT_AMAZON_FWDS = "(none)"
DEFAULT_AMAZON_FWDS = []
DEFAULT_ALLOW_EXTERNAL = False
DEFAULT_CUSTOM_IMG = False
DEFAULT_CUSTOM_IMG_FILE = "custom_components/mail_and_packages/images/mail_none.gif"
Expand Down
3 changes: 2 additions & 1 deletion custom_components/mail_and_packages/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import aiohttp
import dateparser
import homeassistant.helpers.config_validation as cv
from bs4 import BeautifulSoup
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
Expand Down Expand Up @@ -332,7 +333,7 @@ def fetch(
img_out_path = f"{hass.config.path()}/{config.get(CONF_PATH)}"
gif_duration = config.get(CONF_DURATION)
generate_mp4 = config.get(CONF_GENERATE_MP4)
amazon_fwds = config.get(CONF_AMAZON_FWDS)
amazon_fwds = cv.ensure_list_csv(config.get(CONF_AMAZON_FWDS))
image_name = data[ATTR_IMAGE_NAME]
amazon_image_name = data[ATTR_AMAZON_IMAGE]
amazon_days = config.get(CONF_AMAZON_DAYS)
Expand Down
4 changes: 2 additions & 2 deletions custom_components/mail_and_packages/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"allow_external": "Create image for notification apps",
"custom_img": "Use custom 'no image' image?"
},
"description": "Finish the configuration by customizing the following based on your email structure and Home Assistant installation.\n\nFor details on the [Mail and Packages integration](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) options review the [configuration, templates, and automations section](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) on GitHub.\n\nIf using Amazon forwarded emails please seperate each address with a comma.",
"description": "Finish the configuration by customizing the following based on your email structure and Home Assistant installation.\n\nFor details on the [Mail and Packages integration](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) options review the [configuration, templates, and automations section](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) on GitHub.\n\nIf using Amazon forwarded emails please seperate each address with a comma or enter (none) to clear this setting.",
"title": "Mail and Packages (Step 2 of 2)"
},
"options_3": {
Expand Down Expand Up @@ -86,7 +86,7 @@
"allow_external": "Create image for notification apps",
"custom_img": "Use custom 'no image' image?"
},
"description": "Finish the configuration by customizing the following based on your email structure and Home Assistant installation.\n\nFor details on the [Mail and Packages integration](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) options review the [configuration, templates, and automations section](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) on GitHub.\n\nIf using Amazon forwarded emails please seperate each address with a comma.",
"description": "Finish the configuration by customizing the following based on your email structure and Home Assistant installation.\n\nFor details on the [Mail and Packages integration](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) options review the [configuration, templates, and automations section](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) on GitHub.\n\nIf using Amazon forwarded emails please seperate each address with a comma or enter (none) to clear this setting.",
"title": "Mail and Packages (Step 2 of 2)"
},
"options_3": {
Expand Down
4 changes: 2 additions & 2 deletions custom_components/mail_and_packages/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"amazon_days": "Days back to check for Amazon emails",
"custom_img": "Use custom 'no image' image?"
},
"description": "Finish the configuration by customizing the following based on your email structure and Home Assistant installation.\n\nFor details on the [Mail and Packages integration](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) options review the [configuration, templates, and automations section](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) on GitHub.",
"description": "Finish the configuration by customizing the following based on your email structure and Home Assistant installation.\n\nFor details on the [Mail and Packages integration](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) options review the [configuration, templates, and automations section](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) on GitHub.\n\nIf using Amazon forwarded emails please seperate each address with a comma or enter (none) to clear this setting.",
"title": "Mail and Packages (Step 2 of 2)"
},
"options_3": {
Expand Down Expand Up @@ -87,7 +87,7 @@
"amazon_days": "Days back to check for Amazon emails",
"custom_img": "Use custom 'no image' image?"
},
"description": "Finish the configuration by customizing the following based on your email structure and Home Assistant installation.\n\nFor details on the [Mail and Packages integration](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) options review the [configuration, templates, and automations section](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) on GitHub.",
"description": "Finish the configuration by customizing the following based on your email structure and Home Assistant installation.\n\nFor details on the [Mail and Packages integration](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) options review the [configuration, templates, and automations section](https://github.com/moralmunky/Home-Assistant-Mail-And-Packages/wiki/Configuration-and-Email-Settings#configuration) on GitHub.\n\nIf using Amazon forwarded emails please seperate each address with a comma or enter (none) to clear this setting.",
"title": "Mail and Packages (Step 2 of 2)"
},
"options_3": {
Expand Down
14 changes: 14 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
FAKE_CONFIG_DATA_MISSING_TIMEOUT,
FAKE_CONFIG_DATA_AMAZON_FWD_STRING,
FAKE_CONFIG_DATA_EXTERNAL,
FAKE_CONFIG_DATA_V4_MIGRATE,
)
from pytest_homeassistant_custom_component.common import MockConfigEntry

Expand Down Expand Up @@ -135,6 +136,19 @@ async def integration_fixture_6(hass):

return entry

@pytest.fixture(name="integration_v4_migration")
async def integration_fixture_7(hass):
"""Set up the mail_and_packages integration."""
entry = MockConfigEntry(
domain=DOMAIN,
title="imap.test.email",
data=FAKE_CONFIG_DATA_V4_MIGRATE,
)
entry.add_to_hass(hass)
await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()

return entry

@pytest.fixture()
def mock_imap():
Expand Down
59 changes: 59 additions & 0 deletions tests/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -803,3 +803,62 @@
"gls_packages": 3,
"gls_tracking": ["51687952111"],
}
FAKE_CONFIG_DATA_V4_MIGRATE = {
"allow_external": True,
"amazon_fwds": ['""'],
"custom_img": False,
"folder": '"INBOX"',
"generate_mp4": False,
"gif_duration": 5,
"host": "imap.test.email",
"image_name": "mail_today.gif",
"image_path": "custom_components/mail_and_packages/images/",
"image_security": True,
"imap_timeout": 30,
"password": "suchfakemuchpassword",
"port": 993,
"resources": [
"zpackages_delivered",
"zpackages_transit",
"amazon_delivered",
"amazon_hub",
"amazon_packages",
"capost_delivered",
"capost_delivering",
"capost_packages",
"dhl_delivered",
"dhl_delivering",
"dhl_packages",
"fedex_delivered",
"fedex_delivering",
"fedex_packages",
"hermes_delivered",
"hermes_delivering",
"mail_updated",
"royal_delivered",
"royal_delivering",
"ups_delivered",
"ups_delivering",
"ups_packages",
"usps_delivered",
"usps_delivering",
"usps_mail",
"usps_packages",
"auspost_delivered",
"auspost_delivering",
"auspost_packages",
"poczta_polska_delivering",
"poczta_polska_packages",
"inpost_pl_delivered",
"inpost_pl_delivering",
"inpost_pl_packages",
"dpd_com_pl_delivered",
"dpd_com_pl_delivering",
"dpd_com_pl_packages",
"gls_delivered",
"gls_delivering",
"gls_packages",
],
"scan_interval": 20,
"username": "[email protected]",
}
Loading

0 comments on commit 2a3e000

Please sign in to comment.