Skip to content
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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ process = base.ps(all=True).call(capture_output=True)
print(process.stdout.encode("UTF-8"))
# Name Command State Ports
# -------------------------------------------------------------------
# myapp_app_70fd8b786b76 myapp --start-server Exit 0
# myapp_app_6ac3db4e1b55 myapp --client Exit 0
# myapp_app_70fd8b786b76 myapp --start-server Exit 0
# myapp_app_6ac3db4e1b55 myapp --client Exit 0
```

## Develop
Expand Down
20 changes: 18 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "docker-composer"
version = "5.4.0"
description = "Use docker-compose (V2) from within Python"
authors = [{ name = "Micha", email = "schollm-git@gmx.com" }]
requires-python = ">=3.9,<4.0"
requires-python = ">=3.9"
readme = "README.md"
license = "Apache-2.0"
classifiers = [
Expand All @@ -29,7 +29,7 @@ dev = [
"poethepoet>=0.30.0",
"pytest>=6.1.2",
"pytest-cov>=6.1.1",
"ruff>=0.11.10",
"ruff>=0.16.2",
]

[tool.hatch.build.targets.sdist]
Expand All @@ -46,6 +46,22 @@ exclude = ["src/docker_composer/_utils"]
requires = ["hatchling"]
build-backend = "hatchling.build"


[tool.ruff.lint]
ignore = [
"COM812",
"D213",
"D203",
"CPY001",
"UP045",
"EM101",
"TRY003",
]
[tool.ruff.lint.per-file-ignores]
"!src/docker_composer/_utils/*.py" = ["ALL"]
Comment on lines +60 to +61



[tool.pytest.ini_options]
addopts = """
--junit-xml=.out/junit-pytest.xml
Expand Down
30 changes: 13 additions & 17 deletions src/docker_composer/_utils/argument.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
"""Helper modules to parse docker compoose --help arguments"""

from __future__ import annotations
from typing import Iterable, Iterator

import logging
from collections.abc import Iterable, Iterator
from dataclasses import dataclass

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -61,7 +61,7 @@ def is_option(self) -> bool:
return self.type_desc == OPTION

@staticmethod
def from_line(line: str) -> "Argument":
def from_line(line: str) -> Argument:
if " " in line:
return _from_line_has_sep(line)
raise ValueError(line)
Expand All @@ -80,8 +80,7 @@ def _collect_arguments(arguments: Iterable[str]) -> Iterator[str]:


def parse_dc_argument(lines: list[str]) -> list[Argument]:
"""
Parse arguments from lines of docker-compose specifications
"""Parse arguments from lines of docker-compose specifications
:param lines: Lines of the Options sections from `docker-compose --help`.
:return: List of arguments
"""
Expand All @@ -90,7 +89,7 @@ def parse_dc_argument(lines: list[str]) -> list[Argument]:


def _get_type(type_name) -> type:
res = _TYPE_CONVERSIONS.get(type_name, None)
res = _TYPE_CONVERSIONS.get(type_name)
if res is None:
if "=" in type_name:
res = dict
Expand All @@ -108,30 +107,27 @@ def _parse_arg(arg: str) -> tuple[str, str, bool]:
if has_more:
arg = arg[:-1]
default = ""
elif "=" in arg:
default = arg[arg.index("=") + 1 :]
arg = arg[: arg.index("=")]
else:
if "=" in arg:
default = arg[arg.index("=") + 1 :]
arg = arg[: arg.index("=")]
else:
default = ""
default = ""
return arg.replace("-", "_").strip(), default, has_more


def _get_type_name_from_default(default: str) -> str:
"""Extract type name from default value"""
if not default:
return OPTION
elif default == "index":
if default == "index":
return "int"
elif default == "proto":
if default == "proto":
return "str"
else:
raise NotImplementedError(default)
raise NotImplementedError(default)


def _from_line_has_sep(line) -> "Argument":
"""
Get the argument from a docker-compose Options line, assuming there are at least two spaces before the description
def _from_line_has_sep(line) -> Argument:
"""Get the argument from a docker-compose Options line, assuming there are at least two spaces before the description
Sample " -f, --foo=[] FILES Foo of files"

:param line: a single line with the description separated from the definition by at least two blanks
Expand Down
36 changes: 19 additions & 17 deletions src/docker_composer/_utils/generate_class.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,42 @@
from __future__ import annotations

import logging
import subprocess
from collections import defaultdict
from collections.abc import Iterator, Mapping
from functools import lru_cache, reduce
from operator import add
from pathlib import Path
from typing import Iterator, Mapping, Union

import black
import isort
from isort.exceptions import ISortError


from docker_composer._utils.argument import Argument, parse_dc_argument
import logging

logger = logging.getLogger(__name__)

# must be larger than 50 (otherwise it's ignored by docker compose)
_DEFAULT_HELP_COLUMNS = 120


@lru_cache()
@lru_cache
def project_root():
for path in Path(__file__).parents:
if "pyproject.toml" in (p.name for p in path.iterdir()):
logger.debug("Project Path root: %s", path)
return path
raise EnvironmentError("No pyproject.toml found in path hierarchy")
raise OSError("No pyproject.toml found in path hierarchy")


@lru_cache()
@lru_cache
def _version() -> str:
return subprocess.run(
("docker", "compose", "version"), capture_output=True, text=True
("docker", "compose", "version"), capture_output=True, text=True, check=True
).stdout.strip()


@lru_cache()
@lru_cache
def get_help_message(subcommand: str = "") -> str:
"""Obtain the help message for subcommand from docker-compose."""
cmd = " ".join(arg for arg in ["docker", "compose", subcommand, "--help"] if arg)
Expand All @@ -45,6 +46,7 @@ def get_help_message(subcommand: str = "") -> str:
["script", "-q", "-c", full_cmd, "/dev/null"],
capture_output=True,
text=True,
check=True,
)
except Exception:
logger.error("FAILED to run %s.", full_cmd)
Expand Down Expand Up @@ -79,7 +81,7 @@ def parse_help(msg: str) -> tuple[Mapping[str, list[str]], list[Argument]]:
return sections, arguments


def indent(lines: Union[str, list[str]], level: int = 4) -> str:
def indent(lines: str | list[str], level: int = 4) -> str:
"""Indent lines by `level`.
:param lines: List of strings or a single string. A single string is splt up into individual lines.
:param level: number of spaces to indent
Expand All @@ -91,8 +93,7 @@ def indent(lines: Union[str, list[str]], level: int = 4) -> str:
prefix = " " * level
if lines:
return prefix + f"\n{prefix}".join(lines)
else:
return ""
return ""


def get_docstring(sections: Mapping[str, list[str]]) -> list[str]:
Expand Down Expand Up @@ -177,6 +178,8 @@ def generate_class(cmd: str) -> str:
# DO NOT EDIT: Autogenerated by {"/".join(Path(__file__).parts[-3:])}
# for {_version()}

from __future__ import annotations

import dataclasses as _dc
from typing import Optional

Expand All @@ -197,18 +200,17 @@ class {class_name}(DockerBaseRunner):
res = isort.code(
res, config=isort.Config(settings_path=project_root().as_posix())
)
except ISortError as exc:
logger.exception(exc)
except ISortError:
logger.exception("Error sorting imports for %s", cmd)
try:
return black.format_str(res, mode=black.Mode())
except Exception as exc:
logger.exception(exc)
except Exception:
logger.exception("Error formatting code for %s", cmd)
return res


def write_class(cmd: str = "") -> None:
"""
Generate a class for `cmd` and write it to `file_name`
"""Generate a class for `cmd` and write it to `file_name`.

:param cmd: docker-compose command to create or an empty string for root.
:param file_name: Name of output file (empty/None for auto-generation)
Expand Down
2 changes: 2 additions & 0 deletions src/docker_composer/runner/cmd/attach.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# DO NOT EDIT: Autogenerated by docker_composer/_utils/generate_class.py
# for Docker Compose version v5.4.0

from __future__ import annotations

import dataclasses as _dc
from typing import Optional

Expand Down
2 changes: 2 additions & 0 deletions src/docker_composer/runner/cmd/build.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# DO NOT EDIT: Autogenerated by docker_composer/_utils/generate_class.py
# for Docker Compose version v5.4.0

from __future__ import annotations

import dataclasses as _dc
from typing import Optional

Expand Down
2 changes: 2 additions & 0 deletions src/docker_composer/runner/cmd/commit.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# DO NOT EDIT: Autogenerated by docker_composer/_utils/generate_class.py
# for Docker Compose version v5.4.0

from __future__ import annotations

import dataclasses as _dc
from typing import Optional

Expand Down
2 changes: 2 additions & 0 deletions src/docker_composer/runner/cmd/config.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# DO NOT EDIT: Autogenerated by docker_composer/_utils/generate_class.py
# for Docker Compose version v5.4.0

from __future__ import annotations

import dataclasses as _dc
from typing import Optional

Expand Down
2 changes: 2 additions & 0 deletions src/docker_composer/runner/cmd/cp.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# DO NOT EDIT: Autogenerated by docker_composer/_utils/generate_class.py
# for Docker Compose version v5.4.0

from __future__ import annotations

import dataclasses as _dc
from typing import Optional

Expand Down
2 changes: 2 additions & 0 deletions src/docker_composer/runner/cmd/create.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# DO NOT EDIT: Autogenerated by docker_composer/_utils/generate_class.py
# for Docker Compose version v5.4.0

from __future__ import annotations

import dataclasses as _dc
from typing import Optional

Expand Down
2 changes: 2 additions & 0 deletions src/docker_composer/runner/cmd/down.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# DO NOT EDIT: Autogenerated by docker_composer/_utils/generate_class.py
# for Docker Compose version v5.4.0

from __future__ import annotations

import dataclasses as _dc
from typing import Optional

Expand Down
2 changes: 2 additions & 0 deletions src/docker_composer/runner/cmd/events.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# DO NOT EDIT: Autogenerated by docker_composer/_utils/generate_class.py
# for Docker Compose version v5.4.0

from __future__ import annotations

import dataclasses as _dc
from typing import Optional

Expand Down
2 changes: 2 additions & 0 deletions src/docker_composer/runner/cmd/exec.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# DO NOT EDIT: Autogenerated by docker_composer/_utils/generate_class.py
# for Docker Compose version v5.4.0

from __future__ import annotations

import dataclasses as _dc
from typing import Optional

Expand Down
2 changes: 2 additions & 0 deletions src/docker_composer/runner/cmd/export.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# DO NOT EDIT: Autogenerated by docker_composer/_utils/generate_class.py
# for Docker Compose version v5.4.0

from __future__ import annotations

import dataclasses as _dc
from typing import Optional

Expand Down
2 changes: 2 additions & 0 deletions src/docker_composer/runner/cmd/images.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# DO NOT EDIT: Autogenerated by docker_composer/_utils/generate_class.py
# for Docker Compose version v5.4.0

from __future__ import annotations

import dataclasses as _dc
from typing import Optional

Expand Down
2 changes: 2 additions & 0 deletions src/docker_composer/runner/cmd/kill.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# DO NOT EDIT: Autogenerated by docker_composer/_utils/generate_class.py
# for Docker Compose version v5.4.0

from __future__ import annotations

import dataclasses as _dc
from typing import Optional

Expand Down
2 changes: 2 additions & 0 deletions src/docker_composer/runner/cmd/logs.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# DO NOT EDIT: Autogenerated by docker_composer/_utils/generate_class.py
# for Docker Compose version v5.4.0

from __future__ import annotations

import dataclasses as _dc
from typing import Optional

Expand Down
2 changes: 2 additions & 0 deletions src/docker_composer/runner/cmd/ls.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# DO NOT EDIT: Autogenerated by docker_composer/_utils/generate_class.py
# for Docker Compose version v5.4.0

from __future__ import annotations

import dataclasses as _dc
from typing import Optional

Expand Down
2 changes: 2 additions & 0 deletions src/docker_composer/runner/cmd/pause.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# DO NOT EDIT: Autogenerated by docker_composer/_utils/generate_class.py
# for Docker Compose version v5.4.0

from __future__ import annotations

import dataclasses as _dc
from typing import Optional

Expand Down
2 changes: 2 additions & 0 deletions src/docker_composer/runner/cmd/port.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# DO NOT EDIT: Autogenerated by docker_composer/_utils/generate_class.py
# for Docker Compose version v5.4.0

from __future__ import annotations

import dataclasses as _dc
from typing import Optional

Expand Down
2 changes: 2 additions & 0 deletions src/docker_composer/runner/cmd/ps.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# DO NOT EDIT: Autogenerated by docker_composer/_utils/generate_class.py
# for Docker Compose version v5.4.0

from __future__ import annotations

import dataclasses as _dc
from typing import Optional

Expand Down
Loading
Loading