Coverage for src / toolbox_python / checkers.py: 100%
94 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-02 22:56 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-02 22:56 +0000
1# ============================================================================ #
2# #
3# Title: Checkers #
4# Purpose: Check certain values against other objects. #
5# #
6# ============================================================================ #
9# ---------------------------------------------------------------------------- #
10# #
11# Overview ####
12# #
13# ---------------------------------------------------------------------------- #
16# ---------------------------------------------------------------------------- #
17# Description ####
18# ---------------------------------------------------------------------------- #
21"""
22!!! note "Summary"
23 This module provides functions to check certain values against other objects. It includes type checking, value validation, and membership checks.
24"""
27# ---------------------------------------------------------------------------- #
28# #
29# Setup ####
30# #
31# ---------------------------------------------------------------------------- #
34## --------------------------------------------------------------------------- #
35## Imports ####
36## --------------------------------------------------------------------------- #
39# ## Python StdLib Imports ----
40import operator
41from collections.abc import Collection
42from typing import Any, Callable, Union, overload
44# ## Python Third Party Imports ----
45from typeguard import typechecked
48## --------------------------------------------------------------------------- #
49## Exports ####
50## --------------------------------------------------------------------------- #
53__all__: list[str] = [
54 "OPERATORS",
55 "is_value_of_type",
56 "is_all_values_of_type",
57 "is_any_values_of_type",
58 "is_value_in_iterable",
59 "is_all_values_in_iterable",
60 "is_any_values_in_iterable",
61 "is_valid_value",
62 "is_type",
63 "is_all_type",
64 "is_any_type",
65 "is_in",
66 "is_any_in",
67 "is_all_in",
68 "is_valid",
69 "assert_value_of_type",
70 "assert_all_values_of_type",
71 "assert_any_values_of_type",
72 "assert_value_in_iterable",
73 "assert_any_values_in_iterable",
74 "assert_all_values_in_iterable",
75 "assert_is_valid_value",
76 "assert_type",
77 "assert_is_type",
78 "assert_all_type",
79 "assert_all_is_type",
80 "assert_any_type",
81 "assert_any_is_type",
82 "assert_in",
83 "assert_any_in",
84 "assert_all_in",
85 "assert_is_valid",
86 "any_element_contains",
87 "all_elements_contains",
88 "get_elements_containing",
89]
92## --------------------------------------------------------------------------- #
93## Constants ####
94## --------------------------------------------------------------------------- #
97OPERATORS: dict[str, Callable[[Any, Any], bool]] = {
98 "<": operator.lt,
99 "<=": operator.le,
100 ">": operator.gt,
101 ">=": operator.ge,
102 "==": operator.eq,
103 "!=": operator.ne,
104 "in": lambda a, b: operator.contains(b, a),
105 "not in": lambda a, b: not operator.contains(b, a),
106 "is": operator.is_,
107 "is not": operator.is_not,
108}
111# ---------------------------------------------------------------------------- #
112# #
113# Main Section ####
114# #
115# ---------------------------------------------------------------------------- #
118## --------------------------------------------------------------------------- #
119## `is_*()` functions ####
120## --------------------------------------------------------------------------- #
123@overload
124def is_value_of_type(value: Any, check_type: type) -> bool: ...
125@overload
126def is_value_of_type(value: Any, check_type: Collection[type]) -> bool: ...
127def is_value_of_type(value: Any, check_type: Union[type, Collection[type]]) -> bool:
128 """
129 !!! note "Summary"
130 Check if a given value is of a specified type or types.
132 ???+ abstract "Details"
133 This function is used to verify if a given value matches a specified type or any of the types in a tuple of types.
135 Params:
136 value (Any):
137 The value to check.
138 check_type (Union[type, Collection[type]]):
139 The type or Collection of types to check against.
141 Returns:
142 (bool):
143 `#!py True` if the value is of the specified type or one of the specified types; `#!py False` otherwise.
145 ???+ example "Examples"
147 Check if a value is of a specific type:
149 ```pycon {.py .python linenums="1" title="Prepare data"}
150 >>> from toolbox_python.checkers import is_value_of_type
151 >>> value = 42
152 >>> check_type = int
153 ```
155 ```pycon {.py .python linenums="1" title="Example 1: Check if value is of type `#!py int`"}
156 >>> is_value_of_type(value, check_type)
157 ```
158 <div class="result" markdown>
159 ```{.sh .shell title="Output"}
160 True
161 ```
162 !!! success "Conclusion: The value is of type `#!py int`."
163 </div>
165 ```pycon {.py .python linenums="1" title="Example 2: Check if value is of type `#!py str`"}
166 >>> is_value_of_type(value, str)
167 ```
168 <div class="result" markdown>
169 ```{.sh .shell title="Output"}
170 False
171 ```
172 !!! failure "Conclusion: The value is not of type `#!py str`."
173 </div>
175 ??? tip "See Also"
176 - [`is_value_of_type()`][toolbox_python.checkers.is_value_of_type]
177 - [`is_type()`][toolbox_python.checkers.is_type]
178 """
179 check_type = tuple(check_type) if not isinstance(check_type, type) else check_type
180 return isinstance(value, check_type)
183@overload
184def is_all_values_of_type(values: Collection[Any], check_type: type) -> bool: ...
185@overload
186def is_all_values_of_type(values: Collection[Any], check_type: Collection[type]) -> bool: ...
187def is_all_values_of_type(values: Collection[Any], check_type: Union[type, Collection[type]]) -> bool:
188 """
189 !!! note "Summary"
190 Check if all values in an iterable are of a specified type or types.
192 ???+ abstract "Details"
193 This function is used to verify if all values in a given iterable match a specified type or any of the types in a tuple of types.
195 Params:
196 values (Collection[Any]):
197 The iterable containing values to check.
198 check_type (Union[type, Collection[type]]):
199 The type or Collection of types to check against.
201 Returns:
202 (bool):
203 `#!py True` if all values are of the specified type or one of the specified types; `#!py False` otherwise.
205 ???+ example "Examples"
207 Check if all values in an iterable are of a specific type:
209 ```pycon {.py .python linenums="1" title="Prepare data"}
210 >>> from toolbox_python.checkers import is_all_values_of_type
211 >>> values = [1, 2, 3]
212 >>> check_type = int
213 ```
215 ```pycon {.py .python linenums="1" title="Example 1: Check if all values are of type `#!py int`"}
216 >>> is_all_values_of_type(values, check_type)
217 ```
218 <div class="result" markdown>
219 ```{.sh .shell title="Output"}
220 True
221 ```
222 !!! success "Conclusion: All values are of type `#!py int`."
223 </div>
225 ```pycon {.py .python linenums="1" title="Example 2: Check if all values are of type `#!py str`"}
226 >>> is_all_values_of_type(values, str)
227 ```
228 <div class="result" markdown>
229 ```{.sh .shell title="Output"}
230 False
231 ```
232 !!! failure "Conclusion: Not all values are of type `#!py str`."
233 </div>
235 ??? tip "See Also"
236 - [`is_value_of_type()`][toolbox_python.checkers.is_value_of_type]
237 - [`is_all_values_of_type()`][toolbox_python.checkers.is_all_values_of_type]
238 - [`is_type()`][toolbox_python.checkers.is_type]
239 - [`is_all_type()`][toolbox_python.checkers.is_all_type]
240 """
241 check_type = tuple(check_type) if not isinstance(check_type, type) else check_type
242 return all(isinstance(value, check_type) for value in values)
245@overload
246def is_any_values_of_type(values: Collection[Any], check_type: type) -> bool: ...
247@overload
248def is_any_values_of_type(values: Collection[Any], check_type: Collection[type]) -> bool: ...
249def is_any_values_of_type(values: Collection[Any], check_type: Union[type, Collection[type]]) -> bool:
250 """
251 !!! note "Summary"
252 Check if any value in an iterable is of a specified type or types.
254 ???+ abstract "Details"
255 This function is used to verify if any value in a given iterable matches a specified type or any of the types in a tuple of types.
257 Params:
258 values (Collection[Any]):
259 The iterable containing values to check.
260 check_type (Union[type, Collection[type]]):
261 The type or Collection of types to check against.
263 Returns:
264 (bool):
265 `#!py True` if any value is of the specified type or one of the specified types; `#!py False` otherwise.
267 ???+ example "Examples"
269 Check if any value in an iterable is of a specific type:
271 ```pycon {.py .python linenums="1" title="Prepare data"}
272 >>> from toolbox_python.checkers import is_any_values_of_type
273 >>> values = [1, "a", 3.0]
274 >>> check_type = str
275 ```
277 ```pycon {.py .python linenums="1" title="Example 1: Check if any value is of type `#!py str`"}
278 >>> is_any_values_of_type(values, check_type)
279 ```
280 <div class="result" markdown>
281 ```{.sh .shell title="Output"}
282 True
283 ```
284 !!! success "Conclusion: At least one value is of type `#!py str`."
285 </div>
287 ```pycon {.py .python linenums="1" title="Example 2: Check if any value is of type `#!py dict`"}
288 >>> is_any_values_of_type(values, dict)
289 ```
290 <div class="result" markdown>
291 ```{.sh .shell title="Output"}
292 False
293 ```
294 !!! failure "Conclusion: No values are of type `#!py dict`."
295 </div>
297 ??? tip "See Also"
298 - [`is_value_of_type()`][toolbox_python.checkers.is_value_of_type]
299 - [`is_any_values_of_type()`][toolbox_python.checkers.is_any_values_of_type]
300 - [`is_type()`][toolbox_python.checkers.is_type]
301 - [`is_any_type()`][toolbox_python.checkers.is_any_type]
302 """
303 check_type = tuple(check_type) if not isinstance(check_type, type) else check_type
304 return any(isinstance(value, check_type) for value in values)
307@typechecked
308def is_value_in_iterable(value: Any, iterable: Collection[Any]) -> bool:
309 """
310 !!! note "Summary"
311 Check if a given value is present in an iterable.
313 ???+ abstract "Details"
314 This function is used to verify if a given value exists within an iterable such as a list, tuple, or set.
316 Params:
317 value (Any):
318 The value to check.
319 iterable (Collection[Any]):
320 The iterable to check within.
322 Raises:
323 (TypeCheckError):
324 If any of the inputs parsed to the parameters of this function are not the correct type. Uses the [`@typeguard.typechecked`](https://typeguard.readthedocs.io/en/stable/api.html#typeguard.typechecked) decorator.
326 Returns:
327 (bool):
328 `#!py True` if the value is found in the iterable; `#!py False` otherwise.
330 ???+ example "Examples"
332 Check if a value is in an iterable:
334 ```pycon {.py .python linenums="1" title="Prepare data"}
335 >>> from toolbox_python.checkers import is_value_in_iterable
336 >>> value = 2
337 >>> iterable = [1, 2, 3]
338 ```
340 ```pycon {.py .python linenums="1" title="Example 1: Check if value is in the iterable"}
341 >>> is_value_in_iterable(value, iterable)
342 ```
343 <div class="result" markdown>
344 ```{.sh .shell title="Output"}
345 True
346 ```
347 !!! success "Conclusion: The value is in the iterable."
348 </div>
350 ```pycon {.py .python linenums="1" title="Example 2: Check if value is not in the iterable"}
351 >>> is_value_in_iterable(4, iterable)
352 ```
353 <div class="result" markdown>
354 ```{.sh .shell title="Output"}
355 False
356 ```
357 !!! failure "Conclusion: The value is not in the iterable."
358 </div>
360 ??? tip "See Also"
361 - [`is_value_in_iterable()`][toolbox_python.checkers.is_value_in_iterable]
362 - [`is_in()`][toolbox_python.checkers.is_in]
363 """
364 return value in iterable
367@typechecked
368def is_all_values_in_iterable(values: Collection[Any], iterable: Collection[Any]) -> bool:
369 """
370 !!! note "Summary"
371 Check if all values in an iterable are present in another iterable.
373 ???+ abstract "Details"
374 This function is used to verify if all values in a given iterable exist within another iterable.
376 Params:
377 values (Collection[Any]):
378 The iterable containing values to check.
379 iterable (Collection[Any]):
380 The iterable to check within.
382 Raises:
383 (TypeCheckError):
384 If any of the inputs parsed to the parameters of this function are not the correct type. Uses the [`@typeguard.typechecked`](https://typeguard.readthedocs.io/en/stable/api.html#typeguard.typechecked) decorator.
386 Returns:
387 (bool):
388 `#!py True` if all values are found in the iterable; `#!py False` otherwise.
390 ???+ example "Examples"
392 Check if all values in an iterable are present in another iterable:
394 ```pycon {.py .python linenums="1" title="Prepare data"}
395 >>> from toolbox_python.checkers import is_all_values_in_iterable
396 >>> values = [1, 2]
397 >>> iterable = [1, 2, 3]
398 ```
400 ```pycon {.py .python linenums="1" title="Example 1: Check if all values are in the iterable"}
401 >>> is_all_values_in_iterable(values, iterable)
402 ```
403 <div class="result" markdown>
404 ```{.sh .shell title="Output"}
405 True
406 ```
407 !!! success "Conclusion: All values are in the iterable."
408 </div>
410 ```pycon {.py .python linenums="1" title="Example 2: Check if all values are not in the iterable"}
411 >>> is_all_values_in_iterable([1, 4], iterable)
412 ```
413 <div class="result" markdown>
414 ```{.sh .shell title="Output"}
415 False
416 ```
417 !!! failure "Conclusion: Not all values are in the iterable."
418 </div>
420 ??? tip "See Also"
421 - [`is_value_in_iterable()`][toolbox_python.checkers.is_value_in_iterable]
422 - [`is_all_values_of_type()`][toolbox_python.checkers.is_all_values_of_type]
423 - [`is_in()`][toolbox_python.checkers.is_in]
424 - [`is_all_in()`][toolbox_python.checkers.is_all_in]
425 """
426 return all(value in iterable for value in values)
429@typechecked
430def is_any_values_in_iterable(values: Collection[Any], iterable: Collection[Any]) -> bool:
431 """
432 !!! note "Summary"
433 Check if any value in an iterable is present in another iterable.
435 ???+ abstract "Details"
436 This function is used to verify if any value in a given iterable exists within another iterable.
438 Params:
439 values (Collection[Any]):
440 The iterable containing values to check.
441 iterable (Collection[Any]):
442 The iterable to check within.
444 Raises:
445 (TypeCheckError):
446 If any of the inputs parsed to the parameters of this function are not the correct type. Uses the [`@typeguard.typechecked`](https://typeguard.readthedocs.io/en/stable/api.html#typeguard.typechecked) decorator.
448 Returns:
449 (bool):
450 `#!py True` if any value is found in the iterable; `#!py False` otherwise.
452 ???+ example "Examples"
454 Check if any value in an iterable is present in another iterable:
456 ```pycon {.py .python linenums="1" title="Prepare data"}
457 >>> from toolbox_python.checkers import is_any_values_in_iterable
458 >>> values = [1, 4]
459 >>> iterable = [1, 2, 3]
460 ```
462 ```pycon {.py .python linenums="1" title="Example 1: Check if any value is in the iterable"}
463 >>> is_any_values_in_iterable(values, iterable)
464 ```
465 <div class="result" markdown>
466 ```{.sh .shell title="Output"}
467 True
468 ```
469 !!! success "Conclusion: At least one value is in the iterable."
470 </div>
472 ```pycon {.py .python linenums="1" title="Example 2: Check if any value is not in the iterable"}
473 >>> is_any_values_in_iterable([4, 5], iterable)
474 ```
475 <div class="result" markdown>
476 ```{.sh .shell title="Output"}
477 False
478 ```
479 !!! failure "Conclusion: None of the values are in the iterable."
480 </div>
482 ??? tip "See Also"
483 - [`is_value_in_iterable()`][toolbox_python.checkers.is_value_in_iterable]
484 - [`is_any_values_of_type()`][toolbox_python.checkers.is_any_values_of_type]
485 - [`is_in()`][toolbox_python.checkers.is_in]
486 - [`is_any_in()`][toolbox_python.checkers.is_any_in]
487 """
488 return any(value in iterable for value in values)
491def is_valid_value(value: Any, op: str, target: Any) -> bool:
492 """
493 !!! note "Summary"
494 Check if a value is valid based on a specified operator and target.
496 ???+ abstract "Details"
497 This function checks if a given value meets a condition defined by an operator when compared to a target value. The operator can be one of the predefined operators in the [`OPERATORS`][toolbox_python.checkers.OPERATORS] dictionary.
499 Params:
500 value (Any):
501 The value to check.
502 op (str):
503 The operator to use for comparison. Valid operators are defined in the [`OPERATORS`][toolbox_python.checkers.OPERATORS] dictionary.
504 target (Any):
505 The target value to compare against.
507 Raises:
508 (ValueError):
509 If the operator is not recognized or is not valid.
511 Returns:
512 (bool):
513 `#!py True` if the value meets the condition defined by the operator and target; `#!py False` otherwise.
515 ???+ example "Examples"
517 Check if a value is valid based on an operator and target:
519 ```pycon {.py .python linenums="1" title="Prepare data"}
520 >>> from toolbox_python.checkers import is_valid_value
521 ```
523 ```pycon {.py .python linenums="1" title="Example 1: Check if value is greater than target"}
524 >>> is_valid_value(5, ">", 3)
525 ```
526 <div class="result" markdown>
527 ```{.sh .shell title="Output"}
528 True
529 ```
530 !!! success "Conclusion: The value is greater than the target."
531 </div>
533 ```pycon {.py .python linenums="1" title="Example 2: Check if value is less than or equal to target"}
534 >>> is_valid_value(5, "<=", 3)
535 ```
536 <div class="result" markdown>
537 ```{.sh .shell title="Output"}
538 False
539 ```
540 !!! failure "Conclusion: The value is not less than or equal to the target."
541 </div>
542 """
543 if op not in OPERATORS:
544 raise ValueError(f"Unknown operator '{op}'. Valid operators are: {list(OPERATORS.keys())}")
545 op_func: Callable[[Any, Any], bool] = OPERATORS[op]
546 return op_func(value, target)
549### Aliases ----
550is_type: Callable[..., bool] = is_value_of_type
551is_all_type: Callable[..., bool] = is_all_values_of_type
552is_any_type: Callable[..., bool] = is_any_values_of_type
553is_in: Callable[..., bool] = is_value_in_iterable
554is_any_in: Callable[..., bool] = is_any_values_in_iterable
555is_all_in: Callable[..., bool] = is_all_values_in_iterable
556is_valid: Callable[..., bool] = is_valid_value
559## --------------------------------------------------------------------------- #
560## `assert_*()` functions ####
561## --------------------------------------------------------------------------- #
564@overload
565def assert_value_of_type(value: Any, check_type: type) -> None: ...
566@overload
567def assert_value_of_type(value: Any, check_type: Collection[type]) -> None: ...
568def assert_value_of_type(value: Any, check_type: Union[type, Collection[type]]) -> None:
569 """
570 !!! note "Summary"
571 Assert that a given value is of a specified type or types.
573 ???+ abstract "Details"
574 This function is used to assert that a given value matches a specified type or any of the types in a tuple of types. If the value does not match the specified type(s), a `#!py TypeError` is raised.
576 Params:
577 value (Any):
578 The value to check.
579 check_type (Union[type, Collection[type]]):
580 The type or Collection of types to check against.
582 Raises:
583 (TypeError):
584 If the value is not of the specified type or one of the specified types.
586 Returns:
587 (None):
588 This function does not return a value. It raises an exception if the assertion fails.
590 ???+ example "Examples"
592 Assert that a value is of a specific type:
594 ```pycon {.py .python linenums="1" title="Prepare data"}
595 >>> from toolbox_python.checkers import assert_value_of_type
596 >>> value = 42
597 >>> check_type = int
598 ```
600 ```pycon {.py .python linenums="1" title="Example 1: Assert that value is of type int"}
601 >>> assert_value_of_type(value, check_type)
602 ```
603 <div class="result" markdown>
604 ```{.sh .shell title="Output"}
605 (no output, no exception raised)
606 ```
607 !!! success "Conclusion: The value is of type `#!py int`."
608 </div>
610 ```pycon {.py .python linenums="1" title="Example 2: Assert that value is of type str"}
611 >>> assert_value_of_type(value, str)
612 ```
613 <div class="result" markdown>
614 ```{.sh .shell title="Output"}
615 TypeError: Value '42' is not correct type: 'int'. Must be: 'str'
616 ```
617 !!! failure "Conclusion: The value is not of type `#!py str`."
618 </div>
620 ```pycon {.py .python linenums="1" title="Example 3: Assert that value is of type int or float"}
621 >>> assert_value_of_type(value, (int, float))
622 ```
623 <div class="result" markdown>
624 ```{.sh .shell title="Output"}
625 (no output, no exception raised)
626 ```
627 !!! success "Conclusion: The value is of type `#!py int` or `#!py float`."
628 </div>
630 ```pycon {.py .python linenums="1" title="Example 4: Assert that value is of type str or dict"}
631 >>> assert_value_of_type(value, (str, dict))
632 ```
633 <div class="result" markdown>
634 ```{.sh .shell title="Output"}
635 TypeError: Value '42' is not correct type: 'int'. Must be: 'str' or 'dict'.
636 ```
637 !!! failure "Conclusion: The value is not of type `#!py str` or `#!py dict`."
638 </div>
640 ??? tip "See Also"
641 - [`is_value_of_type()`][toolbox_python.checkers.is_value_of_type]
642 - [`is_type()`][toolbox_python.checkers.is_type]
643 """
644 if not is_type(value=value, check_type=check_type):
645 msg: str = f"Value '{value}' is not correct type: '{type(value).__name__}'. "
646 if isinstance(check_type, type):
647 msg += f"Must be: '{check_type.__name__}'."
648 else:
649 msg += f"Must be: '{' or '.join([typ.__name__ for typ in check_type])}'."
650 raise TypeError(msg)
653@overload
654def assert_all_values_of_type(values: Collection[Any], check_type: type) -> None: ...
655@overload
656def assert_all_values_of_type(values: Collection[Any], check_type: Collection[type]) -> None: ...
657def assert_all_values_of_type(values: Collection[Any], check_type: Union[type, Collection[type]]) -> None:
658 """
659 !!! note "Summary"
660 Assert that all values in an iterable are of a specified type or types.
662 ???+ abstract "Details"
663 This function is used to assert that all values in a given iterable match a specified type or any of the types in a tuple of types. If any value does not match the specified type(s), a `#!py TypeError` is raised.
665 Params:
666 values (Collection[Any]):
667 The iterable containing values to check.
668 check_type (Union[type, Collection[type]]):
669 The type or Collection of types to check against.
671 Raises:
672 (TypeError):
673 If any value is not of the specified type or one of the specified types.
675 Returns:
676 (None):
677 This function does not return a value. It raises an exception if the assertion fails.
679 ???+ example "Examples"
681 Assert that all values in an iterable are of a specific type:
683 ```pycon {.py .python linenums="1" title="Prepare data"}
684 >>> from toolbox_python.checkers import assert_all_values_of_type
685 >>> values = [1, 2, 3]
686 >>> check_type = int
687 ```
689 ```pycon {.py .python linenums="1" title="Example 1: Assert that all values are of type int"}
690 >>> assert_all_values_of_type(values, check_type)
691 ```
692 <div class="result" markdown>
693 ```{.sh .shell title="Output"}
694 (no output, no exception raised)
695 ```
696 !!! success "Conclusion: All values are of type `#!py int`."
697 </div>
699 ```pycon {.py .python linenums="1" title="Example 2: Assert that all values are of type str"}
700 >>> assert_all_values_of_type(values, str)
701 ```
702 <div class="result" markdown>
703 ```{.sh .shell title="Output"}
704 TypeError: Some elements [1, 2, 3] have the incorrect type ['int', 'int', 'int']. Must be 'str'
705 ```
706 !!! failure "Conclusion: Not all values are of type `#!py str`."
707 </div>
709 ```pycon {.py .python linenums="1" title="Example 3: Assert that all values are of type int or float"}
710 >>> assert_all_values_of_type(values, (int, float))
711 ```
712 <div class="result" markdown>
713 ```{.sh .shell title="Output"}
714 (no output, no exception raised)
715 ```
716 !!! success "Conclusion: All values are of type `#!py int` or `#!py float`."
717 </div>
719 ```pycon {.py .python linenums="1" title="Example 4: Assert that all values are of type str or dict"}
720 >>> assert_all_values_of_type(values, (str, dict))
721 ```
722 <div class="result" markdown>
723 ```{.sh .shell title="Output"}
724 TypeError: Some elements [1, 2, 3] have the incorrect type ['int', 'int', 'int']. Must be: 'str' or 'dict'
725 ```
726 !!! failure "Conclusion: Not all values are of type `#!py str` or `#!py dict`."
727 </div>
729 ??? tip "See Also"
730 - [`is_value_of_type()`][toolbox_python.checkers.is_value_of_type]
731 - [`is_all_values_of_type()`][toolbox_python.checkers.is_all_values_of_type]
732 - [`is_type()`][toolbox_python.checkers.is_type]
733 - [`is_all_type()`][toolbox_python.checkers.is_all_type]
734 """
735 if not is_all_type(values=values, check_type=check_type):
736 invalid_values: list[Any] = [value for value in values if not is_type(value, check_type)]
737 invalid_types: list[str] = [f"'{type(value).__name__}'" for value in values if not is_type(value, check_type)]
738 msg: str = f"Some elements {invalid_values} have the incorrect type {invalid_types}. "
739 if isinstance(check_type, type):
740 msg += f"Must be '{check_type.__name__}'"
741 else:
742 types: list[str] = [f"'{typ.__name__}'" for typ in check_type]
743 msg += f"Must be: {' or '.join(types)}"
744 raise TypeError(msg)
747@overload
748def assert_any_values_of_type(values: Collection[Any], check_type: type) -> None: ...
749@overload
750def assert_any_values_of_type(values: Collection[Any], check_type: Collection[type]) -> None: ...
751def assert_any_values_of_type(values: Collection[Any], check_type: Union[type, Collection[type]]) -> None:
752 """
753 !!! note "Summary"
754 Assert that any value in an iterable is of a specified type or types.
756 ???+ abstract "Details"
757 This function is used to assert that at least one value in a given iterable matches a specified type or any of the types in a tuple of types. If none of the values match the specified type(s), a `#!py TypeError` is raised.
759 Params:
760 values (Collection[Any]):
761 The iterable containing values to check.
762 check_type (Union[type, Collection[type]]):
763 The type or Collection of types to check against.
765 Raises:
766 (TypeError):
767 If none of the values are of the specified type or one of the specified types.
769 Returns:
770 (None):
771 This function does not return a value. It raises an exception if the assertion fails.
773 ???+ example "Examples"
775 Assert that any value in an iterable is of a specific type:
777 ```pycon {.py .python linenums="1" title="Prepare data"}
778 >>> from toolbox_python.checkers import assert_any_values_of_type
779 >>> values = [1, "a", 3.0]
780 >>> check_type = str
781 ```
783 ```pycon {.py .python linenums="1" title="Example 1: Assert that any value is of type str"}
784 >>> assert_any_values_of_type(values, check_type)
785 ```
786 <div class="result" markdown>
787 ```{.sh .shell title="Output"}
788 (no output, no exception raised)
789 ```
790 !!! success "Conclusion: At least one value is of type `#!py str`."
791 </div>
793 ```pycon {.py .python linenums="1" title="Example 2: Assert that any value is of type dict"}
794 >>> assert_any_values_of_type(values, dict)
795 ```
796 <div class="result" markdown>
797 ```{.sh .shell title="Output"}
798 TypeError: None of the elements in [1, 'a', 3.0] have the correct type. Must be: 'dict'
799 ```
800 !!! failure "Conclusion: None of the values are of type `#!py dict`."
801 </div>
803 ```pycon {.py .python linenums="1" title="Example 3: Assert that any value is of type int or float"}
804 >>> assert_any_values_of_type(values, (int, float))
805 ```
806 <div class="result" markdown>
807 ```{.sh .shell title="Output"}
808 (no output, no exception raised)
809 ```
810 !!! success "Conclusion: At least one value is of type `#!py int` or `#!py float`."
811 </div>
813 ```pycon {.py .python linenums="1" title="Example 4: Assert that any value is of type dict or list"}
814 >>> assert_any_values_of_type(values, (dict, list))
815 ```
816 <div class="result" markdown>
817 ```{.sh .shell title="Output"}
818 TypeError: None of the elements in [1, 'a', 3.0] have the correct type. Must be: 'dict' or 'list'
819 ```
820 !!! failure "Conclusion: None of the values are of type `#!py dict` or `#!py list`."
821 </div>
823 ??? tip "See Also"
824 - [`is_value_of_type()`][toolbox_python.checkers.is_value_of_type]
825 - [`is_any_values_of_type()`][toolbox_python.checkers.is_any_values_of_type]
826 - [`is_type()`][toolbox_python.checkers.is_type]
827 - [`is_any_type()`][toolbox_python.checkers.is_any_type]
828 """
829 if not is_any_type(values=values, check_type=check_type):
830 invalid_values: list[Any] = [value for value in values if not is_type(value, check_type)]
831 msg: str = f"None of the elements in {invalid_values} have the correct type. "
832 if isinstance(check_type, type):
833 msg += f"Must be: '{check_type.__name__}'"
834 else:
835 types: list[str] = [f"'{typ.__name__}'" for typ in check_type]
836 msg += f"Must be: {' or '.join(types)}"
837 raise TypeError(msg)
840def assert_value_in_iterable(value: Any, iterable: Collection[Any]) -> None:
841 """
842 !!! note "Summary"
843 Assert that a given value is present in an iterable.
845 ???+ abstract "Details"
846 This function is used to assert that a given value exists within an iterable such as a `#!py list`, `#!py tuple`, or `#!py set`. If the value is not found in the iterable, a `#!py LookupError` is raised.
848 Params:
849 value (Any):
850 The value to check.
851 iterable (Collection[Any]):
852 The iterable to check within.
854 Raises:
855 (LookupError):
856 If the value is not found in the iterable.
858 Returns:
859 (None):
860 This function does not return a value. It raises an exception if the assertion fails.
862 ???+ example "Examples"
864 Assert that a value is in an iterable:
866 ```pycon {.py .python linenums="1" title="Prepare data"}
867 >>> from toolbox_python.checkers import assert_value_in_iterable
868 >>> value = 2
869 >>> iterable = [1, 2, 3]
870 ```
872 ```pycon {.py .python linenums="1" title="Example 1: Assert that value is in the iterable"}
873 >>> assert_value_in_iterable(value, iterable)
874 ```
875 <div class="result" markdown>
876 ```{.sh .shell title="Output"}
877 (no output, no exception raised)
878 ```
879 !!! success "Conclusion: The value is in the iterable."
880 </div>
882 ```pycon {.py .python linenums="1" title="Example 2: Assert that value is not in the iterable"}
883 >>> assert_value_in_iterable(4, iterable)
884 ```
885 <div class="result" markdown>
886 ```{.sh .shell title="Output"}
887 LookupError: Value '4' not found in iterable: [1, 2, 3]
888 ```
889 !!! failure "Conclusion: The value is not in the iterable."
890 </div>
892 ??? tip "See Also"
893 - [`is_value_in_iterable()`][toolbox_python.checkers.is_value_in_iterable]
894 - [`is_in()`][toolbox_python.checkers.is_in]
895 """
896 if not is_in(value=value, iterable=iterable):
897 raise LookupError(f"Value '{value}' not found in iterable: {iterable}")
900def assert_any_values_in_iterable(values: Collection[Any], iterable: Collection[Any]) -> None:
901 """
902 !!! note "Summary"
903 Assert that any value in an iterable is present in another iterable.
905 ???+ abstract "Details"
906 This function is used to assert that at least one value in a given iterable exists within another iterable. If none of the values are found in the iterable, a `#!py LookupError` is raised.
908 Params:
909 values (Collection[Any]):
910 The iterable containing values to check.
911 iterable (Collection[Any]):
912 The iterable to check within.
914 Raises:
915 (LookupError):
916 If none of the values are found in the iterable.
918 Returns:
919 (None):
920 This function does not return a value. It raises an exception if the assertion fails.
922 ???+ example "Examples"
924 Assert that any value in an iterable is present in another iterable:
926 ```pycon {.py .python linenums="1" title="Prepare data"}
927 >>> from toolbox_python.checkers import assert_any_values_in_iterable
928 >>> values = [1, 4]
929 >>> iterable = [1, 2, 3]
930 ```
932 ```pycon {.py .python linenums="1" title="Example 1: Assert that any value is in the iterable"}
933 >>> assert_any_values_in_iterable(values, iterable)
934 ```
935 <div class="result" markdown>
936 ```{.sh .shell title="Output"}
937 (no output, no exception raised)
938 ```
939 !!! success "Conclusion: At least one value is in the iterable."
940 </div>
942 ```pycon {.py .python linenums="1" title="Example 2: Assert that any value is not in the iterable"}
943 >>> assert_any_values_in_iterable([4, 5], iterable)
944 ```
945 <div class="result" markdown>
946 ```{.sh .shell title="Output"}
947 LookupError: None of the values in [4, 5] can be found in [1, 2, 3]
948 ```
949 !!! failure "Conclusion: None of the values are in the iterable."
950 </div>
952 ??? tip "See Also"
953 - [`is_value_in_iterable()`][toolbox_python.checkers.is_value_in_iterable]
954 - [`is_any_values_of_type()`][toolbox_python.checkers.is_any_values_of_type]
955 - [`is_in()`][toolbox_python.checkers.is_in]
956 - [`is_any_in()`][toolbox_python.checkers.is_any_in]
957 """
958 if not is_any_in(values=values, iterable=iterable):
959 raise LookupError(f"None of the values in {values} can be found in {iterable}")
962def assert_all_values_in_iterable(values: Collection[Any], iterable: Collection[Any]) -> None:
963 """
964 !!! note "Summary"
965 Assert that all values in an iterable are present in another iterable.
967 ???+ abstract "Details"
968 This function is used to assert that all values in a given iterable exist within another iterable. If any value is not found in the iterable, a `#!py LookupError` is raised.
970 Params:
971 values (Collection[Any]):
972 The iterable containing values to check.
973 iterable (Collection[Any]):
974 The iterable to check within.
976 Raises:
977 (LookupError):
978 If any value is not found in the iterable.
980 Returns:
981 (None):
982 This function does not return a value. It raises an exception if the assertion fails.
984 ???+ example "Examples"
986 Assert that all values in an iterable are present in another iterable:
988 ```pycon {.py .python linenums="1" title="Prepare data"}
989 >>> from toolbox_python.checkers import assert_all_values_in_iterable
990 >>> values = [1, 2]
991 >>> iterable = [1, 2, 3]
992 ```
994 ```pycon {.py .python linenums="1" title="Example 1: Assert that all values are in the iterable"}
995 >>> assert_all_values_in_iterable(values, iterable)
996 ```
997 <div class="result" markdown>
998 ```{.sh .shell title="Output"}
999 (no output, no exception raised)
1000 ```
1001 !!! success "Conclusion: All values are in the iterable."
1002 </div>
1004 ```pycon {.py .python linenums="1" title="Example 2: Assert that all values are not in the iterable"}
1005 >>> assert_all_values_in_iterable([1, 4], iterable)
1006 ```
1007 <div class="result" markdown>
1008 ```{.sh .shell title="Output"}
1009 LookupError: Some values [4] are missing from [1, 2, 3]
1010 ```
1011 !!! failure "Conclusion: Not all values are in the iterable."
1012 </div>
1014 ??? tip "See Also"
1015 - [`is_value_in_iterable()`][toolbox_python.checkers.is_value_in_iterable]
1016 - [`is_all_values_of_type()`][toolbox_python.checkers.is_all_values_of_type]
1017 - [`is_in()`][toolbox_python.checkers.is_in]
1018 - [`is_all_in()`][toolbox_python.checkers.is_all_in]
1019 """
1020 if not is_all_in(values=values, iterable=iterable):
1021 missing_values: list[Any] = [value for value in values if not is_in(value, iterable)]
1022 raise LookupError(f"Some values {missing_values} are missing from {iterable}")
1025def assert_is_valid_value(value: Any, op: str, target: Any) -> None:
1026 """
1027 !!! note "Summary"
1028 Assert that a value is valid based on a specified operator and target.
1030 ???+ abstract "Details"
1031 This function checks if a given value meets a condition defined by an operator when compared to a target value. The operator can be one of the predefined operators in the [`OPERATORS`][toolbox_python.checkers.OPERATORS] dictionary. If the condition is not met, a `#!py ValueError` is raised.
1033 Params:
1034 value (Any):
1035 The value to check.
1036 op (str):
1037 The operator to use for comparison. Valid operators are defined in the [`OPERATORS`][toolbox_python.checkers.OPERATORS] dictionary.
1038 target (Any):
1039 The target value to compare against.
1041 Raises:
1042 (ValueError):
1043 If the operator is not recognized or if the value does not meet the condition defined by the operator and target.
1045 Returns:
1046 (None):
1047 This function does not return a value. It raises an exception if the condition is not met.
1049 ???+ example "Examples"
1051 Assert that a value is valid based on an operator and target:
1053 ```pycon {.py .python linenums="1" title="Prepare data"}
1054 >>> from toolbox_python.checkers import assert_is_valid_value
1055 ```
1057 ```pycon {.py .python linenums="1" title="Example 1: Assert that value is greater than target"}
1058 >>> assert_is_valid_value(5, ">", 3)
1059 ```
1060 <div class="result" markdown>
1061 ```{.sh .shell title="Output"}
1062 (no output, no exception raised)
1063 ```
1064 !!! success "Conclusion: The value is greater than the target."
1065 </div>
1067 ```pycon {.py .python linenums="1" title="Example 2: Assert that value is less than or equal to target"}
1068 >>> assert_is_valid_value(5, "<=", 3)
1069 ```
1070 <div class="result" markdown>
1071 ```{.sh .shell title="Output"}
1072 ValueError: Validation failed: '5 <= 3' is not True
1073 ```
1074 !!! failure "Conclusion: The value is not less than or equal to the target."
1075 </div>
1076 """
1077 if not is_valid_value(value, op, target):
1078 raise ValueError(f"Validation failed: '{value} {op} {target}' is not True")
1081### Aliases ----
1082assert_type: Callable[..., None] = assert_value_of_type
1083assert_is_type: Callable[..., None] = assert_value_of_type
1084assert_all_type: Callable[..., None] = assert_all_values_of_type
1085assert_all_is_type: Callable[..., None] = assert_all_values_of_type
1086assert_any_type: Callable[..., None] = assert_any_values_of_type
1087assert_any_is_type: Callable[..., None] = assert_any_values_of_type
1088assert_in: Callable[..., None] = assert_value_in_iterable
1089assert_any_in: Callable[..., None] = assert_any_values_in_iterable
1090assert_all_in: Callable[..., None] = assert_all_values_in_iterable
1091assert_is_valid: Callable[..., None] = assert_is_valid_value
1094## --------------------------------------------------------------------------- #
1095## `*_contains()` functions ####
1096## --------------------------------------------------------------------------- #
1099@typechecked
1100def any_element_contains(iterable: Collection[str], check: str) -> bool:
1101 """
1102 !!! note "Summary"
1103 Check to see if any element in a given iterable contains a given string value.
1104 !!! warning "Note: This check _is_ case sensitive."
1106 ???+ abstract "Details"
1107 This function is helpful for doing a quick check to see if any element in a `#!py list` contains a given `#!py str` value. For example, checking if any column header contains a specific string value.
1109 Params:
1110 iterable (Collection[str]):
1111 The iterables to check within. Because this function uses an `#!py in` operation to check if `check` string exists in the elements of `iterable`, therefore all elements of `iterable` must be `#!py str` type.
1112 check (str):
1113 The string value to check exists in any of the elements in `iterable`.
1115 Raises:
1116 (TypeCheckError):
1117 If any of the inputs parsed to the parameters of this function are not the correct type. Uses the [`@typeguard.typechecked`](https://typeguard.readthedocs.io/en/stable/api.html#typeguard.typechecked) decorator.
1119 Returns:
1120 (bool):
1121 `#!py True` if at least one element in `iterable` contains `check` string; `#!py False` if no elements contain `check`.
1123 ???+ example "Examples"
1125 Check if any element in an iterable contains a specific string:
1127 ```pycon {.py .python linenums="1" title="Prepare data"}
1128 >>> from toolbox_python.checkers import any_element_contains
1129 >>> iterable = ["apple", "banana", "cherry"]
1130 >>> check = "an"
1131 ```
1133 ```pycon {.py .python linenums="1" title="Example 1: Check if any element contains 'an'"}
1134 >>> any_element_contains(iterable, check)
1135 ```
1136 <div class="result" markdown>
1137 ```{.sh .shell title="Output"}
1138 True
1139 ```
1140 !!! success "Conclusion: At least one element contains `'an'`."
1141 </div>
1143 ```pycon {.py .python linenums="1" title="Example 2: Check if any element contains 'xy'"}
1144 >>> any_element_contains(iterable, "xy")
1145 ```
1146 <div class="result" markdown>
1147 ```{.sh .shell title="Output"}
1148 False
1149 ```
1150 !!! failure "Conclusion: No elements contain `'xy'`."
1151 </div>
1152 """
1153 return any(check in elem for elem in iterable)
1156@typechecked
1157def all_elements_contains(iterable: Collection[str], check: str) -> bool:
1158 """
1159 !!! note "Summary"
1160 Check to see if all elements in a given iterable contains a given string value.
1161 !!! warning "Note: This check _is_ case sensitive."
1163 ???+ abstract "Details"
1164 This function is helpful for doing a quick check to see if all element in a `#!py list` contains a given `#!py str` value. For example, checking if all columns in a DataFrame contains a specific string value.
1166 Params:
1167 iterable (Collection[str]):
1168 The iterables to check within. Because this function uses an `#!py in` operation to check if `check` string exists in the elements of `iterable`, therefore all elements of `iterable` must be `#!py str` type.
1169 check (str):
1170 The string value to check exists in any of the elements in `iterable`.
1172 Raises:
1173 (TypeCheckError):
1174 If any of the inputs parsed to the parameters of this function are not the correct type. Uses the [`@typeguard.typechecked`](https://typeguard.readthedocs.io/en/stable/api.html#typeguard.typechecked) decorator.
1176 Returns:
1177 (bool):
1178 `#!py True` if all elements in `iterable` contains `check` string; `#!py False` otherwise.
1180 ???+ example "Examples"
1182 Check if all elements in an iterable contain a specific string:
1184 ```pycon {.py .python linenums="1" title="Prepare data"}
1185 >>> from toolbox_python.checkers import all_elements_contains
1186 >>> iterable = ["apple", "banana", "peach"]
1187 >>> check = "a"
1188 ```
1190 ```pycon {.py .python linenums="1" title="Example 1: Check if all elements contain 'a'"}
1191 >>> all_elements_contains(iterable, check)
1192 ```
1193 <div class="result" markdown>
1194 ```{.sh .shell title="Output"}
1195 True
1196 ```
1197 !!! success "Conclusion: All elements contain `'a'`."
1198 </div>
1200 ```pycon {.py .python linenums="1" title="Example 2: Check if all elements contain 'e'"}
1201 >>> all_elements_contains(iterable, "e")
1202 ```
1203 <div class="result" markdown>
1204 ```{.sh .shell title="Output"}
1205 False
1206 ```
1207 !!! failure "Conclusion: Not all elements contain `'e'`."
1208 </div>
1209 """
1210 return all(check in elem for elem in iterable)
1213@typechecked
1214def get_elements_containing(iterable: Collection[str], check: str) -> tuple[str, ...]:
1215 """
1216 !!! note "Summary"
1217 Extract all elements in a given iterable which contains a given string value.
1218 !!! warning "Note: This check _is_ case sensitive."
1220 Params:
1221 iterable (Collection[str]):
1222 The iterables to check within. Because this function uses an `#!py in` operation to check if `check` string exists in the elements of `iterable`, therefore all elements of `iterable` must be `#!py str` type.
1223 check (str):
1224 The string value to check exists in any of the elements in `iterable`.
1226 Raises:
1227 (TypeCheckError):
1228 If any of the inputs parsed to the parameters of this function are not the correct type. Uses the [`@typeguard.typechecked`](https://typeguard.readthedocs.io/en/stable/api.html#typeguard.typechecked) decorator.
1230 Returns:
1231 (tuple):
1232 A `#!py tuple` containing all the string elements from `iterable` which contains the `check` string.
1234 ???+ example "Examples"
1236 Extract elements in an iterable that contain a specific string:
1238 ```pycon {.py .python linenums="1" title="Prepare data"}
1239 >>> from toolbox_python.checkers import get_elements_containing
1240 >>> iterable = ["apple", "banana", "cherry"]
1241 >>> check = "an"
1242 ```
1244 ```pycon {.py .python linenums="1" title="Example 1: Extract elements containing 'an'"}
1245 >>> get_elements_containing(iterable, check)
1246 ```
1247 <div class="result" markdown>
1248 ```{.sh .shell title="Output"}
1249 ('banana',)
1250 ```
1251 !!! success "Conclusion: The element(s) containing `'an'` are extracted."
1252 </div>
1254 ```pycon {.py .python linenums="1" title="Example 2: Extract elements containing 'xy'"}
1255 >>> get_elements_containing(iterable, "xy")
1256 ```
1257 <div class="result" markdown>
1258 ```{.sh .shell title="Output"}
1259 ()
1260 ```
1261 !!! failure "Conclusion: No elements contain `'xy'`."
1262 </div>
1263 """
1264 return tuple(elem for elem in iterable if check in elem)