Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set up command construction to support generic iterables and mappings #595

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 20 additions & 7 deletions python_on_whales/client_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@
from dataclasses import dataclass, field
from datetime import datetime, timedelta
from pathlib import Path
from typing import Any, Dict, List, Literal, Optional, Union
from typing import Any, Dict, Iterable, List, Literal, Mapping, Optional, Union

import pydantic

from python_on_whales.download_binaries import (
download_docker_cli,
get_docker_binary_path_in_cache,
)
from python_on_whales.utils import to_list

from .utils import ValidPath, run
from . import utils
from .utils import ValidPath, run, to_list

CACHE_VALIDITY_PERIOD = 0.01

Expand All @@ -37,10 +37,23 @@ def add_flag(self, name: str, value: bool):
if value:
self.append(name)

def add_args_list(self, arg_name: str, list_values: list):
for value in to_list(list_values):
def add_args_iterable(self, arg_name: str, values: Iterable[Any]):
for value in values:
self.extend([arg_name, value])
gabrieldemarmiesse marked this conversation as resolved.
Show resolved Hide resolved

def add_args_iterable_or_single(
self, arg_name: str, iterable_or_single: Union[Iterable[Any], Any]
):
for value in to_list(iterable_or_single):
self.extend([arg_name, value])

def add_args_mapping(
self, arg_name: str, mapping: Mapping[Any, Any], *, separator="="
):
self.add_args_iterable(
arg_name, utils.format_mapping_for_cli(mapping, separator)
)

def __add__(self, other) -> "Command":
return Command(super().__add__(other))

