diff --git a/src/molecule/config.py b/src/molecule/config.py index 35aa5dd68c..1e56ebdf3a 100644 --- a/src/molecule/config.py +++ b/src/molecule/config.py @@ -281,7 +281,7 @@ def collection(self) -> CollectionData | None: LOG.warning( "The detected galaxy.yml file (%s) is incomplete, missing %s", galaxy_file, - missing_keys, + util.oxford_comma(missing_keys), ) return None diff --git a/src/molecule/util.py b/src/molecule/util.py index a57abc61ea..a53b327470 100644 --- a/src/molecule/util.py +++ b/src/molecule/util.py @@ -597,3 +597,27 @@ def print_as_yaml(data: object) -> None: # https://github.com/Textualize/rich/discussions/990#discussioncomment-342217 result = Syntax(code=safe_dump(data), lexer="yaml", background_color="default") console.print(result) + + +def oxford_comma(listed: Iterable[bool | str | Path], condition: str = "and") -> str: + """Format a list into a sentence. + + Args: + listed: List of string entries to modify + condition: String to splice into string, usually 'and' + + Returns: + Modified string + """ + match [f"'{entry!s}'" for entry in listed]: + case []: + return "" + case [one]: + return one + case [one, two]: + return f"{one} {condition} {two}" + case [*front, back]: + return f"{', '.join(s for s in front)}, {condition} {back}" + case _: + # This should be unreachable, but is included for completeness. + return "" diff --git a/tests/unit/test_util.py b/tests/unit/test_util.py index 0b94bd5207..1e9cbb48b4 100644 --- a/tests/unit/test_util.py +++ b/tests/unit/test_util.py @@ -354,7 +354,7 @@ def test_abs_path_with_symlink() -> None: @pytest.mark.parametrize( ("a", "b", "x"), - [ # noqa: PT007 + ( # Base of recursion scenarios ({"key": 1}, {"key": 2}, {"key": 2}), ({"key": {}}, {"key": 2}, {"key": 2}), @@ -368,7 +368,27 @@ def test_abs_path_with_symlink() -> None: {"a": 1, "b": [{"c": 3}], "d": {"e": "bbb"}}, {"a": 1, "b": [{"c": 3}], "d": {"e": "bbb", "f": 3}}, ), - ], + ), ) def test_merge_dicts(a: MutableMapping, b: MutableMapping, x: MutableMapping) -> None: # type: ignore[type-arg] # noqa: D103 assert x == util.merge_dicts(a, b) + + +@pytest.mark.parametrize( + ("sequence", "output"), + ( + ([], ""), + (["item1"], "'item1'"), + (["item1", False], "'item1' and 'False'"), + (["item1", False, Path()], "'item1', 'False', and '.'"), + ), + ids=("empty", "one", "two", "three"), +) +def test_oxford_comma(sequence: list[str], output: str) -> None: + """Test the oxford_comma function. + + Args: + sequence: sequence of items. + output: expected output string. + """ + assert util.oxford_comma(sequence) == output