diff --git a/docs/types_of_tokens/ConditionToken.md b/docs/types_of_tokens/ConditionToken.md index a05a709..a3aef4f 100644 --- a/docs/types_of_tokens/ConditionToken.md +++ b/docs/types_of_tokens/ConditionToken.md @@ -9,7 +9,7 @@ token = ConditionToken(lambda: counter >= 5) while token: counter += 1 -print(counter) # 5 +print(counter) #> 5 ``` By default, if the passed function raises an exception, it will be silently suppressed. However, you can make the raised exceptions explicit by setting the `suppress_exceptions` parameter to `False`: @@ -27,9 +27,9 @@ If you still use exception suppression mode, by default, in case of an exception ```python def function(): raise ValueError -print(ConditionToken(function).cancelled) # False -print(ConditionToken(function, default=False).cancelled) # False -print(ConditionToken(function, default=True).cancelled) # True +print(ConditionToken(function).cancelled) #> False +print(ConditionToken(function, default=False).cancelled) #> False +print(ConditionToken(function, default=True).cancelled) #> True ``` If the condition is complex enough and requires additional preparation before it can be checked, you can pass a function that runs before the condition is checked. To do this, pass any function without arguments as the `before` argument: @@ -40,9 +40,8 @@ from cantok import ConditionToken token = ConditionToken(lambda: print(2), before=lambda: print(1)) token.check() -# Will be printed: -# 1 -# 2 +#> 1 +#> 2 ``` By analogy with `before`, you can pass a function that will be executed after checking the condition as the `after` argument: @@ -51,9 +50,8 @@ By analogy with `before`, you can pass a function that will be executed after ch token = ConditionToken(lambda: print(1), after=lambda: print(2)) token.check() -# Will be printed: -# 1 -# 2 +#> 1 +#> 2 ``` `ConditionToken` has another feature. If the condition has detonated at least once and canceled it, then the condition is no longer polled and the token is permanently considered canceled. You can change this by manipulating the `caching` parameter when creating a token. By setting it to `False`, you will make sure that the condition is polled every time. @@ -70,11 +68,11 @@ def increment_counter_and_get_the_value(): token = ConditionToken(increment_counter_and_get_the_value, caching=False) print(token.cancelled) -# False +#> False print(token.cancelled) -# True +#> True print(token.cancelled) -# False +#> False ``` However, we do not recommend doing this. In the vast majority of cases, you do not want your token to be able to roll back the fact of its cancellation. If the token has been cancelled once, it must remain cancelled. Manipulate the `caching` parameter only if you are sure that you understand what you are doing. diff --git a/docs/types_of_tokens/CounterToken.md b/docs/types_of_tokens/CounterToken.md index b61e0f8..6e99e26 100644 --- a/docs/types_of_tokens/CounterToken.md +++ b/docs/types_of_tokens/CounterToken.md @@ -11,7 +11,7 @@ counter = 0 while token: counter += 1 -print(counter) # 5 +print(counter) #> 5 ``` The counter inside the `CounterToken` is reduced under one of three conditions: @@ -28,9 +28,9 @@ from cantok import SimpleToken, CounterToken first_counter_token = CounterToken(1, direct=False) second_counter_token = CounterToken(1, direct=True) -print(SimpleToken(first_counter_token, second_counter_token).cancelled) # False -print(first_counter_token.cancelled) # True -print(second_counter_token.cancelled) # False +print(SimpleToken(first_counter_token, second_counter_token).cancelled) #> False +print(first_counter_token.cancelled) #> True +print(second_counter_token.cancelled) #> False ``` Like all other tokens, `CounterToken` can accept other tokens as parameters during initialization: diff --git a/docs/types_of_tokens/SimpleToken.md b/docs/types_of_tokens/SimpleToken.md index 14e93ff..8e43abb 100644 --- a/docs/types_of_tokens/SimpleToken.md +++ b/docs/types_of_tokens/SimpleToken.md @@ -4,9 +4,9 @@ The base token is `SimpleToken`. It has no built-in automation that can cancel i from cantok import SimpleToken token = SimpleToken() -print(token.cancelled) # False +print(token.cancelled) #> False token.cancel() -print(token.cancelled) # True +print(token.cancelled) #> True ``` `SimpleToken` is also implicitly generated by the operation of summing two other tokens: @@ -15,7 +15,7 @@ print(token.cancelled) # True from cantok import CounterToken, TimeoutToken print(repr(CounterToken(5) + TimeoutToken(5))) -# SimpleToken(CounterToken(5, direct=True), 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/types_of_tokens/TimeoutToken.md b/docs/types_of_tokens/TimeoutToken.md index a9c0e68..8f3cb59 100644 --- a/docs/types_of_tokens/TimeoutToken.md +++ b/docs/types_of_tokens/TimeoutToken.md @@ -5,9 +5,9 @@ from time import sleep from cantok import TimeoutToken token = TimeoutToken(5) -print(token.cancelled) # False +print(token.cancelled) #> False sleep(10) -print(token.cancelled) # True +print(token.cancelled) #> True ``` Just like `ConditionToken`, `TimeoutToken` can include other tokens: diff --git a/docs/what_are_tokens/cancel_and_read_the_status.md b/docs/what_are_tokens/cancel_and_read_the_status.md index fbb2117..3789751 100644 --- a/docs/what_are_tokens/cancel_and_read_the_status.md +++ b/docs/what_are_tokens/cancel_and_read_the_status.md @@ -4,9 +4,9 @@ Each token object has a `cancelled` attribute and a `cancel()` method. By the at from cantok import SimpleToken token = SimpleToken() -print(token.cancelled) # False +print(token.cancelled) #> False token.cancel() -print(token.cancelled) # True +print(token.cancelled) #> True ``` The cancelled attribute is dynamically calculated and takes into account, among other things, specific conditions that are checked by a specific token. Here is an example with a [token that measures time](../types_of_tokens/TimeoutToken.md): @@ -16,9 +16,9 @@ from time import sleep from cantok import TimeoutToken token = TimeoutToken(5) -print(token.cancelled) # False +print(token.cancelled) #> False sleep(10) -print(token.cancelled) # True +print(token.cancelled) #> True ``` In addition to this attribute, each token implements the `is_cancelled()` method. It does exactly the same thing as the attribute: @@ -27,11 +27,11 @@ In addition to this attribute, each token implements the `is_cancelled()` method from cantok import SimpleToken token = SimpleToken() -print(token.cancelled) # False -print(token.is_cancelled()) # False +print(token.cancelled) #> False +print(token.is_cancelled()) #> False token.cancel() -print(token.cancelled) # True -print(token.is_cancelled()) # True +print(token.cancelled) #> True +print(token.is_cancelled()) #> True ``` Choose what you like best. To the author of the library, the use of the attribute seems more beautiful, but the method call more clearly reflects the complexity of the work that is actually being done to answer the question "has the token been canceled?". @@ -42,11 +42,11 @@ There is another method opposite to `is_cancelled()` - `keep_on()`. It answers t from cantok import SimpleToken token = SimpleToken() -print(token.cancelled) # False -print(token.keep_on()) # True +print(token.cancelled) #> False +print(token.keep_on()) #> True token.cancel() -print(token.cancelled) # True -print(token.keep_on()) # False +print(token.cancelled) #> True +print(token.keep_on()) #> False ``` You don't have to call the `keep_on()` method directly. Use the token itself as a boolean value, and the method call will occur "under the hood" automatically: @@ -55,11 +55,11 @@ You don't have to call the `keep_on()` method directly. Use the token itself as from cantok import SimpleToken token = SimpleToken() -print(bool(token)) # True -print(token.keep_on()) # True +print(bool(token)) #> True +print(token.keep_on()) #> True token.cancel() -print(bool(token)) # False -print(token.keep_on()) # False +print(bool(token)) #> False +print(token.keep_on()) #> False ``` There is another method that is close in meaning to `is_cancelled()` - `check()`. It does nothing if the token is not canceled, or raises an exception if canceled. If the token was canceled by calling the `cancel()` method, a `CancellationError` exception will be raised: @@ -70,7 +70,9 @@ from cantok import SimpleToken token = SimpleToken() token.check() # Nothing happens. token.cancel() -token.check() # cantok.errors.CancellationError: The token has been cancelled. +token.check() +#> ... +#> cantok.errors.CancellationError: The token has been cancelled. ``` Otherwise, a special exception inherited from `CancellationError` will be raised: @@ -79,5 +81,7 @@ Otherwise, a special exception inherited from `CancellationError` will be raised from cantok import TimeoutToken token = TimeoutToken(0) -token.check() # cantok.errors.TimeoutCancellationError: The timeout of 0 seconds has expired. +token.check() +#> ... +#> cantok.errors.TimeoutCancellationError: The timeout of 0 seconds has expired. ``` diff --git a/docs/what_are_tokens/embedding.md b/docs/what_are_tokens/embedding.md index 0a23fe0..83e3cbd 100644 --- a/docs/what_are_tokens/embedding.md +++ b/docs/what_are_tokens/embedding.md @@ -9,7 +9,7 @@ third_token = SimpleToken(first_token, second_token) first_token.cancel() -print(first_token.cancelled) # True -print(second_token.cancelled) # False -print(third_token.cancelled) # True +print(first_token.cancelled) #> True +print(second_token.cancelled) #> False +print(third_token.cancelled) #> True ``` diff --git a/docs/what_are_tokens/exceptions.md b/docs/what_are_tokens/exceptions.md index c5ee3e4..fe0d261 100644 --- a/docs/what_are_tokens/exceptions.md +++ b/docs/what_are_tokens/exceptions.md @@ -6,7 +6,8 @@ from cantok import TimeoutToken token = TimeoutToken(1) token.wait() token.check() -# cantok.errors.TimeoutCancellationError: The timeout of 1 seconds has expired. +#> ... +#> cantok.errors.TimeoutCancellationError: The timeout of 1 seconds has expired. ``` Each type of token (except [`DefaultToken`](../types_of_tokens/DefaultToken.md)) has a corresponding type of exception that can be raised in this case: @@ -34,7 +35,7 @@ token = TimeoutToken(0) try: token.check() except CancellationError as e: - print(type(e) is TimeoutToken.exception) # True + print(type(e) is TimeoutToken.exception) #> True ``` And each exception object has a `token` attribute indicating the specific token that was canceled. This can be useful in situations where several tokens are nested in one another and you want to find out which one has been canceled: @@ -48,5 +49,5 @@ token = SimpleToken(nested_token) try: token.check() except CancellationError as e: - print(e.token is nested_token) # True + print(e.token is nested_token) #> True ``` diff --git a/docs/what_are_tokens/waiting.md b/docs/what_are_tokens/waiting.md index 22bcebe..13b567c 100644 --- a/docs/what_are_tokens/waiting.md +++ b/docs/what_are_tokens/waiting.md @@ -6,7 +6,8 @@ from cantok import TimeoutToken token = TimeoutToken(5) token.wait() # It will take about 5 seconds. token.check() # Since the timeout has expired, an exception will be raised. -# cantok.errors.TimeoutCancellationError: The timeout of 5 seconds has expired. +#> ... +#> cantok.errors.TimeoutCancellationError: The timeout of 5 seconds has expired. ``` If you add the `await` keyword before calling `wait()`, the method will be automatically used in non-blocking mode: diff --git a/pyproject.toml b/pyproject.toml index 71fba0a..5a5a2af 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "cantok" -version = "0.0.26" +version = "0.0.27" authors = [ { name="Evgeniy Blinov", email="zheni-b@yandex.ru" }, ] diff --git a/tests/units/tokens/test_simple_token.py b/tests/units/tokens/test_simple_token.py index 5b6ce2a..99ec299 100644 --- a/tests/units/tokens/test_simple_token.py +++ b/tests/units/tokens/test_simple_token.py @@ -1,7 +1,7 @@ import pytest from cantok.tokens.abstract.abstract_token import CancelCause, CancellationReport -from cantok import SimpleToken, CancellationError +from cantok import SimpleToken, TimeoutToken, ConditionToken, CancellationError def test_just_created_token_without_arguments(): @@ -155,6 +155,17 @@ def test_sum_of_2_not_temp_simple_tokens(): assert result.tokens[1] is second_token +def test_sum_of_2_not_temp_simple_tokens_and_one_temp(): + first_token = SimpleToken() + second_token = SimpleToken() + result = first_token + second_token + SimpleToken() + + assert isinstance(result, SimpleToken) + assert len(result.tokens) == 2 + assert result.tokens[0] is first_token + assert result.tokens[1] is second_token + + def test_sum_of_3_not_temp_simple_tokens(): first_token = SimpleToken() second_token = SimpleToken() @@ -166,3 +177,194 @@ def test_sum_of_3_not_temp_simple_tokens(): assert result.tokens[0] is first_token assert result.tokens[1] is second_token assert result.tokens[2] is third_token + + +def test_sum_of_2_temp_timeout_tokens_throw_temp_simple_tokens(): + token = SimpleToken(TimeoutToken(1)) + SimpleToken(TimeoutToken(2)) + + assert isinstance(token, SimpleToken) + assert len(token.tokens) == 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_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.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_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.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) + second_timeout_token = TimeoutToken(2) + token = SimpleToken(first_timeout_token) + SimpleToken(second_timeout_token) + + assert isinstance(token, SimpleToken) + assert len(token.tokens) == 2 + + assert token.tokens[0] is first_timeout_token + assert isinstance(token.tokens[0], TimeoutToken) + assert token.tokens[0].timeout == 1 + + assert token.tokens[1] is second_timeout_token + assert isinstance(token.tokens[1], TimeoutToken) + assert token.tokens[1].timeout == 2 + + +def test_sum_of_first_temp_and_second_not_temp_timeout_tokens_throw_temp_simple_tokens(): + second_timeout_token = TimeoutToken(2) + token = SimpleToken(TimeoutToken(1)) + SimpleToken(second_timeout_token) + + assert isinstance(token, SimpleToken) + assert len(token.tokens) == 2 + + assert isinstance(token.tokens[0], TimeoutToken) + assert token.tokens[0].timeout == 1 + + assert token.tokens[1] is second_timeout_token + assert isinstance(token.tokens[1], TimeoutToken) + assert token.tokens[1].timeout == 2 + + +def test_sum_of_first_not_temp_and_second_temp_timeout_tokens_throw_temp_simple_tokens(): + first_timeout_token = TimeoutToken(1) + token = SimpleToken(first_timeout_token) + SimpleToken(TimeoutToken(2)) + + assert isinstance(token, SimpleToken) + assert len(token.tokens) == 2 + + assert token.tokens[0] is first_timeout_token + 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_temp_timeout_token_and_temp_condition_token_throw_temp_simple_tokens(): + token = SimpleToken(TimeoutToken(1)) + SimpleToken(ConditionToken(lambda: False)) + + assert isinstance(token, SimpleToken) + assert len(token.tokens) == 2 + assert token + + assert isinstance(token.tokens[0], TimeoutToken) + assert token.tokens[0].timeout == 1 + + assert isinstance(token.tokens[1], ConditionToken) + + +def test_sum_of_temp_condition_token_and_temp_timeout_token_throw_temp_simple_tokens(): + token = SimpleToken(ConditionToken(lambda: False)) + SimpleToken(TimeoutToken(1)) + + assert isinstance(token, SimpleToken) + assert len(token.tokens) == 2 + assert token + + assert isinstance(token.tokens[0], ConditionToken) + + assert isinstance(token.tokens[1], TimeoutToken) + assert token.tokens[1].timeout == 1 + + +def test_sum_of_not_temp_timeout_token_and_temp_condition_token_throw_temp_simple_tokens(): + timeout_token = TimeoutToken(1) + token = SimpleToken(timeout_token) + SimpleToken(ConditionToken(lambda: False)) + + assert isinstance(token, SimpleToken) + assert len(token.tokens) == 2 + assert token + + assert token.tokens[0] is timeout_token + assert isinstance(token.tokens[0], TimeoutToken) + assert token.tokens[0].timeout == 1 + + assert isinstance(token.tokens[1], ConditionToken) + + +def test_sum_of_temp_timeout_token_and_not_temp_condition_token_throw_temp_simple_tokens(): + condition_token = ConditionToken(lambda: False) + token = SimpleToken(TimeoutToken(1)) + SimpleToken(condition_token) + + assert isinstance(token, SimpleToken) + assert len(token.tokens) == 2 + assert token + + assert isinstance(token.tokens[0], TimeoutToken) + assert token.tokens[0].timeout == 1 + + assert isinstance(token.tokens[1], ConditionToken) + assert token.tokens[1] is condition_token + + +def test_sum_of_not_temp_condition_token_and_temp_timeout_token_throw_temp_simple_tokens(): + condition_token = ConditionToken(lambda: False) + token = SimpleToken(condition_token) + SimpleToken(TimeoutToken(1)) + + assert isinstance(token, SimpleToken) + assert len(token.tokens) == 2 + assert token + + assert isinstance(token.tokens[0], ConditionToken) + assert token.tokens[0] is condition_token + + assert isinstance(token.tokens[1], TimeoutToken) + assert token.tokens[1].timeout == 1 + + +def test_sum_of_not_temp_timeout_token_and_not_temp_condition_token_throw_temp_simple_tokens(): + timeout_token = TimeoutToken(1) + condition_token = ConditionToken(lambda: False) + token = SimpleToken(timeout_token) + SimpleToken(condition_token) + + assert isinstance(token, SimpleToken) + assert len(token.tokens) == 2 + assert token + + assert token.tokens[0] is timeout_token + assert isinstance(token.tokens[0], TimeoutToken) + assert token.tokens[0].timeout == 1 + + assert token.tokens[1] is condition_token + assert isinstance(token.tokens[1], ConditionToken) + + +def test_sum_of_not_temp_condition_token_and_not_temp_timeout_token_throw_temp_simple_tokens(): + timeout_token = TimeoutToken(1) + condition_token = ConditionToken(lambda: False) + token = SimpleToken(condition_token) + SimpleToken(timeout_token) + + assert isinstance(token, SimpleToken) + assert len(token.tokens) == 2 + assert token + + assert token.tokens[0] is condition_token + assert isinstance(token.tokens[0], ConditionToken) + + assert token.tokens[1] is timeout_token + assert isinstance(token.tokens[1], TimeoutToken) + assert token.tokens[1].timeout == 1