diff --git a/cantok/tokens/abstract/abstract_token.py b/cantok/tokens/abstract/abstract_token.py index d29dbe6..286168e 100644 --- a/cantok/tokens/abstract/abstract_token.py +++ b/cantok/tokens/abstract/abstract_token.py @@ -18,8 +18,15 @@ def __init__(self, *tokens: 'AbstractToken', cancelled: bool = False) -> None: from cantok import DefaultToken self.cached_report: Optional[CancellationReport] = None - self.tokens: List[AbstractToken] = [token for token in tokens if not isinstance(token, DefaultToken)] self._cancelled: bool = cancelled + self.tokens: List[AbstractToken] = [] + + for token in tokens: + if isinstance(token, DefaultToken): + pass + else: + self.tokens.append(token) + self.lock: RLock = RLock() def __repr__(self) -> str: @@ -54,17 +61,28 @@ def __add__(self, item: 'AbstractToken') -> 'AbstractToken': if not isinstance(item, AbstractToken): raise TypeError('Cancellation Token can only be combined with another Cancellation Token.') - from cantok import SimpleToken + from cantok import SimpleToken, DefaultToken nested_tokens = [] + container_token: Optional[AbstractToken] = None for token in self, item: - if isinstance(token, SimpleToken) and getrefcount(token) < 6: + if token._cancelled: + return SimpleToken(cancelled=True) + elif isinstance(token, SimpleToken) and getrefcount(token) < 6: nested_tokens.extend(token.tokens) + elif isinstance(token, DefaultToken): + pass + elif not isinstance(token, SimpleToken) and getrefcount(token) < 6 and container_token is None: + container_token = token else: nested_tokens.append(token) - return SimpleToken(*nested_tokens) + if container_token is None: + return SimpleToken(*nested_tokens) + else: + container_token.tokens.extend(nested_tokens) + return container_token def __bool__(self) -> bool: return self.keep_on() diff --git a/cantok/tokens/condition_token.py b/cantok/tokens/condition_token.py index 8e3538f..d99e8cb 100644 --- a/cantok/tokens/condition_token.py +++ b/cantok/tokens/condition_token.py @@ -57,13 +57,23 @@ def run_function(self) -> bool: return result def text_representation_of_superpower(self) -> str: - return repr(self.function) + result = self.function.__name__ + + if result == '': + return 'λ' + + return result def get_extra_kwargs(self) -> Dict[str, Any]: - return { - 'suppress_exceptions': self.suppress_exceptions, - 'default': self.default, - } + result = {} + + if not self.suppress_exceptions: + result['suppress_exceptions'] = self.suppress_exceptions + + if self.default is not False: + result['default'] = self.default # type: ignore[assignment] + + return result def get_superpower_exception_message(self) -> str: return 'The cancellation condition was satisfied.' diff --git a/cantok/tokens/counter_token.py b/cantok/tokens/counter_token.py index 7e737a8..449b2cb 100644 --- a/cantok/tokens/counter_token.py +++ b/cantok/tokens/counter_token.py @@ -12,30 +12,40 @@ def __init__(self, counter: int, *tokens: AbstractToken, cancelled: bool = False if counter < 0: raise ValueError('The counter must be greater than or equal to zero.') - self.counter = counter self.initial_counter = counter self.direct = direct self.rollback_if_nondirect_polling = self.direct + counter_bag = {'counter': counter} + self.counter_bag = counter_bag + def function() -> bool: - with self.lock: - if not self.counter: + with counter_bag['lock']: # type: ignore[attr-defined] + if not counter_bag['counter']: return True - self.counter -= 1 + counter_bag['counter'] -= 1 return False super().__init__(function, *tokens, cancelled=cancelled) + self.counter_bag['lock'] = self.lock # type: ignore[assignment] + + @property + def counter(self) -> int: + return self.counter_bag['counter'] + def superpower_rollback(self, superpower_data: Dict[str, Any]) -> None: - self.counter = superpower_data['counter'] + self.counter_bag['counter'] = superpower_data['counter'] def text_representation_of_superpower(self) -> str: - return str(self.counter) + return str(self.counter_bag['counter']) def get_extra_kwargs(self) -> Dict[str, Any]: - return { - 'direct': self.direct, - } + if not self.direct: + return { + 'direct': self.direct, + } + return {} def get_superpower_data(self) -> Dict[str, Any]: return {'counter': self.counter} diff --git a/docs/types_of_tokens/SimpleToken.md b/docs/types_of_tokens/SimpleToken.md index 8e43abb..6e8f9da 100644 --- a/docs/types_of_tokens/SimpleToken.md +++ b/docs/types_of_tokens/SimpleToken.md @@ -9,13 +9,4 @@ token.cancel() print(token.cancelled) #> True ``` -`SimpleToken` is also implicitly generated by the operation of summing two other tokens: - -```python -from cantok import CounterToken, TimeoutToken - -print(repr(CounterToken(5) + TimeoutToken(5))) -#> SimpleToken(CounterToken(5, direct=True), TimeoutToken(5)) -``` - There is not much more to tell about it if you have read [the story](../what_are_tokens/in_general.md) about tokens in general. diff --git a/docs/what_are_tokens/summation.md b/docs/what_are_tokens/summation.md index fa4600e..5e8c317 100644 --- a/docs/what_are_tokens/summation.md +++ b/docs/what_are_tokens/summation.md @@ -1,10 +1,10 @@ -Any tokens can be summed up among themselves. The summation operation generates another [`SimpleToken`](../types_of_tokens/SimpleToken.md) that includes the previous 2: +Tokens can be summed using the operator `+`: ```python -from cantok import SimpleToken, TimeoutToken - -print(repr(SimpleToken() + TimeoutToken(5))) -#> SimpleToken(TimeoutToken(5)) +first_token = TimeoutToken(5) +second_token = ConditionToken(lambda: True) +print(repr(first_token + second_token)) +#> SimpleToken(TimeoutToken(5), ConditionToken(λ)) ``` This feature is convenient to use if your function has received a token with certain restrictions and wants to throw it into other called functions, imposing additional restrictions: @@ -17,3 +17,23 @@ def function(token: AbstractToken): another_function(token + TimeoutToken(5)) # Imposes an additional restriction on the function being called: work for no more than 5 seconds. At the same time, it does not know anything about what restrictions were imposed earlier. ... ``` + +The token summation operation always generates a new token. If at least one of the operand tokens is canceled, the sum will also be canceled. It is also guaranteed that the cancellation of this token does not lead to the cancellation of operands. That is, the sum of two tokens always behaves as if it were a [`SimpleToken`](../types_of_tokens/SimpleToken.md) in which both operands were [nested](embedding.md). However, it is difficult to say exactly which token will result from summation, since the library strives to minimize the generated graph of tokens for the sake of performance. + +You may notice that some tokens disappear altogether during summation: + +```python +print(repr(SimpleToken() + TimeoutToken(5))) +#> TimeoutToken(5) +print(repr(SimpleToken(cancelled=True) + TimeoutToken(5))) +#> SimpleToken(cancelled=True) +``` + +In addition, you can not be afraid to sum more than 2 tokens - this does not generate anything superfluous: + +```python +print(repr(TimeoutToken(5) + ConditionToken(lambda: False) + CounterToken(23))) +#> TimeoutToken(5, ConditionToken(λ), CounterToken(23)) +``` + +In fact, there are quite a few effective ways to optimize the token addition operation that are implemented in the library. This operation is pretty well optimized, so it is recommended in all cases when you need to combine the constraints of different tokens in one. diff --git a/pyproject.toml b/pyproject.toml index 5a5a2af..f8ff70f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "cantok" -version = "0.0.27" +version = "0.0.28" authors = [ { name="Evgeniy Blinov", email="zheni-b@yandex.ru" }, ] diff --git a/tests/units/tokens/abstract/test_abstract_token.py b/tests/units/tokens/abstract/test_abstract_token.py index 8377ce5..eeb15b4 100644 --- a/tests/units/tokens/abstract/test_abstract_token.py +++ b/tests/units/tokens/abstract/test_abstract_token.py @@ -142,7 +142,7 @@ def test_str(token_fabric): 'second_token_fabric', ALL_TOKENS_FABRICS, ) -def test_add_tokens(first_token_fabric, second_token_fabric): +def test_add_not_temp_tokens(first_token_fabric, second_token_fabric): first_token = first_token_fabric() second_token = second_token_fabric() @@ -154,6 +154,83 @@ def test_add_tokens(first_token_fabric, second_token_fabric): assert tokens_sum.tokens[1] is second_token +@pytest.mark.parametrize( + ['first_token_class', 'first_arguments'], + [ + (TimeoutToken, [15]), + (ConditionToken, [lambda: False]), + (CounterToken, [15]), + ], +) +@pytest.mark.parametrize( + ['second_token_class', 'second_arguments'], + [ + (TimeoutToken, [15]), + (ConditionToken, [lambda: False]), + (CounterToken, [15]), + ], +) +def test_add_temp_tokens(first_token_class, second_token_class, first_arguments, second_arguments): + tokens_sum = first_token_class(*first_arguments) + second_token_class(*second_arguments) + + assert isinstance(tokens_sum, first_token_class) + assert len(tokens_sum.tokens) == 1 + assert isinstance(tokens_sum.tokens[0], second_token_class) + assert len(tokens_sum.tokens[0].tokens) == 0 + + +@pytest.mark.parametrize( + ['first_token_class', 'first_arguments'], + [ + (TimeoutToken, [15]), + (ConditionToken, [lambda: False]), + (CounterToken, [15]), + ], +) +@pytest.mark.parametrize( + ['second_token_class', 'second_arguments'], + [ + (TimeoutToken, [15]), + (ConditionToken, [lambda: False]), + (CounterToken, [15]), + ], +) +def test_add_not_temp_token_and_temp_token(first_token_class, second_token_class, first_arguments, second_arguments): + first_token = first_token_class(*first_arguments) + tokens_sum = first_token + second_token_class(*second_arguments) + + assert isinstance(tokens_sum, second_token_class) + assert len(tokens_sum.tokens) == 1 + assert isinstance(tokens_sum.tokens[0], first_token_class) + assert len(tokens_sum.tokens[0].tokens) == 0 + + +@pytest.mark.parametrize( + ['first_token_class', 'first_arguments'], + [ + (TimeoutToken, [15]), + (ConditionToken, [lambda: False]), + (CounterToken, [15]), + ], +) +@pytest.mark.parametrize( + ['second_token_class', 'second_arguments'], + [ + (TimeoutToken, [15]), + (ConditionToken, [lambda: False]), + (CounterToken, [15]), + ], +) +def test_add_temp_token_and_not_temp_token(first_token_class, second_token_class, first_arguments, second_arguments): + second_token = second_token_class(*second_arguments) + tokens_sum = first_token_class(*first_arguments) + second_token + + assert isinstance(tokens_sum, first_token_class) + assert len(tokens_sum.tokens) == 1 + assert isinstance(tokens_sum.tokens[0], second_token_class) + assert len(tokens_sum.tokens[0].tokens) == 0 + + @pytest.mark.parametrize( 'first_token_fabric', ALL_TOKENS_FABRICS_WITH_NOT_CANCELLING_SUPERPOWER, @@ -669,3 +746,40 @@ def test_superpower_is_more_important_than_cache(first_token_fabric, second_toke assert isinstance(report, CancellationReport) assert report.from_token is token assert report.cause == CancelCause.CANCELLED + + +@pytest.mark.parametrize( + 'token_fabric', + ALL_TOKENS_FABRICS, +) +def test_just_neste_temp_simple_token_to_another_token(token_fabric): + token = token_fabric(SimpleToken()) + + assert len(token.tokens) == 1 + assert isinstance(token.tokens[0], SimpleToken) + assert token + + +@pytest.mark.parametrize( + 'token_fabric', + ALL_TOKENS_FABRICS, +) +def test_any_token_plus_temp_cancelled_simple_token_gives_cancelled_simple_token(token_fabric): + token = token_fabric() + SimpleToken(cancelled=True) + + assert isinstance(token, SimpleToken) + assert len(token.tokens) == 0 + assert not token + + +@pytest.mark.parametrize( + 'token_fabric', + ALL_TOKENS_FABRICS, +) +def test_any_token_plus_cancelled_simple_token_gives_cancelled_simple_token(token_fabric): + simple_token = SimpleToken(cancelled=True) + token = token_fabric() + simple_token + + assert isinstance(token, SimpleToken) + assert len(token.tokens) == 0 + assert not token diff --git a/tests/units/tokens/test_condition_token.py b/tests/units/tokens/test_condition_token.py index 1126888..2a4fb6a 100644 --- a/tests/units/tokens/test_condition_token.py +++ b/tests/units/tokens/test_condition_token.py @@ -99,22 +99,6 @@ def test_condition_function_returning_not_bool_value(): ConditionToken(lambda: 'kek', suppress_exceptions=False).cancelled -@pytest.mark.parametrize( - 'suppress_exceptions_flag', - [True, False], -) -@pytest.mark.parametrize( - 'default_flag', - [True, False], -) -def test_test_representaion_of_extra_kwargs(suppress_exceptions_flag, default_flag): - assert ConditionToken( - lambda: False, - suppress_exceptions=suppress_exceptions_flag, - default=default_flag, - ).text_representation_of_extra_kwargs() == f'suppress_exceptions={suppress_exceptions_flag}, default={default_flag}' - - @pytest.mark.parametrize( 'default', [True, False], @@ -345,9 +329,8 @@ def condition(): def test_quasitemp_condition_token_plus_temp_simple_token(): token = ConditionToken(lambda: False) + SimpleToken() - assert isinstance(token, SimpleToken) - assert len(token.tokens) == 1 - assert isinstance(token.tokens[0], ConditionToken) + assert isinstance(token, ConditionToken) + assert len(token.tokens) == 0 def test_not_quasitemp_condition_token_plus_temp_simple_token(): @@ -364,11 +347,11 @@ def test_quasitemp_condition_token_plus_not_temp_simple_token(): simple_token = SimpleToken() token = ConditionToken(lambda: False) + simple_token - assert isinstance(token, SimpleToken) + assert isinstance(token, ConditionToken) assert token is not simple_token - assert len(token.tokens) == 2 - assert isinstance(token.tokens[0], ConditionToken) - assert token.tokens[1] is simple_token + assert len(token.tokens) == 1 + assert isinstance(token.tokens[0], SimpleToken) + assert token.tokens[0] is simple_token def test_not_quasitemp_condition_token_plus_not_temp_simple_token(): @@ -387,9 +370,8 @@ def test_not_quasitemp_condition_token_plus_not_temp_simple_token(): def test_quasitemp_condition_token_plus_temp_simple_token_reverse(): token = SimpleToken() + ConditionToken(lambda: False) - assert isinstance(token, SimpleToken) - assert len(token.tokens) == 1 - assert isinstance(token.tokens[0], ConditionToken) + assert isinstance(token, ConditionToken) + assert len(token.tokens) == 0 def test_not_quasitemp_condition_token_plus_temp_simple_token_reverse(): @@ -406,10 +388,9 @@ def test_quasitemp_condition_token_plus_not_temp_simple_token_reverse(): simple_token = SimpleToken() token = simple_token + ConditionToken(lambda: False) - assert isinstance(token, SimpleToken) + assert isinstance(token, ConditionToken) assert token is not simple_token - assert len(token.tokens) == 2 - assert isinstance(token.tokens[1], ConditionToken) + assert len(token.tokens) == 1 assert token.tokens[0] is simple_token @@ -444,3 +425,39 @@ def test_condition_function_is_more_important_than_cache(): assert isinstance(report, CancellationReport) assert report.from_token is token assert report.cause == CancelCause.SUPERPOWER + + +def test_zero_condition_token_report_is_about_superpower(): + for report in ConditionToken(lambda: True).get_report(True), ConditionToken(lambda: True).get_report(False): + assert report.cause == CancelCause.SUPERPOWER + + +def test_creating_condition_token_with_no_suppress_exceptions_is_not_calling_condition(): + calls = [] + + ConditionToken(lambda: calls.append(True) is None, suppress_exceptions=False) + + assert not calls + + +def test_repr_of_condition_token(): + def function(): return False + + assert repr(ConditionToken(lambda: False)) == 'ConditionToken(λ)' + assert repr(ConditionToken(lambda: False, ConditionToken(lambda: False))) == 'ConditionToken(λ, ConditionToken(λ))' + assert repr(ConditionToken(lambda: False, suppress_exceptions=True)) == 'ConditionToken(λ)' + assert repr(ConditionToken(lambda: False, suppress_exceptions=False)) == 'ConditionToken(λ, suppress_exceptions=False)' + assert repr(ConditionToken(lambda: False, default=False)) == 'ConditionToken(λ)' + assert repr(ConditionToken(lambda: False, default=True)) == 'ConditionToken(λ, default=True)' + assert repr(ConditionToken(lambda: False, suppress_exceptions=False, default=True)) == 'ConditionToken(λ, suppress_exceptions=False, default=True)' + assert repr(ConditionToken(lambda: False, suppress_exceptions=False, default=True, cancelled=True)) == 'ConditionToken(λ, cancelled=True, suppress_exceptions=False, default=True)' + + assert repr(ConditionToken(function)) == 'ConditionToken(function)' + assert repr(ConditionToken(function, ConditionToken(function))) == 'ConditionToken(function, ConditionToken(function))' + assert repr(ConditionToken(function, suppress_exceptions=True)) == 'ConditionToken(function)' + assert repr(ConditionToken(function, suppress_exceptions=False)) == 'ConditionToken(function, suppress_exceptions=False)' + assert repr(ConditionToken(function, default=False)) == 'ConditionToken(function)' + assert repr(ConditionToken(function, default=True)) == 'ConditionToken(function, default=True)' + assert repr(ConditionToken(function, suppress_exceptions=False, default=True)) == 'ConditionToken(function, suppress_exceptions=False, default=True)' + + assert repr(ConditionToken(function, suppress_exceptions=False, default=True, cancelled=True)) == 'ConditionToken(function, cancelled=True, suppress_exceptions=False, default=True)' diff --git a/tests/units/tokens/test_counter_token.py b/tests/units/tokens/test_counter_token.py index 1fd106e..d491206 100644 --- a/tests/units/tokens/test_counter_token.py +++ b/tests/units/tokens/test_counter_token.py @@ -232,9 +232,8 @@ def test_decrement_counter_after_zero(): def test_quasitemp_counter_token_plus_temp_simple_token(): token = CounterToken(0) + SimpleToken() - assert isinstance(token, SimpleToken) - assert len(token.tokens) == 1 - assert isinstance(token.tokens[0], CounterToken) + assert isinstance(token, CounterToken) + assert len(token.tokens) == 0 def test_not_quasitemp_counter_token_plus_temp_simple_token(): @@ -251,11 +250,11 @@ def test_quasitemp_counter_token_plus_not_temp_simple_token(): simple_token = SimpleToken() token = CounterToken(1) + simple_token - assert isinstance(token, SimpleToken) + assert isinstance(token, CounterToken) assert token is not simple_token - assert len(token.tokens) == 2 - assert isinstance(token.tokens[0], CounterToken) - assert token.tokens[1] is simple_token + assert len(token.tokens) == 1 + assert isinstance(token.tokens[0], SimpleToken) + assert token.tokens[0] is simple_token def test_not_quasitemp_counter_token_plus_not_temp_simple_token(): @@ -274,9 +273,8 @@ def test_not_quasitemp_counter_token_plus_not_temp_simple_token(): def test_quasitemp_counter_token_plus_temp_simple_token_reverse(): token = SimpleToken() + CounterToken(1) - assert isinstance(token, SimpleToken) - assert len(token.tokens) == 1 - assert isinstance(token.tokens[0], CounterToken) + assert isinstance(token, CounterToken) + assert len(token.tokens) == 0 def test_not_quasitemp_counter_token_plus_temp_simple_token_reverse(): @@ -293,10 +291,10 @@ def test_quasitemp_counter_token_plus_not_temp_simple_token_reverse(): simple_token = SimpleToken() token = simple_token + CounterToken(1) - assert isinstance(token, SimpleToken) + assert isinstance(token, CounterToken) assert token is not simple_token - assert len(token.tokens) == 2 - assert isinstance(token.tokens[1], CounterToken) + assert len(token.tokens) == 1 + assert isinstance(token.tokens[0], SimpleToken) assert token.tokens[0] is simple_token @@ -311,3 +309,26 @@ def test_not_quasitemp_counter_token_plus_not_temp_simple_token_reverse(): assert isinstance(token.tokens[1], CounterToken) assert token.tokens[1] is counter_token assert token.tokens[0] is simple_token + + +def test_zero_counter_token_report_is_about_superpower(): + for report in CounterToken(0).get_report(True), CounterToken(0).get_report(False): + assert report.cause == CancelCause.SUPERPOWER + + +def test_repr_for_counter_token(): + assert repr(CounterToken(0)) == 'CounterToken(0)' + assert repr(CounterToken(1)) == 'CounterToken(1)' + assert repr(CounterToken(10000)) == 'CounterToken(10000)' + + assert repr(CounterToken(10000, CounterToken(10000))) == 'CounterToken(10000, CounterToken(10000))' + assert repr(CounterToken(10000, CounterToken(10000), CounterToken(10000))) == 'CounterToken(10000, CounterToken(10000), CounterToken(10000))' + + assert repr(CounterToken(10000, direct=True)) == 'CounterToken(10000)' + assert repr(CounterToken(10000, direct=False)) == 'CounterToken(10000, direct=False)' + + assert repr(CounterToken(10000, cancelled=False)) == 'CounterToken(10000)' + assert repr(CounterToken(10000, cancelled=True)) == 'CounterToken(10000, cancelled=True)' + + assert repr(CounterToken(10000, direct=False, cancelled=True)) == 'CounterToken(10000, cancelled=True, direct=False)' + assert repr(CounterToken(10000, CounterToken(10000), direct=False, cancelled=True)) == 'CounterToken(10000, CounterToken(10000), cancelled=True, direct=False)' diff --git a/tests/units/tokens/test_default_token.py b/tests/units/tokens/test_default_token.py index 18ae8eb..1fc4c29 100644 --- a/tests/units/tokens/test_default_token.py +++ b/tests/units/tokens/test_default_token.py @@ -3,7 +3,7 @@ import pytest import full_match -from cantok import DefaultToken, SimpleToken, ImpossibleCancelError +from cantok import DefaultToken, SimpleToken, TimeoutToken, ImpossibleCancelError def test_dafault_token_is_not_cancelled_by_default(): @@ -93,3 +93,19 @@ def test_default_token_plus_not_temp_simple_token(): assert len(sum.tokens) == 1 assert sum is not simple_token assert sum.tokens[0] is simple_token + + +def test_temp_default_token_plus_temp_timeout_token(): + token = DefaultToken() + TimeoutToken(1) + + assert isinstance(token, TimeoutToken) + assert token.timeout == 1 + assert len(token.tokens) == 0 + + +def test_temp_timeout_token_plus_temp_default_token(): + token = TimeoutToken(1) + DefaultToken() + + assert isinstance(token, TimeoutToken) + assert token.timeout == 1 + assert len(token.tokens) == 0 diff --git a/tests/units/tokens/test_simple_token.py b/tests/units/tokens/test_simple_token.py index 99ec299..33a74a4 100644 --- a/tests/units/tokens/test_simple_token.py +++ b/tests/units/tokens/test_simple_token.py @@ -195,28 +195,24 @@ def test_sum_of_2_temp_timeout_tokens_throw_temp_simple_tokens(): def test_sum_of_2_temp_timeout_tokens_throw_right_temp_simple_token(): token = TimeoutToken(1) + SimpleToken(TimeoutToken(2)) - assert isinstance(token, SimpleToken) - assert len(token.tokens) == 2 + assert isinstance(token, TimeoutToken) + assert len(token.tokens) == 1 + assert token.timeout == 1 assert isinstance(token.tokens[0], TimeoutToken) - assert token.tokens[0].timeout == 1 - - assert isinstance(token.tokens[1], TimeoutToken) - assert token.tokens[1].timeout == 2 + assert token.tokens[0].timeout == 2 def test_sum_of_2_temp_timeout_tokens_throw_left_temp_simple_token(): token = SimpleToken(TimeoutToken(1)) + TimeoutToken(2) - assert isinstance(token, SimpleToken) - assert len(token.tokens) == 2 + assert isinstance(token, TimeoutToken) + assert len(token.tokens) == 1 + assert token.timeout == 2 assert isinstance(token.tokens[0], TimeoutToken) assert token.tokens[0].timeout == 1 - assert isinstance(token.tokens[1], TimeoutToken) - assert token.tokens[1].timeout == 2 - def test_sum_of_2_not_temp_timeout_tokens_throw_temp_simple_tokens(): first_timeout_token = TimeoutToken(1) @@ -368,3 +364,11 @@ def test_sum_of_not_temp_condition_token_and_not_temp_timeout_token_throw_temp_s assert token.tokens[1] is timeout_token assert isinstance(token.tokens[1], TimeoutToken) assert token.tokens[1].timeout == 1 + + +def test_temp_timeout_token_plus_temp_cancelled_simple_token(): + token = TimeoutToken(1) + SimpleToken(cancelled=True) + + assert isinstance(token, SimpleToken) + assert not token + assert len(token.tokens) == 0 diff --git a/tests/units/tokens/test_timeout_token.py b/tests/units/tokens/test_timeout_token.py index 50f6cf7..15549c5 100644 --- a/tests/units/tokens/test_timeout_token.py +++ b/tests/units/tokens/test_timeout_token.py @@ -224,9 +224,9 @@ def test_timeout_wait(): def test_quasitemp_timeout_token_plus_temp_simple_token(): token = TimeoutToken(1) + SimpleToken() - assert isinstance(token, SimpleToken) - assert len(token.tokens) == 1 - assert isinstance(token.tokens[0], TimeoutToken) + assert isinstance(token, TimeoutToken) + assert len(token.tokens) == 0 + assert token.timeout == 1 def test_not_quasitemp_timeout_token_plus_temp_simple_token(): @@ -243,11 +243,11 @@ def test_quasitemp_timeout_token_plus_not_temp_simple_token(): simple_token = SimpleToken() token = TimeoutToken(1) + simple_token - assert isinstance(token, SimpleToken) + assert isinstance(token, TimeoutToken) assert token is not simple_token - assert len(token.tokens) == 2 - assert isinstance(token.tokens[0], TimeoutToken) - assert token.tokens[1] is simple_token + assert len(token.tokens) == 1 + assert isinstance(token.tokens[0], SimpleToken) + assert token.tokens[0] is simple_token def test_not_quasitemp_timeout_token_plus_not_temp_simple_token(): @@ -266,9 +266,9 @@ def test_not_quasitemp_timeout_token_plus_not_temp_simple_token(): def test_quasitemp_timeout_token_plus_temp_simple_token_reverse(): token = SimpleToken() + TimeoutToken(1) - assert isinstance(token, SimpleToken) - assert len(token.tokens) == 1 - assert isinstance(token.tokens[0], TimeoutToken) + assert isinstance(token, TimeoutToken) + assert len(token.tokens) == 0 + assert token.timeout == 1 def test_not_quasitemp_timeout_token_plus_temp_simple_token_reverse(): @@ -285,10 +285,11 @@ def test_quasitemp_timeout_token_plus_not_temp_simple_token_reverse(): simple_token = SimpleToken() token = simple_token + TimeoutToken(1) - assert isinstance(token, SimpleToken) + assert isinstance(token, TimeoutToken) + assert token.timeout == 1 assert token is not simple_token - assert len(token.tokens) == 2 - assert isinstance(token.tokens[1], TimeoutToken) + assert len(token.tokens) == 1 + assert isinstance(token.tokens[0], SimpleToken) assert token.tokens[0] is simple_token @@ -316,10 +317,15 @@ def test_timeout_is_more_important_than_cache(): assert report.from_token is inner_token assert report.cause == CancelCause.CANCELLED - sleep(sleep_time * 2) + sleep(sleep_time * 10) for report in token.get_report(True), token.get_report(False): assert report is not None assert isinstance(report, CancellationReport) assert report.from_token is token assert report.cause == CancelCause.SUPERPOWER + + +def test_zero_timeout_token_report_is_about_superpower(): + for report in TimeoutToken(0).get_report(True), TimeoutToken(0).get_report(False): + assert report.cause == CancelCause.SUPERPOWER