11# ruff: noqa: D100, D101, D102, D103, D104, D105, D107
22from __future__ import annotations
33
4- import functools
54import inspect
65import weakref
76from asyncio import Task , iscoroutine
8- from inspect import signature
9- from typing import TYPE_CHECKING , Any , Callable , Generic , cast
7+ from typing import TYPE_CHECKING , Any , Callable , Concatenate , Generic , cast
108
119from redux .basic_types import (
1210 Action ,
11+ AutorunArgs ,
1312 AutorunOptions ,
1413 AutorunOriginalReturnType ,
1514 ComparatorOutput ,
1918)
2019
2120if TYPE_CHECKING :
22- from types import MethodType
23-
2421 from redux .main import Store
2522
2623
@@ -32,6 +29,7 @@ class Autorun(
3229 SelectorOutput ,
3330 ComparatorOutput ,
3431 AutorunOriginalReturnType ,
32+ AutorunArgs ,
3533 ],
3634):
3735 def __init__ ( # noqa: PLR0913
@@ -40,8 +38,10 @@ def __init__( # noqa: PLR0913
4038 store : Store [State , Action , Event ],
4139 selector : Callable [[State ], SelectorOutput ],
4240 comparator : Callable [[State ], Any ] | None ,
43- func : Callable [[SelectorOutput ], AutorunOriginalReturnType ]
44- | Callable [[SelectorOutput , SelectorOutput ], AutorunOriginalReturnType ],
41+ func : Callable [
42+ Concatenate [SelectorOutput , AutorunArgs ],
43+ AutorunOriginalReturnType ,
44+ ],
4545 options : AutorunOptions [AutorunOriginalReturnType ],
4646 ) -> None :
4747 if not options .reactive and options .auto_call :
@@ -54,9 +54,9 @@ def __init__( # noqa: PLR0913
5454 if options .keep_ref :
5555 self ._func = func
5656 elif inspect .ismethod (func ):
57- self ._func = weakref .WeakMethod (func )
57+ self ._func = weakref .WeakMethod (func , self . unsubscribe )
5858 else :
59- self ._func = weakref .ref (func , lambda _ : self .unsubscribe () )
59+ self ._func = weakref .ref (func , self .unsubscribe )
6060 self ._options = options
6161
6262 self ._last_selector_result : SelectorOutput | None = None
@@ -70,12 +70,19 @@ def __init__( # noqa: PLR0913
7070 | weakref .ref [Callable [[AutorunOriginalReturnType ], Any ]]
7171 ] = set ()
7272
73- self ._check_and_call (store ._state , call = self ._options .initial_call ) # noqa: SLF001
73+ self ._check_and_call (store ._state , self ._options .initial_call ) # noqa: SLF001
7474
7575 if self ._options .reactive :
76- self .unsubscribe = store .subscribe (
77- functools . partial ( self ._check_and_call , call = self ._options .auto_call ),
76+ self ._unsubscribe = store .subscribe (
77+ lambda state : self ._check_and_call ( state , self ._options .auto_call ),
7878 )
79+ else :
80+ self ._unsubscribe = None
81+
82+ def unsubscribe (self : Autorun , _ : weakref .ref | None = None ) -> None :
83+ if self ._unsubscribe :
84+ self ._unsubscribe ()
85+ self ._unsubscribe = None
7986
8087 def inform_subscribers (
8188 self : Autorun [
@@ -85,6 +92,7 @@ def inform_subscribers(
8592 SelectorOutput ,
8693 ComparatorOutput ,
8794 AutorunOriginalReturnType ,
95+ AutorunArgs ,
8896 ],
8997 ) -> None :
9098 for subscriber_ in self ._subscriptions .copy ():
@@ -97,37 +105,6 @@ def inform_subscribers(
97105 subscriber = subscriber_
98106 subscriber (self ._latest_value )
99107
100- def call_func (
101- self : Autorun [
102- State ,
103- Action ,
104- Event ,
105- SelectorOutput ,
106- ComparatorOutput ,
107- AutorunOriginalReturnType ,
108- ],
109- selector_result : SelectorOutput ,
110- previous_result : SelectorOutput | None ,
111- func : Callable [
112- [SelectorOutput , SelectorOutput ],
113- AutorunOriginalReturnType ,
114- ]
115- | Callable [[SelectorOutput ], AutorunOriginalReturnType ]
116- | MethodType ,
117- ) -> AutorunOriginalReturnType :
118- if len (signature (func ).parameters ) == 1 :
119- return cast (
120- Callable [[SelectorOutput ], AutorunOriginalReturnType ],
121- func ,
122- )(selector_result )
123- return cast (
124- Callable [
125- [SelectorOutput , SelectorOutput | None ],
126- AutorunOriginalReturnType ,
127- ],
128- func ,
129- )(selector_result , previous_result )
130-
131108 def _task_callback (
132109 self : Autorun [
133110 State ,
@@ -136,6 +113,7 @@ def _task_callback(
136113 SelectorOutput ,
137114 ComparatorOutput ,
138115 AutorunOriginalReturnType ,
116+ AutorunArgs ,
139117 ],
140118 task : Task ,
141119 ) -> None :
@@ -150,10 +128,12 @@ def _check_and_call(
150128 SelectorOutput ,
151129 ComparatorOutput ,
152130 AutorunOriginalReturnType ,
131+ AutorunArgs ,
153132 ],
154133 state : State ,
155- * ,
156- call : bool = True ,
134+ _call : bool , # noqa: FBT001
135+ * args : AutorunArgs .args ,
136+ ** kwargs : AutorunArgs .kwargs ,
157137 ) -> None :
158138 try :
159139 selector_result = self ._selector (state )
@@ -167,26 +147,19 @@ def _check_and_call(
167147 except AttributeError :
168148 return
169149 if self ._should_be_called or comparator_result != self ._last_comparator_result :
170- self ._should_be_called = False
171- previous_result = self ._last_selector_result
172150 self ._last_selector_result = selector_result
173151 self ._last_comparator_result = comparator_result
174- func = self ._func () if isinstance (self ._func , weakref .ref ) else self ._func
175- if func :
176- if call :
177- self ._latest_value = self .call_func (
178- selector_result ,
179- previous_result ,
180- func ,
181- )
152+ self ._should_be_called = not _call
153+ if _call :
154+ func = (
155+ self ._func () if isinstance (self ._func , weakref .ref ) else self ._func
156+ )
157+ if func :
158+ self ._latest_value = func (selector_result , * args , ** kwargs )
182159 create_task = self ._store ._create_task # noqa: SLF001
183160 if iscoroutine (self ._latest_value ) and create_task :
184161 create_task (self ._latest_value , callback = self ._task_callback )
185162 self .inform_subscribers ()
186- else :
187- self ._should_be_called = True
188- else :
189- self .unsubscribe ()
190163
191164 def __call__ (
192165 self : Autorun [
@@ -196,11 +169,14 @@ def __call__(
196169 SelectorOutput ,
197170 ComparatorOutput ,
198171 AutorunOriginalReturnType ,
172+ AutorunArgs ,
199173 ],
174+ * args : AutorunArgs .args ,
175+ ** kwargs : AutorunArgs .kwargs ,
200176 ) -> AutorunOriginalReturnType :
201177 state = self ._store ._state # noqa: SLF001
202178 if state is not None :
203- self ._check_and_call (state , call = True )
179+ self ._check_and_call (state , True , * args , ** kwargs ) # noqa: FBT003
204180 return cast (AutorunOriginalReturnType , self ._latest_value )
205181
206182 def __repr__ (
@@ -211,6 +187,7 @@ def __repr__(
211187 SelectorOutput ,
212188 ComparatorOutput ,
213189 AutorunOriginalReturnType ,
190+ AutorunArgs ,
214191 ],
215192 ) -> str :
216193 return f"""{ super ().__repr__ ()} (func: { self ._func } , last_value: {
@@ -225,6 +202,7 @@ def value(
225202 SelectorOutput ,
226203 ComparatorOutput ,
227204 AutorunOriginalReturnType ,
205+ AutorunArgs ,
228206 ],
229207 ) -> AutorunOriginalReturnType :
230208 return cast (AutorunOriginalReturnType , self ._latest_value )
@@ -237,6 +215,7 @@ def subscribe(
237215 SelectorOutput ,
238216 ComparatorOutput ,
239217 AutorunOriginalReturnType ,
218+ AutorunArgs ,
240219 ],
241220 callback : Callable [[AutorunOriginalReturnType ], Any ],
242221 * ,
0 commit comments