From adbd2cd601c01f7375a4d992055348f4380298ec Mon Sep 17 00:00:00 2001 From: Carl Csaposs Date: Thu, 18 May 2023 14:52:38 +0000 Subject: [PATCH 01/10] Copy full virtual environment to packed charm Create symlink to site-packages for backwards compatability --- charmcraft/charm_builder.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/charmcraft/charm_builder.py b/charmcraft/charm_builder.py index 1508d8898..0389d63c9 100644 --- a/charmcraft/charm_builder.py +++ b/charmcraft/charm_builder.py @@ -39,6 +39,7 @@ # Some constants that are used through the code. WORK_DIRNAME = "work_dir" VENV_DIRNAME = "venv" +SITE_PACKAGES_DIRNAME = "site-packages" STAGING_VENV_DIRNAME = "staging-venv" DEPENDENCIES_HASH_FILENAME = "charmcraft-dependencies-hash.txt" @@ -50,7 +51,7 @@ # to be the value it would've otherwise been. DISPATCH_CONTENT = """#!/bin/sh -JUJU_DISPATCH_PATH="${{JUJU_DISPATCH_PATH:-$0}}" PYTHONPATH=lib:venv \\ +JUJU_DISPATCH_PATH="${{JUJU_DISPATCH_PATH:-$0}}" PYTHONPATH=lib:site-packages \\ exec ./{entrypoint_relative_path} """ @@ -319,10 +320,13 @@ def handle_dependencies(self): # save the hash file after all successful installations hash_file.write_text(current_deps_hash, encoding="utf8") - # always copy the virtualvenv site-packages directory to /venv in charm - basedir = pathlib.Path(STAGING_VENV_DIRNAME) - site_packages_dir = _find_venv_site_packages(basedir) - shutil.copytree(site_packages_dir, self.installdir / VENV_DIRNAME) + # copy the virtual environment directory to /venv in charm + venv_dir = self.installdir / VENV_DIRNAME + shutil.copytree(pathlib.Path(STAGING_VENV_DIRNAME), venv_dir) + # symlink /site-packages directory in charm to virtual environment site-packages directory + # (backwards compatability for charms that do not use the full virtual environment) + site_packages_dir = _find_venv_site_packages(venv_dir) + (self.installdir / SITE_PACKAGES_DIRNAME).symlink_to(site_packages_dir) def _find_venv_bin(basedir, exec_base): From 90e3d19bb5d351e7eee9bea1b51cd247a3506666 Mon Sep 17 00:00:00 2001 From: Carl Csaposs Date: Thu, 18 May 2023 15:33:12 +0000 Subject: [PATCH 02/10] Update tests --- tests/test_charm_builder.py | 45 +++++++++++++------------------------ 1 file changed, 15 insertions(+), 30 deletions(-) diff --git a/tests/test_charm_builder.py b/tests/test_charm_builder.py index 2a89be62f..583e6b460 100644 --- a/tests/test_charm_builder.py +++ b/tests/test_charm_builder.py @@ -619,8 +619,7 @@ def test_build_dependencies_virtualenv_simple(tmp_path, assert_output): ), ] - site_packages_dir = charm_builder._find_venv_site_packages(pathlib.Path(STAGING_VENV_DIRNAME)) - assert mock_copytree.mock_calls == [call(site_packages_dir, build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] assert_output("Handling dependencies", "Installing dependencies") @@ -664,8 +663,7 @@ def test_build_dependencies_virtualenv_multiple(tmp_path, assert_output): ), ] - site_packages_dir = charm_builder._find_venv_site_packages(pathlib.Path(STAGING_VENV_DIRNAME)) - assert mock_copytree.mock_calls == [call(site_packages_dir, build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] assert_output("Handling dependencies", "Installing dependencies") @@ -716,8 +714,7 @@ def test_build_dependencies_virtualenv_packages(tmp_path, assert_output): call([pip_cmd, "install", "--upgrade", "--no-binary", ":all:", "pkg1", "pkg2"]), ] - site_packages_dir = charm_builder._find_venv_site_packages(pathlib.Path(STAGING_VENV_DIRNAME)) - assert mock_copytree.mock_calls == [call(site_packages_dir, build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] assert_output("Handling dependencies", "Installing dependencies") @@ -747,8 +744,7 @@ def test_build_dependencies_virtualenv_binary_packages(tmp_path, assert_output): call([pip_cmd, "install", "--upgrade", "pkg1", "pkg2"]), ] - site_packages_dir = charm_builder._find_venv_site_packages(pathlib.Path(STAGING_VENV_DIRNAME)) - assert mock_copytree.mock_calls == [call(site_packages_dir, build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] assert_output("Handling dependencies", "Installing dependencies") @@ -797,8 +793,7 @@ def test_build_dependencies_virtualenv_all(tmp_path, assert_output): call([pip_cmd, "install", "--upgrade", "--no-binary", ":all:", "pkg5", "pkg6"]), ] - site_packages_dir = charm_builder._find_venv_site_packages(pathlib.Path(STAGING_VENV_DIRNAME)) - assert mock_copytree.mock_calls == [call(site_packages_dir, build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] assert_output("Handling dependencies", "Installing dependencies") @@ -832,8 +827,7 @@ def test_build_dependencies_no_reused_missing_venv(tmp_path, assert_output): assert staging_venv_dir.exists() # installation directory copied to the build directory - site_packages_dir = charm_builder._find_venv_site_packages(pathlib.Path(STAGING_VENV_DIRNAME)) - assert mock_copytree.mock_calls == [call(site_packages_dir, build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] # remove the site venv directory staging_venv_dir.rmdir() @@ -849,8 +843,7 @@ def test_build_dependencies_no_reused_missing_venv(tmp_path, assert_output): assert staging_venv_dir.exists() # installation directory copied *again* to the build directory - site_packages_dir = charm_builder._find_venv_site_packages(pathlib.Path(STAGING_VENV_DIRNAME)) - assert mock_copytree.mock_calls == [call(site_packages_dir, build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] def test_build_dependencies_no_reused_missing_hash_file(tmp_path, assert_output): @@ -883,8 +876,7 @@ def test_build_dependencies_no_reused_missing_hash_file(tmp_path, assert_output) assert staging_venv_dir.exists() # installation directory copied to the build directory - site_packages_dir = charm_builder._find_venv_site_packages(pathlib.Path(STAGING_VENV_DIRNAME)) - assert mock_copytree.mock_calls == [call(site_packages_dir, build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] # remove the hash file (tmp_path / DEPENDENCIES_HASH_FILENAME).unlink() @@ -900,8 +892,7 @@ def test_build_dependencies_no_reused_missing_hash_file(tmp_path, assert_output) assert staging_venv_dir.exists() # installation directory copied *again* to the build directory - site_packages_dir = charm_builder._find_venv_site_packages(pathlib.Path(STAGING_VENV_DIRNAME)) - assert mock_copytree.mock_calls == [call(site_packages_dir, build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] def test_build_dependencies_no_reused_problematic_hash_file(tmp_path, assert_output): @@ -934,8 +925,7 @@ def test_build_dependencies_no_reused_problematic_hash_file(tmp_path, assert_out assert staging_venv_dir.exists() # installation directory copied to the build directory - site_packages_dir = charm_builder._find_venv_site_packages(pathlib.Path(STAGING_VENV_DIRNAME)) - assert mock_copytree.mock_calls == [call(site_packages_dir, build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] # avoid the file to be read succesfully (tmp_path / DEPENDENCIES_HASH_FILENAME).write_bytes(b"\xc3\x28") # invalid UTF8 @@ -954,8 +944,7 @@ def test_build_dependencies_no_reused_problematic_hash_file(tmp_path, assert_out assert staging_venv_dir.exists() # installation directory copied *again* to the build directory - site_packages_dir = charm_builder._find_venv_site_packages(pathlib.Path(STAGING_VENV_DIRNAME)) - assert mock_copytree.mock_calls == [call(site_packages_dir, build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] @pytest.mark.parametrize( @@ -1008,8 +997,7 @@ def test_build_dependencies_no_reused_different_dependencies( assert staging_venv_dir.exists() # installation directory copied to the build directory - site_packages_dir = charm_builder._find_venv_site_packages(pathlib.Path(STAGING_VENV_DIRNAME)) - assert mock_copytree.mock_calls == [call(site_packages_dir, build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] # for the second call, default new dependencies to first ones so only one is changed at a time if new_reqs_content is not None: @@ -1033,8 +1021,7 @@ def test_build_dependencies_no_reused_different_dependencies( assert staging_venv_dir.exists() # installation directory copied *again* to the build directory - site_packages_dir = charm_builder._find_venv_site_packages(pathlib.Path(STAGING_VENV_DIRNAME)) - assert mock_copytree.mock_calls == [call(site_packages_dir, build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] def test_build_dependencies_reused(tmp_path, assert_output): @@ -1071,8 +1058,7 @@ def test_build_dependencies_reused(tmp_path, assert_output): assert staging_venv_dir.exists() # installation directory copied to the build directory - site_packages_dir = charm_builder._find_venv_site_packages(pathlib.Path(STAGING_VENV_DIRNAME)) - assert mock_copytree.mock_calls == [call(site_packages_dir, build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] # second run! with patch("shutil.copytree") as mock_copytree: @@ -1083,8 +1069,7 @@ def test_build_dependencies_reused(tmp_path, assert_output): # installation directory copied *again* to the build directory (this is always done as # buildpath is cleaned) - site_packages_dir = charm_builder._find_venv_site_packages(pathlib.Path(STAGING_VENV_DIRNAME)) - assert mock_copytree.mock_calls == [call(site_packages_dir, build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] # -- tests about juju ignore From 46a379c73bfb820f3ea9b6618337aa9048590c6b Mon Sep 17 00:00:00 2001 From: Carl Csaposs Date: Thu, 18 May 2023 15:58:05 +0000 Subject: [PATCH 03/10] format --- tests/test_charm_builder.py | 60 +++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/tests/test_charm_builder.py b/tests/test_charm_builder.py index 583e6b460..7d25597ac 100644 --- a/tests/test_charm_builder.py +++ b/tests/test_charm_builder.py @@ -619,7 +619,9 @@ def test_build_dependencies_virtualenv_simple(tmp_path, assert_output): ), ] - assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [ + call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME) + ] assert_output("Handling dependencies", "Installing dependencies") @@ -663,7 +665,9 @@ def test_build_dependencies_virtualenv_multiple(tmp_path, assert_output): ), ] - assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [ + call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME) + ] assert_output("Handling dependencies", "Installing dependencies") @@ -714,7 +718,9 @@ def test_build_dependencies_virtualenv_packages(tmp_path, assert_output): call([pip_cmd, "install", "--upgrade", "--no-binary", ":all:", "pkg1", "pkg2"]), ] - assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [ + call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME) + ] assert_output("Handling dependencies", "Installing dependencies") @@ -744,7 +750,9 @@ def test_build_dependencies_virtualenv_binary_packages(tmp_path, assert_output): call([pip_cmd, "install", "--upgrade", "pkg1", "pkg2"]), ] - assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [ + call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME) + ] assert_output("Handling dependencies", "Installing dependencies") @@ -793,7 +801,9 @@ def test_build_dependencies_virtualenv_all(tmp_path, assert_output): call([pip_cmd, "install", "--upgrade", "--no-binary", ":all:", "pkg5", "pkg6"]), ] - assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [ + call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME) + ] assert_output("Handling dependencies", "Installing dependencies") @@ -827,7 +837,9 @@ def test_build_dependencies_no_reused_missing_venv(tmp_path, assert_output): assert staging_venv_dir.exists() # installation directory copied to the build directory - assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [ + call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME) + ] # remove the site venv directory staging_venv_dir.rmdir() @@ -843,7 +855,9 @@ def test_build_dependencies_no_reused_missing_venv(tmp_path, assert_output): assert staging_venv_dir.exists() # installation directory copied *again* to the build directory - assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [ + call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME) + ] def test_build_dependencies_no_reused_missing_hash_file(tmp_path, assert_output): @@ -876,7 +890,9 @@ def test_build_dependencies_no_reused_missing_hash_file(tmp_path, assert_output) assert staging_venv_dir.exists() # installation directory copied to the build directory - assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [ + call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME) + ] # remove the hash file (tmp_path / DEPENDENCIES_HASH_FILENAME).unlink() @@ -892,7 +908,9 @@ def test_build_dependencies_no_reused_missing_hash_file(tmp_path, assert_output) assert staging_venv_dir.exists() # installation directory copied *again* to the build directory - assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [ + call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME) + ] def test_build_dependencies_no_reused_problematic_hash_file(tmp_path, assert_output): @@ -925,7 +943,9 @@ def test_build_dependencies_no_reused_problematic_hash_file(tmp_path, assert_out assert staging_venv_dir.exists() # installation directory copied to the build directory - assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [ + call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME) + ] # avoid the file to be read succesfully (tmp_path / DEPENDENCIES_HASH_FILENAME).write_bytes(b"\xc3\x28") # invalid UTF8 @@ -944,7 +964,9 @@ def test_build_dependencies_no_reused_problematic_hash_file(tmp_path, assert_out assert staging_venv_dir.exists() # installation directory copied *again* to the build directory - assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [ + call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME) + ] @pytest.mark.parametrize( @@ -997,7 +1019,9 @@ def test_build_dependencies_no_reused_different_dependencies( assert staging_venv_dir.exists() # installation directory copied to the build directory - assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [ + call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME) + ] # for the second call, default new dependencies to first ones so only one is changed at a time if new_reqs_content is not None: @@ -1021,7 +1045,9 @@ def test_build_dependencies_no_reused_different_dependencies( assert staging_venv_dir.exists() # installation directory copied *again* to the build directory - assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [ + call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME) + ] def test_build_dependencies_reused(tmp_path, assert_output): @@ -1058,7 +1084,9 @@ def test_build_dependencies_reused(tmp_path, assert_output): assert staging_venv_dir.exists() # installation directory copied to the build directory - assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [ + call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME) + ] # second run! with patch("shutil.copytree") as mock_copytree: @@ -1069,7 +1097,9 @@ def test_build_dependencies_reused(tmp_path, assert_output): # installation directory copied *again* to the build directory (this is always done as # buildpath is cleaned) - assert mock_copytree.mock_calls == [call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME)] + assert mock_copytree.mock_calls == [ + call(pathlib.Path(STAGING_VENV_DIRNAME), build_dir / VENV_DIRNAME) + ] # -- tests about juju ignore From 25d18cbf6a162ea3afd405286ab76de832c94d74 Mon Sep 17 00:00:00 2001 From: Carl Csaposs Date: Thu, 18 May 2023 18:16:32 +0000 Subject: [PATCH 04/10] Remove existing symlink if present --- charmcraft/charm_builder.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/charmcraft/charm_builder.py b/charmcraft/charm_builder.py index 0389d63c9..fed4ae934 100644 --- a/charmcraft/charm_builder.py +++ b/charmcraft/charm_builder.py @@ -39,7 +39,7 @@ # Some constants that are used through the code. WORK_DIRNAME = "work_dir" VENV_DIRNAME = "venv" -SITE_PACKAGES_DIRNAME = "site-packages" +SITE_PACKAGES_SYMLINK_NAME = "site-packages" STAGING_VENV_DIRNAME = "staging-venv" DEPENDENCIES_HASH_FILENAME = "charmcraft-dependencies-hash.txt" @@ -326,7 +326,9 @@ def handle_dependencies(self): # symlink /site-packages directory in charm to virtual environment site-packages directory # (backwards compatability for charms that do not use the full virtual environment) site_packages_dir = _find_venv_site_packages(venv_dir) - (self.installdir / SITE_PACKAGES_DIRNAME).symlink_to(site_packages_dir) + site_packages_symlink_path = self.installdir / SITE_PACKAGES_SYMLINK_NAME + site_packages_symlink_path.unlink(missing_ok=True) + site_packages_symlink_path.symlink_to(site_packages_dir) def _find_venv_bin(basedir, exec_base): From c98c7a61433c9735914a0f11fadbfdeee5b0cbc4 Mon Sep 17 00:00:00 2001 From: Carl Csaposs Date: Fri, 19 May 2023 18:47:09 +0000 Subject: [PATCH 05/10] Fix smoketests --- tests/spread/smoketests/basic/task.yaml | 2 +- tests/spread/smoketests/different-dependencies/task.yaml | 6 +++--- tests/spread/smoketests/full-lifecycle/task.yaml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/spread/smoketests/basic/task.yaml b/tests/spread/smoketests/basic/task.yaml index d713e4361..5d16d340d 100644 --- a/tests/spread/smoketests/basic/task.yaml +++ b/tests/spread/smoketests/basic/task.yaml @@ -18,5 +18,5 @@ execute: | cd charm charmcraft pack --verbose test -f charm*.charm - unzip -l charm*.charm | grep "venv/ops/charm.py" + unzip -l charm*.charm | grep "site-packages/ops/charm.py" test ! -d build diff --git a/tests/spread/smoketests/different-dependencies/task.yaml b/tests/spread/smoketests/different-dependencies/task.yaml index 78c99ec55..3295a32d6 100644 --- a/tests/spread/smoketests/different-dependencies/task.yaml +++ b/tests/spread/smoketests/different-dependencies/task.yaml @@ -28,6 +28,6 @@ execute: | cd charm charmcraft pack --verbose test -f charm*.charm - unzip -l charm*.charm | grep "venv/pytest/__init__.py" - unzip -l charm*.charm | grep "venv/bumpversion/__init__.py" - unzip -l charm*.charm | grep "venv/fades/__init__.py" + unzip -l charm*.charm | grep "site-packages/pytest/__init__.py" + unzip -l charm*.charm | grep "site-packages/bumpversion/__init__.py" + unzip -l charm*.charm | grep "site-packages/fades/__init__.py" diff --git a/tests/spread/smoketests/full-lifecycle/task.yaml b/tests/spread/smoketests/full-lifecycle/task.yaml index 246cc1559..f0b1ab010 100644 --- a/tests/spread/smoketests/full-lifecycle/task.yaml +++ b/tests/spread/smoketests/full-lifecycle/task.yaml @@ -39,6 +39,6 @@ execute: | charmcraft pack --verbose test -f charm*.charm unzip -c charm*.charm hello.txt | grep "^Hello, world!" - unzip -l charm*.charm | grep "venv/ops/charm.py" + unzip -l charm*.charm | grep "site-packages/ops/charm.py" unzip -l charm*.charm | grep extra_file.txt ! unzip -l charm*.charm | grep secrets.txt From 00b02e06095b4dcc03d04c748da410d971577c2b Mon Sep 17 00:00:00 2001 From: Carl Csaposs Date: Fri, 19 May 2023 18:49:29 +0000 Subject: [PATCH 06/10] Add symlink to PRIME --- charmcraft/commands/build.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/charmcraft/commands/build.py b/charmcraft/commands/build.py index 702aad727..ec172ff76 100644 --- a/charmcraft/commands/build.py +++ b/charmcraft/commands/build.py @@ -39,6 +39,7 @@ # Some constants that are used through the code. BUILD_DIRNAME = "build" VENV_DIRNAME = "venv" +SITE_PACKAGES_SYMLINK_NAME = "site-packages" CHARM_FILES = [ "metadata.yaml", @@ -233,6 +234,7 @@ def _set_prime_filter(self): or charmlib_pydeps ): charm_part_prime.append(VENV_DIRNAME) + charm_part_prime.append(SITE_PACKAGES_SYMLINK_NAME) # add mandatory and optional charm files charm_part_prime.extend(CHARM_FILES) From 596751f92cd04adb49d93f45e7a5043456baa6df Mon Sep 17 00:00:00 2001 From: Carl Csaposs Date: Fri, 19 May 2023 19:05:29 +0000 Subject: [PATCH 07/10] Fix test --- tests/commands/test_build.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/commands/test_build.py b/tests/commands/test_build.py index 71921c1f2..b68d64607 100644 --- a/tests/commands/test_build.py +++ b/tests/commands/test_build.py @@ -1257,6 +1257,7 @@ def test_build_part_from_config(basic_project, monkeypatch): "prime": [ "src", "venv", + "site-packages", "metadata.yaml", "dispatch", "hooks", @@ -1332,6 +1333,7 @@ def test_build_part_include_venv_pydeps(basic_project, monkeypatch): "prime": [ "src", "venv", + "site-packages", "metadata.yaml", "dispatch", "hooks", From fb6189f76345bcd3c6560955fa78c67a52e6d31d Mon Sep 17 00:00:00 2001 From: Carl Csaposs Date: Fri, 19 May 2023 19:35:43 +0000 Subject: [PATCH 08/10] Use relative path instead of absolute path for symlink --- charmcraft/charm_builder.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/charmcraft/charm_builder.py b/charmcraft/charm_builder.py index fed4ae934..f683cc020 100644 --- a/charmcraft/charm_builder.py +++ b/charmcraft/charm_builder.py @@ -322,13 +322,12 @@ def handle_dependencies(self): # copy the virtual environment directory to /venv in charm venv_dir = self.installdir / VENV_DIRNAME - shutil.copytree(pathlib.Path(STAGING_VENV_DIRNAME), venv_dir) + shutil.copytree(staging_venv_dir, venv_dir) # symlink /site-packages directory in charm to virtual environment site-packages directory # (backwards compatability for charms that do not use the full virtual environment) - site_packages_dir = _find_venv_site_packages(venv_dir) site_packages_symlink_path = self.installdir / SITE_PACKAGES_SYMLINK_NAME site_packages_symlink_path.unlink(missing_ok=True) - site_packages_symlink_path.symlink_to(site_packages_dir) + site_packages_symlink_path.symlink_to(_find_venv_site_packages(pathlib.Path(VENV_DIRNAME))) def _find_venv_bin(basedir, exec_base): From 8b3df600d34bc09d6da93eea1cf020274f6c930b Mon Sep 17 00:00:00 2001 From: Carl Csaposs Date: Fri, 19 May 2023 19:38:10 +0000 Subject: [PATCH 09/10] Remove unused variable --- charmcraft/charm_builder.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/charmcraft/charm_builder.py b/charmcraft/charm_builder.py index f683cc020..7b71daf1f 100644 --- a/charmcraft/charm_builder.py +++ b/charmcraft/charm_builder.py @@ -321,8 +321,7 @@ def handle_dependencies(self): hash_file.write_text(current_deps_hash, encoding="utf8") # copy the virtual environment directory to /venv in charm - venv_dir = self.installdir / VENV_DIRNAME - shutil.copytree(staging_venv_dir, venv_dir) + shutil.copytree(staging_venv_dir, self.installdir / VENV_DIRNAME) # symlink /site-packages directory in charm to virtual environment site-packages directory # (backwards compatability for charms that do not use the full virtual environment) site_packages_symlink_path = self.installdir / SITE_PACKAGES_SYMLINK_NAME From 76976c25715ac1db6ac4717077a0af25a58ef702 Mon Sep 17 00:00:00 2001 From: Carl Csaposs Date: Fri, 19 May 2023 19:45:29 +0000 Subject: [PATCH 10/10] Use relative basedir path to fix unit tests --- charmcraft/charm_builder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charmcraft/charm_builder.py b/charmcraft/charm_builder.py index 7b71daf1f..9022ab810 100644 --- a/charmcraft/charm_builder.py +++ b/charmcraft/charm_builder.py @@ -321,7 +321,7 @@ def handle_dependencies(self): hash_file.write_text(current_deps_hash, encoding="utf8") # copy the virtual environment directory to /venv in charm - shutil.copytree(staging_venv_dir, self.installdir / VENV_DIRNAME) + shutil.copytree(pathlib.Path(STAGING_VENV_DIRNAME), self.installdir / VENV_DIRNAME) # symlink /site-packages directory in charm to virtual environment site-packages directory # (backwards compatability for charms that do not use the full virtual environment) site_packages_symlink_path = self.installdir / SITE_PACKAGES_SYMLINK_NAME