Skip to content

Commit 3fd8216

Browse files
committed
updates tests for python 3.10 and HA 2023.3.6
1 parent c9a1744 commit 3fd8216

17 files changed

+133
-33
lines changed

.github/workflows/validate.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
- uses: "actions/checkout@v2"
1919
- uses: "actions/setup-python@v1"
2020
with:
21-
python-version: "3.9"
21+
python-version: "3.10"
2222
- run: python3 -m pip install black
2323
- run: black .
2424

@@ -29,7 +29,7 @@ jobs:
2929
- uses: "actions/checkout@v2"
3030
- uses: "actions/setup-python@v1"
3131
with:
32-
python-version: "3.9"
32+
python-version: "3.10"
3333
- run: python3 -m pip install -r tests/requirements_test.txt
3434
- run: pytest --cov=custom_components
3535

@@ -40,7 +40,7 @@ jobs:
4040
- uses: "actions/checkout@v2"
4141
- uses: "actions/setup-python@v1"
4242
with:
43-
python-version: "3.9"
43+
python-version: "3.10"
4444
- run: python3 -m pip install -r tests/requirements_test.txt
4545
- run: pylint custom_components/pyscript/*.py tests/*.py
4646

@@ -51,6 +51,6 @@ jobs:
5151
- uses: "actions/checkout@v2"
5252
- uses: "actions/setup-python@v1"
5353
with:
54-
python-version: "3.9"
54+
python-version: "3.10"
5555
- run: python3 -m pip install -r tests/requirements_test.txt
5656
- run: mypy custom_components/pyscript/*.py tests/*.py

custom_components/pyscript/function.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,12 @@ def service_register(cls, global_ctx_name, domain, service, callback):
463463
)
464464
cls.service_cnt[key] += 1
465465
cls.hass.services.async_register(domain, service, callback)
466+
_LOGGER.info(
467+
"TESTXX service_register: %s.%s, %s",
468+
domain,
469+
service,
470+
cls.hass.services.has_service(domain, service),
471+
)
466472

467473
@classmethod
468474
def service_remove(cls, global_ctx_name, domain, service):

tests/requirements_test.txt

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
coverage>=6.3.1
2-
croniter>=1.3.8
3-
watchdog>=2.0.3
1+
coverage==7.1.0
2+
croniter==1.3.8
3+
watchdog==2.1.9
44
mock-open==1.4.0
5-
mypy>=0.991
6-
pre-commit>=2.21.0
7-
pytest>=7.0.1
8-
pytest-cov>=2.9.0
9-
pytest-homeassistant-custom-component==0.11.26
10-
pylint>=2.15.0
11-
pylint-strict-informational>=0.1
5+
mypy==1.1.1
6+
pre-commit==3.2.1
7+
pytest==7.2.1
8+
pytest-cov==3.0.0
9+
pytest-homeassistant-custom-component==0.13.10
10+
pylint==2.17.1
11+
pylint-strict-informational==0.1

tests/test_apps_modules.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
import re
66
from unittest.mock import patch
77

8-
from custom_components.pyscript.const import DOMAIN, FOLDER
98
from mock_open import MockOpen
9+
import pytest
1010

11+
from custom_components.pyscript.const import DOMAIN, FOLDER
1112
from homeassistant.const import EVENT_STATE_CHANGED
1213
from homeassistant.setup import async_setup_component
1314

@@ -17,6 +18,7 @@ async def wait_until_done(notify_q):
1718
return await asyncio.wait_for(notify_q.get(), timeout=4)
1819

1920

21+
@pytest.mark.asyncio
2022
async def test_service_exists(hass, caplog):
2123
"""Test importing a pyscript module."""
2224

@@ -148,7 +150,7 @@ def func15():
148150
def isfile_side_effect(arg):
149151
return arg in file_contents
150152

151-
def glob_side_effect(path, recursive=None):
153+
def glob_side_effect(path, recursive=None, root_dir=None, dir_fd=None, include_hidden=False):
152154
result = []
153155
path_re = path.replace("*", "[^/]*").replace(".", "\\.")
154156
path_re = path_re.replace("[^/]*[^/]*/", ".*")
@@ -190,6 +192,7 @@ async def state_changed(event):
190192

