Skip to content

Commit ffb1931

Browse files
committed
chore(lint): update ruff to 0.10.0 and fix linting issues, make store.subscribe private
1 parent f0a8eb3 commit ffb1931

18 files changed

+104
-82
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## Upcoming
4+
5+
- chore(lint): update `ruff` to `0.10.0` and fix linting issues, make `store.subscribe` private
6+
37
## Version 0.20.1
48

59
- fix: avoid using `asdict` in combine-reducers's reducer as it can get too costly for large dataclasses and may even run into errors

demo.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ def event_handler(event: SleepEvent) -> None:
136136
# -----
137137

138138
# Subscription <
139-
store.subscribe(lambda state: print('Subscription state:', state))
139+
store._subscribe(lambda state: print('Subscription state:', state)) # noqa: SLF001
140140
# >
141141

142142
# -----

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ dependencies = ["python-immutable >= 1.1.1", "python-strtobool >= 1.0.0"]
1414
dev-dependencies = [
1515
"poethepoet >= 0.24.4",
1616
"pyright >= 1.1.396",
17-
"ruff >= 0.9.10",
17+
"ruff >= 0.10.0",
1818
"pytest >= 8.1.1",
1919
"pytest-cov >= 4.1.0",
2020
"pytest-timeout >= 2.3.1",

redux/autorun.py

+7-7
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ def __init__(
102102

103103
self._last_selector_result: SelectorOutput | None = None
104104
self._last_comparator_result: ComparatorOutput = cast(
105-
ComparatorOutput,
105+
'ComparatorOutput',
106106
object(),
107107
)
108108
if iscoroutinefunction(func):
@@ -118,7 +118,7 @@ def __init__(
118118
self._call()
119119

120120
if self._options.reactive:
121-
self._unsubscribe = store.subscribe(
121+
self._unsubscribe = store._subscribe( # noqa: SLF001
122122
lambda state: self._call() if self._check(state) else None,
123123
)
124124
else:
@@ -190,7 +190,7 @@ def _check(
190190
except AttributeError:
191191
return False
192192
if self._comparator is None:
193-
comparator_result = cast(ComparatorOutput, selector_result)
193+
comparator_result = cast('ComparatorOutput', selector_result)
194194
else:
195195
try:
196196
comparator_result = self._comparator(state)
@@ -228,7 +228,7 @@ def _call(
228228
if iscoroutine(value) and create_task:
229229
if self._options.auto_await:
230230
future = Future()
231-
self._latest_value = cast(ReturnType, future)
231+
self._latest_value = cast('ReturnType', future)
232232
create_task(
233233
value,
234234
callback=functools.partial(
@@ -244,7 +244,7 @@ def _call(
244244
):
245245
self._latest_value.close()
246246
self._latest_value = cast(
247-
ReturnType,
247+
'ReturnType',
248248
AwaitableWrapper(value),
249249
)
250250
else:
@@ -268,7 +268,7 @@ def __call__(
268268
self._check(state)
269269
if self._should_be_called or args or kwargs or not self._options.memoization:
270270
self._call(*args, **kwargs)
271-
return cast(ReturnType, self._latest_value)
271+
return cast('ReturnType', self._latest_value)
272272

273273
def __repr__(
274274
self: Autorun[
@@ -298,7 +298,7 @@ def value(
298298
Args,
299299
],
300300
) -> ReturnType:
301-
return cast(ReturnType, self._latest_value)
301+
return cast('ReturnType', self._latest_value)
302302

303303
def subscribe(
304304
self: Autorun[

redux/basic_types.py

+10-5
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class BaseEvent(Immutable): ...
3939
State = TypeVar('State', bound=Immutable | None, infer_variance=True)
4040
Action = TypeVar('Action', bound=BaseAction | None, infer_variance=True)
4141
Event = TypeVar('Event', bound=BaseEvent | None, infer_variance=True)
42-
Event2 = TypeVar('Event2', bound=BaseEvent, infer_variance=True)
42+
StrictEvent = TypeVar('StrictEvent', bound=BaseEvent, infer_variance=True)
4343
SelectorOutput = TypeVar('SelectorOutput', infer_variance=True)
4444
ComparatorOutput = TypeVar('ComparatorOutput', infer_variance=True)
4545
ReturnType = TypeVar('ReturnType', infer_variance=True)
@@ -168,10 +168,7 @@ def unsubscribe(self: AutorunReturnType) -> None: ...
168168
__name__: str
169169

170170

171-
class AutorunDecorator(
172-
Protocol,
173-
Generic[SelectorOutput, ReturnType],
174-
):
171+
class AutorunDecorator(Protocol, Generic[SelectorOutput, ReturnType]):
175172
@overload
176173
def __call__(
177174
self: AutorunDecorator,
@@ -340,3 +337,11 @@ class CombineReducerUnregisterAction(CombineReducerAction):
340337
| dict[str, 'SnapshotAtom']
341338
| list['SnapshotAtom']
342339
)
340+
341+
342+
class SubscribeEventCleanup(Immutable, Generic[StrictEvent]):
343+
unsubscribe: Callable[[], None]
344+
handler: EventHandler[StrictEvent]
345+
346+
def __call__(self: SubscribeEventCleanup) -> None:
347+
self.unsubscribe()

redux/combine_reducers.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def combined_reducer(
104104
del fields_copy[key]
105105
del annotations_copy[key]
106106
state_class = make_immutable(state_type.__name__, annotations_copy)
107-
cast(Any, state_class).__dataclass_fields__ = fields_copy
107+
cast('Any', state_class).__dataclass_fields__ = fields_copy
108108

109109
state = state_class(
110110
_id=state._id, # noqa: SLF001

redux/main.py

+29-27
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import queue
88
import weakref
99
from collections import defaultdict
10-
from collections.abc import Callable
1110
from threading import Lock, Thread
1211
from typing import (
1312
TYPE_CHECKING,
@@ -35,7 +34,6 @@
3534
CreateStoreOptions,
3635
DispatchParameters,
3736
Event,
38-
Event2,
3937
EventHandler,
4038
EventMiddleware,
4139
FinishAction,
@@ -46,6 +44,8 @@
4644
SelectorOutput,
4745
SnapshotAtom,
4846
State,
47+
StrictEvent,
48+
SubscribeEventCleanup,
4949
UnknownAutorunDecorator,
5050
UnknownViewDecorator,
5151
ViewDecorator,
@@ -61,7 +61,7 @@
6161
from redux.side_effect_runner import SideEffectRunnerThread
6262

6363
if TYPE_CHECKING:
64-
from collections.abc import Awaitable
64+
from collections.abc import Awaitable, Callable
6565

6666

6767
class Store(Generic[State, Action, Event], SerializationMixin):
@@ -112,11 +112,11 @@ def __init__(
112112
if self.store_options.auto_init:
113113
if self.store_options.scheduler:
114114
self.store_options.scheduler(
115-
lambda: self.dispatch(cast(Action, InitAction())),
115+
lambda: self.dispatch(cast('Action', InitAction())),
116116
interval=False,
117117
)
118118
else:
119-
self.dispatch(cast(Action, InitAction()))
119+
self.dispatch(cast('Action', InitAction()))
120120

121121
if self.store_options.scheduler:
122122
self.store_options.scheduler(self.run, interval=True)
@@ -148,7 +148,7 @@ def _run_actions(self: Store[State, Action, Event]) -> None:
148148
self._call_listeners(self._state)
149149

150150
if isinstance(action, FinishAction):
151-
self._dispatch([cast(Event, FinishEvent())])
151+
self._dispatch([cast('Event', FinishEvent())])
152152

153153
def _run_event_handlers(self: Store[State, Action, Event]) -> None:
154154
while len(self._events) > 0:
@@ -216,7 +216,7 @@ def _dispatch(
216216
) -> None:
217217
for item in items:
218218
if isinstance(item, BaseAction):
219-
action = cast(Action, item)
219+
action = cast('Action', item)
220220
for action_middleware in self._action_middlewares:
221221
action_ = action_middleware(action)
222222
if action_ is None:
@@ -225,7 +225,7 @@ def _dispatch(
225225
else:
226226
self._actions.append(action)
227227
if isinstance(item, BaseEvent):
228-
event = cast(Event, item)
228+
event = cast('Event', item)
229229
for event_middleware in self._event_middlewares:
230230
event_ = event_middleware(event)
231231
if event_ is None:
@@ -237,7 +237,7 @@ def _dispatch(
237237
if self.store_options.scheduler is None and not self._is_running.locked():
238238
self.run()
239239

240-
def subscribe(
240+
def _subscribe(
241241
self: Store[State, Action, Event],
242242
listener: Callable[[State], Any],
243243
*,
@@ -256,11 +256,11 @@ def subscribe(
256256

257257
def subscribe_event(
258258
self: Store[State, Action, Event],
259-
event_type: type[Event2],
260-
handler: EventHandler[Event2],
259+
event_type: type[StrictEvent],
260+
handler: EventHandler[StrictEvent],
261261
*,
262262
keep_ref: bool = True,
263-
) -> Callable[[], None]:
263+
) -> SubscribeEventCleanup:
264264
"""Subscribe to events."""
265265
if keep_ref:
266266
handler_ref = handler
@@ -269,12 +269,12 @@ def subscribe_event(
269269
else:
270270
handler_ref = weakref.ref(handler)
271271

272-
self._event_handlers[cast(Any, event_type)].add(handler_ref)
272+
self._event_handlers[cast('Any', event_type)].add(handler_ref)
273273

274274
def unsubscribe() -> None:
275-
self._event_handlers[cast(Any, event_type)].discard(handler_ref)
275+
self._event_handlers[cast('Any', event_type)].discard(handler_ref)
276276

277-
return unsubscribe
277+
return SubscribeEventCleanup(unsubscribe=unsubscribe, handler=handler)
278278

279279
def _wait_for_store_to_finish(self: Store[State, Action, Event]) -> None:
280280
"""Wait for the store to finish."""
@@ -325,20 +325,20 @@ def autorun(
325325
"""Create a new autorun, reflecting on state changes."""
326326

327327
@overload
328-
def decorator(
328+
def autorun_decorator(
329329
func: Callable[
330330
Concatenate[SelectorOutput, Args],
331331
ReturnType,
332332
],
333333
) -> AutorunReturnType[ReturnType, Args]: ...
334334
@overload
335-
def decorator(
335+
def autorun_decorator(
336336
func: Callable[
337337
Concatenate[SelectorOutput, Args],
338338
Awaitable[ReturnType],
339339
],
340340
) -> AutorunReturnType[Awaitable[ReturnType], Args]: ...
341-
def decorator(
341+
def autorun_decorator(
342342
func: Callable[
343343
Concatenate[SelectorOutput, Args],
344344
AwaitableOrNot[ReturnType],
@@ -348,11 +348,11 @@ def decorator(
348348
store=self,
349349
selector=selector,
350350
comparator=comparator,
351-
func=cast(Callable, func),
351+
func=cast('Callable', func),
352352
options=options or AutorunOptions(),
353353
)
354354

355-
return decorator
355+
return autorun_decorator
356356

357357
@overload
358358
def view(
@@ -379,21 +379,21 @@ def view(
379379
"""Create a new view, throttling calls for unchanged selector results."""
380380

381381
@overload
382-
def decorator(
382+
def view_decorator(
383383
func: Callable[
384384
Concatenate[SelectorOutput, Args],
385385
ReturnType,
386386
],
387387
) -> ViewReturnType[ReturnType, Args]: ...
388388
@overload
389-
def decorator(
389+
def view_decorator(
390390
func: Callable[
391391
Concatenate[SelectorOutput, Args],
392392
Awaitable[ReturnType],
393393
],
394394
) -> ViewReturnType[Awaitable[ReturnType], Args]: ...
395395

396-
def decorator(
396+
def view_decorator(
397397
func: Callable[
398398
Concatenate[SelectorOutput, Args],
399399
AwaitableOrNot[ReturnType],
@@ -404,7 +404,7 @@ def decorator(
404404
store=self,
405405
selector=selector,
406406
comparator=None,
407-
func=cast(Callable, func),
407+
func=cast('Callable', func),
408408
options=AutorunOptions(
409409
default_value=_options.default_value,
410410
auto_await=True,
@@ -417,7 +417,7 @@ def decorator(
417417
),
418418
)
419419

420-
return decorator
420+
return view_decorator
421421

422422
def with_state(
423423
self: Store[State, Action, Event],
@@ -433,7 +433,7 @@ def with_state(
433433
`store._state` is also possible.
434434
"""
435435

436-
def decorator(
436+
def with_state_decorator(
437437
func: Callable[
438438
Concatenate[SelectorOutput, Args],
439439
ReturnType,
@@ -445,9 +445,11 @@ def wrapper(*args: Args.args, **kwargs: Args.kwargs) -> ReturnType:
445445
raise RuntimeError(msg)
446446
return func(selector(self._state), *args, **kwargs)
447447

448+
wrapper.__name__ = f'with_state:{func.__name__}'
449+
448450
return wrapper
449451

450-
return decorator
452+
return with_state_decorator
451453

452454
@property
453455
def snapshot(self: Store[State, Action, Event]) -> SnapshotAtom:

0 commit comments

Comments
 (0)