|
13 | 13 | from collections.abc import Generator
|
14 | 14 | from re import Match
|
15 | 15 | from re import Pattern
|
16 |
| -from typing import Any |
17 |
| -from typing import cast |
| 16 | +from typing import Concatenate |
18 | 17 | from typing import IO
|
19 | 18 | from typing import Literal
|
20 | 19 | from typing import NamedTuple
|
| 20 | +from typing import ParamSpec |
21 | 21 | from typing import TYPE_CHECKING
|
22 | 22 | from typing import TypedDict
|
23 | 23 | from typing import TypeVar
|
|
37 | 37 | if TYPE_CHECKING:
|
38 | 38 | from babi.main import Screen # XXX: circular
|
39 | 39 |
|
40 |
| -TCallable = TypeVar('TCallable', bound=Callable[..., Any]) |
| 40 | +P = ParamSpec('P') |
| 41 | +R = TypeVar('R') |
| 42 | +FileMethod = Callable[Concatenate['File', P], R] |
41 | 43 |
|
42 | 44 | WS_RE = re.compile(r'^\s*')
|
43 | 45 |
|
@@ -127,43 +129,55 @@ def apply(self, file: File) -> Action:
|
127 | 129 | return action
|
128 | 130 |
|
129 | 131 |
|
130 |
| -def action(func: TCallable) -> TCallable: |
| 132 | +def action(func: FileMethod[P, R]) -> FileMethod[P, R]: |
131 | 133 | @functools.wraps(func)
|
132 |
| - def action_inner(self: File, *args: Any, **kwargs: Any) -> Any: |
| 134 | + def action_inner(self: File, *args: P.args, **kwargs: P.kwargs) -> R: |
133 | 135 | self.finalize_previous_action()
|
134 | 136 | return func(self, *args, **kwargs)
|
135 |
| - return cast(TCallable, action_inner) |
| 137 | + return action_inner |
136 | 138 |
|
137 | 139 |
|
138 | 140 | def edit_action(
|
139 | 141 | name: str,
|
140 | 142 | *,
|
141 | 143 | final: bool,
|
142 |
| -) -> Callable[[TCallable], TCallable]: |
143 |
| - def edit_action_decorator(func: TCallable) -> TCallable: |
| 144 | +) -> Callable[[FileMethod[P, R]], FileMethod[P, R]]: |
| 145 | + def edit_action_decorator(func: FileMethod[P, R]) -> FileMethod[P, R]: |
144 | 146 | @functools.wraps(func)
|
145 |
| - def edit_action_inner(self: File, *args: Any, **kwargs: Any) -> Any: |
| 147 | + def edit_action_inner( |
| 148 | + self: File, |
| 149 | + *args: P.args, |
| 150 | + **kwargs: P.kwargs, |
| 151 | + ) -> R: |
146 | 152 | with self.edit_action_context(name, final=final):
|
147 | 153 | return func(self, *args, **kwargs)
|
148 |
| - return cast(TCallable, edit_action_inner) |
| 154 | + return edit_action_inner |
149 | 155 | return edit_action_decorator
|
150 | 156 |
|
151 | 157 |
|
152 |
| -def keep_selection(func: TCallable) -> TCallable: |
| 158 | +def keep_selection(func: FileMethod[P, R]) -> FileMethod[P, R]: |
153 | 159 | @functools.wraps(func)
|
154 |
| - def keep_selection_inner(self: File, *args: Any, **kwargs: Any) -> Any: |
| 160 | + def keep_selection_inner( |
| 161 | + self: File, |
| 162 | + *args: P.args, |
| 163 | + **kwargs: P.kwargs, |
| 164 | + ) -> R: |
155 | 165 | with self.select():
|
156 | 166 | return func(self, *args, **kwargs)
|
157 |
| - return cast(TCallable, keep_selection_inner) |
| 167 | + return keep_selection_inner |
158 | 168 |
|
159 | 169 |
|
160 |
| -def clear_selection(func: TCallable) -> TCallable: |
| 170 | +def clear_selection(func: FileMethod[P, R]) -> FileMethod[P, R]: |
161 | 171 | @functools.wraps(func)
|
162 |
| - def clear_selection_inner(self: File, *args: Any, **kwargs: Any) -> Any: |
| 172 | + def clear_selection_inner( |
| 173 | + self: File, |
| 174 | + *args: P.args, |
| 175 | + **kwargs: P.kwargs, |
| 176 | + ) -> R: |
163 | 177 | ret = func(self, *args, **kwargs)
|
164 | 178 | self.selection.clear()
|
165 | 179 | return ret
|
166 |
| - return cast(TCallable, clear_selection_inner) |
| 180 | + return clear_selection_inner |
167 | 181 |
|
168 | 182 |
|
169 | 183 | class Found(NamedTuple):
|
|
0 commit comments