Skip to content

Commit

Permalink
change type of ParameterValuePair to named tuple
Browse files Browse the repository at this point in the history
- introduce new type ParameterValueSingle
- add option to remove_parameter_value_pair() remove all pairs only by given name independent of the version number
  • Loading branch information
SimeonEhrig committed Feb 7, 2024
1 parent 4b63360 commit 8d9764c
Show file tree
Hide file tree
Showing 6 changed files with 456 additions and 75 deletions.
8 changes: 7 additions & 1 deletion bashi/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@
ParameterValue = NamedTuple("ParameterValue", [("name", ValueName), ("version", ValueVersion)])
ParameterValueList: TypeAlias = List[ParameterValue]
ParameterValueMatrix: TypeAlias = OrderedDict[Parameter, ParameterValueList]
ParameterValuePair: TypeAlias = OrderedDict[Parameter, ParameterValue]
ParameterValueSingle = NamedTuple(
"ParameterValueSingle", [("parameter", Parameter), ("parameterValue", ParameterValue)]
)
ParameterValuePair = NamedTuple(
"ParameterValuePair",
[("first", ParameterValueSingle), ("second", ParameterValueSingle)],
)
ParameterValueTuple: TypeAlias = OrderedDict[Parameter, ParameterValue]
Combination: TypeAlias = OrderedDict[Parameter, ParameterValue]
CombinationList: TypeAlias = List[Combination]
Expand Down
109 changes: 92 additions & 17 deletions bashi/utils.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
"""Different helper functions for bashi"""

