forked from snaptec/openWB
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: while the main thread is blocked signals might pile up and cause…
… a "maximum recursion depth exceeded" error when they are eventually executed all at once closes snaptec#2003, closes snaptec#1994
- Loading branch information
Showing
3 changed files
with
82 additions
and
59 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import threading | ||
from typing import Callable, TypeVar | ||
|
||
T = TypeVar("T") | ||
|
||
|
||
def skip_while_unchanged(source: Callable, initial=None): | ||
"""Before each call check if value given by `source` has changed. If it has not, ignore the call""" | ||
def wrap(function: T) -> T: | ||
previous = [initial] | ||
lock = threading.Lock() | ||
|
||
def wrapper(*args, **kwargs): | ||
with lock: | ||
next = source() | ||
if previous[0] != next: | ||
function(*args, **kwargs) | ||
previous[0] = next | ||
|
||
return wrapper | ||
|
||
return wrap |
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,55 @@ | ||
import itertools | ||
from unittest.mock import Mock, call | ||
|
||
import pytest | ||
|
||
from helpermodules.skip_while_unchanged import skip_while_unchanged | ||
|
||
|
||
def test_skip_while_unchanged_calls_original_with_arguments(): | ||
# setup | ||
mock = Mock() | ||
|
||
# execution | ||
decorated = skip_while_unchanged(itertools.count().__next__)(mock) | ||
decorated(1, 2, some_key="some value") | ||
decorated(3) | ||
|
||
# evaluation | ||
expected_calls = [call(1, 2, some_key="some value"), call(3)] | ||
mock.assert_has_calls(expected_calls) | ||
assert mock.call_count == len(expected_calls) | ||
|
||
|
||
def test_skip_while_unchanged_skips_calls_on_no_change(): | ||
# setup | ||
mock = Mock() | ||
|
||
# execution | ||
decorated = skip_while_unchanged([1, 1, 1, 2, 2].__iter__().__next__)(mock) | ||
decorated(1) | ||
decorated(2) | ||
decorated(3) | ||
decorated(4) | ||
decorated(5) | ||
|
||
# evaluation | ||
expected_calls = [call(1), call(4)] | ||
mock.assert_has_calls(expected_calls) | ||
assert mock.call_count == len(expected_calls) | ||
|
||
|
||
def test_skip_while_unchanged_recalls_if_function_throws_exception(): | ||
# setup | ||
mock = Mock(side_effect=Exception("dummy")) | ||
|
||
# execution | ||
decorated = skip_while_unchanged(itertools.count().__next__)(mock) | ||
for i in range(1, 3): | ||
with pytest.raises(Exception): | ||
decorated(i) | ||
|
||
# evaluation | ||
expected_calls = [call(1), call(2)] | ||
mock.assert_has_calls(expected_calls) | ||
assert mock.call_count == len(expected_calls) |
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