Skip to content

Commit 2ae313b

Browse files
shbatmclaude
andauthored
chore: migrate clean asyncio.gather fan-outs to TaskGroup (#500)
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 8ab2c72 commit 2ae313b

3 files changed

Lines changed: 32 additions & 28 deletions

File tree

pyisy/connection.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -304,10 +304,9 @@ async def get_variables(self) -> str | None:
304304
[URL_VARIABLES, METHOD_GET, VAR_STATE],
305305
]
306306
req_urls = [self.compile_url(req) for req in req_list]
307-
results = await asyncio.gather(
308-
*[self.request(req_url) for req_url in req_urls], return_exceptions=True
309-
)
310-
results = [r for r in results if r is not None] # Strip any bad requests.
307+
async with asyncio.TaskGroup() as tg:
308+
tasks = [tg.create_task(self.request(req_url)) for req_url in req_urls]
309+
results = [r for r in (t.result() for t in tasks) if r is not None]
311310
result = "".join(results)
312311
return result.replace('</vars><?xml version="1.0" encoding="UTF-8"?><vars>', "")
313312

pyisy/isy.py

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -147,37 +147,40 @@ async def initialize(self, with_node_servers=False):
147147
if not self.configuration["model"].startswith("ISY 994"):
148148
self.conn.increase_available_connections()
149149

150-
isy_setup_tasks = [
151-
self.conn.get_status(),
152-
self.conn.get_time(),
153-
self.conn.get_nodes(),
154-
self.conn.get_programs(),
155-
self.conn.get_variable_defs(),
156-
self.conn.get_variables(),
157-
]
158-
if self.configuration[CONFIG_NETWORKING] or self.configuration.get(CONFIG_PORTAL):
159-
isy_setup_tasks.append(asyncio.create_task(self.conn.get_network()))
160-
isy_setup_results = await asyncio.gather(*isy_setup_tasks)
150+
load_network = bool(self.configuration[CONFIG_NETWORKING] or self.configuration.get(CONFIG_PORTAL))
151+
async with asyncio.TaskGroup() as tg:
152+
status_task = tg.create_task(self.conn.get_status())
153+
time_task = tg.create_task(self.conn.get_time())
154+
nodes_task = tg.create_task(self.conn.get_nodes())
155+
programs_task = tg.create_task(self.conn.get_programs())
156+
var_defs_task = tg.create_task(self.conn.get_variable_defs())
157+
vars_task = tg.create_task(self.conn.get_variables())
158+
network_task = tg.create_task(self.conn.get_network()) if load_network else None
159+
160+
status_xml = status_task.result()
161+
time_xml = time_task.result()
162+
nodes_xml = nodes_task.result()
163+
programs_xml = programs_task.result()
161164

162165
# Fail fast if the controller didn't return any of the load-bearing
163166
# responses — most often because the ISY is still booting. Mounting
164167
# empty managers silently leads to confused downstream consumers.
165-
if any(isy_setup_results[i] is None for i in (0, 1, 2, 3)):
168+
if any(x is None for x in (status_xml, time_xml, nodes_xml, programs_xml)):
166169
raise ISYResponseParseError(
167170
"ISY did not return all setup data; the controller may still be initializing."
168171
)
169172

170-
self.clock = Clock(self, xml=isy_setup_results[1])
171-
self.nodes = Nodes(self, xml=isy_setup_results[2])
172-
self.programs = Programs(self, xml=isy_setup_results[3])
173+
self.clock = Clock(self, xml=time_xml)
174+
self.nodes = Nodes(self, xml=nodes_xml)
175+
self.programs = Programs(self, xml=programs_xml)
173176
self.variables = Variables(
174177
self,
175-
def_xml=isy_setup_results[4],
176-
var_xml=isy_setup_results[5],
178+
def_xml=var_defs_task.result(),
179+
var_xml=vars_task.result(),
177180
)
178-
if self.configuration[CONFIG_NETWORKING] or self.configuration.get(CONFIG_PORTAL):
179-
self.networking = NetworkResources(self, xml=isy_setup_results[6])
180-
await self.nodes.update(xml=isy_setup_results[0])
181+
if network_task is not None:
182+
self.networking = NetworkResources(self, xml=network_task.result())
183+
await self.nodes.update(xml=status_xml)
181184
if self.node_servers and with_node_servers:
182185
await self.node_servers.load_node_servers()
183186

pyisy/node_servers.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,10 +150,12 @@ async def get_node_server_profiles(self) -> None:
150150
file_name = attr_from_element(file, TAG_NAME)
151151
file_list.append(f"{slot}/download/{dir_name}/{file_name}")
152152

153-
file_tasks = [
154-
self.isy.conn.request(self.isy.conn.compile_url([URL_PROFILE_NS, file])) for file in file_list
155-
]
156-
file_contents: list[str] = await asyncio.gather(*file_tasks)
153+
async with asyncio.TaskGroup() as tg:
154+
file_tasks = [
155+
tg.create_task(self.isy.conn.request(self.isy.conn.compile_url([URL_PROFILE_NS, file])))
156+
for file in file_list
157+
]
158+
file_contents: list[str] = [t.result() for t in file_tasks]
157159
self._profiles: dict[str, str] = dict(zip(file_list, file_contents, strict=True))
158160

159161
_LOGGER.info("ISY downloaded node server files")

0 commit comments

Comments
 (0)