from typing import Dict, List, IO
from typing import Dict, List, IO, Union
from collections import OrderedDict
import dataclasses
import sys
from typeguard import typechecked
import packaging.version
from bashi.types import (
Parameter,
ParameterValue,
ParameterValueTuple,
ParameterValueSingle,
ParameterValuePair,
ParameterValueMatrix,
CombinationList,
Expand Down Expand Up @@ -104,6 +106,50 @@ def get_default_filter_chain(
)


@typechecked
def create_parameter_value_pair( # pylint: disable=too-many-arguments
parameter1: str,
value_name1: str,
value_version1: Union[int, float, str, packaging.version.Version],
parameter2: str,
value_name2: str,
value_version2: Union[int, float, str, packaging.version.Version],
) -> ParameterValuePair:
"""Create parameter-value-pair from the given arguments. Parse parameter-versions if required.
Args:
parameter1 (str): name of the first parameter
value_name1 (str): name of the first value-name
value_version1 (Union[int, float, str, packaging.version.Version]): version of first
value-version
parameter2 (str): name of the second parameter
value_name2 (str): name of the second value-name
value_version2 (Union[int, float, str, packaging.version.Version]): version of the second
value-version
Returns:
ParameterValuePair: parameter-value-pair
"""
if isinstance(value_version1, packaging.version.Version):
parsed_value_version1: packaging.version.Version = value_version1
else:
parsed_value_version1: packaging.version.Version = packaging.version.parse(
str(value_version1)
)

if isinstance(value_version2, packaging.version.Version):
parsed_value_version2: packaging.version.Version = value_version2
else:
parsed_value_version2: packaging.version.Version = packaging.version.parse(
str(value_version2)
)

return ParameterValuePair(
ParameterValueSingle(parameter1, ParameterValue(value_name1, parsed_value_version1)),
ParameterValueSingle(parameter2, ParameterValue(value_name2, parsed_value_version2)),
)


@typechecked
def get_expected_parameter_value_pairs(
parameter_matrix: ParameterValueMatrix,
Expand Down Expand Up @@ -156,35 +202,44 @@ def _loop_over_parameter_values(
"""
for v1_name, v1_version in parameters[v1_parameter]:
for v2_name, v2_version in parameters[v2_parameter]:
param_val_pair: ParameterValuePair = OrderedDict()
param_val_pair[v1_parameter] = ParameterValue(v1_name, v1_version)
param_val_pair[v2_parameter] = ParameterValue(v2_name, v2_version)
expected_pairs.append(param_val_pair)
expected_pairs.append(
create_parameter_value_pair(
v1_parameter, v1_name, v1_version, v2_parameter, v2_name, v2_version
)
)


@typechecked
def remove_parameter_value_pair(
to_remove: ParameterValuePair, parameter_value_pairs: List[ParameterValuePair]
to_remove: Union[ParameterValueSingle, ParameterValuePair],
parameter_value_pairs: List[ParameterValuePair],
all_versions: bool = False,
) -> bool:
"""Removes a parameter-value pair with one or two entries from the parameter-value-pair list. If
the parameter-value-pair only has one parameter value, all parameter-value-pairs that contain
the parameter value are removed.
Args:
to_remove (ParameterValuePair): Parameter-value-pair to remove
to_remove (Union[ParameterValueSingle, ParameterValuePair]): Parameter-value-single or
parameter-value-pair to remove
param_val_pairs (List[ParameterValuePair]): List of parameter-value-pairs. Will be modified.
all_versions (bool): If it is `True` and `to_remove` has type of `ParameterValuePair`,
removes all parameter-value-pairs witch matches the value-names independent of the
value-version. Defaults to False.
Raises:
RuntimeError: If `to_remove` 0 or more than 2 entries.
RuntimeError: If `all_versions=True` and `to_remove` is a `ParameterValueSingle`
Returns:
bool: True if entry was removed from parameter_value_pairs
"""
if len(to_remove) == 1:
if isinstance(to_remove, ParameterValueSingle):
if all_versions:
raise RuntimeError("all_versions=True is not support for ParameterValueSingle")

return _remove_single_entry_parameter_value_pair(to_remove, parameter_value_pairs)

if len(to_remove) == 0 or len(to_remove) > 2:
raise RuntimeError("More than two parameter-values are not allowed")
if all_versions:
return _remove_parameter_value_pair_all_versions(to_remove, parameter_value_pairs)

try:
parameter_value_pairs.remove(to_remove)
Expand All @@ -195,14 +250,34 @@ def remove_parameter_value_pair(

@typechecked
def _remove_single_entry_parameter_value_pair(
to_remove: ParameterValuePair, param_val_pairs: List[ParameterValuePair]
to_remove: ParameterValueSingle, param_val_pairs: List[ParameterValuePair]
) -> bool:
val_name, val_version = next(iter(to_remove.items()))
len_before = len(param_val_pairs)

def filter_function(param_val_pair: ParameterValuePair) -> bool:
for param_val_entry in param_val_pair:
if param_val_entry == to_remove:
return False
return True

param_val_pairs[:] = list(filter(filter_function, param_val_pairs))

return len_before != len(param_val_pairs)


@typechecked
def _remove_parameter_value_pair_all_versions(
to_remove: ParameterValuePair, param_val_pairs: List[ParameterValuePair]
) -> bool:
len_before = len(param_val_pairs)

def filter_function(param_val_pair: ParameterValuePair) -> bool:
if val_name in param_val_pair and param_val_pair[val_name] == val_version:
if (
param_val_pair.first.parameter == to_remove.first.parameter
and param_val_pair.second.parameter == to_remove.second.parameter
and param_val_pair.first.parameterValue.name == to_remove.first.parameterValue.name
and param_val_pair.second.parameterValue.name == to_remove.second.parameterValue.name
):
return False
return True

Expand Down Expand Up @@ -232,8 +307,8 @@ def check_parameter_value_pair_in_combination_list(
missing_expected_param = False

for ex_param_val_pair in parameter_value_pairs:
param1, param_val1 = list(ex_param_val_pair.items())[0]
param2, param_val2 = list(ex_param_val_pair.items())[1]
param1, param_val1 = ex_param_val_pair[0]
param2, param_val2 = ex_param_val_pair[1]
found = False
for comb in combination_list:
# comb contains all parameters, therefore a check is not required
Expand Down
5 changes: 3 additions & 2 deletions docs/naming.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ The [pair-wise testing](https://en.wikipedia.org/wiki/All-pairs_testing) takes a
The real Python types are implemented in [types.py](../bashi/types.py)

- **parameter** (`str`): A `parameter` represents a software component like the host compiler or a specific software like `CMake` or `Boost`. A `parameter` names a list of `parameter-values` and expresses how a `parameter-value` is used.
- **parameter-value** (`Tuple[value-name: str, value-version: packaging.version.Version]`): A `parameter-value` represents of a specific version of a `parameter`, for example `GCC 10`, `nvcc 12.2` or `CMake 3.28`. The pair wise generator takes on `parameter-value` of each `parameter` for is combinatorics.
- **parameter-value** (`NamedTuple[value-name: str, value-version: packaging.version.Version]`): A `parameter-value` represents of a specific version of a `parameter`, for example `GCC 10`, `nvcc 12.2` or `CMake 3.28`. The pair wise generator takes on `parameter-value` of each `parameter` for is combinatorics.
- **value-name** (`str`): The `value-name` is the first part of the `parameter-value`. It names a specific software component, like `GCC` or `CMake`. If the `parameter` names a specific software, `parameter` and `value-name` are equal.
- **value-version** (`packaging.version.Version`): The `value-version` is the second part of the `parameter-value`. It defines a specific version of a software component such like `12.2` or `3.12`.
- **parameter-value-list** (`parameter: str = List[parameter-value: Tuple[value-name: str, value-version: packaging.version.Version]]`): A `parameter-value-list` is a list of `parameter-values` assigned to a `parameter`. For example:
Expand All @@ -16,4 +16,5 @@ The real Python types are implemented in [types.py](../bashi/types.py)
- **parameter-value-tuple** (`OrderedList[parameter: str, parameter-value: Tuple[value-name: str, value-version: packaging.version.Version]]`): A `parameter-value-tuple` is a list of one ore more `parameter-value`s. The `parameter-value-tuple` is created from a `parameter-value-matrix` and each `parameter-value` is assigned to a different `parameter`. This means, each `parameter-value` is from a different `parameter-value-list` in a `parameter-value-matrix`. The `parameter-value-tuple` has the same or a smaller number of entries as the number of `parameters` in a `parameter-value-matrix`.
- **combination** (`OrderedList[parameter: str, parameter-value: Tuple[value-name: str, value-version: packaging.version.Version]]`): A `combination` is a `parameter-value-tuple` with the same number of `parameter-value`s as the number of input `parameters`.
- **combination-list** (`List[OrderedList[parameter : str, parameter-value: Tuple[value-name: str, value-version: packaging.version.Version]]]`): A `combination-list` is a list of `combination`s an the result of the pair-wise generator.
- **parameter-value-pair** (`OrderedList[parameter: str, parameter-value: Tuple[value-name: str, value-version: packaging.version.Version]]`): A `parameter-value-pair` is a `parameter-value-tuple` with exact two `parameter-values`. The pair-wise generator guaranties that each `parameter-value-pair`, which can be created by the given `parameter-value-matrix` exists at least in one `combination` of the `combination-list`. The only exception is, if a `parameter-value-pair` is forbidden by a filter rule.
- **parameter-value-single** (`NamedTuple[parameter: str, parameter-value: NamedTuple[value-name: str, value-version: packaging.version.Version]]`): A `parameter-value-single` connects a `parameter` with a single `parameter-value`.
- **parameter-value-pair** (`NamedTuple[first: NamedTuple[parameter: str, parameter-value: NamedTuple[value-name: str, value-version: packaging.version.Version]], second: NamedTuple[parameter: str, parameter-value: NamedTuple[value-name: str, value-version: packaging.version.Version]]]`): A `parameter-value-pair` is a `parameter-value-tuple` with exact two `parameter-values`. The pair-wise generator guaranties that each `parameter-value-pair`, which can be created by the given `parameter-value-matrix` exists at least in one `combination` of the `combination-list`. The only exception is, if a `parameter-value-pair` is forbidden by a filter rule.
Loading

0 comments on commit 8d9764c

Please sign in to comment.