From 03e9ea5360502c649f6e8e7a98a884ffbf150140 Mon Sep 17 00:00:00 2001 From: Alex Lowe Date: Thu, 17 Oct 2024 17:04:58 -0400 Subject: [PATCH] fix(python,poetry): remove duplicate files in the charm Fixes #1966 The lib64 directory exists as a symbolic link in virtual environments for historic reasons, but is not necessary. This prevents the charm from packing it twice (due to Python's inability to put symlinks into zip files). --- charmcraft/parts/plugins/_poetry.py | 10 ++++++---- charmcraft/parts/plugins/_python.py | 10 ++++++---- charmcraft/utils/__init__.py | 2 ++ charmcraft/utils/parts.py | 20 +++++++++++++++++++ .../integration/parts/plugins/test_poetry.py | 1 + .../integration/parts/plugins/test_python.py | 1 + 6 files changed, 36 insertions(+), 8 deletions(-) diff --git a/charmcraft/parts/plugins/_poetry.py b/charmcraft/parts/plugins/_poetry.py index 21415dd6b..5af1d1f2a 100644 --- a/charmcraft/parts/plugins/_poetry.py +++ b/charmcraft/parts/plugins/_poetry.py @@ -91,7 +91,9 @@ def _get_rewrite_shebangs_commands(self) -> list[str]: @override def get_build_commands(self) -> list[str]: """Get the build commands for the Python plugin.""" - if self._options.poetry_keep_bins: - return super().get_build_commands() - venv_bin = self._get_venv_directory() / "bin" - return [*super().get_build_commands(), f"rm -rf {venv_bin}"] + return [ + *super().get_build_commands(), + *utils.get_venv_cleanup_commands( + self._get_venv_directory(), keep_bins=self._options.poetry_keep_bins + ), + ] diff --git a/charmcraft/parts/plugins/_python.py b/charmcraft/parts/plugins/_python.py index f4dabd3f8..999250085 100644 --- a/charmcraft/parts/plugins/_python.py +++ b/charmcraft/parts/plugins/_python.py @@ -96,7 +96,9 @@ def _get_rewrite_shebangs_commands(self) -> list[str]: @override def get_build_commands(self) -> list[str]: """Get the build commands for the Python plugin.""" - if self._options.python_keep_bins: - return super().get_build_commands() - venv_bin = self._get_venv_directory() / "bin" - return [*super().get_build_commands(), f"rm -rf {venv_bin}"] + return [ + *super().get_build_commands(), + *utils.get_venv_cleanup_commands( + self._get_venv_directory(), keep_bins=self._options.python_keep_bins + ), + ] diff --git a/charmcraft/utils/__init__.py b/charmcraft/utils/__init__.py index 48269b186..dad8da549 100644 --- a/charmcraft/utils/__init__.py +++ b/charmcraft/utils/__init__.py @@ -66,6 +66,7 @@ from charmcraft.utils.parts import ( extend_python_build_environment, get_charm_copy_commands, + get_venv_cleanup_commands, ) from charmcraft.utils.project import ( find_charm_sources, @@ -116,6 +117,7 @@ "humanize_list", "extend_python_build_environment", "get_charm_copy_commands", + "get_venv_cleanup_commands", "find_charm_sources", "get_charm_name_from_path", "get_templates_environment", diff --git a/charmcraft/utils/parts.py b/charmcraft/utils/parts.py index 11583aa3e..2c994621a 100644 --- a/charmcraft/utils/parts.py +++ b/charmcraft/utils/parts.py @@ -17,6 +17,7 @@ import pathlib import shlex +import textwrap from collections.abc import Collection @@ -54,3 +55,22 @@ def get_charm_copy_commands( ) return commands + + +def get_venv_cleanup_commands(venv_path: pathlib.Path, *, keep_bins: bool) -> list[str]: + """Get a script do Charmcraft-specific venv cleanup. + + :param venv_path: The path to the venv. + :param keep_bins: Whether to keep the bin directory of the venv. + :returns: A shell script to do this, as a string. + """ + venv_bin = venv_path / "bin" + venv_lib64 = venv_path / "lib64" + delete_bins = [] if keep_bins else [f"rm -rf {venv_bin}"] + delete_lib64 = textwrap.dedent(f""" + if [ -L '{venv_lib64}' ]; then + rm -f '{venv_lib64}' + fi + """) + + return [*delete_bins, delete_lib64] diff --git a/tests/integration/parts/plugins/test_poetry.py b/tests/integration/parts/plugins/test_poetry.py index f210e2d6d..a04939826 100644 --- a/tests/integration/parts/plugins/test_poetry.py +++ b/tests/integration/parts/plugins/test_poetry.py @@ -88,3 +88,4 @@ def test_poetry_plugin( # Check that the stage directory looks correct. assert (stage_path / "src" / "charm.py").read_text() == "# Charm file" assert (stage_path / "venv" / "lib").is_dir() + assert not (stage_path / "venv" / "lib64").is_symlink() diff --git a/tests/integration/parts/plugins/test_python.py b/tests/integration/parts/plugins/test_python.py index d03e7193c..4d393333e 100644 --- a/tests/integration/parts/plugins/test_python.py +++ b/tests/integration/parts/plugins/test_python.py @@ -87,3 +87,4 @@ def test_python_plugin( # Check that the stage directory looks correct. assert (stage_path / "src" / "charm.py").read_text() == "# Charm file" assert (stage_path / "venv" / "lib").is_dir() + assert not (stage_path / "venv" / "lib64").is_symlink()