summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernát Gábor <gaborjbernat@gmail.com>2018-08-29 19:28:00 +0100
committerGitHub <noreply@github.com>2018-08-29 19:28:00 +0100
commitcb13cd6d7fe41baf4668b884ec4fbedd1e8159f5 (patch)
treeb5c6dc8f6a473b52507d06ede3238c973bc56ad9
parentc6112ce73e50990991fa5a673ebcc52d597bc50c (diff)
downloadtox-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.rst1
-rwxr-xr-xsrc/tox/config.py3
-rw-r--r--src/tox/hookspecs.py7
-rw-r--r--src/tox/package.py85
-rw-r--r--src/tox/session.py90
-rw-r--r--tests/test_package.py140
-rw-r--r--tests/test_z_cmdline.py133
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",