8
8
from flask import copy_current_request_context , has_request_context , request
9
9
from werkzeug .exceptions import BadRequest
10
10
11
+ from typing import Optional , Iterable , Dict , Any , Callable
12
+
11
13
from ..deque import LockableDeque
12
14
from ..utilities import TimeoutTracker
13
15
@@ -25,12 +27,12 @@ class ActionThread(threading.Thread):
25
27
26
28
def __init__ (
27
29
self ,
28
- action ,
29
- target = None ,
30
- name = None ,
31
- args = None ,
32
- kwargs = None ,
33
- daemon = True ,
30
+ action : str ,
31
+ target : Optional [ Callable ] = None ,
32
+ name : Optional [ str ] = None ,
33
+ args : Optional [ Iterable [ Any ]] = None ,
34
+ kwargs : Optional [ Dict [ str , Any ]] = None ,
35
+ daemon : bool = True ,
34
36
default_stop_timeout : int = 5 ,
35
37
log_len : int = 100 ,
36
38
):
@@ -39,34 +41,32 @@ def __init__(
39
41
group = None ,
40
42
target = target ,
41
43
name = name ,
42
- args = args ,
43
- kwargs = kwargs ,
44
+ args = args or () ,
45
+ kwargs = kwargs or {} ,
44
46
daemon = daemon ,
45
47
)
46
48
47
- # Safely populate missing arguments
48
- args = args or ()
49
- kwargs = kwargs or {}
50
-
51
49
# Action resource corresponding to this action object
52
50
self .action = action
53
51
54
52
# A UUID for the ActionThread (not the same as the threading.Thread ident)
55
53
self ._ID = uuid .uuid4 () # Task ID
56
54
57
55
# Event to track if the task has started
58
- self .started = threading .Event ()
56
+ self .started : threading . Event = threading .Event ()
59
57
# Event to track if the user has requested stop
60
- self .stopping = threading .Event ()
61
- self .default_stop_timeout = default_stop_timeout
58
+ self .stopping : threading . Event = threading .Event ()
59
+ self .default_stop_timeout : int = default_stop_timeout
62
60
63
61
# Make _target, _args, and _kwargs available to the subclass
64
- self ._target = target
65
- self ._args = args
66
- self ._kwargs = kwargs
62
+ self ._target : Optional [ Callable ] = target
63
+ self ._args : Iterable [ Any ] = args or ()
64
+ self ._kwargs : Dict [ str , Any ] = kwargs or {}
67
65
68
66
# Nice string representation of target function
69
- self .target_string = f"{ self ._target } (args={ self ._args } , kwargs={ self ._kwargs } )"
67
+ self .target_string : str = (
68
+ f"{ self ._target } (args={ self ._args } , kwargs={ self ._kwargs } )"
69
+ )
70
70
71
71
# copy_current_request_context allows threads to access flask current_app
72
72
if has_request_context ():
@@ -82,14 +82,14 @@ def __init__(
82
82
83
83
# Private state properties
84
84
self ._status : str = "pending" # Task status
85
- self ._return_value = None # Return value
86
- self ._request_time = datetime .datetime .now ()
87
- self ._start_time = None # Task start time
88
- self ._end_time = None # Task end time
85
+ self ._return_value : Optional [ Any ] = None # Return value
86
+ self ._request_time : datetime . datetime = datetime .datetime .now ()
87
+ self ._start_time : Optional [ datetime . datetime ] = None # Task start time
88
+ self ._end_time : Optional [ datetime . datetime ] = None # Task end time
89
89
90
90
# Public state properties
91
- self .progress : int = None # Percent progress of the task
92
- self .data = {} # Dictionary of custom data added during the task
91
+ self .progress : Optional [ int ] = None # Percent progress of the task
92
+ self .data : dict = {} # Dictionary of custom data added during the task
93
93
self ._log = LockableDeque (
94
94
None , log_len
95
95
) # The log will hold dictionary objects with log information
@@ -100,14 +100,14 @@ def __init__(
100
100
) # Lock obtained while self._target is running
101
101
102
102
@property
103
- def id (self ):
103
+ def id (self ) -> uuid . UUID :
104
104
"""
105
105
UUID for the thread. Note this not the same as the native thread ident.
106
106
"""
107
107
return self ._ID
108
108
109
109
@property
110
- def output (self ):
110
+ def output (self ) -> Any :
111
111
"""
112
112
Return value of the Action function. If the Action is still running, returns None.
113
113
"""
@@ -119,7 +119,7 @@ def log(self):
119
119
return list (logdeque )
120
120
121
121
@property
122
- def status (self ):
122
+ def status (self ) -> str :
123
123
"""
124
124
Current running status of the thread.
125
125
@@ -136,19 +136,19 @@ def status(self):
136
136
return self ._status
137
137
138
138
@property
139
- def dead (self ):
139
+ def dead (self ) -> bool :
140
140
"""
141
141
Has the thread finished, by any means (return, exception, termination).
142
142
"""
143
143
return not self .is_alive ()
144
144
145
145
@property
146
- def stopped (self ):
146
+ def stopped (self ) -> bool :
147
147
"""Has the thread been cancelled"""
148
148
return self .stopping .is_set ()
149
149
150
150
@property
151
- def cancelled (self ):
151
+ def cancelled (self ) -> bool :
152
152
"""Alias of `stopped`"""
153
153
return self .stopped
154
154
@@ -162,7 +162,7 @@ def update_progress(self, progress: int):
162
162
# Update progress of the task
163
163
self .progress = progress
164
164
165
- def update_data (self , data : dict ):
165
+ def update_data (self , data : Dict [ Any , Any ] ):
166
166
"""
167
167
168
168
:param data: dict:
@@ -183,7 +183,7 @@ def run(self):
183
183
# an argument that has a member that points to the thread.
184
184
del self ._target , self ._args , self ._kwargs
185
185
186
- def _thread_proc (self , f ):
186
+ def _thread_proc (self , f : Callable ):
187
187
"""Wraps the target function to handle recording `status` and `return` to `state`.
188
188
Happens inside the task thread.
189
189
@@ -228,7 +228,7 @@ def wrapped(*args, **kwargs):
228
228
229
229
return wrapped
230
230
231
- def get (self , block = True , timeout = None ):
231
+ def get (self , block : bool = True , timeout : Optional [ int ] = None ):
232
232
"""Start waiting for the task to finish before returning
233
233
234
234
:param block: (Default value = True)
@@ -275,7 +275,7 @@ def _async_raise(self, exc_type):
275
275
% (exc_type , self .name , self .ident , result )
276
276
)
277
277
278
- def _is_thread_proc_running (self ):
278
+ def _is_thread_proc_running (self ) -> bool :
279
279
"""Test if thread funtion (_thread_proc) is running,
280
280
by attemtping to acquire the lock _thread_proc acquires at runtime.
281
281
@@ -285,13 +285,13 @@ def _is_thread_proc_running(self):
285
285
:rtype: bool
286
286
287
287
"""
288
- could_acquire = self ._running_lock .acquire (0 )
288
+ could_acquire = self ._running_lock .acquire (False )
289
289
if could_acquire :
290
290
self ._running_lock .release ()
291
291
return False
292
292
return True
293
293
294
- def terminate (self , exception = ActionKilledException ):
294
+ def terminate (self , exception = ActionKilledException ) -> bool :
295
295
"""
296
296
297
297
:param exception: (Default value = ActionKilledException)
@@ -314,7 +314,7 @@ def terminate(self, exception=ActionKilledException):
314
314
self .progress = None
315
315
return True
316
316
317
- def stop (self , timeout = None , exception = ActionKilledException ):
317
+ def stop (self , timeout = None , exception = ActionKilledException ) -> bool :
318
318
"""Sets the threads internal stopped event, waits for timeout seconds for the
319
319
thread to stop nicely, then forcefully kills the thread.
320
320
0 commit comments