Skip to content

Commit 31c73a7

Browse files
committed
Bump version
1 parent f0dab96 commit 31c73a7

File tree

9 files changed

+104
-47
lines changed

9 files changed

+104
-47
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# pytest-homeassistant-custom-component
22

3-
![HA core version](https://img.shields.io/static/v1?label=HA+core+version&message=2022.10.5&labelColor=blue)
3+
![HA core version](https://img.shields.io/static/v1?label=HA+core+version&message=2022.11.0b0&labelColor=blue)
44

55
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/MatthewFlamm/pytest-homeassistant-custom-component)
66

ha_version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2022.10.5
1+
2022.11.0b0

pytest_homeassistant_custom_component/common.py

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from unittest.mock import AsyncMock, Mock, patch
2626

2727
from aiohttp.test_utils import unused_port as get_test_instance_port # noqa: F401
28+
import voluptuous as vol
2829

2930
from homeassistant import auth, config_entries, core as ha, loader
3031
from homeassistant.auth import (
@@ -47,7 +48,7 @@
4748
STATE_OFF,
4849
STATE_ON,
4950
)
50-
from homeassistant.core import BLOCK_LOG_TIMEOUT, HomeAssistant
51+
from homeassistant.core import BLOCK_LOG_TIMEOUT, HomeAssistant, ServiceCall, State
5152
from homeassistant.helpers import (
5253
area_registry,
5354
device_registry,
@@ -62,6 +63,7 @@
6263
)
6364
from homeassistant.helpers.dispatcher import async_dispatcher_connect
6465
from homeassistant.helpers.json import JSONEncoder
66+
from homeassistant.helpers.typing import ConfigType
6567
from homeassistant.setup import setup_component
6668
from homeassistant.util.async_ import run_callback_threadsafe
6769
import homeassistant.util.dt as date_util
@@ -333,7 +335,9 @@ def clear_instance(event):
333335
return hass
334336

335337

336-
def async_mock_service(hass, domain, service, schema=None):
338+
def async_mock_service(
339+
hass: HomeAssistant, domain: str, service: str, schema: vol.Schema | None = None
340+
) -> list[ServiceCall]:
337341
"""Set up a fake service & return a calls log list to this service."""
338342
calls = []
339343

@@ -423,18 +427,20 @@ def get_fixture_path(filename: str, integration: str | None = None) -> pathlib.P
423427

424428
if integration is None:
425429
return pathlib.Path(start_path).parent.joinpath("fixtures", filename)
426-
else:
427-
return pathlib.Path(start_path).parent.joinpath(
428-
"components", integration, "fixtures", filename
429-
)
430+
431+
return pathlib.Path(start_path).parent.joinpath(
432+
"components", integration, "fixtures", filename
433+
)
430434

431435

432-
def load_fixture(filename, integration=None):
436+
def load_fixture(filename: str, integration: str | None = None) -> str:
433437
"""Load a fixture."""
434438
return get_fixture_path(filename, integration).read_text()
435439

436440

437-
def mock_state_change_event(hass, new_state, old_state=None):
441+
def mock_state_change_event(
442+
hass: HomeAssistant, new_state: State, old_state: State | None = None
443+
) -> None:
438444
"""Mock state change envent."""
439445
event_data = {"entity_id": new_state.entity_id, "new_state": new_state}
440446

@@ -445,15 +451,18 @@ def mock_state_change_event(hass, new_state, old_state=None):
445451

446452

447453
@ha.callback
448-
def mock_component(hass, component):
454+
def mock_component(hass: HomeAssistant, component: str) -> None:
449455
"""Mock a component is setup."""
450456
if component in hass.config.components:
451457
AssertionError(f"Integration {component} is already setup")
452458

453459
hass.config.components.add(component)
454460

455461

456-
def mock_registry(hass, mock_entries=None):
462+
def mock_registry(
463+
hass: HomeAssistant,
464+
mock_entries: dict[str, entity_registry.RegistryEntry] | None = None,
465+
) -> entity_registry.EntityRegistry:
457466
"""Mock the Entity Registry."""
458467
registry = entity_registry.EntityRegistry(hass)
459468
if mock_entries is None:
@@ -466,7 +475,9 @@ def mock_registry(hass, mock_entries=None):
466475
return registry
467476

468477

469-
def mock_area_registry(hass, mock_entries=None):
478+
def mock_area_registry(
479+
hass: HomeAssistant, mock_entries: dict[str, area_registry.AreaEntry] | None = None
480+
) -> area_registry.AreaRegistry:
470481
"""Mock the Area Registry."""
471482
registry = area_registry.AreaRegistry(hass)
472483
registry.areas = mock_entries or OrderedDict()
@@ -475,7 +486,10 @@ def mock_area_registry(hass, mock_entries=None):
475486
return registry
476487

477488

478-
def mock_device_registry(hass, mock_entries=None):
489+
def mock_device_registry(
490+
hass: HomeAssistant,
491+
mock_entries: dict[str, device_registry.DeviceEntry] | None = None,
492+
) -> device_registry.DeviceRegistry:
479493
"""Mock the Device Registry."""
480494
registry = device_registry.DeviceRegistry(hass)
481495
registry.devices = device_registry.DeviceRegistryItems()
@@ -551,7 +565,9 @@ def mock_policy(self, policy):
551565
self._permissions = auth_permissions.PolicyPermissions(policy, self.perm_lookup)
552566

553567

554-
async def register_auth_provider(hass, config):
568+
async def register_auth_provider(
569+
hass: HomeAssistant, config: ConfigType
570+
) -> auth_providers.AuthProvider:
555571
"""Register an auth provider."""
556572
provider = await auth_providers.auth_provider_from_config(
557573
hass, hass.auth._store, config
@@ -915,17 +931,15 @@ async def mock_psc(hass, config_input, integration):
915931
SetupRecorderInstanceT = Callable[..., Awaitable[recorder.Recorder]]
916932

917933

918-
def init_recorder_component(hass, add_config=None):
934+
def init_recorder_component(hass, add_config=None, db_url="sqlite://"):
919935
"""Initialize the recorder."""
920936
config = dict(add_config) if add_config else {}
921937
if recorder.CONF_DB_URL not in config:
922-
config[recorder.CONF_DB_URL] = "sqlite://" # In memory DB
938+
config[recorder.CONF_DB_URL] = db_url
923939
if recorder.CONF_COMMIT_INTERVAL not in config:
924940
config[recorder.CONF_COMMIT_INTERVAL] = 0
925941

926-
with patch("homeassistant.components.recorder.ALLOW_IN_MEMORY_DB", True), patch(
927-
"homeassistant.components.recorder.migration.migrate_schema"
928-
):
942+
with patch("homeassistant.components.recorder.ALLOW_IN_MEMORY_DB", True):
929943
if recorder.DOMAIN not in hass.data:
930944
recorder_helper.async_initialize_recorder(hass)
931945
assert setup_component(hass, recorder.DOMAIN, {recorder.DOMAIN: config})

pytest_homeassistant_custom_component/components/recorder/common.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import asyncio
99
from dataclasses import dataclass
10-
from datetime import datetime, timedelta
10+
from datetime import datetime
1111
import time
1212
from typing import Any, cast
1313

@@ -25,8 +25,6 @@
2525

2626
from . import db_schema_0
2727

28-
from ...common import async_fire_time_changed, fire_time_changed
29-
3028
DEFAULT_PURGE_TASKS = 3
3129

3230

@@ -73,9 +71,7 @@ def wait_recording_done(hass: HomeAssistant) -> None:
7371

7472
def trigger_db_commit(hass: HomeAssistant) -> None:
7573
"""Force the recorder to commit."""
76-
for _ in range(recorder.DEFAULT_COMMIT_INTERVAL):
77-
# We only commit on time change
78-
fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=1))
74+
recorder.get_instance(hass)._async_commit(dt_util.utcnow())
7975

