Skip to content

Commit a3c9bd5

Browse files
committed
Implement support for PEP517 backend-path setting
Resolves tox-dev#1575
1 parent f71cfb5 commit a3c9bd5

File tree

2 files changed

+36
-2
lines changed

2 files changed

+36
-2
lines changed

src/tox/helper/build_isolated.py

+11
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
1+
"""PEP 517 build backend invocation script.
2+
3+
It accepts externally parsed build configuration from `[build-system]`
4+
in `pyproject.toml` and invokes an API endpoint for building an sdist
5+
tarball.
6+
"""
7+
8+
import os
19
import sys
210

311
dist_folder = sys.argv[1]
412
backend_spec = sys.argv[2]
513
backend_obj = sys.argv[3] if len(sys.argv) >= 4 else None
14+
backend_paths = sys.argv[4].split(os.path.pathsep) if sys.argv[4] else []
15+
16+
sys.path[:0] = backend_paths
617

718
backend = __import__(backend_spec, fromlist=["_trash"])
819
if backend_obj:

src/tox/package/builder/isolated.py

+25-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import unicode_literals
22

33
import json
4+
import os
45
from collections import namedtuple
56

67
import six
@@ -11,7 +12,9 @@
1112
from tox.config import DepConfig, get_py_project_toml
1213
from tox.constants import BUILD_ISOLATED, BUILD_REQUIRE_SCRIPT
1314

14-
BuildInfo = namedtuple("BuildInfo", ["requires", "backend_module", "backend_object"])
15+
BuildInfo = namedtuple(
16+
"BuildInfo", ["requires", "backend_module", "backend_object", "backend_paths"],
17+
)
1518

1619

1720
def build(config, session):
@@ -47,6 +50,17 @@ def build(config, session):
4750
return perform_isolated_build(build_info, package_venv, config.distdir, config.setupdir)
4851

4952

53+
def _ensure_importable_in_path(python_path, importable):
54+
"""Figure out if the importable exists in the given path."""
55+
mod_chunks = importable.split(".")
56+
pkg_path = python_path.join(*mod_chunks[:-1])
57+
if not pkg_path.exists():
58+
return False
59+
if pkg_path.join(mod_chunks[-1], "__init__.py").exists():
60+
return True
61+
return pkg_path.join(mod_chunks[-1] + ".py").exists()
62+
63+
5064
def get_build_info(folder):
5165
toml_file = folder.join("pyproject.toml")
5266

@@ -84,7 +98,15 @@ def abort(message):
8498
module = args[0]
8599
obj = args[1] if len(args) > 1 else ""
86100

87-
return BuildInfo(requires, module, obj)
101+
backend_paths = build_system.get("backend-path", [])
102+
if not isinstance(backend_paths, list):
103+
abort("backend-path key at build-system section must be a list, if specified")
104+
backend_paths = [folder.join(p) for p in backend_paths]
105+
106+
if backend_paths and not any(_ensure_importable_in_path(p, module) for p in backend_paths):
107+
abort("build-backend must exist in one of the paths specified by backend-path")
108+
109+
return BuildInfo(requires, module, obj, backend_paths)
88110

89111

90112
def perform_isolated_build(build_info, package_venv, dist_dir, setup_dir):
@@ -103,6 +125,7 @@ def perform_isolated_build(build_info, package_venv, dist_dir, setup_dir):
103125
str(dist_dir),
104126
build_info.backend_module,
105127
build_info.backend_object,
128+
os.path.pathsep.join(str(p) for p in build_info.backend_paths),
106129
],
107130
returnout=True,
108131
action=action,

0 commit comments

Comments
 (0)