Skip to content

Commit bd253bf

Browse files
authored
Merge pull request #762 from plugwise/sc-fixes
Implement async aiofiles.open()
2 parents 6e7bf61 + b9d2eb6 commit bd253bf

File tree

9 files changed

+63
-56
lines changed

9 files changed

+63
-56
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## Ongoing
4+
5+
- Implement async file-open in tests
6+
37
## v1.7.6
48

59
- Maintenance chores (mostly reworking Github CI Actions) backporting from efforts on Python Plugwise [USB: #264](https://github.com/plugwise/python-plugwise-usb/pull/264) after porting our progress using [USB: #263](https://github.com/plugwise/python-plugwise-usb/pull/263)

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ maintainers = [
2525
]
2626
requires-python = ">=3.13"
2727
dependencies = [
28+
"aiofiles",
2829
"aiohttp",
2930
"defusedxml",
3031
"munch",

tests/test_adam.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ async def test_connect_adam_plus_anna_new(self):
2121
"""Test extended Adam (firmware 3.7) with Anna and a switch-group setup."""
2222
self.smile_setup = "adam_plus_anna_new"
2323

24-
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
24+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
2525
server, smile, client = await self.connect_wrapper()
2626
assert smile.smile_hostname == "smile000000"
2727

@@ -139,7 +139,7 @@ async def test_connect_adam_plus_anna_new(self):
139139

140140
# Now change some data and change directory reading xml from
141141
# emulating reading newer dataset after an update_interval
142-
testdata_updated = self.load_testdata(
142+
testdata_updated = await self.load_testdata(
143143
SMILE_TYPE, f"{self.smile_setup}_UPDATED_DATA"
144144
)
145145
self.smile_setup = "updated/adam_plus_anna_new"
@@ -167,7 +167,7 @@ async def test_connect_adam_plus_anna_new(self):
167167
await self.disconnect(server, client)
168168

169169
self.smile_setup = "adam_plus_anna_new"
170-
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
170+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
171171
server, smile, client = await self.connect_wrapper(raise_timeout=True)
172172
await self.device_test(
173173
smile, "2023-12-17 00:00:01", testdata, skip_testing=True
@@ -190,7 +190,7 @@ async def test_connect_adam_plus_anna_new_regulation_off(self):
190190
"""Test regultaion_mode off with control_state key missing for Adam."""
191191
self.smile_setup = "adam_plus_anna_new_regulation_off"
192192

193-
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
193+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
194194
server, smile, client = await self.connect_wrapper()
195195
assert smile.smile_hostname == "smile000000"
196196

@@ -204,7 +204,7 @@ async def test_connect_adam_zone_per_device(self):
204204
"""Test an extensive setup of Adam with a zone per device."""
205205
self.smile_setup = "adam_zone_per_device"
206206

207-
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
207+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
208208
server, smile, client = await self.connect_wrapper()
209209
assert smile.smile_hostname == "smile000000"
210210

@@ -285,7 +285,7 @@ async def test_connect_adam_multiple_devices_per_zone(self):
285285
"""Test an extensive setup of Adam with multiple devices per zone."""
286286
self.smile_setup = "adam_multiple_devices_per_zone"
287287

288-
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
288+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
289289
server, smile, client = await self.connect_wrapper()
290290
assert smile.smile_hostname == "smile000000"
291291

@@ -333,7 +333,7 @@ async def test_adam_heatpump_cooling(self):
333333
"""Test Adam with heatpump in cooling mode and idle."""
334334
self.smile_setup = "adam_heatpump_cooling"
335335

336-
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
336+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
337337
server, smile, client = await self.connect_wrapper()
338338

339339
await self.device_test(smile, "2022-01-02 00:00:01", testdata)
@@ -359,7 +359,7 @@ async def test_connect_adam_onoff_cooling_fake_firmware(self):
359359
"""Test an Adam with a fake OnOff cooling device in cooling mode."""
360360
self.smile_setup = "adam_onoff_cooling_fake_firmware"
361361

362-
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
362+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
363363
server, smile, client = await self.connect_wrapper()
364364
assert smile.smile_hostname == "smile000000"
365365

@@ -382,7 +382,7 @@ async def test_connect_adam_plus_anna(self):
382382
"""Test Adam (firmware 3.0) with Anna setup."""
383383
self.smile_setup = "adam_plus_anna"
384384

385-
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
385+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
386386
server, smile, client = await self.connect_wrapper()
387387
assert smile.smile_hostname == "smile000000"
388388

@@ -432,7 +432,7 @@ async def test_adam_plus_jip(self):
432432
"""Test Adam with Jip setup."""
433433
self.smile_setup = "adam_jip"
434434

435-
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
435+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
436436
server, smile, client = await self.connect_wrapper()
437437

438438
await self.device_test(smile, "2021-06-20 00:00:01", testdata)

tests/test_anna.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ async def test_connect_anna_v4(self):
1717
"""Test an Anna firmware 4 setup."""
1818
self.smile_setup = "anna_v4"
1919

20-
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
20+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
2121
server, smile, client = await self.connect_wrapper()
2222
assert smile.smile_hostname == "smile000000"
2323

@@ -55,7 +55,7 @@ async def test_connect_anna_v4(self):
5555

5656
# Now change some data and change directory reading xml from
5757
# emulating reading newer dataset after an update_interval
58-
testdata_updated = self.load_testdata(
58+
testdata_updated = await self.load_testdata(
5959
SMILE_TYPE, f"{self.smile_setup}_UPDATED_DATA"
6060
)
6161

@@ -97,7 +97,7 @@ async def test_connect_anna_v4_dhw(self):
9797
"""Test an Anna firmware 4 setup for domestic hot water."""
9898
self.smile_setup = "anna_v4_dhw"
9999

100-
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
100+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
101101
server, smile, client = await self.connect_wrapper()
102102
assert smile.smile_hostname == "smile000000"
103103

@@ -127,7 +127,7 @@ async def test_connect_anna_v4_no_tag(self):
127127
"""Test an Anna firmware 4 setup - missing tag (issue)."""
128128
self.smile_setup = "anna_v4_no_tag"
129129

130-
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
130+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
131131
server, smile, client = await self.connect_wrapper()
132132
assert smile.smile_hostname == "smile000000"
133133

@@ -155,7 +155,7 @@ async def test_connect_anna_without_boiler_fw441(self):
155155
"""Test an Anna with firmware 4.4, without a boiler."""
156156
self.smile_setup = "anna_without_boiler_fw441"
157157

158-
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
158+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
159159
server, smile, client = await self.connect_wrapper()
160160
assert smile.smile_hostname == "smile000000"
161161

@@ -183,7 +183,7 @@ async def test_connect_anna_heatpump_heating(self):
183183

184184
self.smile_setup = "anna_heatpump_heating"
185185

186-
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
186+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
187187
server, smile, client = await self.connect_wrapper()
188188
assert smile.smile_hostname == "smile000000"
189189

@@ -218,7 +218,7 @@ async def test_connect_anna_heatpump_heating(self):
218218
# Now change some data and change directory reading xml from
219219
# emulating reading newer dataset after an update_interval,
220220
# set testday to Monday to force an incremental update
221-
testdata_updated = self.load_testdata(
221+
testdata_updated = await self.load_testdata(
222222
SMILE_TYPE, f"{self.smile_setup}_UPDATED_DATA"
223223
)
224224

@@ -240,7 +240,7 @@ async def test_connect_anna_heatpump_cooling(self):
240240
"""
241241
self.smile_setup = "anna_heatpump_cooling"
242242

243-
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
243+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
244244
server, smile, client = await self.connect_wrapper()
245245
assert smile.smile_hostname == "smile000000"
246246

@@ -287,7 +287,7 @@ async def test_connect_anna_heatpump_cooling_fake_firmware(self):
287287
"""
288288
self.smile_setup = "anna_heatpump_cooling_fake_firmware"
289289

290-
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
290+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
291291
server, smile, client = await self.connect_wrapper()
292292
assert smile.smile_hostname == "smile000000"
293293

@@ -312,7 +312,7 @@ async def test_connect_anna_elga_no_cooling(self):
312312

313313
self.smile_setup = "anna_elga_no_cooling"
314314

315-
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
315+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
316316
server, smile, client = await self.connect_wrapper()
317317
assert smile.smile_hostname == "smile000000"
318318

@@ -337,7 +337,7 @@ async def test_connect_anna_elga_2(self):
337337
"""Test a 2nd Anna with Elga setup, cooling off, in idle mode (with missing outdoor temperature - solved)."""
338338
self.smile_setup = "anna_elga_2"
339339

340-
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
340+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
341341
server, smile, client = await self.connect_wrapper()
342342
assert smile.smile_hostname == "smile000000"
343343

@@ -366,7 +366,7 @@ async def test_connect_anna_elga_2_schedule_off(self):
366366
"""Test Anna with Elga setup, cooling off, in idle mode, modified to schedule off."""
367367
self.smile_setup = "anna_elga_2_schedule_off"
368368

369-
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
369+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
370370
server, smile, client = await self.connect_wrapper()
371371
assert smile.smile_hostname == "smile000000"
372372

@@ -391,7 +391,7 @@ async def test_connect_anna_elga_2_cooling(self):
391391
"""
392392
self.smile_setup = "anna_elga_2_cooling"
393393

394-
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
394+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
395395
server, smile, client = await self.connect_wrapper()
396396
assert smile.smile_hostname == "smile000000"
397397

@@ -421,7 +421,7 @@ async def test_connect_anna_elga_2_cooling(self):
421421
assert result
422422

423423
# Simulate a change of season: from cooling to heating after an update_interval
424-
testdata_updated = self.load_testdata(
424+
testdata_updated = await self.load_testdata(
425425
SMILE_TYPE, f"{self.smile_setup}_UPDATED_DATA"
426426
)
427427

@@ -448,7 +448,7 @@ async def test_connect_anna_loria_heating_idle(self):
448448
"""Test an Anna with a Loria in heating mode - state idle."""
449449
self.smile_setup = "anna_loria_heating_idle"
450450

451-
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
451+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
452452
server, smile, client = await self.connect_wrapper()
453453
assert smile.smile_hostname == "smile000000"
454454

@@ -516,7 +516,7 @@ async def test_connect_anna_loria_cooling_active(self):
516516
"""Test an Anna with a Loria in heating mode - state idle."""
517517
self.smile_setup = "anna_loria_cooling_active"
518518

519-
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
519+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
520520
server, smile, client = await self.connect_wrapper()
521521
assert smile.smile_hostname == "smile000000"
522522

@@ -540,7 +540,7 @@ async def test_connect_anna_loria_driessens(self):
540540
"""Test an Anna with a Loria in heating mode - state idle."""
541541
self.smile_setup = "anna_loria_driessens"
542542

543-
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
543+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
544544
server, smile, client = await self.connect_wrapper()
545545
assert smile.smile_hostname == "smile000000"
546546

tests/test_init.py

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import pytest
1717

1818
# Testing
19+
import aiofiles
1920
import aiohttp
2021
from freezegun import freeze_time
2122
from packaging import version
@@ -50,7 +51,7 @@
5051
class TestPlugwise: # pylint: disable=attribute-defined-outside-init
5152
"""Tests for Plugwise Smile."""
5253

53-
def _write_json(self, call, data):
54+
async def _write_json(self, call, data):
5455
"""Store JSON data to per-setup files for HA component testing."""
5556
no_fixtures = os.getenv("NO_FIXTURES") == "1"
5657
if no_fixtures:
@@ -65,8 +66,8 @@ def _write_json(self, call, data):
6566
if not os.path.exists(os.path.dirname(datafile)): # pragma: no cover
6667
os.mkdir(os.path.dirname(datafile))
6768

68-
with open(datafile, "w", encoding="utf-8") as fixture_file:
69-
fixture_file.write(
69+
async with aiofiles.open(datafile, "w", encoding="utf-8") as fixture_file:
70+
await fixture_file.write(
7071
json.dumps(
7172
data,
7273
indent=2,
@@ -77,15 +78,16 @@ def _write_json(self, call, data):
7778
+ "\n"
7879
)
7980

80-
def load_testdata(
81+
async def load_testdata(
8182
self, smile_type: str = "adam", smile_setup: str = "adam_zone_per_device"
8283
):
8384
"""Load JSON data from setup, return as object."""
8485
path = os.path.join(
8586
os.path.dirname(__file__), f"../tests/data/{smile_type}/{smile_setup}.json"
8687
)
87-
with open(path, encoding="utf-8") as testdata_file:
88-
return json.load(testdata_file)
88+
async with aiofiles.open(path, encoding="utf-8") as testdata_file:
89+
content = await testdata_file.read()
90+
return json.loads(content)
8991

9092
async def setup_app(
9193
self,
@@ -187,8 +189,8 @@ async def smile_appliances(self, request):
187189
os.path.dirname(__file__),
188190
f"../userdata/{self.smile_setup}/core.appliances.xml",
189191
)
190-
with open(userdata, encoding="utf-8") as filedata:
191-
data = filedata.read()
192+
async with aiofiles.open(userdata, encoding="utf-8") as filedata:
193+
data = await filedata.read()
192194
return aiohttp.web.Response(text=data)
193195

194196
async def smile_domain_objects(self, request):
@@ -197,8 +199,8 @@ async def smile_domain_objects(self, request):
197199
os.path.dirname(__file__),
198200
f"../userdata/{self.smile_setup}/core.domain_objects.xml",
199201
)
200-
with open(userdata, encoding="utf-8") as filedata:
201-
data = filedata.read()
202+
async with aiofiles.open(userdata, encoding="utf-8") as filedata:
203+
data = await filedata.read()
202204
return aiohttp.web.Response(text=data)
203205

204206
async def smile_locations(self, request):
@@ -207,8 +209,8 @@ async def smile_locations(self, request):
207209
os.path.dirname(__file__),
208210
f"../userdata/{self.smile_setup}/core.locations.xml",
209211
)
210-
with open(userdata, encoding="utf-8") as filedata:
211-
data = filedata.read()
212+
async with aiofiles.open(userdata, encoding="utf-8") as filedata:
213+
data = await filedata.read()
212214
return aiohttp.web.Response(text=data)
213215

214216
async def smile_modules(self, request):
@@ -217,8 +219,8 @@ async def smile_modules(self, request):
217219
os.path.dirname(__file__),
218220
f"../userdata/{self.smile_setup}/core.modules.xml",
219221
)
220-
with open(userdata, encoding="utf-8") as filedata:
221-
data = filedata.read()
222+
async with aiofiles.open(userdata, encoding="utf-8") as filedata:
223+
data = await filedata.read()
222224
return aiohttp.web.Response(text=data)
223225

224226
async def smile_status(self, request):
@@ -228,8 +230,8 @@ async def smile_status(self, request):
228230
os.path.dirname(__file__),
229231
f"../userdata/{self.smile_setup}/system_status_xml.xml",
230232
)
231-
with open(userdata, encoding="utf-8") as filedata:
232-
data = filedata.read()
233+
async with aiofiles.open(userdata, encoding="utf-8") as filedata:
234+
data = await filedata.read()
233235
return aiohttp.web.Response(text=data)
234236
except OSError as exc:
235237
raise aiohttp.web.HTTPNotFound from exc
@@ -641,7 +643,7 @@ def test_and_assert(test_dict, data, header):
641643
"cooling_state"
642644
]
643645

644-
self._write_json("data", data)
646+
await self._write_json("data", data)
645647

646648
if "FIXTURES" in os.environ:
647649
_LOGGER.info("Skipping tests: Requested fixtures only") # pragma: no cover

tests/test_legacy_anna.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class TestPlugwiseAnna(TestPlugwise): # pylint: disable=attribute-defined-outsi
1616
async def test_connect_legacy_anna(self):
1717
"""Test a legacy Anna device."""
1818
self.smile_setup = "legacy_anna"
19-
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
19+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
2020

2121
server, smile, client = await self.connect_legacy_wrapper()
2222
assert smile.smile_hostname == "smile000000"
@@ -53,7 +53,7 @@ async def test_connect_legacy_anna_2(self):
5353
"""Test another legacy Anna device."""
5454
self.smile_setup = "legacy_anna_2"
5555

56-
testdata = self.load_testdata(SMILE_TYPE, self.smile_setup)
56+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
5757
server, smile, client = await self.connect_legacy_wrapper()
5858
assert smile.smile_hostname == "smile000000"
5959

0 commit comments

Comments
 (0)