-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update unregister implementation to remove all references to the prev…
…iously registered function (#5) * Update unregister implementation to remove all references to the registered function * Added tests and corrected implementation Corrected implementation of reference cleanup for signals and when exiting normally. Added tests to ensure functionality. The case where exiting normally was tested locally but no test was added due to higher complexity and low marginal benefit now that normal exit behavior will call unregister and use the same codepaths. * Drop support for 3.6 and 3.7, add 3.11 Behavior is odd on 3.7, and there's no good reason to maintain support for these. --------- Co-authored-by: Natalie Cygan <[email protected]> Co-authored-by: Jeremy Ephron <[email protected]>
- Loading branch information
1 parent
7a7a3d7
commit 285551e
Showing
4 changed files
with
273 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
import pyterminate | ||
import gc | ||
import weakref | ||
import signal | ||
|
||
|
||
class Canary(): | ||
pass | ||
|
||
|
||
def test_unregister_refcount(): | ||
"""Tests that unregistering cleans up all references.""" | ||
|
||
weakref_c = None | ||
|
||
def func(): | ||
nonlocal weakref_c | ||
|
||
c = Canary() | ||
weakref_c = weakref.ref(c) | ||
|
||
def cleanup(): | ||
print(c) | ||
|
||
pyterminate.register(cleanup) | ||
pyterminate.unregister(cleanup) | ||
|
||
func() | ||
assert weakref_c() is None, gc.get_referrers(weakref_c()) | ||
|
||
|
||
def test_unregister_refcount_with_decorator(): | ||
""" | ||
Tests that unregistering cleans up all references when registered using the | ||
decorator. | ||
""" | ||
|
||
weakref_c = None | ||
|
||
def func(): | ||
nonlocal weakref_c | ||
|
||
c = Canary() | ||
weakref_c = weakref.ref(c) | ||
|
||
@pyterminate.register | ||
def cleanup(): | ||
print(c) | ||
|
||
pyterminate.unregister(cleanup) | ||
|
||
func() | ||
assert weakref_c() is None, gc.get_referrers(weakref_c()) | ||
|
||
|
||
def test_unregister_refcount_duplicate_calls(): | ||
""" | ||
Tests that unregistering cleans up all references when duplicate register | ||
and unregister calls are made. | ||
""" | ||
|
||
weakref_c = None | ||
|
||
def func(): | ||
nonlocal weakref_c | ||
|
||
c = Canary() | ||
weakref_c = weakref.ref(c) | ||
|
||
@pyterminate.register | ||
def cleanup(): | ||
print(c) | ||
|
||
pyterminate.register(cleanup) | ||
pyterminate.register(cleanup) | ||
pyterminate.register(cleanup) | ||
pyterminate.unregister(cleanup) | ||
pyterminate.unregister(cleanup) | ||
|
||
func() | ||
assert weakref_c() is None, gc.get_referrers(weakref_c()) | ||
|
||
|
||
def test_unregister_refcount_multiple_signals(): | ||
""" | ||
Tests that unregistering cleans up all references when multiple signals | ||
are used. | ||
""" | ||
|
||
weakref_c = None | ||
|
||
def func(): | ||
nonlocal weakref_c | ||
|
||
c = Canary() | ||
weakref_c = weakref.ref(c) | ||
|
||
@pyterminate.register( | ||
signals=(signal.SIGINT, signal.SIGSEGV, signal.SIGTERM) | ||
) | ||
def cleanup(): | ||
print(c) | ||
|
||
pyterminate.unregister(cleanup) | ||
|
||
func() | ||
assert weakref_c() is None, gc.get_referrers(weakref_c()) | ||
|
||
|
||
def test_unregister_refcount_multiple_functions(): | ||
""" | ||
Tests that unregistering cleans up all references when multiple functions | ||
are registered. | ||
""" | ||
|
||
weakref_c = None | ||
|
||
def func(): | ||
nonlocal weakref_c | ||
|
||
c = Canary() | ||
weakref_c = weakref.ref(c) | ||
|
||
def cleanup_1(): | ||
print(c) | ||
|
||
def cleanup_2(): | ||
print(c) | ||
|
||
def cleanup_3(): | ||
print(c) | ||
|
||
pyterminate.register(cleanup_1) | ||
pyterminate.register(cleanup_2) | ||
pyterminate.register(cleanup_3) | ||
pyterminate.unregister(cleanup_3) | ||
pyterminate.unregister(cleanup_2) | ||
pyterminate.unregister(cleanup_1) | ||
|
||
func() | ||
assert weakref_c() is None, gc.get_referrers(weakref_c()) | ||
|
||
|
||
def test_unregister_refcount_multiple_functions_out_of_order(): | ||
""" | ||
Tests that unregistering cleans up all references when multiple functions | ||
are registered and then unregistered not in reverse order. | ||
""" | ||
|
||
weakref_c = None | ||
|
||
def func(): | ||
nonlocal weakref_c | ||
|
||
c = Canary() | ||
weakref_c = weakref.ref(c) | ||
|
||
def cleanup_1(): | ||
print(c) | ||
|
||
def cleanup_2(): | ||
print(c) | ||
|
||
def cleanup_3(): | ||
print(c) | ||
|
||
pyterminate.register(cleanup_1) | ||
pyterminate.register(cleanup_2) | ||
pyterminate.register(cleanup_3) | ||
pyterminate.unregister(cleanup_1) | ||
pyterminate.unregister(cleanup_3) | ||
pyterminate.unregister(cleanup_2) | ||
|
||
func() | ||
assert weakref_c() is None, gc.get_referrers(weakref_c()) |