diff options
author | Bernát Gábor <gaborjbernat@gmail.com> | 2018-08-29 19:28:00 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-08-29 19:28:00 +0100 |
commit | cb13cd6d7fe41baf4668b884ec4fbedd1e8159f5 (patch) | |
tree | b5c6dc8f6a473b52507d06ede3238c973bc56ad9 | |
parent | c6112ce73e50990991fa5a673ebcc52d597bc50c (diff) | |
download | tox-git-cb13cd6d7fe41baf4668b884ec4fbedd1e8159f5.tar.gz |
Expose the packaging as a plugin hook (#952)
Resolves #951. This will allow having PEP-517/518 for the end users.
-rw-r--r-- | changelog/951.feature.rst | 1 | ||||
-rwxr-xr-x | src/tox/config.py | 3 | ||||
-rw-r--r-- | src/tox/hookspecs.py | 7 | ||||
-rw-r--r-- | src/tox/package.py | 85 | ||||
-rw-r--r-- | src/tox/session.py | 90 | ||||
-rw-r--r-- | tests/test_package.py | 140 | ||||
-rw-r--r-- | tests/test_z_cmdline.py | 133 |
7 files changed, 241 insertions, 218 deletions
diff --git a/changelog/951.feature.rst b/changelog/951.feature.rst new file mode 100644 index 00000000..0dd27638 --- /dev/null +++ b/changelog/951.feature.rst @@ -0,0 +1 @@ +packaging now is exposed as a hook via ``tox_package(session, venv)`` - by :user:`gaborbernat` diff --git a/src/tox/config.py b/src/tox/config.py index f381d843..891eb0a9 100755 --- a/src/tox/config.py +++ b/src/tox/config.py @@ -43,6 +43,9 @@ def get_plugin_manager(plugins=()): pm.register(tox.interpreters) pm.register(tox.venv) pm.register(tox.session) + from tox import package + + pm.register(package) pm.load_setuptools_entrypoints("tox") for plugin in plugins: pm.register(plugin) diff --git a/src/tox/hookspecs.py b/src/tox/hookspecs.py index fca24f4a..e4a2bf2a 100644 --- a/src/tox/hookspecs.py +++ b/src/tox/hookspecs.py @@ -18,6 +18,13 @@ def tox_configure(config): @hookspec(firstresult=True) +def tox_package(session, venv): + """Return the package to be installed for the given venv. + + Called once for every environment.""" + + +@hookspec(firstresult=True) def tox_get_python_executable(envconfig): """Return a python executable for the given python base name. diff --git a/src/tox/package.py b/src/tox/package.py new file mode 100644 index 00000000..b23cb1a3 --- /dev/null +++ b/src/tox/package.py @@ -0,0 +1,85 @@ +import sys + +import py + +import tox + + +@tox.hookimpl +def tox_package(session, venv): + """Build an sdist at first call return that for all calls""" + if not hasattr(session, "package"): + session.package = get_package(session) + return session.package + + +def get_package(session): + """"Perform the package operation""" + config, report = session.config, session.report + if config.skipsdist: + report.info("skipping sdist step") + return None + if not config.option.sdistonly and (config.sdistsrc or config.option.installpkg): + path = config.option.installpkg + if not path: + path = config.sdistsrc + path = session._resolve_package(path) + report.info("using package {!r}, skipping 'sdist' activity ".format(str(path))) + else: + try: + path = make_sdist(report, config, session) + except tox.exception.InvocationError: + v = sys.exc_info()[1] + report.error("FAIL could not package project - v = {!r}".format(v)) + return None + sdist_file = config.distshare.join(path.basename) + if sdist_file != path: + report.info("copying new sdistfile to {!r}".format(str(sdist_file))) + try: + sdist_file.dirpath().ensure(dir=1) + except py.error.Error: + report.warning("could not copy distfile to {}".format(sdist_file.dirpath())) + else: + path.copy(sdist_file) + return path + + +def make_sdist(report, config, session): + setup = config.setupdir.join("setup.py") + if not setup.check(): + report.error( + "No setup.py file found. The expected location is:\n" + " {}\n" + "You can\n" + " 1. Create one:\n" + " https://packaging.python.org/tutorials/distributing-packages/#setup-py\n" + " 2. Configure tox to avoid running sdist:\n" + " http://tox.readthedocs.io/en/latest/example/general.html" + "#avoiding-expensive-sdist".format(setup) + ) + raise SystemExit(1) + with session.newaction(None, "packaging") as action: + action.setactivity("sdist-make", setup) + session.make_emptydir(config.distdir) + action.popen( + [sys.executable, setup, "sdist", "--formats=zip", "--dist-dir", config.distdir], + cwd=config.setupdir, + ) + try: + return config.distdir.listdir()[0] + except py.error.ENOENT: + # check if empty or comment only + data = [] + with open(str(setup)) as fp: + for line in fp: + if line and line[0] == "#": + continue + data.append(line) + if not "".join(data).strip(): + report.error("setup.py is empty") + raise SystemExit(1) + report.error( + "No dist directory found. Please check setup.py, e.g with:\n" + " python setup.py sdist" + ) + raise SystemExit(1) diff --git a/src/tox/session.py b/src/tox/session.py index ef170809..12db45cf 100644 --- a/src/tox/session.py +++ b/src/tox/session.py @@ -431,53 +431,6 @@ class Session: target.dirpath().ensure(dir=1) src.copy(target) - def _makesdist(self): - setup = self.config.setupdir.join("setup.py") - if not setup.check(): - self.report.error( - "No setup.py file found. The expected location is:\n" - " {}\n" - "You can\n" - " 1. Create one:\n" - " https://packaging.python.org/tutorials/distributing-packages/#setup-py\n" - " 2. Configure tox to avoid running sdist:\n" - " http://tox.readthedocs.io/en/latest/example/general.html" - "#avoiding-expensive-sdist".format(setup) - ) - raise SystemExit(1) - with self.newaction(None, "packaging") as action: - action.setactivity("sdist-make", setup) - self.make_emptydir(self.config.distdir) - action.popen( - [ - sys.executable, - setup, - "sdist", - "--formats=zip", - "--dist-dir", - self.config.distdir, - ], - cwd=self.config.setupdir, - ) - try: - return self.config.distdir.listdir()[0] - except py.error.ENOENT: - # check if empty or comment only - data = [] - with open(str(setup)) as fp: - for line in fp: - if line and line[0] == "#": - continue - data.append(line) - if not "".join(data).strip(): - self.report.error("setup.py is empty") - raise SystemExit(1) - self.report.error( - "No dist directory found. Please check setup.py, e.g with:\n" - " python setup.py sdist" - ) - raise SystemExit(1) - def make_emptydir(self, path): if path.check(): self.report.info(" removing {}".format(path)) @@ -564,47 +517,14 @@ class Session: venv.status = sys.exc_info()[1] return False - def get_installpkg_path(self): - """ - :return: Path to the distribution - :rtype: py.path.local - """ - if not self.config.option.sdistonly and ( - self.config.sdistsrc or self.config.option.installpkg - ): - path = self.config.option.installpkg - if not path: - path = self.config.sdistsrc - path = self._resolve_package(path) - self.report.info("using package {!r}, skipping 'sdist' activity ".format(str(path))) - else: - try: - path = self._makesdist() - except tox.exception.InvocationError: - v = sys.exc_info()[1] - self.report.error("FAIL could not package project - v = {!r}".format(v)) - return - sdistfile = self.config.distshare.join(path.basename) - if sdistfile != path: - self.report.info("copying new sdistfile to {!r}".format(str(sdistfile))) - try: - sdistfile.dirpath().ensure(dir=1) - except py.error.Error: - self.report.warning( - "could not copy distfile to {}".format(sdistfile.dirpath()) - ) - else: - path.copy(sdistfile) - return path - def subcommand_test(self): if self.config.skipsdist: self.report.info("skipping sdist step") - path = None else: - path = self.get_installpkg_path() - if not path: - return 2 + for venv in self.venvlist: + venv.package = self.hook.tox_package(session=self, venv=venv) + if not venv.package: + return 2 if self.config.option.sdistonly: return for venv in self.venvlist: @@ -617,7 +537,7 @@ class Session: elif self.config.skipsdist: self.finishvenv(venv) else: - self.installpkg(venv, path) + self.installpkg(venv, venv.package) self.runenvreport(venv) self.runtestenv(venv) diff --git a/tests/test_package.py b/tests/test_package.py new file mode 100644 index 00000000..e8bd0961 --- /dev/null +++ b/tests/test_package.py @@ -0,0 +1,140 @@ +import re + +from tox.config import parseconfig +from tox.package import get_package +from tox.session import Session + + +def test_make_sdist(initproj): + initproj( + "example123-0.5", + filedefs={ + "tests": {"test_hello.py": "def test_hello(): pass"}, + "tox.ini": """ + """, + }, + ) + config = parseconfig([]) + session = Session(config) + sdist = get_package(session) + assert sdist.check() + assert sdist.ext == ".zip" + assert sdist == config.distdir.join(sdist.basename) + sdist2 = get_package(session) + assert sdist2 == sdist + sdist.write("hello") + assert sdist.stat().size < 10 + sdist_new = get_package(Session(config)) + assert sdist_new == sdist + assert sdist_new.stat().size > 10 + + +def test_make_sdist_distshare(tmpdir, initproj): + distshare = tmpdir.join("distshare") + initproj( + "example123-0.6", + filedefs={ + "tests": {"test_hello.py": "def test_hello(): pass"}, + "tox.ini": """ + [tox] + distshare={} + """.format( + distshare + ), + }, + ) + config = parseconfig([]) + session = Session(config) + sdist = get_package(session) + assert sdist.check() + assert sdist.ext == ".zip" + assert sdist == config.distdir.join(sdist.basename) + sdist_share = config.distshare.join(sdist.basename) + assert sdist_share.check() + assert sdist_share.read("rb") == sdist.read("rb"), (sdist_share, sdist) + + +def test_sdistonly(initproj, cmd): + initproj( + "example123", + filedefs={ + "tox.ini": """ + """ + }, + ) + result = cmd("-v", "--sdistonly") + assert not result.ret + assert re.match(r".*sdist-make.*setup.py.*", result.out, re.DOTALL) + assert "-mvirtualenv" not in result.out + + +def test_separate_sdist_no_sdistfile(cmd, initproj, tmpdir): + distshare = tmpdir.join("distshare") + initproj( + ("pkg123-foo", "0.7"), + filedefs={ + "tox.ini": """ + [tox] + distshare={} + """.format( + distshare + ) + }, + ) + result = cmd("--sdistonly") + assert not result.ret + distshare_files = distshare.listdir() + assert len(distshare_files) == 1 + sdistfile = distshare_files[0] + assert "pkg123-foo-0.7.zip" in str(sdistfile) + + +def test_separate_sdist(cmd, initproj, tmpdir): + distshare = tmpdir.join("distshare") + initproj( + "pkg123-0.7", + filedefs={ + "tox.ini": """ + [tox] + distshare={} + sdistsrc={{distshare}}/pkg123-0.7.zip + """.format( + distshare + ) + }, + ) + result = cmd("--sdistonly") + assert not result.ret + sdistfiles = distshare.listdir() + assert len(sdistfiles) == 1 + sdistfile = sdistfiles[0] + result = cmd("-v", "--notest") + assert not result.ret + assert "python inst: {}".format(sdistfile) in result.out + + +def test_sdist_latest(tmpdir, newconfig): + distshare = tmpdir.join("distshare") + config = newconfig( + [], + """ + [tox] + distshare={} + sdistsrc={{distshare}}/pkg123-* + """.format( + distshare + ), + ) + p = distshare.ensure("pkg123-1.4.5.zip") + distshare.ensure("pkg123-1.4.5a1.zip") + session = Session(config) + sdist_path = get_package(session) + assert sdist_path == p + + +def test_installpkg(tmpdir, newconfig): + p = tmpdir.ensure("pkg123-1.0.zip") + config = newconfig(["--installpkg={}".format(p)], "") + session = Session(config) + sdist_path = get_package(session) + assert sdist_path == p diff --git a/tests/test_z_cmdline.py b/tests/test_z_cmdline.py index 42104c97..20eed9f7 100644 --- a/tests/test_z_cmdline.py +++ b/tests/test_z_cmdline.py @@ -45,53 +45,6 @@ def test_report_protocol(newconfig): class TestSession: - def test_make_sdist(self, initproj): - initproj( - "example123-0.5", - filedefs={ - "tests": {"test_hello.py": "def test_hello(): pass"}, - "tox.ini": """ - """, - }, - ) - config = parseconfig([]) - session = Session(config) - sdist = session.get_installpkg_path() - assert sdist.check() - assert sdist.ext == ".zip" - assert sdist == config.distdir.join(sdist.basename) - sdist2 = session.get_installpkg_path() - assert sdist2 == sdist - sdist.write("hello") - assert sdist.stat().size < 10 - sdist_new = Session(config).get_installpkg_path() - assert sdist_new == sdist - assert sdist_new.stat().size > 10 - - def test_make_sdist_distshare(self, tmpdir, initproj): - distshare = tmpdir.join("distshare") - initproj( - "example123-0.6", - filedefs={ - "tests": {"test_hello.py": "def test_hello(): pass"}, - "tox.ini": """ - [tox] - distshare={} - """.format( - distshare - ), - }, - ) - config = parseconfig([]) - session = Session(config) - sdist = session.get_installpkg_path() - assert sdist.check() - assert sdist.ext == ".zip" - assert sdist == config.distdir.join(sdist.basename) - sdist_share = config.distshare.join(sdist.basename) - assert sdist_share.check() - assert sdist_share.read("rb") == sdist.read("rb"), (sdist_share, sdist) - def test_log_pcall(self, mocksession): mocksession.config.logdir.ensure(dir=1) assert not mocksession.config.logdir.listdir() @@ -787,92 +740,6 @@ def test_env_VIRTUALENV_PYTHON(initproj, cmd, monkeypatch): assert "create" in result.out -def test_sdistonly(initproj, cmd): - initproj( - "example123", - filedefs={ - "tox.ini": """ - """ - }, - ) - result = cmd("-v", "--sdistonly") - assert not result.ret - assert re.match(r".*sdist-make.*setup.py.*", result.out, re.DOTALL) - assert "-mvirtualenv" not in result.out - - -def test_separate_sdist_no_sdistfile(cmd, initproj, tmpdir): - distshare = tmpdir.join("distshare") - initproj( - ("pkg123-foo", "0.7"), - filedefs={ - "tox.ini": """ - [tox] - distshare={} - """.format( - distshare - ) - }, - ) - result = cmd("--sdistonly") - assert not result.ret - distshare_files = distshare.listdir() - assert len(distshare_files) == 1 - sdistfile = distshare_files[0] - assert "pkg123-foo-0.7.zip" in str(sdistfile) - - -def test_separate_sdist(cmd, initproj, tmpdir): - distshare = tmpdir.join("distshare") - initproj( - "pkg123-0.7", - filedefs={ - "tox.ini": """ - [tox] - distshare={} - sdistsrc={{distshare}}/pkg123-0.7.zip - """.format( - distshare - ) - }, - ) - result = cmd("--sdistonly") - assert not result.ret - sdistfiles = distshare.listdir() - assert len(sdistfiles) == 1 - sdistfile = sdistfiles[0] - result = cmd("-v", "--notest") - assert not result.ret - assert "python inst: {}".format(sdistfile) in result.out - - -def test_sdist_latest(tmpdir, newconfig): - distshare = tmpdir.join("distshare") - config = newconfig( - [], - """ - [tox] - distshare={} - sdistsrc={{distshare}}/pkg123-* - """.format( - distshare - ), - ) - p = distshare.ensure("pkg123-1.4.5.zip") - distshare.ensure("pkg123-1.4.5a1.zip") - session = Session(config) - sdist_path = session.get_installpkg_path() - assert sdist_path == p - - -def test_installpkg(tmpdir, newconfig): - p = tmpdir.ensure("pkg123-1.0.zip") - config = newconfig(["--installpkg={}".format(p)], "") - session = Session(config) - sdist_path = session.get_installpkg_path() - assert sdist_path == p - - def test_envsitepackagesdir(cmd, initproj): initproj( "pkg512-0.0.5", |