summaryrefslogtreecommitdiff
path: root/startop/scripts/app_startup/lib/args_utils.py
diff options
context:
space:
mode:
authorXin Li <delphij@google.com>2020-08-31 21:21:38 -0700
committerXin Li <delphij@google.com>2020-08-31 21:21:38 -0700
commit628590d7ec80e10a3fc24b1c18a1afb55cca10a8 (patch)
tree4b1c3f52d86d7fb53afbe9e9438468588fa489f8 /startop/scripts/app_startup/lib/args_utils.py
parentb11b8ec3aec8bb42f2c07e1c5ac7942da293baa8 (diff)
parentd2d3a20624d968199353ccf6ddbae6f3ac39c9af (diff)
Merge Android R (rvc-dev-plus-aosp-without-vendor@6692709)
Bug: 166295507 Merged-In: I3d92a6de21a938f6b352ec26dc23420c0fe02b27 Change-Id: Ifdb80563ef042738778ebb8a7581a97c4e3d96e2
Diffstat (limited to 'startop/scripts/app_startup/lib/args_utils.py')
-rw-r--r--startop/scripts/app_startup/lib/args_utils.py77
1 files changed, 77 insertions, 0 deletions
diff --git a/startop/scripts/app_startup/lib/args_utils.py b/startop/scripts/app_startup/lib/args_utils.py
new file mode 100644
index 000000000000..080f3b53157b
--- /dev/null
+++ b/startop/scripts/app_startup/lib/args_utils.py
@@ -0,0 +1,77 @@
+import itertools
+import os
+import sys
+from typing import Any, Callable, Dict, Iterable, List, NamedTuple, Tuple, \
+ TypeVar, Optional
+
+# local import
+sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(
+ os.path.abspath(__file__)))))
+import lib.print_utils as print_utils
+
+T = TypeVar('T')
+NamedTupleMeta = Callable[
+ ..., T] # approximation of a (S : NamedTuple<T> where S() == T) metatype.
+FilterFuncType = Callable[[NamedTuple], bool]
+
+def dict_lookup_any_key(dictionary: dict, *keys: List[Any]):
+ for k in keys:
+ if k in dictionary:
+ return dictionary[k]
+
+
+ print_utils.debug_print("None of the keys {} were in the dictionary".format(
+ keys))
+ return [None]
+
+def generate_run_combinations(named_tuple: NamedTupleMeta[T],
+ opts_dict: Dict[str, List[Optional[object]]],
+ loop_count: int = 1) -> Iterable[T]:
+ """
+ Create all possible combinations given the values in opts_dict[named_tuple._fields].
+
+ :type T: type annotation for the named_tuple type.
+ :param named_tuple: named tuple type, whose fields are used to make combinations for
+ :param opts_dict: dictionary of keys to value list. keys correspond to the named_tuple fields.
+ :param loop_count: number of repetitions.
+ :return: an iterable over named_tuple instances.
+ """
+ combinations_list = []
+ for k in named_tuple._fields:
+ # the key can be either singular or plural , e.g. 'package' or 'packages'
+ val = dict_lookup_any_key(opts_dict, k, k + "s")
+
+ # treat {'x': None} key value pairs as if it was [None]
+ # otherwise itertools.product throws an exception about not being able to iterate None.
+ combinations_list.append(val or [None])
+
+ print_utils.debug_print("opts_dict: ", opts_dict)
+ print_utils.debug_print_nd("named_tuple: ", named_tuple)
+ print_utils.debug_print("combinations_list: ", combinations_list)
+
+ for i in range(loop_count):
+ for combo in itertools.product(*combinations_list):
+ yield named_tuple(*combo)
+
+def filter_run_combinations(named_tuple: NamedTuple,
+ filters: List[FilterFuncType]) -> bool:
+ for filter in filters:
+ if filter(named_tuple):
+ return False
+ return True
+
+def generate_group_run_combinations(run_combinations: Iterable[NamedTuple],
+ dst_nt: NamedTupleMeta[T]) \
+ -> Iterable[Tuple[T, Iterable[NamedTuple]]]:
+ def group_by_keys(src_nt):
+ src_d = src_nt._asdict()
+ # now remove the keys that aren't legal in dst.
+ for illegal_key in set(src_d.keys()) - set(dst_nt._fields):
+ if illegal_key in src_d:
+ del src_d[illegal_key]
+
+ return dst_nt(**src_d)
+
+ for args_list_it in itertools.groupby(run_combinations, group_by_keys):
+ (group_key_value, args_it) = args_list_it
+ yield (group_key_value, args_it)