From 9d8b0b8632c7c604fc191468ae57b77ca68aa5de Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Sat, 9 Mar 2024 15:37:32 +0100 Subject: [PATCH 1/8] add editorconfig Signed-off-by: Bas Zoetekouw --- .editorconfig | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..79736ca --- /dev/null +++ b/.editorconfig @@ -0,0 +1,19 @@ +root = true + +[*] +indent_style = space +indent_size = tab +tab_width = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +max_line_length = 100 + +[*.{yml,yaml}] +indent_style = space +indent_size = 2 + +[*.py] +indent_style = space + From bd60bc9f210aa31150ac78105de6097a57e10a32 Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Sat, 9 Mar 2024 15:45:21 +0100 Subject: [PATCH 2/8] Run tests on all supported python versions Signed-off-by: Bas Zoetekouw --- .github/workflows/test.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 281f877..e8c8b6c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,9 +6,14 @@ on: jobs: test: + strategy: + fail-fast: false + matrix: + python-version: [ '3.8', '3.9', '3.10', '3.11', '3.12' ] + runs-on: ubuntu-latest container: - image: docker.io/library/python:3.11-bookworm + image: "docker.io/library/python:${{ matrix.python-version }}-bookworm" # cgroupns needed to address the following error: # write /sys/fs/cgroup/cgroup.subtree_control: operation not supported options: --privileged --cgroupns=host From c3a152e68f2001202058609daf0ff0fc362caac6 Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Sat, 9 Mar 2024 16:03:02 +0100 Subject: [PATCH 3/8] Enable pylint, because it catches stuff that ruff misses Signed-off-by: Bas Zoetekouw --- .github/workflows/static-checks.yml | 3 +++ test-requirements.txt | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/.github/workflows/static-checks.yml b/.github/workflows/static-checks.yml index 5223ef6..792662b 100644 --- a/.github/workflows/static-checks.yml +++ b/.github/workflows/static-checks.yml @@ -20,3 +20,6 @@ jobs: pip install -r test-requirements.txt ruff format --check ruff check + - name: Analysing the code with pylint + run: | + pylint podman-compose.py diff --git a/test-requirements.txt b/test-requirements.txt index a123291..541e3e7 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -4,6 +4,7 @@ parameterized==0.9.0 pytest==8.0.2 tox==4.13.0 ruff==0.3.1 +pylint==3.1.0 # The packages below are transitive dependencies of the packages above and are included here # to make testing reproducible. @@ -12,16 +13,21 @@ ruff==0.3.1 # pip freeze > test-requirements.txt # and edit test-requirements.txt to add this comment +astroid==3.1.0 cachetools==5.3.3 chardet==5.2.0 colorama==0.4.6 +dill==0.3.8 distlib==0.3.8 filelock==3.13.1 iniconfig==2.0.0 +isort==5.13.2 +mccabe==0.7.0 packaging==23.2 platformdirs==4.2.0 pluggy==1.4.0 pyproject-api==1.6.1 python-dotenv==1.0.1 PyYAML==6.0.1 +tomlkit==0.12.4 virtualenv==20.25.1 From 688ee9a1046029acb332c7d725687c2c983a135a Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Sat, 9 Mar 2024 16:14:34 +0100 Subject: [PATCH 4/8] Fix pylint issues Signed-off-by: Bas Zoetekouw --- .github/workflows/static-checks.yml | 2 +- podman_compose.py | 23 +++++++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/.github/workflows/static-checks.yml b/.github/workflows/static-checks.yml index 792662b..b0c13d2 100644 --- a/.github/workflows/static-checks.yml +++ b/.github/workflows/static-checks.yml @@ -22,4 +22,4 @@ jobs: ruff check - name: Analysing the code with pylint run: | - pylint podman-compose.py + pylint podman_compose.py diff --git a/podman_compose.py b/podman_compose.py index e3ee67b..3099e2d 100755 --- a/podman_compose.py +++ b/podman_compose.py @@ -1169,15 +1169,15 @@ class Podman: xargs = self.compose.get_podman_args(cmd) if cmd else [] cmd_ls = [self.podman_path, *podman_args, cmd] + xargs + cmd_args log.info(str(cmd_ls)) - p = await asyncio.subprocess.create_subprocess_exec( + p = await asyncio.create_subprocess_exec( *cmd_ls, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE ) stdout_data, stderr_data = await p.communicate() if p.returncode == 0: return stdout_data - else: - raise subprocess.CalledProcessError(p.returncode, " ".join(cmd_ls), stderr_data) + + raise subprocess.CalledProcessError(p.returncode, " ".join(cmd_ls), stderr_data) def exec( self, @@ -1191,7 +1191,7 @@ class Podman: log.info(" ".join([str(i) for i in cmd_ls])) os.execlp(self.podman_path, *cmd_ls) - async def run( + async def run( # pylint: disable=dangerous-default-value self, podman_args, cmd="", @@ -1219,7 +1219,7 @@ class Podman: if stdout.at_eof(): break - p = await asyncio.subprocess.create_subprocess_exec( + p = await asyncio.create_subprocess_exec( *cmd_ls, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE ) # pylint: disable=consider-using-with @@ -1234,7 +1234,7 @@ class Podman: err_t.add_done_callback(task_reference.discard) else: - p = await asyncio.subprocess.create_subprocess_exec(*cmd_ls) # pylint: disable=consider-using-with + p = await asyncio.create_subprocess_exec(*cmd_ls) # pylint: disable=consider-using-with try: exit_code = await p.wait() @@ -1912,9 +1912,12 @@ class PodmanCompose: podman_compose = PodmanCompose() + ################### # decorators to add commands and parse options ################### +class PodmanComposeError(Exception): + pass class cmd_run: # pylint: disable=invalid-name,too-few-public-methods @@ -1928,7 +1931,7 @@ class cmd_run: # pylint: disable=invalid-name,too-few-public-methods return func(*args, **kw) if not asyncio.iscoroutinefunction(func): - raise Exception("Command must be async") + raise PodmanComposeError("Command must be async") wrapped._compose = self.compose # Trim extra indentation at start of multiline docstrings. wrapped.desc = self.cmd_desc or re.sub(r"^\s+", "", func.__doc__) @@ -2010,8 +2013,8 @@ async def compose_systemd(compose, args): f.write(f"{k}={v}\n") log.debug("writing [%s]: done.", fn) log.info("\n\ncreating the pod without starting it: ...\n\n") - process = await asyncio.subprocess.create_subprocess_exec(script, ["up", "--no-start"]) - log.info("\nfinal exit code is ", process) + process = await asyncio.create_subprocess_exec(script, ["up", "--no-start"]) + log.info("\nfinal exit code is %d", process) username = getpass.getuser() print( f""" @@ -2305,7 +2308,7 @@ async def compose_up(compose: PodmanCompose, args): # cause the status to overwrite. Sleeping for 1 seems to fix this and make it match # docker-compose await asyncio.sleep(1) - [_.cancel() for _ in tasks if not _.cancelling() and not _.cancelled()] + _ = [_.cancel() for _ in tasks if not _.cancelling() and not _.cancelled()] t: Task exiting = True for t in done: From c592596a5ecd0127236135ceba30ea2600daa147 Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Sat, 9 Mar 2024 16:33:31 +0100 Subject: [PATCH 5/8] Split out the different tests into separate CI steps Signed-off-by: Bas Zoetekouw --- .github/workflows/test.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e8c8b6c..a6b494a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,11 +26,15 @@ jobs: python -m pip install --upgrade pip if [ -f requirements.txt ]; then pip install -r requirements.txt; fi if [ -f test-requirements.txt ]; then pip install -r test-requirements.txt; fi - - name: Test with unittest + - name: Run tests in tests/ run: | - coverage run --source podman_compose -m unittest pytests/*.py python -m unittest tests/*.py - coverage combine - coverage report env: TESTS_DEBUG: 1 + - name: Run tests in pytests/ + run: | + coverage run --source podman_compose -m unittest pytests/*.py + - name: Report coverage + run: | + coverage combine + coverage report From fde7995cb8bd574a9fe3df6ef6daa5a5fa2df1b7 Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Sat, 9 Mar 2024 17:06:41 +0100 Subject: [PATCH 6/8] Fix python < 3.11 compatibility Signed-off-by: Bas Zoetekouw --- podman_compose.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/podman_compose.py b/podman_compose.py index 3099e2d..18bdf32 100755 --- a/podman_compose.py +++ b/podman_compose.py @@ -2298,6 +2298,14 @@ async def compose_up(compose: PodmanCompose, args): ) ) + def _task_cancelled(task: Task) -> bool: + if task.cancelled(): + return True + # Task.cancelling() is new in python 3.11 + if sys.version_info >= (3, 11) and task.cancelling(): + return True + return False + exit_code = 0 exiting = False while tasks: @@ -2308,7 +2316,9 @@ async def compose_up(compose: PodmanCompose, args): # cause the status to overwrite. Sleeping for 1 seems to fix this and make it match # docker-compose await asyncio.sleep(1) - _ = [_.cancel() for _ in tasks if not _.cancelling() and not _.cancelled()] + for t in tasks: + if not _task_cancelled(t): + t.cancel() t: Task exiting = True for t in done: From 5e55df890c1bf0e0685176044555af590b784a46 Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Sat, 9 Mar 2024 17:06:54 +0100 Subject: [PATCH 7/8] fix python < 3.9 compatibility Signed-off-by: Bas Zoetekouw --- pytests/test_can_merge_build.py | 1 + pytests/test_can_merge_cmd_ent.py | 1 + pytests/test_normalize_final_build.py | 1 + 3 files changed, 3 insertions(+) diff --git a/pytests/test_can_merge_build.py b/pytests/test_can_merge_build.py index 2519da7..e5ab1f6 100644 --- a/pytests/test_can_merge_build.py +++ b/pytests/test_can_merge_build.py @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 +from __future__ import annotations import argparse import os diff --git a/pytests/test_can_merge_cmd_ent.py b/pytests/test_can_merge_cmd_ent.py index 973a691..59fe8a3 100644 --- a/pytests/test_can_merge_cmd_ent.py +++ b/pytests/test_can_merge_cmd_ent.py @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 +from __future__ import annotations import argparse import copy diff --git a/pytests/test_normalize_final_build.py b/pytests/test_normalize_final_build.py index 98d3ad7..55a6faf 100644 --- a/pytests/test_normalize_final_build.py +++ b/pytests/test_normalize_final_build.py @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 # pylint: disable=protected-access +from __future__ import annotations import argparse import os From da630487755f9d4ecbbe5933b7dc049e2d9105fe Mon Sep 17 00:00:00 2001 From: Bas Zoetekouw Date: Sat, 9 Mar 2024 18:05:33 +0100 Subject: [PATCH 8/8] Don't spellcheck requirementfiles As some python module names are not proper english words Signed-off-by: Bas Zoetekouw --- .codespellrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.codespellrc b/.codespellrc index 54b143e..1fd4110 100644 --- a/.codespellrc +++ b/.codespellrc @@ -1,4 +1,4 @@ [codespell] -skip = .git,*.pdf,*.svg +skip = .git,*.pdf,*.svg,requirements.txt,test-requirements.txt # poped - loved variable name ignore-words-list = poped