Expand Down Expand Up @@ -144,8 +157,8 @@ def docker_cmd(self) -> Command:
@property
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_args_iterable_or_single("--file", self.compose_files)
base_cmd.add_args_iterable_or_single("--profile", self.compose_profiles)
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)
Expand Down
30 changes: 18 additions & 12 deletions python_on_whales/components/buildx/cli_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
from python_on_whales.components.buildx.models import BuilderInspectResult
from python_on_whales.utils import (
ValidPath,
format_dict_for_cli,
format_mapping_for_cli,
run,
stream_stdout_and_stderr,
to_list,
Expand Down Expand Up @@ -196,7 +196,7 @@ def bake(
full_cmd += ["--progress", progress]
for file in to_list(files):
full_cmd.add_simple_arg("--file", file)
full_cmd.add_args_list("--set", format_dict_for_cli(set))
full_cmd.add_args_iterable_or_single("--set", format_mapping_for_cli(set))
targets = to_list(targets)
env = dict(variables)
if print:
Expand Down Expand Up @@ -326,16 +326,20 @@ def build(
if progress != "auto" and isinstance(progress, str):
full_cmd += ["--progress", progress]

full_cmd.add_args_list(
"--add-host", format_dict_for_cli(add_hosts, separator=":")
full_cmd.add_args_iterable_or_single(
"--add-host", format_mapping_for_cli(add_hosts, separator=":")
)
full_cmd.add_args_list("--allow", allow)
full_cmd.add_args_iterable_or_single("--allow", allow)
if isinstance(attest, dict):
full_cmd.add_simple_arg("--attest", format_dict_for_buildx(attest))
full_cmd.add_args_list("--build-arg", format_dict_for_cli(build_args))
full_cmd.add_args_list("--build-context", format_dict_for_cli(build_contexts))
full_cmd.add_args_iterable_or_single(
"--build-arg", format_mapping_for_cli(build_args)
)
full_cmd.add_args_iterable_or_single(
"--build-context", format_mapping_for_cli(build_contexts)
)
full_cmd.add_simple_arg("--builder", builder)
full_cmd.add_args_list("--label", format_dict_for_cli(labels))
full_cmd.add_args_iterable_or_single("--label", format_mapping_for_cli(labels))

full_cmd.add_simple_arg("--ssh", ssh)

Expand Down Expand Up @@ -363,14 +367,14 @@ def build(
full_cmd.add_simple_arg("--cache-to", format_dict_for_buildx(cache_to))
else:
full_cmd.add_simple_arg("--cache-to", cache_to)
full_cmd.add_args_list("--secret", to_list(secrets))
full_cmd.add_args_iterable_or_single("--secret", to_list(secrets))
if output != {}:
full_cmd += ["--output", format_dict_for_buildx(output)]
if platforms is not None:
full_cmd += ["--platform", ",".join(platforms)]
full_cmd.add_simple_arg("--network", network)
full_cmd.add_flag("--no-cache", not cache)
full_cmd.add_args_list("--tag", tags)
full_cmd.add_args_iterable_or_single("--tag", tags)

if stream_logs:
if progress in (False, "tty"):
Expand Down Expand Up @@ -558,7 +562,9 @@ def prune(
"""
full_cmd = self.docker_cmd + ["buildx", "prune", "--force"]
full_cmd.add_flag("--all", all)
full_cmd.add_args_list("--filter", format_dict_for_cli(filters))
full_cmd.add_args_iterable_or_single(
"--filter", format_mapping_for_cli(filters)
)
if stream_logs:
return stream_buildx_logs(full_cmd)
run(full_cmd)
Expand Down Expand Up @@ -640,7 +646,7 @@ def removesuffix(base_string: str, suffix: str) -> str:


def format_dict_for_buildx(options: Dict[str, str]) -> str:
return ",".join(format_dict_for_cli(options, separator="="))
return ",".join(format_mapping_for_cli(options, separator="="))


def stream_buildx_logs(full_cmd: list, env: Dict[str, str] = None) -> Iterator[str]:
Expand Down
12 changes: 8 additions & 4 deletions python_on_whales/components/compose/cli_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from python_on_whales.client_config import DockerCLICaller
from python_on_whales.components.compose.models import ComposeConfig, ComposeProject
from python_on_whales.utils import (
format_dict_for_cli,
format_mapping_for_cli,
format_signal_arg,
parse_ls_status_count,
run,
Expand Down Expand Up @@ -89,7 +89,9 @@ def build(
)

full_cmd = self.docker_compose_cmd + ["build"]
full_cmd.add_args_list("--build-arg", format_dict_for_cli(build_args))
full_cmd.add_args_iterable_or_single(
"--build-arg", format_mapping_for_cli(build_args)
)
full_cmd.add_flag("--no-cache", not cache)
full_cmd.add_simple_arg("--progress", progress)
full_cmd.add_flag("--pull", pull)
Expand Down Expand Up @@ -500,7 +502,9 @@ def ls(
"""
full_cmd = self.docker_compose_cmd + ["ls", "--format", "json"]
full_cmd.add_flag("--all", all)
full_cmd.add_args_list("--filter", format_dict_for_cli(filters))
full_cmd.add_args_iterable_or_single(
"--filter", format_mapping_for_cli(filters)
)

return [
ComposeProject(
Expand Down Expand Up @@ -751,7 +755,7 @@ def run(
full_cmd.add_flag("--use-aliases", use_aliases)
full_cmd.add_simple_arg("--user", user)
full_cmd.add_simple_arg("--workdir", workdir)
full_cmd.add_args_list("--label", format_dict_for_cli(labels))
full_cmd.add_args_iterable_or_single("--label", format_mapping_for_cli(labels))
full_cmd.append(service)
full_cmd += command

Expand Down
8 changes: 5 additions & 3 deletions python_on_whales/components/config/cli_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
ConfigSpec,
DockerObjectVersion,
)
from python_on_whales.utils import format_dict_for_cli, run, to_list
from python_on_whales.utils import format_mapping_for_cli, run, to_list


class Config(ReloadableObjectFromJson):
Expand Down Expand Up @@ -96,7 +96,7 @@ def create(
A `python_on_whales.Config` object.
"""
full_cmd = self.docker_cmd + ["config", "create"]
full_cmd.add_args_list("--label", format_dict_for_cli(labels))
full_cmd.add_args_iterable_or_single("--label", format_mapping_for_cli(labels))
full_cmd.add_simple_arg("--template-driver", template_driver)
full_cmd += [name, file]
return Config(self.client_config, run(full_cmd), is_immutable_id=True)
Expand Down Expand Up @@ -135,7 +135,9 @@ def list(self, filters: Dict[str, str] = {}) -> List[Config]:
A `List[python_on_whales.Config]`.
"""
full_cmd = self.docker_cmd + ["config", "list", "--quiet"]
full_cmd.add_args_list("--filter", format_dict_for_cli(filters))
full_cmd.add_args_iterable_or_single(
"--filter", format_mapping_for_cli(filters)
)
output = run(full_cmd)
ids = output.splitlines()
return [Config(self.client_config, id_, is_immutable_id=True) for id_ in ids]
Expand Down
Loading