Skip to content

Commit

Permalink
(backport) pin pip<23.1 and setuptools<67 (#654)
Browse files Browse the repository at this point in the history
to allow PEP-440 non compliance.

(backported relevant parts from master branch in #653)

PEP-440 is more strict about requirement lines.  As an example:

    pytz>dev

is non-compliant, but is in 5.2.4 of kombu's requirements.  This breaks
building wheelhouses from source (such as the octavia charm).  This
patch pins pip and setuptools to the latest versions that will defintely
still allow PEP-440 non-compliant packages to install.

The option --upgrade-buildvenv-core-deps can be used to override this
and will install the latest versions of pip and setuptools available.

Fixes-Bug: #652
  • Loading branch information
ajkavanagh authored Mar 15, 2023
1 parent 98edcd3 commit 28bd804
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 3 deletions.
1 change: 1 addition & 0 deletions charmtools/build/tactics.py
Original file line number Diff line number Diff line change
Expand Up @@ -1230,6 +1230,7 @@ def __call__(self):
utils.Process(
('virtualenv', '--python', 'python3', self._venv)
).exit_on_error()()
utils.pin_setuptools_for_pep440(self._venv, env=utils.host_env())
if self.per_layer:
self._process_per_layer(wheelhouse)
else:
Expand Down
33 changes: 33 additions & 0 deletions charmtools/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -633,3 +633,36 @@ def validate_display_name(entity, linter):
linter.err('display-name: not in valid format. '
'Only letters, numbers, dashes, and hyphens are permitted.')
return


def host_env():
"""Get environment appropriate for executing commands outside snap context.
:returns: Dictionary with environment variables
:rtype: Dict[str,str]
"""
env = os.environ.copy()
for key in ('PREFIX', 'PYTHONHOME', 'PYTHONPATH',
'GIT_TEMPLATE_DIR', 'GIT_EXEC_PATH'):
if key in env:
del(env[key])
env['PATH'] = ':'.join([
element
for element in env['PATH'].split(':')
if not element.startswith('/snap/charm/')])
return env


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()()
6 changes: 4 additions & 2 deletions tests/test_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -431,14 +431,16 @@ def test_version_tactic_with_existing_version_file(self, mcall, ph, pi,

self.assertEqual((bu.target_dir / 'version').text(), 'sha2')

@mock.patch("charmtools.utils.pin_setuptools_for_pep440")
@mock.patch("charmtools.utils.sign")
@mock.patch("charmtools.build.builder.Builder.plan_version")
@mock.patch("charmtools.build.builder.Builder.plan_interfaces")
@mock.patch("charmtools.build.builder.Builder.plan_hooks")
@mock.patch("path.Path.rmtree_p")
@mock.patch("tempfile.mkdtemp")
@mock.patch("charmtools.utils.Process")
def test_wheelhouse(self, Process, mkdtemp, rmtree_p, ph, pi, pv, sign):
def test_wheelhouse(self, Process, mkdtemp, rmtree_p, ph, pi, pv, sign,
pin_setuptools_for_pep440):
build.tactics.WheelhouseTactic.per_layer = False
mkdtemp.return_value = '/tmp'
bu = build.Builder()
Expand Down Expand Up @@ -486,7 +488,7 @@ def _store_wheelhouses(args):
'',
'# --wheelhouse-overrides',
'git+https://github.com/me/qux#egg=qux',
'setuptools_scm>=3.0<=3.4.1',
'setuptools_scm>=3.0,<=3.4.1',
'',
])

Expand Down
25 changes: 25 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import print_function

import unittest
from unittest import TestCase
from charmtools import utils
from six import StringIO
Expand Down Expand Up @@ -43,3 +44,27 @@ def react(db):
self.assertIn("Beta", output)
self.assertIn("@when('db.ready'", output)
self.assertIn("bar", output)

@unittest.mock.patch("os.environ")
def test_host_env(self, mock_environ):
mock_environ.copy.return_value = {
'PREFIX': 'fake-prefix',
'PYTHONHOME': 'fake-pythonhome',
'PYTHONPATH': 'fake-pythonpath',
'GIT_TEMPLATE_DIR': 'fake-git-template-dir',
'GIT_EXEC_PATH': 'fake-git-exec-path',
'SOME_OTHER_KEY': 'fake-some-other-key',
'PATH': '/snap/charm/current/bin:/usr/bin:'
'/snap/charm/current/usr/bin:/bin',
}
self.assertDictEqual(
{'SOME_OTHER_KEY': 'fake-some-other-key', 'PATH': '/usr/bin:/bin'},
utils.host_env())

@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'})
2 changes: 1 addition & 1 deletion tests/wh-over.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
git+https://github.com/me/qux#egg=qux
setuptools_scm>=3.0<=3.4.1
setuptools_scm>=3.0,<=3.4.1

0 comments on commit 28bd804

Please sign in to comment.