diff --git a/AUTHORS.rst b/AUTHORS.rst index 8f56586..c3ac262 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -6,3 +6,4 @@ Authors * Antonio Botelho - https://github.com/botant * Thomas Grainger - https://github.com/graingert * Michael Rans - https://github.com/mcarans +* Ben Rowland - https://github.com/bennyrowland diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c166d67..b26d5a2 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog ========= +Unreleased changes +------------------ + +* Added option to build wheels (and sdists) in an isolated environment using `build `_. + Contributed by Ben Rowland in `#17 `_. + 0.7.0 (2021-12-29) ------------------ diff --git a/src/tox_wheel/plugin.py b/src/tox_wheel/plugin.py index 0371185..4884e60 100644 --- a/src/tox_wheel/plugin.py +++ b/src/tox_wheel/plugin.py @@ -1,5 +1,6 @@ from contextlib import contextmanager from functools import partial +import os.path import pluggy import py @@ -32,9 +33,12 @@ def tox_addoption(parser): ) parser.add_testenv_attribute( name="wheel_pep517", - type="bool", - default=False, - help="Build wheel using PEP 517/518" + type="string", + default="", + help=( + "Build wheel using PEP 517/518 (pass true to build with pip or " + "build to build with build)" + ), ) parser.add_testenv_attribute( name="wheel_dirty", @@ -60,6 +64,13 @@ def patch(obj, attr, value): setattr(obj, attr, original) +@hookimpl +def tox_testenv_install_deps(venv, action): + if venv.envconfig.wheel_pep517 == "build": + venv.run_install_command(["build[virtualenv]>=0.7.0"], action) + return None + + @hookimpl def tox_package(session, venv): if session.config.option.wheel or venv.envconfig.wheel: @@ -153,16 +164,36 @@ def wheel_build_pep517(config, session, venv): action.setactivity("wheel-make", "cleaning up build directory ...") ensure_empty_dir(config.setupdir.join("build")) ensure_empty_dir(config.distdir) + if venv.envconfig.wheel_pep517 == "build": + commands = [ + "python", + "-Im", + "build", + "--outdir", + config.distdir, + config.setupdir, + ] + else: + commands = [ + "pip", + "wheel", + config.setupdir, + "--no-deps", + "--use-pep517", + "--wheel-dir", + config.distdir, + ] venv.test( name="wheel-make", - commands=[["pip", "wheel", config.setupdir, "--no-deps", "--use-pep517", "--wheel-dir", config.distdir]], + commands=[commands], redirect=False, ignore_outcome=False, ignore_errors=False, display_hash_seed=False, ) try: - dists = config.distdir.listdir() + # we need to filter our list of dists to include only wheels + dists = [dist for dist in config.distdir.listdir() if os.path.splitext(dist)[1] == ".whl"] except py.error.ENOENT: reporter.error( "No dist directory found. Please check pyproject.toml, e.g with:\n" diff --git a/tests/test_tox_wheel.py b/tests/test_tox_wheel.py index 7f3cd4e..6c24df6 100644 --- a/tests/test_tox_wheel.py +++ b/tests/test_tox_wheel.py @@ -54,6 +54,32 @@ def testdir_pep517(testdir): return testdir +@pytest.fixture +def testdir_pep517_build(testdir): + testdir.tmpdir.join('tox.ini').write(""" +[tox] +envlist = py-{a,b} + +[testenv] +wheel = true +wheel_pep517 = build +""") + testdir.tmpdir.join('setup.py').write(""" +from setuptools import setup + +setup(name='foobar', packages=[]) +""") + testdir.tmpdir.join('pyproject.toml').write(""" +[build-system] +requires = [ + "setuptools >= 35.0.2" +] +build-backend = "setuptools.build_meta" +""") + testdir.tmpdir.join('build').ensure(dir=1) + return testdir + + @pytest.fixture(params=['', '--parallel 1 --parallel-live'], ids=['sequential', 'parallel']) def options(request): return ['-e', 'py-a,py-b'] + request.param.split() @@ -99,6 +125,16 @@ def test_enabled_pep517(testdir_pep517, options): assert result.ret == 0 +def test_enabled_pep517_build(testdir_pep517_build, options): + result = testdir_pep517_build.run('tox', *options) + result.stdout.fnmatch_lines([ + 'py* wheel-make: *', + ]) + build_string = 'Successfully built foobar-0.0.0.tar.gz and foobar-0.0.0-py3-none-any.whl' + assert result.stdout.str().count(build_string) == 2 + assert result.ret == 0 + + def test_build_env_legacy(testdir_legacy, options): testdir_legacy.tmpdir.join('setup.cfg').write(""" [bdist_wheel] @@ -141,6 +177,25 @@ def test_build_env_pep517(testdir_pep517, options): assert result.ret == 0 +def test_build_env_pep517_build(testdir_pep517_build, options): + testdir_pep517_build.tmpdir.join('setup.cfg').write(""" +[bdist_wheel] +universal = 1 +""") + testdir_pep517_build.tmpdir.join('tox.ini').write(""" +wheel_build_env = build + +[testenv:build] +""", mode='a') + result = testdir_pep517_build.run('tox', *options) + result.stdout.fnmatch_lines([ + 'build wheel-make: *', + ]) + build_string = 'Successfully built foobar-0.0.0.tar.gz and foobar-0.0.0-py2.py3-none-any.whl' + assert result.stdout.str().count(build_string) == 1 + assert result.ret == 0 + + @pytest.mark.parametrize('wheel_build_env', ['', 'wheel_build_env']) def test_skip_usedevelop(testdir_legacy, options, wheel_build_env): testdir_legacy.tmpdir.join('tox.ini').write("""