8076

8177
async def async_wait_recording_done(hass: HomeAssistant) -> None:
@@ -104,8 +100,7 @@ async def async_wait_purge_done(hass: HomeAssistant, max: int = None) -> None:
104100
@ha.callback
105101
def async_trigger_db_commit(hass: HomeAssistant) -> None:
106102
"""Force the recorder to commit. Async friendly."""
107-
for _ in range(recorder.DEFAULT_COMMIT_INTERVAL):
108-
async_fire_time_changed(hass, dt_util.utcnow() + timedelta(seconds=1))
103+
recorder.get_instance(hass)._async_commit(dt_util.utcnow())
109104

110105

111106
async def async_recorder_block_till_done(hass: HomeAssistant) -> None:

pytest_homeassistant_custom_component/const.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010

1111
APPLICATION_NAME: Final = "HomeAssistant"
1212
MAJOR_VERSION: Final = 2022
13-
MINOR_VERSION: Final = 10
14-
PATCH_VERSION: Final = "5"
13+
MINOR_VERSION: Final = 11
14+
PATCH_VERSION: Final = "0b0"
1515
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
1616
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
1717
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 9, 0)

pytest_homeassistant_custom_component/plugins.py

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@
8383
asyncio.set_event_loop_policy = lambda policy: None
8484

