From de15161354142fd59e75a0e11fb19dae69972c88 Mon Sep 17 00:00:00 2001 From: Einar Wigum Arbo Date: Fri, 22 Mar 2024 13:13:13 +0100 Subject: [PATCH 1/4] Update cli_wrapper.py --- python_on_whales/components/compose/cli_wrapper.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/python_on_whales/components/compose/cli_wrapper.py b/python_on_whales/components/compose/cli_wrapper.py index 5571a350..6ce9b496 100644 --- a/python_on_whales/components/compose/cli_wrapper.py +++ b/python_on_whales/components/compose/cli_wrapper.py @@ -107,6 +107,14 @@ def build( else: run(full_cmd, capture_stdout=False) + @overload + def config(self, return_json: Literal[False] = ...) -> ComposeConfig: + ... + + @overload + def config(self, return_json: Literal[True] = ...) -> Dict[str, Any]: + ... + def config(self, return_json: bool = False) -> Union[ComposeConfig, Dict[str, Any]]: """Returns the configuration of the compose stack for further inspection. From ba64d5163411b6a9f73526f78d6e5809bd08439d Mon Sep 17 00:00:00 2001 From: "Einar W. Arbo" Date: Thu, 1 Aug 2024 12:44:13 +0000 Subject: [PATCH 2/4] Support multiple env-files --- python_on_whales/client_config.py | 17 ++++++- python_on_whales/docker_client.py | 2 + tests/python_on_whales/test_client_config.py | 53 +++++++++++++++++++- 3 files changed, 69 insertions(+), 3 deletions(-) diff --git a/python_on_whales/client_config.py b/python_on_whales/client_config.py index 207961c1..c8eb2a52 100644 --- a/python_on_whales/client_config.py +++ b/python_on_whales/client_config.py @@ -2,6 +2,7 @@ import shutil import tempfile import warnings +from collections.abc import Sequence from dataclasses import dataclass, field from datetime import datetime, timedelta from pathlib import Path @@ -37,7 +38,7 @@ def add_flag(self, name: str, value: bool): if value: self.append(name) - def add_args_list(self, arg_name: str, list_values: list): + def add_args_list(self, arg_name: str, list_values: Sequence): for value in to_list(list_values): self.extend([arg_name, value]) @@ -61,6 +62,7 @@ class ClientConfig: compose_files: List[ValidPath] = field(default_factory=list) compose_profiles: List[str] = field(default_factory=list) compose_env_file: Optional[ValidPath] = None + compose_env_files: Sequence[ValidPath] = field(default_factory=list) compose_project_name: Optional[str] = None compose_project_directory: Optional[ValidPath] = None compose_compatibility: Optional[bool] = None @@ -146,7 +148,18 @@ def docker_compose_cmd(self) -> Command: base_cmd = self.docker_cmd + ["compose"] base_cmd.add_args_list("--file", self.compose_files) base_cmd.add_args_list("--profile", self.compose_profiles) - base_cmd.add_simple_arg("--env-file", self.compose_env_file) + if self.compose_env_files: + if self.compose_env_file: + warnings.warn( + "You can't set both `compose_env_file` and `compose_env_files`. Files used in `compose_env_files` will be used." + ) + base_cmd.add_args_list("--env-file", self.compose_env_files) + elif self.compose_env_file: + warnings.warn( + "`compose_env_file` is deprecated. Use `compose_env_files` instead." + ) + base_cmd.add_simple_arg("--env-file", self.compose_env_file) + base_cmd.add_simple_arg("--project-name", self.compose_project_name) base_cmd.add_simple_arg("--project-directory", self.compose_project_directory) base_cmd.add_flag("--compatibility", self.compose_compatibility) diff --git a/python_on_whales/docker_client.py b/python_on_whales/docker_client.py index d7e5eae3..7a109985 100644 --- a/python_on_whales/docker_client.py +++ b/python_on_whales/docker_client.py @@ -104,6 +104,7 @@ def __init__( compose_files: List[ValidPath] = [], compose_profiles: List[str] = [], compose_env_file: Optional[ValidPath] = None, + compose_env_files: List[ValidPath] = [], compose_project_name: Optional[str] = None, compose_project_directory: Optional[ValidPath] = None, compose_compatibility: Optional[bool] = None, @@ -133,6 +134,7 @@ def __init__( compose_files=compose_files, compose_profiles=compose_profiles, compose_env_file=compose_env_file, + compose_env_files=compose_env_files, compose_project_name=compose_project_name, compose_project_directory=compose_project_directory, compose_compatibility=compose_compatibility, diff --git a/tests/python_on_whales/test_client_config.py b/tests/python_on_whales/test_client_config.py index 63128a1d..ba30d214 100644 --- a/tests/python_on_whales/test_client_config.py +++ b/tests/python_on_whales/test_client_config.py @@ -1,10 +1,11 @@ import json +from collections.abc import Sequence from pathlib import Path import pytest from python_on_whales import docker -from python_on_whales.client_config import ParsingError +from python_on_whales.client_config import ClientConfig, ParsingError fake_json_message = { "CreatedAt": "2020-10-08T18:32:55Z", @@ -36,3 +37,53 @@ def test_pretty_exception_message_and_report(mocker): raise IndexError assert Path(word).read_text() == json.dumps(fake_json_message, indent=2) + + +def test_compose_env_file(): + """Test that the deprecated `compose_env_file` gives a warning, and adds the `--env-file` argument to the compose command""" + with pytest.warns(UserWarning): + example_env_file_name = "example.env" + client_config = ClientConfig(compose_env_file=example_env_file_name) + assert client_config.docker_compose_cmd.count("--env-file") == 1 + # Since we are operating of a list of commands, we first find the index of the `--env-file` argument, then we check that the next argument is the file name. + index = client_config.docker_compose_cmd.index("--env-file") + assert client_config.docker_compose_cmd[index + 1] == example_env_file_name + + +@pytest.mark.parametrize( + "compose_env_files", + [ + ["example1.env", "example2.env"], + ["example1.env"], + ], + ids=["multiple_files", "single_file"], +) +def test_compose_env_files(compose_env_files: Sequence[str]): + """Test that using only `compose_env_files` adds all the files to the command line arguments""" + client_config = ClientConfig(compose_env_files=compose_env_files) + # Since we are operating of a list of commands, we first find the indices of the `--env-file` argument, then we check that the next argument is the file name. + indices = [ + index + for index, item in enumerate(client_config.docker_compose_cmd) + if item == "--env-file" + ] + assert len(indices) == len(compose_env_files) + for index, env_file in zip(indices, compose_env_files): + assert client_config.docker_compose_cmd[index + 1] == env_file + + +def test_compose_env_files_and_env_file(): + """Test that using both `compose_env_files` and `compose_env_file` gives a warning, and only uses `compose_env_files`""" + env_files_input = "example1.env" + env_file_input = "example2.env" + + with pytest.warns(UserWarning): + client_config = ClientConfig( + compose_env_files=[env_files_input], compose_env_file=env_file_input + ) + assert client_config.docker_compose_cmd.count("--env-file") == len( + [env_files_input] + ) + # Since we are operating of a list of commands, we first find the index of the `--env-file` argument, then we check that the next argument is the file name. + index = client_config.docker_compose_cmd.index("--env-file") + assert client_config.docker_compose_cmd[index + 1] == env_files_input From ccdfb225a085b54966f02c171fe5087ec084b209 Mon Sep 17 00:00:00 2001 From: "Einar W. Arbo" Date: Thu, 1 Aug 2024 12:50:26 +0000 Subject: [PATCH 3/4] Change to Iterable --- python_on_whales/client_config.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/python_on_whales/client_config.py b/python_on_whales/client_config.py index 7000376f..d6663e8a 100644 --- a/python_on_whales/client_config.py +++ b/python_on_whales/client_config.py @@ -2,7 +2,6 @@ import shutil import tempfile import warnings -from collections.abc import Sequence from dataclasses import dataclass, field from datetime import datetime, timedelta from pathlib import Path @@ -75,7 +74,7 @@ class ClientConfig: compose_files: List[ValidPath] = field(default_factory=list) compose_profiles: List[str] = field(default_factory=list) compose_env_file: Optional[ValidPath] = None - compose_env_files: Sequence[ValidPath] = field(default_factory=list) + compose_env_files: Iterable[ValidPath] = field(default_factory=list) compose_project_name: Optional[str] = None compose_project_directory: Optional[ValidPath] = None compose_compatibility: Optional[bool] = None From 04935ecde79012bb4e313b6d52caeb1bbbea1e2e Mon Sep 17 00:00:00 2001 From: "Einar W. Arbo" Date: Thu, 1 Aug 2024 13:00:25 +0000 Subject: [PATCH 4/4] Import Sequence from Typing instead of collections.abc --- tests/python_on_whales/test_client_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/python_on_whales/test_client_config.py b/tests/python_on_whales/test_client_config.py index ba30d214..3b1e3651 100644 --- a/tests/python_on_whales/test_client_config.py +++ b/tests/python_on_whales/test_client_config.py @@ -1,6 +1,6 @@ import json -from collections.abc import Sequence from pathlib import Path +from typing import Sequence import pytest