Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump minimum HA version to 2024.4.1 #3672

Merged
merged 10 commits into from
May 22, 2024
4 changes: 2 additions & 2 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ jobs:
- name: 📥 Checkout the repository
uses: actions/checkout@v4.1.1

- name: 🛠️ Set up Python 3.11
- name: 🛠️ Set up Python 3.12
uses: actions/setup-python@v5.1.0
with:
python-version: "3.11"
python-version: "3.12"
cache: 'pip'
cache-dependency-path: |
requirements_core_min.txt
Expand Down
2 changes: 1 addition & 1 deletion action/action.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ async def preflight():
try:
hacs.hass = HomeAssistant() # pylint: disable=no-value-for-parameter
except TypeError:
hacs.hass = HomeAssistant("") # pylint: disable=too-many-function-args
hacs.hass = HomeAssistant(".") # pylint: disable=too-many-function-args

hacs.system.action = True
hacs.configuration.token = TOKEN
Expand Down
6 changes: 3 additions & 3 deletions requirements_core_min.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# https://github.com/home-assistant/core/blob/2023.6.0/homeassistant/components/frontend/manifest.json
home-assistant-frontend==20230607.0
homeassistant==2023.6.0
# https://github.com/home-assistant/core/blob/2024.4.0/homeassistant/components/frontend/manifest.json
home-assistant-frontend==20240403.1
homeassistant==2024.4.0
4 changes: 2 additions & 2 deletions requirements_test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ asynctest==0.13.0
fnv-hash-fast==0.5.0
freezegun==1.4.0
janus==1.0.0
Pillow==10.3.0
Pillow==10.2.0
psutil-home-assistant==0.0.1
pytest==7.4.3
pytest-asyncio==0.21.1
pytest-cov==4.1.0
pytest-snapshot==0.9.0
pytest-socket==0.6.0
RestrictedPython==7.0
SQLAlchemy==2.0.23
SQLAlchemy==2.0.29
2 changes: 1 addition & 1 deletion scripts/data/generate_category_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def __init__(self, session: ClientSession, *, token: str | None = None):
try:
self.hass = HomeAssistant() # pylint: disable=no-value-for-parameter
except TypeError:
self.hass = HomeAssistant("") # pylint: disable=too-many-function-args
self.hass = HomeAssistant(".") # pylint: disable=too-many-function-args

self.queue = QueueManager(self.hass)
self.repositories = HacsRepositories()
Expand Down
96 changes: 63 additions & 33 deletions tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,16 @@
from homeassistant.core import CoreState, HomeAssistant, callback
from homeassistant.helpers import (
area_registry as ar,
category_registry as cr,
device_registry as dr,
entity,
entity_registry as er,
floor_registry as fr,
issue_registry as ir,
label_registry as lr,
restore_state as rs,
storage,
translation,
)
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.json import ExtendedJSONEncoder
Expand Down Expand Up @@ -255,15 +259,18 @@ def async_save_delay(self, *args: Any, **kwargs: Any) -> None:


