diff --git a/charmtools/build/tactics.py b/charmtools/build/tactics.py index c3ca269..49b7351 100644 --- a/charmtools/build/tactics.py +++ b/charmtools/build/tactics.py @@ -1252,6 +1252,8 @@ def __call__(self): ).exit_on_error()() if self.upgrade_deps: utils.upgrade_venv_core_packages(self._venv, env=self._get_env()) + else: + utils.pin_setuptools_for_pep440(self._venv, env=self._get_env()) log.debug( 'Packages in buildvenv:\n{}' .format( diff --git a/charmtools/utils.py b/charmtools/utils.py index ed41983..961e288 100644 --- a/charmtools/utils.py +++ b/charmtools/utils.py @@ -670,6 +670,24 @@ def upgrade_venv_core_packages(venv_dir, env=None): env=env).exit_on_error()() +def pin_setuptools_for_pep440(venv_dir, env=None): + """Pin setuptools so that pep440 non-compliant packages can be installed. + + Also pins pip as it's a combination that definitely works. + + :param venv_dir: Full path to virtualenv in which packages will be upgraded + :type venv_dir: str + :param env: Environment to use when executing command + :type env: Optional[Dict[str,str]] + :returns: This function is called for its side effect + """ + log.debug('Pinning setuptools < 67 for pep440 non compliant packages "{}"' + .format(venv_dir)) + Process((os.path.join(venv_dir, 'bin/pip'), + 'install', '-U', 'pip<23.1', 'setuptools<67'), + env=env).exit_on_error()() + + def get_venv_package_list(venv_dir, env=None): """Get list of packages and their version in virtualenv. diff --git a/tests/test_utils.py b/tests/test_utils.py index 800d7ac..4339cf9 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -68,6 +68,14 @@ def test_upgrade_venv_core_packages(self, mock_Process): ('/some/dir/bin/pip', 'install', '-U', 'pip', 'setuptools'), env={'some': 'envvar'}) + @unittest.mock.patch.object(utils, "Process") + def test_pin_setuptools_for_pep440(self, mock_Process): + utils.pin_setuptools_for_pep440('/some/dir', env={'some': 'envvar'}) + mock_Process.assert_called_once_with( + ('/some/dir/bin/pip', 'install', '-U', 'pip<23.1', + 'setuptools<67'), + env={'some': 'envvar'}) + @unittest.mock.patch("sys.exit") @unittest.mock.patch.object(utils, "Process") def test_get_venv_package_list(self, mock_Process, mock_sys_exit):