191193
assert not hass.services.has_service("pyscript", "func10")
192194
assert not hass.services.has_service("pyscript", "func11")
195+
assert hass.services.has_service("pyscript", "func1")
193196
assert hass.services.has_service("pyscript", "func13")
194197
assert hass.services.has_service("pyscript", "func14")
195198
assert not hass.services.has_service("pyscript", "func15")
@@ -205,4 +208,5 @@ async def state_changed(event):
205208
assert "modules/xyz2 global_ctx=modules.xyz2;" in caplog.text
206209
assert "func14 global_ctx=scripts.a.b.c.d.func14;" in caplog.text
207210
assert "ModuleNotFoundError: import of no_such_package not allowed" in caplog.text
208-
assert "SyntaxError: invalid syntax (bad_module.py, line 2)" in caplog.text
211+
# assert "SyntaxError: invalid syntax (bad_module.py, line 2)" in caplog.text # <= 3.9
212+
assert "SyntaxError: expected ':' (bad_module.py, line 2)" in caplog.text

tests/test_config_flow.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
"""Tests for pyscript config flow."""
2+
23
import logging
34
from unittest.mock import patch
45

5-
from custom_components.pyscript import PYSCRIPT_SCHEMA
6-
from custom_components.pyscript.const import CONF_ALLOW_ALL_IMPORTS, CONF_HASS_IS_GLOBAL, DOMAIN
76
import pytest
87

8+
from custom_components.pyscript import PYSCRIPT_SCHEMA
9+
from custom_components.pyscript.const import CONF_ALLOW_ALL_IMPORTS, CONF_HASS_IS_GLOBAL, DOMAIN
910
from homeassistant import data_entry_flow
1011
from homeassistant.config_entries import SOURCE_IMPORT, SOURCE_USER
1112

@@ -20,6 +21,7 @@ def pyscript_bypass_setup_fixture():
2021
yield
2122

2223

24+
@pytest.mark.asyncio
2325
async def test_user_flow_minimum_fields(hass, pyscript_bypass_setup):
2426
"""Test user config flow with minimum fields."""
2527
# test form shows
@@ -36,6 +38,7 @@ async def test_user_flow_minimum_fields(hass, pyscript_bypass_setup):
3638
assert not result["data"][CONF_HASS_IS_GLOBAL]
3739

3840

41+
@pytest.mark.asyncio
3942
async def test_user_flow_all_fields(hass, pyscript_bypass_setup):
4043
"""Test user config flow with all fields."""
4144
# test form shows
@@ -54,6 +57,7 @@ async def test_user_flow_all_fields(hass, pyscript_bypass_setup):
5457
assert result["data"][CONF_HASS_IS_GLOBAL]
5558

5659