# pylint: disable=protected-access
@asynccontextmanager
async def async_test_home_assistant_min_version(
loop, load_registries=True, config_dir: str | None = None
):
event_loop: asyncio.AbstractEventLoop | None = None,
load_registries: bool = True,
config_dir: str | None = None,
) -> AsyncGenerator[HomeAssistant, None]:
"""Return a Home Assistant object pointing at test config dir.

This should be copied from the minimum supported version,
currently Home Assistant Core 2023.6.0.
currently Home Assistant Core 2024.4.0.
frenck marked this conversation as resolved.
Show resolved Hide resolved
"""
hass = HomeAssistant()
hass = HomeAssistant(config_dir or get_test_config_dir())
store = auth_store.AuthStore(hass)
hass.auth = auth.AuthManager(hass, store, {}, {})
ensure_auth_manager_loaded(hass.auth)
Expand All @@ -272,8 +279,9 @@ async def async_test_home_assistant_min_version(
orig_async_add_job = hass.async_add_job
orig_async_add_executor_job = hass.async_add_executor_job
orig_async_create_task = hass.async_create_task
orig_tz = dt_util.DEFAULT_TIME_ZONE

def async_add_job(target, *args):
def async_add_job(target, *args, eager_start: bool = False):
"""Add job."""
check_target = target
while isinstance(check_target, ft.partial):
Expand All @@ -284,7 +292,7 @@ def async_add_job(target, *args):
fut.set_result(target(*args))
return fut

return orig_async_add_job(target, *args)
return orig_async_add_job(target, *args, eager_start=eager_start)

def async_add_executor_job(target, *args):
"""Add executor job."""
Expand All @@ -299,14 +307,14 @@ def async_add_executor_job(target, *args):

return orig_async_add_executor_job(target, *args)

def async_create_task(coroutine, name=None):
def async_create_task(coroutine, name=None, eager_start=False):
ludeeus marked this conversation as resolved.
Show resolved Hide resolved
"""Create task."""
if isinstance(coroutine, Mock) and not isinstance(coroutine, AsyncMock):
fut = asyncio.Future()
fut.set_result(None)
return fut

return orig_async_create_task(coroutine, name)
return orig_async_create_task(coroutine, name, eager_start)

hass.async_add_job = async_add_job
hass.async_add_executor_job = async_add_executor_job
Expand All @@ -315,45 +323,73 @@ def async_create_task(coroutine, name=None):
hass.data[loader.DATA_CUSTOM_COMPONENTS] = {}

hass.config.location_name = "test home"
# HACS: Modified to use the passed in config_dir
# hass.config.config_dir = get_test_config_dir()
hass.config.config_dir = config_dir
hass.config.latitude = 32.87336
hass.config.longitude = -117.22743
hass.config.elevation = 0
hass.config.set_time_zone("US/Pacific")
hass.config.units = METRIC_SYSTEM
# HACS: Disabled
# hass.config.media_dirs = {"local": get_test_config_dir("media")}
hass.config.media_dirs = {"local": get_test_config_dir("media")}
hass.config.skip_pip = True
hass.config.skip_pip_packages = []

hass.config_entries = config_entries.ConfigEntries(
hass,
{"_": ("Not empty or else some bad checks for hass config in discovery.py" " breaks")},
)
hass.bus.async_listen_once(
EVENT_HOMEASSISTANT_STOP,
hass.config_entries._async_shutdown,
run_immediately=True,
)

# Load the registries
entity.async_setup(hass)
loader.async_setup(hass)

# setup translation cache instead of calling translation.async_setup(hass)
hass.data[translation.TRANSLATION_FLATTEN_CACHE] = translation._TranslationCache(hass)
if load_registries:
with (
patch("homeassistant.helpers.storage.Store.async_load", return_value=None),
patch.object(StoreWithoutWriteLoad, "async_load", return_value=None),
patch(
"homeassistant.helpers.area_registry.AreaRegistryStore",
StoreWithoutWriteLoad,
),
patch(
"homeassistant.helpers.device_registry.DeviceRegistryStore",
StoreWithoutWriteLoad,
),
patch(
"homeassistant.helpers.entity_registry.EntityRegistryStore",
StoreWithoutWriteLoad,
),
patch(
"homeassistant.helpers.storage.Store", # Floor & label registry are different
StoreWithoutWriteLoad,
),
patch(
"homeassistant.helpers.issue_registry.IssueRegistryStore",
StoreWithoutWriteLoad,
),
patch(
"homeassistant.helpers.restore_state.RestoreStateData.async_setup_dump",
return_value=None,
),
patch("homeassistant.helpers.restore_state.start.async_at_start"),
patch(
"homeassistant.helpers.restore_state.start.async_at_start",
),
):
await asyncio.gather(
ar.async_load(hass),
dr.async_load(hass),
er.async_load(hass),
ir.async_load(hass),
rs.async_load(hass),
)
await ar.async_load(hass)
await cr.async_load(hass)
await dr.async_load(hass)
await er.async_load(hass)
await fr.async_load(hass)
await ir.async_load(hass)
await lr.async_load(hass)
await rs.async_load(hass)
hass.data[bootstrap.DATA_REGISTRIES_LOADED] = None

hass.state = CoreState.running
hass.set_state(CoreState.running)

@callback
def clear_instance(event):
Expand All @@ -362,7 +398,10 @@ def clear_instance(event):

hass.bus.async_listen_once(EVENT_HOMEASSISTANT_CLOSE, clear_instance)

return hass
yield hass

# Restore timezone, it is set when creating the hass object
dt_util.DEFAULT_TIME_ZONE = orig_tz


@asynccontextmanager
Expand All @@ -376,15 +415,6 @@ async def async_test_home_assistant_dev(
This should be copied from latest Home Assistant version,
currently Home Assistant Core 2024.5.0dev0 (2024-4-11).
"""

# Local imports of features not present in min version
from homeassistant.helpers import (
category_registry as cr,
floor_registry as fr,
label_registry as lr,
translation,
)

hass = HomeAssistant(config_dir or get_test_config_dir())
store = auth_store.AuthStore(hass)
hass.auth = auth.AuthManager(hass, store, {}, {})
Expand Down
8 changes: 4 additions & 4 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,13 @@ def exc_handle(loop, context):
orig_exception_handler(loop, context)

exceptions: list[Exception] = []
if AwesomeVersion(HA_VERSION) > "2023.6.0":
if AwesomeVersion(HA_VERSION) > "2024.4.0":
context_manager = async_test_home_assistant_dev(event_loop, config_dir=tmpdir.strpath)
hass_obj = event_loop.run_until_complete(context_manager.__aenter__())
else:
hass_obj = event_loop.run_until_complete(
async_test_home_assistant_min_version(event_loop, config_dir=tmpdir.strpath)
context_manager = async_test_home_assistant_min_version(
event_loop, config_dir=tmpdir.strpath
)
hass_obj = event_loop.run_until_complete(context_manager.__aenter__())
event_loop.run_until_complete(async_setup_component(hass_obj, "homeassistant", {}))
with patch("homeassistant.components.python_script.setup", return_value=True):
assert event_loop.run_until_complete(async_setup_component(hass_obj, "python_script", {}))
Expand Down