Coverage for src/sensai/util/helper.py: 73%
37 statements
« prev ^ index » next coverage.py v7.6.1, created at 2024-11-29 18:29 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2024-11-29 18:29 +0000
1"""
2This module contains various helper functions.
3"""
4import math
5from typing import Any, Sequence, Union, TypeVar, List, Optional, Dict, Container, Iterable
7T = TypeVar("T")
10def count_none(*args: Any) -> int:
11 """
12 Counts the number of arguments that are None
14 :param args: various arguments
15 :return: the number of arguments that are None
16 """
17 c = 0
18 for a in args:
19 if a is None:
20 c += 1
21 return c
24def count_not_none(*args: Any) -> int:
25 """
26 Counts the number of arguments that are not None
28 :param args: various arguments
29 :return: the number of arguments that are not None
30 """
31 return len(args) - count_none(*args)
34def any_none(*args: Any) -> bool:
35 """
36 :param args: various arguments
37 :return: True if any of the arguments are None, False otherwise
38 """
39 return count_none(*args) > 0
42def all_none(*args: Any) -> bool:
43 """
44 :param args: various arguments
45 :return: True if all of the arguments are None, False otherwise
46 """
47 return count_none(*args) == len(args)
50def check_not_nan_dict(d: dict):
51 """
52 Raises ValueError if any of the values in the given dictionary are NaN, reporting the respective keys
54 :param d: a dictionary mapping to floats that are to be checked for NaN
55 """
56 invalid_keys = [k for k, v in d.items() if math.isnan(v)]
57 if len(invalid_keys) > 0:
58 raise ValueError(f"Got one or more NaN values: {invalid_keys}")
61def contains_any(container: Union[Container, Iterable], items: Sequence) -> bool:
62 for item in items:
63 if item in container:
64 return True
65 return False
68# noinspection PyUnusedLocal
69def mark_used(*args):
70 """
71 Utility function to mark identifiers as used.
72 The function does nothing.
74 :param args: pass identifiers that shall be marked as used here
75 """
76 pass
79def flatten_arguments(args: Sequence[Union[T, Sequence[T]]]) -> List[T]:
80 """
81 Main use case is to support both interfaces of the type f(T1, T2, ...) and f([T1, T2, ...]) simultaneously.
82 It is assumed that if the latter form is passed, the arguments are either in a list or a tuple. Moreover,
83 T cannot be a tuple or a list itself.
85 Overall this function is not all too safe and one should be aware of what one is doing when using it
86 """
87 result = []
88 for arg in args:
89 if isinstance(arg, list) or isinstance(arg, tuple):
90 result.extend(arg)
91 else:
92 result.append(arg)
93 return result
96def kwarg_if_not_none(arg_name: str, arg_value: Any) -> Dict[str, Any]:
97 """
98 Supports the optional passing of a kwarg, returning a non-empty dictionary with the kwarg only
99 if the value is not None.
101 This can be helpful to improve backward compatibility for cases where a kwarg was added later
102 but old implementations weren't updated to have it, such that an exception will be raised only
103 if the kwarg is actually used.
105 :param arg_name: the argument name
106 :param arg_value: the value
107 :return: a dictionary containing the kwarg or, if the value is None, an empty dictionary
108 """
109 if arg_value is None:
110 return {}
111 else:
112 return {arg_name: arg_value}