easy-exit-calls 1.0.0.dev1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- easy_exit_calls/__init__.py +33 -0
- easy_exit_calls/classes.py +477 -0
- easy_exit_calls/classes.py~ +388 -0
- easy_exit_calls/common/__init__.py +8 -0
- easy_exit_calls/common/meta/__init__.py +9 -0
- easy_exit_calls/common/meta/author/__init__.py +10 -0
- easy_exit_calls/common/meta/author/contributors/CONTRIB_TEMPLATE.json +52 -0
- easy_exit_calls/common/meta/author/contributors/__init__.py +8 -0
- easy_exit_calls/common/meta/author/main/__init__.py +8 -0
- easy_exit_calls/common/meta/author/software_org/__init__.py +8 -0
- easy_exit_calls/common/meta/package/__init__.py +8 -0
- easy_exit_calls/common/meta/package/version/__VERSION__ +2 -0
- easy_exit_calls/common/meta/package/version/__init__.py +13 -0
- easy_exit_calls/decorator.py +50 -0
- easy_exit_calls/example_helpers.py +71 -0
- easy_exit_calls/helpers/__init__.py +8 -0
- easy_exit_calls/helpers/decorator.py +50 -0
- easy_exit_calls/helpers/handler_list.py +123 -0
- easy_exit_calls/log_engine.py +12 -0
- easy_exit_calls-1.0.0.dev1.dist-info/LICENSE.md +19 -0
- easy_exit_calls-1.0.0.dev1.dist-info/METADATA +156 -0
- easy_exit_calls-1.0.0.dev1.dist-info/RECORD +23 -0
- easy_exit_calls-1.0.0.dev1.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides a simple way to register exit handlers for your Python applications.
|
|
3
|
+
|
|
4
|
+
The main class is ExitCallHandler, which is used to register and manage exit handlers.
|
|
5
|
+
|
|
6
|
+
Included is a decorator, register_exit_handler, which can be used to register an exit handler for a function. This is a
|
|
7
|
+
convenient way to register exit handlers for functions.
|
|
8
|
+
|
|
9
|
+
Example:
|
|
10
|
+
>>> from easy_exit_calls import register_exit_handler, ExitCallHandler
|
|
11
|
+
>>>
|
|
12
|
+
>>> @register_exit_handler()
|
|
13
|
+
... def my_exit_handler():
|
|
14
|
+
... print("Exiting...")
|
|
15
|
+
...
|
|
16
|
+
>>> # Create an instance of ExitCallHandler
|
|
17
|
+
>>> eh = ExitCallHandler()
|
|
18
|
+
>>>
|
|
19
|
+
>>> # Register an exit handler
|
|
20
|
+
>>> eh.register_handler(my_exit_handler)
|
|
21
|
+
>>>
|
|
22
|
+
>>> # Call the exit handlers
|
|
23
|
+
>>> eh.call_handlers()
|
|
24
|
+
Exiting...
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
from easy_exit_calls.classes import ExitCallHandler
|
|
28
|
+
from easy_exit_calls.decorator import register_exit_handler
|
|
29
|
+
|
|
30
|
+
__all__ = [
|
|
31
|
+
'ExitCallHandler',
|
|
32
|
+
'register_exit_handler',
|
|
33
|
+
]
|
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
import atexit
|
|
2
|
+
import threading
|
|
3
|
+
import traceback
|
|
4
|
+
from uuid import uuid4, UUID
|
|
5
|
+
from easy_exit_calls.log_engine import ROOT_LOGGER, Loggable
|
|
6
|
+
from easy_exit_calls.helpers.handler_list import HandlerList
|
|
7
|
+
|
|
8
|
+
MOD_LOGGER = ROOT_LOGGER.get_child('components.exit_calls')
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ExitCallHandler(Loggable):
|
|
12
|
+
"""
|
|
13
|
+
A singleton class for managing exit handlers that are executed when the program terminates.
|
|
14
|
+
|
|
15
|
+
This class allows registration, execution, and removal of exit handlers. Handlers can be executed in
|
|
16
|
+
**either** LIFO (Last-In-First-Out) or FIFO (First-In-First-Out) order. It integrates with Python's `atexit`
|
|
17
|
+
module to ensure handlers are executed upon normal program termination.
|
|
18
|
+
|
|
19
|
+
Properties:
|
|
20
|
+
fifo (bool):
|
|
21
|
+
If True, handlers execute in FIFO order; otherwise, LIFO.
|
|
22
|
+
|
|
23
|
+
handler_keys (list):
|
|
24
|
+
A list of unique keys representing registered handlers.
|
|
25
|
+
|
|
26
|
+
handlers (list):
|
|
27
|
+
A list of registered handlers.
|
|
28
|
+
|
|
29
|
+
handler_uuids (list):
|
|
30
|
+
A list of UUIDs for registered handlers.
|
|
31
|
+
|
|
32
|
+
lifo (bool):
|
|
33
|
+
Indicates whether handlers execute in LIFO order.
|
|
34
|
+
|
|
35
|
+
registered_with_atexit (bool):
|
|
36
|
+
Indicates whether the handler is registered with `atexit`.
|
|
37
|
+
|
|
38
|
+
Methods:
|
|
39
|
+
call_handlers():
|
|
40
|
+
Executes all registered exit handlers.
|
|
41
|
+
|
|
42
|
+
clear_handlers():
|
|
43
|
+
Removes all registered exit handlers.
|
|
44
|
+
|
|
45
|
+
find_handler_by_uuid(uuid):
|
|
46
|
+
Retrieves a handler by its UUID.
|
|
47
|
+
|
|
48
|
+
function_registered(func):
|
|
49
|
+
Checks if a function is already registered as an exit handler.
|
|
50
|
+
|
|
51
|
+
has_key(key):
|
|
52
|
+
Determines if a handler with a given key exists.
|
|
53
|
+
|
|
54
|
+
has_uuid(uuid):
|
|
55
|
+
Determines if a handler with a given UUID exists.
|
|
56
|
+
|
|
57
|
+
register_handler(func, *args, return_func=False, **kwargs):
|
|
58
|
+
Registers a function as an exit handler.
|
|
59
|
+
|
|
60
|
+
register_self_with_atexit():
|
|
61
|
+
Registers the handler with Python’s `atexit` module.
|
|
62
|
+
|
|
63
|
+
unregister_all():
|
|
64
|
+
Unregisters all exit handlers.
|
|
65
|
+
|
|
66
|
+
unregister_all_with_name(name):
|
|
67
|
+
Unregisters all handlers with a specific name.
|
|
68
|
+
|
|
69
|
+
unregister_by_uuid(uuid):
|
|
70
|
+
Removes a registered handler by UUID.
|
|
71
|
+
|
|
72
|
+
unregister_handler(func, *args, **kwargs):
|
|
73
|
+
Unregisters a specific exit handler by function reference and arguments.
|
|
74
|
+
|
|
75
|
+
unregister_self_with_atexit():
|
|
76
|
+
Removes this handler from Python’s `atexit` module.
|
|
77
|
+
|
|
78
|
+
Example Usage:
|
|
79
|
+
```python
|
|
80
|
+
handler = ExitCallHandler()
|
|
81
|
+
|
|
82
|
+
def cleanup():
|
|
83
|
+
print("Cleaning up!")
|
|
84
|
+
|
|
85
|
+
handler.register_handler(cleanup)
|
|
86
|
+
```
|
|
87
|
+
"""
|
|
88
|
+
_instance = None
|
|
89
|
+
|
|
90
|
+
def __new__(cls, *args, **kwargs):
|
|
91
|
+
if cls._instance is None:
|
|
92
|
+
cls._instance = super(ExitCallHandler, cls).__new__(cls, *args, **kwargs)
|
|
93
|
+
# Use a list to store handler dictionaries
|
|
94
|
+
cls._instance._handlers = HandlerList(
|
|
95
|
+
on_empty=cls._instance.unregister_self_with_atexit,
|
|
96
|
+
on_non_empty=cls._instance.register_self_with_atexit
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
cls._instance._lifo = True
|
|
100
|
+
cls._instance._lock = threading.Lock()
|
|
101
|
+
|
|
102
|
+
# Register cleanup method to run on exit
|
|
103
|
+
atexit.register(cls._instance._cleanup)
|
|
104
|
+
|
|
105
|
+
return cls._instance
|
|
106
|
+
|
|
107
|
+
def __init__(self, fifo=False):
|
|
108
|
+
|
|
109
|
+
self.__registered_with_atexit = False
|
|
110
|
+
|
|
111
|
+
if isinstance(fifo, bool) and fifo:
|
|
112
|
+
self._lifo = False
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
if not hasattr(self, '_initialized'):
|
|
116
|
+
super().__init__(MOD_LOGGER)
|
|
117
|
+
self._initialized = True
|
|
118
|
+
|
|
119
|
+
def _check_for_key(self, key):
|
|
120
|
+
"""
|
|
121
|
+
Checks if a key already exists in the registered handlers.
|
|
122
|
+
|
|
123
|
+
Parameters:
|
|
124
|
+
key (tuple):
|
|
125
|
+
A tuple containing the function, arguments, and keyword arguments of the handler.
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
bool:
|
|
129
|
+
True if the key exists, False otherwise.
|
|
130
|
+
"""
|
|
131
|
+
for entry in self.handlers:
|
|
132
|
+
existing_key = self._get_key(entry['func'], entry['args'], entry['kwargs'])
|
|
133
|
+
if existing_key == key:
|
|
134
|
+
return True
|
|
135
|
+
|
|
136
|
+
def _cleanup(self):
|
|
137
|
+
"""
|
|
138
|
+
Executes all registered exit handlers.
|
|
139
|
+
"""
|
|
140
|
+
log = self.method_logger
|
|
141
|
+
|
|
142
|
+
handlers = reversed(self._handlers) if self.lifo else self._handlers
|
|
143
|
+
|
|
144
|
+
for entry in list(handlers):
|
|
145
|
+
name = ''
|
|
146
|
+
if 'handler_info' in entry:
|
|
147
|
+
info = entry['handler_info']
|
|
148
|
+
# Build a name based on module and function name
|
|
149
|
+
name = f"{info.get('module', '')}."
|
|
150
|
+
if info.get('name'):
|
|
151
|
+
name += info['name']
|
|
152
|
+
else:
|
|
153
|
+
name = "Unknown"
|
|
154
|
+
|
|
155
|
+
log.debug(f"Running exit handler {name}")
|
|
156
|
+
|
|
157
|
+
func = entry['func']
|
|
158
|
+
args = entry['args']
|
|
159
|
+
kwargs = entry['kwargs']
|
|
160
|
+
|
|
161
|
+
log.debug(f"Running exit handler {name} | Function: {func} | Args: {args} | Kwargs: {kwargs}")
|
|
162
|
+
|
|
163
|
+
try:
|
|
164
|
+
func(*args, **kwargs)
|
|
165
|
+
except Exception as e:
|
|
166
|
+
log.error(f"Error while running exit handler {func}: {e}")
|
|
167
|
+
log.debug(f"Traceback:\n{traceback.format_exc()}")
|
|
168
|
+
raise e from e
|
|
169
|
+
|
|
170
|
+
def _get_key(self, func: callable, args: tuple, kwargs: dict):
|
|
171
|
+
"""
|
|
172
|
+
Create a unique key from a function, its arguments, and keyword arguments.
|
|
173
|
+
|
|
174
|
+
Parameters:
|
|
175
|
+
func (callable):
|
|
176
|
+
The function to be called.
|
|
177
|
+
|
|
178
|
+
args (tuple):
|
|
179
|
+
Positional arguments to be passed to the function.
|
|
180
|
+
|
|
181
|
+
kwargs (dict):
|
|
182
|
+
Keyword arguments to be passed to the function.
|
|
183
|
+
|
|
184
|
+
Returns:
|
|
185
|
+
tuple:
|
|
186
|
+
A tuple containing the function, arguments, and keyword arguments.
|
|
187
|
+
"""
|
|
188
|
+
return (func, args, frozenset(kwargs.items()))
|
|
189
|
+
|
|
190
|
+
@property
|
|
191
|
+
def fifo(self) -> bool:
|
|
192
|
+
"""
|
|
193
|
+
Get the FIFO mode for the handler.
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
bool:
|
|
197
|
+
True if FIFO mode is enabled, False otherwise.
|
|
198
|
+
|
|
199
|
+
"""
|
|
200
|
+
return not self._lifo
|
|
201
|
+
|
|
202
|
+
@fifo.setter
|
|
203
|
+
def fifo(self, new: bool) -> None:
|
|
204
|
+
"""
|
|
205
|
+
Set the FIFO mode for the handler.
|
|
206
|
+
|
|
207
|
+
Parameters:
|
|
208
|
+
new (bool):
|
|
209
|
+
True to set FIFO mode, False to set LIFO mode.
|
|
210
|
+
|
|
211
|
+
Returns:
|
|
212
|
+
None
|
|
213
|
+
|
|
214
|
+
Raises:
|
|
215
|
+
TypeError:
|
|
216
|
+
If the new value is not a boolean.
|
|
217
|
+
"""
|
|
218
|
+
if not isinstance(new, bool):
|
|
219
|
+
raise TypeError("fifo must be a boolean")
|
|
220
|
+
|
|
221
|
+
self._lifo = not new
|
|
222
|
+
|
|
223
|
+
@property
|
|
224
|
+
def handler_keys(self) -> list[tuple]:
|
|
225
|
+
"""
|
|
226
|
+
Returns a list of tuples containing the keys for all registered handlers.
|
|
227
|
+
|
|
228
|
+
Returns:
|
|
229
|
+
list[tuple]:
|
|
230
|
+
A list of tuples containing the keys for all registered handlers;
|
|
231
|
+
each tuple contains the function, arguments, and keyword arguments.
|
|
232
|
+
"""
|
|
233
|
+
return [self._get_key(entry['func'], entry['args'], entry['kwargs']) for entry in self.handlers]
|
|
234
|
+
|
|
235
|
+
@property
|
|
236
|
+
def handlers(self) -> HandlerList:
|
|
237
|
+
"""
|
|
238
|
+
Returns a list of dictionaries representing the registered exit handlers.
|
|
239
|
+
|
|
240
|
+
Returns:
|
|
241
|
+
HandlerList:
|
|
242
|
+
A list of dictionaries representing the registered exit handlers.
|
|
243
|
+
"""
|
|
244
|
+
return self._handlers
|
|
245
|
+
|
|
246
|
+
@property
|
|
247
|
+
def handler_uuids(self) -> list[UUID]:
|
|
248
|
+
"""
|
|
249
|
+
Returns a list of UUIDs for all registered handlers.
|
|
250
|
+
|
|
251
|
+
Returns:
|
|
252
|
+
list[UUID]:
|
|
253
|
+
A list of UUIDs for all registered handlers.
|
|
254
|
+
"""
|
|
255
|
+
return [entry.get('uuid') for entry in self.handlers]
|
|
256
|
+
|
|
257
|
+
@property
|
|
258
|
+
def lifo(self):
|
|
259
|
+
"""
|
|
260
|
+
Get the LIFO status of the exit call handler.
|
|
261
|
+
|
|
262
|
+
Returns:
|
|
263
|
+
bool: True if the exit call handler is in LIFO mode, False otherwise.
|
|
264
|
+
"""
|
|
265
|
+
return self._lifo
|
|
266
|
+
|
|
267
|
+
@lifo.setter
|
|
268
|
+
def lifo(self, new) -> None:
|
|
269
|
+
"""
|
|
270
|
+
Set the LIFO status of the exit call handler.
|
|
271
|
+
|
|
272
|
+
If the value is True, handlers will execute in LIFO order. If False, handlers will execute in FIFO order.
|
|
273
|
+
|
|
274
|
+
Parameters:
|
|
275
|
+
new (bool):
|
|
276
|
+
The new LIFO status to set.
|
|
277
|
+
|
|
278
|
+
Returns:
|
|
279
|
+
None
|
|
280
|
+
"""
|
|
281
|
+
if not isinstance(new,bool):
|
|
282
|
+
raise ValueError("lifo must be a boolean")
|
|
283
|
+
|
|
284
|
+
self._lifo = new
|
|
285
|
+
|
|
286
|
+
@property
|
|
287
|
+
def registered_with_atexit(self) -> bool:
|
|
288
|
+
"""
|
|
289
|
+
Indicates whether the handler is registered with the `atexit` module.
|
|
290
|
+
|
|
291
|
+
Returns:
|
|
292
|
+
bool:
|
|
293
|
+
True if the handler is registered with `atexit`, False otherwise.
|
|
294
|
+
"""
|
|
295
|
+
return self.__registered_with_atexit
|
|
296
|
+
|
|
297
|
+
def call_handlers(self) -> None:
|
|
298
|
+
"""
|
|
299
|
+
Calls all registered exit handlers.
|
|
300
|
+
|
|
301
|
+
Returns:
|
|
302
|
+
None
|
|
303
|
+
"""
|
|
304
|
+
log = self.method_logger
|
|
305
|
+
|
|
306
|
+
if not self.handlers:
|
|
307
|
+
log.warning("No exit handlers registered")
|
|
308
|
+
return
|
|
309
|
+
|
|
310
|
+
log.debug("Calling exit handlers")
|
|
311
|
+
self._cleanup()
|
|
312
|
+
|
|
313
|
+
def clear_handlers(self) -> None:
|
|
314
|
+
"""
|
|
315
|
+
Removes all registered exit handlers.
|
|
316
|
+
|
|
317
|
+
Note:
|
|
318
|
+
Once all handlers are removed, the handler unregisters itself from the `atexit` module.
|
|
319
|
+
|
|
320
|
+
Returns:
|
|
321
|
+
None
|
|
322
|
+
"""
|
|
323
|
+
log = self.method_logger
|
|
324
|
+
|
|
325
|
+
log.debug("Clearing all exit handlers")
|
|
326
|
+
self._handlers.clear()
|
|
327
|
+
log.debug("All exit handlers cleared")
|
|
328
|
+
|
|
329
|
+
def find_handler_by_uuid(self, uuid):
|
|
330
|
+
log = self.method_logger
|
|
331
|
+
|
|
332
|
+
if not isinstance(uuid, (UUID, str)):
|
|
333
|
+
log.error("UUID must be a UUID object or a string")
|
|
334
|
+
raise ValueError("UUID must be a UUID object or a string")
|
|
335
|
+
|
|
336
|
+
if isinstance(uuid, str):
|
|
337
|
+
uuid = UUID(uuid)
|
|
338
|
+
|
|
339
|
+
for entry in self.handlers:
|
|
340
|
+
if entry.get('uuid') and entry['uuid'] == uuid:
|
|
341
|
+
return entry
|
|
342
|
+
|
|
343
|
+
def function_registered(self, func):
|
|
344
|
+
return any([entry['func'] == func for entry in self.handlers])
|
|
345
|
+
|
|
346
|
+
def has_key(self, key):
|
|
347
|
+
return key in self.handler_keys
|
|
348
|
+
|
|
349
|
+
def has_uuid(self, uuid):
|
|
350
|
+
return any([entry.get('uuid') == uuid for entry in self.handlers])
|
|
351
|
+
|
|
352
|
+
def register_handler(self, func, *args, return_func=False, **kwargs):
|
|
353
|
+
log = self.method_logger
|
|
354
|
+
|
|
355
|
+
log.debug(f"Registering exit handler {func} | Args: {args} | Kwargs: {kwargs}")
|
|
356
|
+
|
|
357
|
+
# Check if the function is already registered
|
|
358
|
+
log.debug(f"Checking if handler {func} is already registered")
|
|
359
|
+
|
|
360
|
+
# Create a unique key from the function, its args, and kwargs
|
|
361
|
+
new_key = self._get_key(func, args, kwargs)
|
|
362
|
+
|
|
363
|
+
log.debug(f"New key: {new_key}")
|
|
364
|
+
|
|
365
|
+
if self.has_key(new_key):
|
|
366
|
+
log.warning(f"Handler {func} is already registered")
|
|
367
|
+
return func
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
info = {
|
|
371
|
+
'handler_info': {
|
|
372
|
+
'module': func.__module__,
|
|
373
|
+
'name': func.__name__,
|
|
374
|
+
},
|
|
375
|
+
'func': func,
|
|
376
|
+
'args': args,
|
|
377
|
+
'kwargs': kwargs,
|
|
378
|
+
'uuid': uuid4()
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
with self._lock:
|
|
382
|
+
# Otherwise, add the handler
|
|
383
|
+
self.handlers.append(info)
|
|
384
|
+
log.debug(f"Handler {func} registered successfully")
|
|
385
|
+
|
|
386
|
+
return info['uuid']
|
|
387
|
+
|
|
388
|
+
def register_self_with_atexit(self):
|
|
389
|
+
log = self.method_logger
|
|
390
|
+
|
|
391
|
+
log.debug('Checking if registered with atexit already...')
|
|
392
|
+
|
|
393
|
+
if not self.registered_with_atexit:
|
|
394
|
+
log.debug('Registering with atexit...')
|
|
395
|
+
atexit.register(self._cleanup)
|
|
396
|
+
self.__registered_with_atexit = True
|
|
397
|
+
|
|
398
|
+
def unregister_all(self):
|
|
399
|
+
self.clear_handlers()
|
|
400
|
+
|
|
401
|
+
def unregister_all_with_name(self, name: str) -> None:
|
|
402
|
+
"""
|
|
403
|
+
Unregister all exit handlers with a specific name.
|
|
404
|
+
|
|
405
|
+
Parameters:
|
|
406
|
+
name (str):
|
|
407
|
+
The name of the exit handlers to unregister.
|
|
408
|
+
|
|
409
|
+
Returns:
|
|
410
|
+
None
|
|
411
|
+
"""
|
|
412
|
+
log = self.method_logger
|
|
413
|
+
|
|
414
|
+
log.debug(f"Unregistering all exit handlers with name {name}")
|
|
415
|
+
|
|
416
|
+
for entry in self._handlers:
|
|
417
|
+
if 'handler_info' in entry:
|
|
418
|
+
info = entry['handler_info']
|
|
419
|
+
if info.get('name') == name:
|
|
420
|
+
log.debug(f"Removing handler {info.get('module', '')}.{info.get('name')}")
|
|
421
|
+
self._handlers.remove(entry)
|
|
422
|
+
|
|
423
|
+
log.debug(f"All handlers with name {name} unregistered successfully")
|
|
424
|
+
|
|
425
|
+
def unregister_by_uuid(self, uuid):
|
|
426
|
+
log = self.method_logger
|
|
427
|
+
|
|
428
|
+
log.debug(f"Unregistering exit handler with UUID {uuid}")
|
|
429
|
+
|
|
430
|
+
handler = self.find_handler_by_uuid(uuid)
|
|
431
|
+
|
|
432
|
+
if handler:
|
|
433
|
+
log.debug(f"Removing handler {handler['func']}")
|
|
434
|
+
self._handlers.remove(handler)
|
|
435
|
+
log.debug(f"Handler with UUID {uuid} unregistered successfully")
|
|
436
|
+
return True
|
|
437
|
+
|
|
438
|
+
log.warning(f"Handler with UUID {uuid} not found")
|
|
439
|
+
|
|
440
|
+
return False
|
|
441
|
+
|
|
442
|
+
def unregister_handler(self, func, *args, **kwargs):
|
|
443
|
+
log = self.method_logger
|
|
444
|
+
|
|
445
|
+
log.debug(f"Unregistering exit handler {func} | Args: {args} | Kwargs: {kwargs}")
|
|
446
|
+
|
|
447
|
+
# Create a unique key from the function, its args, and kwargs
|
|
448
|
+
key = (func, args, frozenset(kwargs.items()))
|
|
449
|
+
|
|
450
|
+
log.debug(f"Key: {key}")
|
|
451
|
+
|
|
452
|
+
for entry in self._handlers:
|
|
453
|
+
existing_key = (entry['func'], entry['args'], frozenset(entry['kwargs'].items()))
|
|
454
|
+
if existing_key == key:
|
|
455
|
+
log.debug(f"Removing handler {func}")
|
|
456
|
+
self._handlers.remove(entry)
|
|
457
|
+
log.debug(f"Handler {func} unregistered successfully")
|
|
458
|
+
return func
|
|
459
|
+
|
|
460
|
+
log.warning(f"Handler {func} not found")
|
|
461
|
+
return None
|
|
462
|
+
|
|
463
|
+
def unregister_self_with_atexit(self):
|
|
464
|
+
log = self.method_logger
|
|
465
|
+
|
|
466
|
+
log.debug('Checking if registered with atexit already...')
|
|
467
|
+
|
|
468
|
+
if self.registered_with_atexit:
|
|
469
|
+
log.debug('Unregistering with atexit...')
|
|
470
|
+
atexit.unregister(self._cleanup)
|
|
471
|
+
self.__registered_with_atexit = False
|
|
472
|
+
return True
|
|
473
|
+
else:
|
|
474
|
+
log.warning('ExitCallHandler is not registered with atexit!')
|
|
475
|
+
|
|
476
|
+
return False
|
|
477
|
+
|