8585

86+
def pytest_addoption(parser):
87+
"""Register custom pytest options."""
88+
parser.addoption("--dburl", action="store", default="sqlite://")
89+
90+
8691
def pytest_configure(config):
8792
"""Register marker for tests that log exceptions."""
8893
config.addinivalue_line(
@@ -112,8 +117,19 @@ def pytest_runtest_setup():
112117
def adapt_datetime(val):
113118
return val.isoformat(" ")
114119

120+
# Setup HAFakeDatetime converter for sqlite3
115121
sqlite3.register_adapter(HAFakeDatetime, adapt_datetime)
116122

123+
# Setup HAFakeDatetime converter for pymysql
124+
try:
125+
import MySQLdb.converters as MySQLdb_converters
126+
except ImportError:
127+
pass
128+
else:
129+
MySQLdb_converters.conversions[
130+
HAFakeDatetime
131+
] = MySQLdb_converters.DateTime2literal
132+
117133

118134
def ha_datetime_to_fakedatetime(datetime):
119135
"""Convert datetime to FakeDatetime.
@@ -316,9 +332,17 @@ async def finalize() -> None:
316332

317333

318334
@pytest.fixture
319-
def hass(loop, load_registries, hass_storage, request):
335+
def hass_fixture_setup():
336+
"""Fixture whichis truthy if the hass fixture has been setup."""
337+
return []
338+
339+
340+
@pytest.fixture
341+
def hass(hass_fixture_setup, loop, load_registries, hass_storage, request):
320342
"""Fixture to provide a test instance of Home Assistant."""
321343

344+
hass_fixture_setup.append(True)
345+
322346
orig_tz = dt_util.DEFAULT_TIME_ZONE
323347

324348
def exc_handle(loop, context):
@@ -861,7 +885,29 @@ def recorder_config():
861885

862886

863887
@pytest.fixture
864-
def hass_recorder(enable_nightly_purge, enable_statistics, hass_storage):
888+
def recorder_db_url(pytestconfig):
889+
"""Prepare a default database for tests and return a connection URL."""
890+
db_url: str = pytestconfig.getoption("dburl")
891+
if db_url.startswith("mysql://"):
892+
import sqlalchemy_utils
893+
894+
charset = "utf8mb4' COLLATE = 'utf8mb4_unicode_ci"
895+
assert not sqlalchemy_utils.database_exists(db_url)
896+
sqlalchemy_utils.create_database(db_url, encoding=charset)
897+
elif db_url.startswith("postgresql://"):
898+
pass
899+
yield db_url
900+
if db_url.startswith("mysql://"):
901+
sqlalchemy_utils.drop_database(db_url)
902+
903+
904+
@pytest.fixture
905+
def hass_recorder(
906+
recorder_db_url,
907+
enable_nightly_purge,
908+
enable_statistics,
909+
hass_storage,
910+
):
865911
"""Home Assistant fixture with in-memory recorder."""
866912
original_tz = dt_util.DEFAULT_TIME_ZONE
867913

@@ -880,7 +926,7 @@ def hass_recorder(enable_nightly_purge, enable_statistics, hass_storage):
880926

881927
def setup_recorder(config=None):
882928
"""Set up with params."""
883-
init_recorder_component(hass, config)
929+
init_recorder_component(hass, config, recorder_db_url)
884930
hass.start()
885931
hass.block_till_done()
886932
hass.data[recorder.DATA_INSTANCE].block_till_done()
@@ -893,17 +939,15 @@ def setup_recorder(config=None):
893939
dt_util.DEFAULT_TIME_ZONE = original_tz
894940

895941

896-
async def _async_init_recorder_component(hass, add_config=None):
942+
async def _async_init_recorder_component(hass, add_config=None, db_url=None):
897943
"""Initialize the recorder asynchronously."""
898944
config = dict(add_config) if add_config else {}
899945
if recorder.CONF_DB_URL not in config:
900-
config[recorder.CONF_DB_URL] = "sqlite://" # In memory DB
946+
config[recorder.CONF_DB_URL] = db_url
901947
if recorder.CONF_COMMIT_INTERVAL not in config:
902948
config[recorder.CONF_COMMIT_INTERVAL] = 0
903949

904-
with patch("homeassistant.components.recorder.ALLOW_IN_MEMORY_DB", True), patch(
905-
"homeassistant.components.recorder.migration.migrate_schema"
906-
):
950+
with patch("homeassistant.components.recorder.ALLOW_IN_MEMORY_DB", True):
907951
if recorder.DOMAIN not in hass.data:
908952
recorder_helper.async_initialize_recorder(hass)
909953
assert await async_setup_component(
@@ -918,9 +962,13 @@ async def _async_init_recorder_component(hass, add_config=None):
918962

919963
@pytest.fixture
920964
async def async_setup_recorder_instance(
921-
enable_nightly_purge, enable_statistics
965+
recorder_db_url,
966+
hass_fixture_setup,
967+
enable_nightly_purge,
968+
enable_statistics,
922969
) -> AsyncGenerator[SetupRecorderInstanceT, None]:
923970
"""Yield callable to setup recorder instance."""
971+
assert not hass_fixture_setup
924972

925973
nightly = recorder.Recorder.async_nightly_tasks if enable_nightly_purge else None
926974
stats = recorder.Recorder.async_periodic_statistics if enable_statistics else None
@@ -938,7 +986,7 @@ async def async_setup_recorder(
938986
hass: HomeAssistant, config: ConfigType | None = None
939987
) -> recorder.Recorder:
940988
"""Setup and return recorder instance.""" # noqa: D401
941-
await _async_init_recorder_component(hass, config)
989+
await _async_init_recorder_component(hass, config, recorder_db_url)
942990
await hass.async_block_till_done()
943991
instance = hass.data[recorder.DATA_INSTANCE]
944992
# The recorder's worker is not started until Home Assistant is running

requirements_dev.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# This file is originally from homeassistant/core and modified by pytest-homeassistant-custom-component.
2-
astroid==2.12.5
2+
astroid==2.12.12
33
codecov==2.1.12
4-
mypy==0.981
4+
mypy==0.982
55
pre-commit==2.20.0
6-
pylint==2.15.0
6+
pylint==2.15.5
77
types-atomicwrites==1.4.1
88
types-croniter==1.0.0
99
types-backports==0.1.3

requirements_test.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
-c homeassistant/package_constraints.txt
1010
-r requirements_test_pre_commit.txt
1111
coverage==6.4.4
12-
freezegun==1.2.1
12+
freezegun==1.2.2
1313
mock-open==1.4.0
1414
pipdeptree==2.3.1
1515
pytest-aiohttp==0.3.0
@@ -26,8 +26,8 @@ respx==0.19.2
2626
stdlib-list==0.7.0
2727
tomli==2.0.1;python_version<"3.11"
2828
tqdm==4.64.0
29-
homeassistant==2022.10.5
30-
sqlalchemy==1.4.41
29+
homeassistant==2022.11.0b0
30+
sqlalchemy==1.4.42
3131

3232
paho-mqtt==1.6.1
3333

version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.12.10
1+
0.12.11

0 commit comments

Comments
 (0)