60+
@pytest.mark.asyncio
5761
async def test_user_already_configured(hass, pyscript_bypass_setup):
5862
"""Test service is already configured during user setup."""
5963
result = await hass.config_entries.flow.async_init(
@@ -74,6 +78,7 @@ async def test_user_already_configured(hass, pyscript_bypass_setup):
7478
assert result["reason"] == "single_instance_allowed"
7579

7680

81+
@pytest.mark.asyncio
7782
async def test_import_flow(hass, pyscript_bypass_setup):
7883
"""Test import config flow works."""
7984
result = await hass.config_entries.flow.async_init(
@@ -83,6 +88,7 @@ async def test_import_flow(hass, pyscript_bypass_setup):
8388
assert result["type"] == data_entry_flow.RESULT_TYPE_CREATE_ENTRY
8489

8590

91+
@pytest.mark.asyncio
8692
async def test_import_flow_update_allow_all_imports(hass, pyscript_bypass_setup):
8793
"""Test import config flow updates existing entry when `allow_all_imports` has changed."""
8894
result = await hass.config_entries.flow.async_init(
@@ -101,6 +107,7 @@ async def test_import_flow_update_allow_all_imports(hass, pyscript_bypass_setup)
101107
assert result["reason"] == "updated_entry"
102108

103109

110+
@pytest.mark.asyncio
104111
async def test_import_flow_update_apps_from_none(hass, pyscript_bypass_setup):
105112
"""Test import config flow updates existing entry when `apps` has changed from None to something."""
106113
result = await hass.config_entries.flow.async_init(
@@ -117,6 +124,7 @@ async def test_import_flow_update_apps_from_none(hass, pyscript_bypass_setup):
117124
assert result["reason"] == "updated_entry"
118125

119126

127+
@pytest.mark.asyncio
120128
async def test_import_flow_update_apps_to_none(hass, pyscript_bypass_setup):
121129
"""Test import config flow updates existing entry when `apps` has changed from something to None."""
122130
result = await hass.config_entries.flow.async_init(
@@ -131,6 +139,7 @@ async def test_import_flow_update_apps_to_none(hass, pyscript_bypass_setup):
131139
assert result["reason"] == "updated_entry"
132140

133141

142+
@pytest.mark.asyncio
134143
async def test_import_flow_no_update(hass, pyscript_bypass_setup):
135144
"""Test import config flow doesn't update existing entry when data is same."""
136145
result = await hass.config_entries.flow.async_init(
@@ -147,6 +156,7 @@ async def test_import_flow_no_update(hass, pyscript_bypass_setup):
147156
assert result["reason"] == "already_configured"
148157

149158

159+
@pytest.mark.asyncio
150160
async def test_import_flow_update_user(hass, pyscript_bypass_setup):
151161
"""Test import config flow update excludes `allow_all_imports` from being updated when updated entry was a user entry."""
152162
result = await hass.config_entries.flow.async_init(
@@ -171,6 +181,7 @@ async def test_import_flow_update_user(hass, pyscript_bypass_setup):
171181
}
172182

173183

184+
@pytest.mark.asyncio
174185
async def test_import_flow_update_import(hass, pyscript_bypass_setup):
175186
"""Test import config flow update includes `allow_all_imports` in update when updated entry was imported entry."""
176187
result = await hass.config_entries.flow.async_init(
@@ -191,6 +202,7 @@ async def test_import_flow_update_import(hass, pyscript_bypass_setup):
191202
assert hass.config_entries.async_entries(DOMAIN)[0].data == {"apps": {"test_app": {"param": 1}}}
192203

193204

205+
@pytest.mark.asyncio
194206
async def test_options_flow_import(hass, pyscript_bypass_setup):
195207
"""Test options flow aborts because configuration needs to be managed via configuration.yaml."""
196208
result = await hass.config_entries.flow.async_init(
@@ -213,6 +225,7 @@ async def test_options_flow_import(hass, pyscript_bypass_setup):
213225
assert result["title"] == ""
214226

215227

228+
@pytest.mark.asyncio
216229
async def test_options_flow_user_change(hass, pyscript_bypass_setup):
217230
"""Test options flow updates config entry when options change."""
218231
result = await hass.config_entries.flow.async_init(
@@ -241,6 +254,7 @@ async def test_options_flow_user_change(hass, pyscript_bypass_setup):
241254
assert entry.data[CONF_HASS_IS_GLOBAL] is False
242255

243256

257+
@pytest.mark.asyncio
244258
async def test_options_flow_user_no_change(hass, pyscript_bypass_setup):
245259
"""Test options flow aborts when options don't change."""
246260
result = await hass.config_entries.flow.async_init(
@@ -270,6 +284,7 @@ async def test_options_flow_user_no_change(hass, pyscript_bypass_setup):
270284
assert result["title"] == ""
271285

272286

287+
@pytest.mark.asyncio
273288
async def test_config_entry_reload(hass):
274289
"""Test that config entry reload does not duplicate listeners."""
275290
with patch("homeassistant.config.load_yaml_config_file", return_value={}), patch(

tests/test_decorator_errors.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
from datetime import datetime as dt
55
from unittest.mock import mock_open, patch
66

7+
import pytest
8+
79
from custom_components.pyscript import trigger
810
from custom_components.pyscript.const import DOMAIN
911
from custom_components.pyscript.function import Function
@@ -70,6 +72,7 @@ async def wait_until_done(notify_q):
7072
return await asyncio.wait_for(notify_q.get(), timeout=4)
7173

7274

75+
@pytest.mark.asyncio
7376
async def test_decorator_errors(hass, caplog):
7477
"""Test decorator syntax and run-time errors."""
7578
notify_q = asyncio.Queue(0)
@@ -164,11 +167,13 @@ def func8():
164167
assert literal_eval(await wait_until_done(notify_q)) == seq_num
165168

166169
assert (
167-
"SyntaxError: unexpected EOF while parsing (file.hello.func1 @state_trigger(), line 1)"
170+
# "SyntaxError: unexpected EOF while parsing (file.hello.func1 @state_trigger(), line 1)" # <= 3.9
171+
"SyntaxError: invalid syntax (file.hello.func1 @state_trigger(), line 1)" # >= 3.10
168172
in caplog.text
169173
)
170174
assert (
171-
"SyntaxError: unexpected EOF while parsing (file.hello.func2 @event_trigger(), line 1)"
175+
# "SyntaxError: unexpected EOF while parsing (file.hello.func2 @event_trigger(), line 1)" # <= 3.9
176+
"SyntaxError: '(' was never closed (file.hello.func2 @event_trigger(), line 1)" # >= 3.10
172177
in caplog.text
173178
)
174179
assert "SyntaxError: invalid syntax (file.hello.func3 @state_active(), line 1)" in caplog.text
@@ -192,10 +197,12 @@ def func8():
192197
in caplog.text
193198
)
194199

195-
assert "unexpected EOF while parsing (file.hello.func7 state_trigger, line 1)" in caplog.text
200+
# assert "unexpected EOF while parsing (file.hello.func7 state_trigger, line 1)" in caplog.text # <= 3.9
201+
assert "invalid syntax (file.hello.func7 state_trigger, line 1)" in caplog.text
196202
assert 'can only concatenate str (not "int") to str' in caplog.text
197203

198204

205+
@pytest.mark.asyncio
199206
async def test_decorator_errors_missing_trigger(hass, caplog):
200207
"""Test decorator syntax and run-time errors."""
201208
notify_q = asyncio.Queue(0)
@@ -215,6 +222,7 @@ def func4():
215222
)
216223

217224

225+
@pytest.mark.asyncio
218226
async def test_decorator_errors_missing_arg(hass, caplog):
219227
"""Test decorator syntax and run-time errors."""
220228
notify_q = asyncio.Queue(0)
@@ -234,6 +242,7 @@ def func8():
234242
)
235243

236244

245+
@pytest.mark.asyncio
237246
async def test_decorator_errors_missing_arg2(hass, caplog):
238247
"""Test decorator syntax and run-time errors."""
239248
notify_q = asyncio.Queue(0)
@@ -253,6 +262,7 @@ def func9():
253262
)
254263

255264

265+
@pytest.mark.asyncio
256266
async def test_decorator_errors_bad_arg_type(hass, caplog):
257267
"""Test decorator syntax and run-time errors."""
258268
notify_q = asyncio.Queue(0)
@@ -272,6 +282,7 @@ def func10():
272282
)
273283

274284

285+
@pytest.mark.asyncio
275286
async def test_decorator_errors_bad_arg_type2(hass, caplog):
276287
"""Test decorator syntax and run-time errors."""
277288
notify_q = asyncio.Queue(0)
@@ -291,6 +302,7 @@ def func11():
291302
)
292303

293304

305+
@pytest.mark.asyncio
294306
async def test_service_reload_error(hass, caplog):
295307
"""Test using a reserved name generates an error."""
296308

@@ -310,6 +322,7 @@ def reload():
310322
)
311323

312324

325+
@pytest.mark.asyncio
313326
async def test_service_state_active_extra_args(hass, caplog):
314327
"""Test using extra args to state_active generates an error."""
315328

@@ -329,6 +342,7 @@ def func4():
329342
)
330343

331344

345+
@pytest.mark.asyncio
332346
async def test_service_wrong_arg_type(hass, caplog):
333347
"""Test using too many args with service an error."""
334348

@@ -348,6 +362,7 @@ def func5():
348362
)
349363

350364

365+
@pytest.mark.asyncio
351366
async def test_time_trigger_wrong_arg_type(hass, caplog):
352367
"""Test using wrong argument type generates an error."""
353368

@@ -367,6 +382,7 @@ def func6():
367382
)
368383

369384

385+
@pytest.mark.asyncio
370386
async def test_decorator_kwargs(hass, caplog):
371387
"""Test invalid keyword arguments generates an error."""
372388

@@ -386,6 +402,7 @@ def func7():
386402
)
387403

388404

405+
@pytest.mark.asyncio
389406
async def test_decorator_kwargs2(hass, caplog):
390407
"""Test invalid keyword arguments generates an error."""
391408

@@ -405,6 +422,7 @@ def func7():
405422
)
406423

407424

425+
@pytest.mark.asyncio
408426
async def test_decorator_kwargs3(hass, caplog):
409427
"""Test invalid keyword arguments type generates an error."""
410428

@@ -424,6 +442,7 @@ def func7():
424442
)
425443

426444

445+
@pytest.mark.asyncio
427446
async def test_decorator_kwargs4(hass, caplog):
428447
"""Test invalid keyword arguments type generates an error."""
429448

0 commit comments

Comments
 (0)