Skip to content

Commit 711526f

Browse files
authored
Remove brackets from decorator in Husqvarna Automower (home-assistant#154042)
1 parent 4be428f commit 711526f

File tree

5 files changed

+53
-21
lines changed

5 files changed

+53
-21
lines changed

homeassistant/components/husqvarna_automower/button.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ def available(self) -> bool:
112112
self.mower_attributes
113113
)
114114

115-
@handle_sending_exception()
115+
@handle_sending_exception
116116
async def async_press(self) -> None:
117117
"""Send a command to the mower."""
118118
await self.entity_description.press_fn(self.coordinator.api, self.mower_id)

homeassistant/components/husqvarna_automower/entity.py

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from collections.abc import Callable, Coroutine
77
import functools
88
import logging
9-
from typing import TYPE_CHECKING, Any, Concatenate
9+
from typing import TYPE_CHECKING, Any, Concatenate, ParamSpec, TypeVar, overload
1010

1111
from aioautomower.exceptions import ApiError
1212
from aioautomower.model import MowerActivities, MowerAttributes, MowerStates, WorkArea
@@ -37,23 +37,42 @@
3737
]
3838

3939

40-
@callback
41-
def _work_area_translation_key(work_area_id: int, key: str) -> str:
42-
"""Return the translation key."""
43-
if work_area_id == 0:
44-
return f"my_lawn_{key}"
45-
return f"work_area_{key}"
40+
_Entity = TypeVar("_Entity", bound="AutomowerBaseEntity")
41+
_P = ParamSpec("_P")
42+
4643

44+
@overload
45+
def handle_sending_exception(
46+
_func: Callable[Concatenate[_Entity, _P], Coroutine[Any, Any, Any]],
47+
) -> Callable[Concatenate[_Entity, _P], Coroutine[Any, Any, None]]: ...
4748

48-
type _FuncType[_T, **_P, _R] = Callable[Concatenate[_T, _P], Coroutine[Any, Any, _R]]
49+
50+
@overload
51+
def handle_sending_exception(
52+
*,
53+
poll_after_sending: bool = False,
54+
) -> Callable[
55+
[Callable[Concatenate[_Entity, _P], Coroutine[Any, Any, Any]]],
56+
Callable[Concatenate[_Entity, _P], Coroutine[Any, Any, None]],
57+
]: ...
4958

5059

51-
def handle_sending_exception[_Entity: AutomowerBaseEntity, **_P](
60+
def handle_sending_exception(
61+
_func: Callable[Concatenate[_Entity, _P], Coroutine[Any, Any, Any]] | None = None,
62+
*,
5263
poll_after_sending: bool = False,
53-
) -> Callable[[_FuncType[_Entity, _P, Any]], _FuncType[_Entity, _P, None]]:
64+
) -> (
65+
Callable[Concatenate[_Entity, _P], Coroutine[Any, Any, None]]
66+
| Callable[
67+
[Callable[Concatenate[_Entity, _P], Coroutine[Any, Any, Any]]],
68+
Callable[Concatenate[_Entity, _P], Coroutine[Any, Any, None]],
69+
]
70+
):
5471
"""Handle exceptions while sending a command and optionally refresh coordinator."""
5572

56-
def decorator(func: _FuncType[_Entity, _P, Any]) -> _FuncType[_Entity, _P, None]:
73+
def decorator(
74+
func: Callable[Concatenate[_Entity, _P], Coroutine[Any, Any, Any]],
75+
) -> Callable[Concatenate[_Entity, _P], Coroutine[Any, Any, None]]:
5776
@functools.wraps(func)
5877
async def wrapper(self: _Entity, *args: _P.args, **kwargs: _P.kwargs) -> None:
5978
try:
@@ -73,7 +92,20 @@ async def wrapper(self: _Entity, *args: _P.args, **kwargs: _P.kwargs) -> None:
7392

7493
return wrapper
7594

76-
return decorator
95+
if _func is None:
96+
# call with brackets: @handle_sending_exception(...)
97+
return decorator
98+
99+
# call without brackets: @handle_sending_exception
100+
return decorator(_func)
101+
102+
103+
@callback
104+
def _work_area_translation_key(work_area_id: int, key: str) -> str:
105+
"""Return the translation key."""
106+
if work_area_id == 0:
107+
return f"my_lawn_{key}"
108+
return f"work_area_{key}"
77109

78110

79111
class AutomowerBaseEntity(CoordinatorEntity[AutomowerDataUpdateCoordinator]):

homeassistant/components/husqvarna_automower/lawn_mower.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -135,22 +135,22 @@ def work_areas(self) -> dict[int, WorkArea] | None:
135135
"""Return the work areas of the mower."""
136136
return self.mower_attributes.work_areas
137137

138-
@handle_sending_exception()
138+
@handle_sending_exception
139139
async def async_start_mowing(self) -> None:
140140
"""Resume schedule."""
141141
await self.coordinator.api.commands.resume_schedule(self.mower_id)
142142

143-
@handle_sending_exception()
143+
@handle_sending_exception
144144
async def async_pause(self) -> None:
145145
"""Pauses the mower."""
146146
await self.coordinator.api.commands.pause_mowing(self.mower_id)
147147

148-
@handle_sending_exception()
148+
@handle_sending_exception
149149
async def async_dock(self) -> None:
150150
"""Parks the mower until next schedule."""
151151
await self.coordinator.api.commands.park_until_next_schedule(self.mower_id)
152152

153-
@handle_sending_exception()
153+
@handle_sending_exception
154154
async def async_override_schedule(
155155
self, override_mode: str, duration: timedelta
156156
) -> None:
@@ -160,7 +160,7 @@ async def async_override_schedule(
160160
if override_mode == PARK:
161161
await self.coordinator.api.commands.park_for(self.mower_id, duration)
162162

163-
@handle_sending_exception()
163+
@handle_sending_exception
164164
async def async_override_schedule_work_area(
165165
self, work_area_id: int, duration: timedelta
166166
) -> None:

homeassistant/components/husqvarna_automower/select.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def current_option(self) -> str:
6767
"""Return the current option for the entity."""
6868
return cast(HeadlightModes, self.mower_attributes.settings.headlight.mode)
6969

70-
@handle_sending_exception()
70+
@handle_sending_exception
7171
async def async_select_option(self, option: str) -> None:
7272
"""Change the selected option."""
7373
await self.coordinator.api.commands.set_headlight_mode(

homeassistant/components/husqvarna_automower/switch.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,12 +108,12 @@ def is_on(self) -> bool:
108108
"""Return the state of the switch."""
109109
return self.mower_attributes.mower.mode != MowerModes.HOME
110110

111-
@handle_sending_exception()
111+
@handle_sending_exception
112112
async def async_turn_off(self, **kwargs: Any) -> None:
113113
"""Turn the entity off."""
114114
await self.coordinator.api.commands.park_until_further_notice(self.mower_id)
115115

116-
@handle_sending_exception()
116+
@handle_sending_exception
117117
async def async_turn_on(self, **kwargs: Any) -> None:
118118
"""Turn the entity on."""
119119
await self.coordinator.api.commands.resume_schedule(self.mower_id)

0 commit comments

Comments
 (0)