diff --git a/gpep517/__main__.py b/gpep517/__main__.py index 362e41f..d519c75 100644 --- a/gpep517/__main__.py +++ b/gpep517/__main__.py @@ -86,20 +86,16 @@ def override_writestr(self, zinfo_or_arcname, data, @contextlib.contextmanager def patch_sysconfig(sysroot: Path, - prefix_from: typing.Optional[Path], - prefix_to: typing.Optional[Path], + prefix: typing.Optional[Path], ): - stdlib_path = Path(sysconfig.get_path("stdlib")) + get_vars = {} + if prefix is not None: + get_vars["installed_base"] = prefix + + stdlib_path = Path(sysconfig.get_path("stdlib", vars=get_vars)) if not stdlib_path.is_absolute(): raise RuntimeError(f"stdlib path {stdlib_path} is not absolute") - try: - unprefixed_stdlib = stdlib_path.relative_to(prefix_from or "/") - except ValueError: - raise RuntimeError(f"stdlib path {stdlib_path!r} does not start with " - f"specified prefix {prefix_from!r}; was correct " - "path passed to --rewrite-prefix-from") - prefixed_stdlib = Path(prefix_to or "/") / unprefixed_stdlib - sysroot_stdlib = sysroot / prefixed_stdlib.relative_to("/") + sysroot_stdlib = sysroot / stdlib_path.relative_to("/") logger.info(f"Searching for sysconfig in {sysroot_stdlib}") data_paths = list(sysroot_stdlib.glob("_sysconfigdata_*.py")) if len(data_paths) != 1: @@ -184,16 +180,7 @@ def build_wheel_impl(args, wheel_dir: Path): if args.sysroot is not None: sysconfig_ctx = patch_sysconfig(args.sysroot, - args.rewrite_prefix_from, - args.rewrite_prefix_to) - elif args.rewrite_prefix_from is not None: - raise RuntimeError( - "The --rewrite-prefix-from argument must only be specified " - "together with the --sysroot option") - elif args.rewrite_prefix_to is not None: - raise RuntimeError( - "The --rewrite-prefix-to argument must only be specified " - "together with the --sysroot option") + args.prefix) else: sysconfig_ctx = contextlib.nullcontext() @@ -255,7 +242,8 @@ def install_wheel_impl(args, wheel: Path): with WheelFile.open(wheel) as source: dest = SchemeDictionaryDestination( - install_scheme_dict(args.prefix, source.distribution), + install_scheme_dict(args.prefix or DEFAULT_PREFIX, + source.distribution), str(args.interpreter), get_launcher_kind(), bytecode_optimization_levels=args.optimize, @@ -284,7 +272,7 @@ def install_from_source(args): def verify_pyc(args): from gpep517.qa import qa_verify_pyc - install_dict = install_scheme_dict(args.prefix, "") + install_dict = install_scheme_dict(args.prefix or DEFAULT_PREFIX, "") sitedirs = frozenset(Path(install_dict[x]) for x in ("purelib", "platlib")) result = qa_verify_pyc(args.destdir, sitedirs) @@ -299,29 +287,19 @@ def fpath(p): return 1 if any(v for v in result.values()) else 0 -def add_install_path_args(parser): - group = parser.add_argument_group("install paths") - group.add_argument("--destdir", - type=Path, - help="Staging directory for the install (it will " - "be prepended to all paths)", - required=True) - group.add_argument("--prefix", - type=Path, - default=DEFAULT_PREFIX, - help="Prefix to install to " - f"(default: {DEFAULT_PREFIX})") - +def add_prefix_args(parser): + parser.add_argument("--prefix", + type=Path, + help="Prefix to install to " + f"(default: {DEFAULT_PREFIX})") -def PrefixPath(value: str) -> Path: - if value == "": - return Path("/") - path = Path(value) - if not path.is_absolute(): - raise argparse.ArgumentTypeError( - f"argument is not an absolute path: {value!r}") - return path +def add_install_path_args(parser): + parser.add_argument("--destdir", + type=Path, + help="Staging directory for the install (it will " + "be prepended to all paths)", + required=True) def add_build_args(parser): @@ -359,14 +337,6 @@ def add_build_args(parser): help="Patch sysconfig paths to use specified sysroot " "(experimental cross-compilation support)", type=Path) - group.add_argument("--rewrite-prefix-from", - help="Additional prefix applied to the build host " - "(only applicable with --sysroot option)", - type=PrefixPath) - group.add_argument("--rewrite-prefix-to", - help="Additional prefix applied to the target host " - "(only applicable with --sysroot option)", - type=PrefixPath) def add_install_args(parser): @@ -421,16 +391,19 @@ def main(argv=sys.argv): type=Path, help="Directory to write the wheel into", required=True) + add_prefix_args(parser) add_build_args(parser) parser = subp.add_parser("install-from-source", help="Build and install wheel from sources " "(without preserving the wheel)") + add_prefix_args(parser) add_build_args(parser) add_install_args(parser) parser = subp.add_parser("install-wheel", help="Install the specified wheel") + add_prefix_args(parser) add_install_args(parser) parser.add_argument("wheel", type=Path, @@ -440,6 +413,7 @@ def main(argv=sys.argv): help="Verify that all installed modules were " "byte-compiled and there are no stray .pyc " "files") + add_prefix_args(parser) add_install_path_args(parser) args = argp.parse_args(argv[1:]) diff --git a/test/test_main.py b/test/test_main.py index fd98889..d3150c9 100644 --- a/test/test_main.py +++ b/test/test_main.py @@ -8,7 +8,6 @@ import shutil import sys import sysconfig -import unittest.mock import zipfile import pytest @@ -425,41 +424,32 @@ def test_backend_opening_zipfile(tmp_path, capfd, backend, verify_mod_cleanup, == {x.compress_type for x in zipf.infolist()}) -@pytest.mark.parametrize("prefix_from", [None, "", "/", "/old_prefix", - "/old_prefix/"]) -@pytest.mark.parametrize("prefix_to", [None, "", "/", "/new_prefix", - "/new_prefix/"]) +@pytest.mark.parametrize("prefix", [None, "/usr", "/new_prefix/usr"]) def test_sysroot(tmp_path, capfd, verify_mod_cleanup, distutils_cache_cleanup, - prefix_from, prefix_to): + prefix): with open(tmp_path / "pyproject.toml", "w") as f: f.write(ZIP_BACKEND_TOML.format(backend="sysroot_backend")) + default_prefix = sysconfig.get_config_var("installed_base") base_stdlib_path = ( - pathlib.Path(sysconfig.get_path("stdlib")).relative_to("/")) - prefix_from_stdlib_path = ( - (prefix_from or "").lstrip("/") / base_stdlib_path) + pathlib.Path(sysconfig.get_path("stdlib")).relative_to(default_prefix)) - norm_prefix_to = (prefix_to or "").rstrip("/") - tmp_prefix = tmp_path / norm_prefix_to.lstrip("/") + norm_prefix_to = (prefix or default_prefix) + tmp_prefix = tmp_path / pathlib.Path(norm_prefix_to).relative_to("/") stdlib_path = tmp_prefix / base_stdlib_path stdlib_path.mkdir(parents=True) (tmp_prefix / "foo/include/python3.11").mkdir(parents=True) with open(stdlib_path / "_sysconfigdata__linux_i386-linux-gnu.py", "w") as f: - f.write(SYSCONFIG_DATA.replace("/foo", norm_prefix_to + "/foo")) + f.write(SYSCONFIG_DATA.replace("/foo", f"{norm_prefix_to}/foo")) - with unittest.mock.patch("sysconfig.get_path") as patched_get_path: - patched_get_path.return_value = "/" + str(prefix_from_stdlib_path) - assert 0 == main(["", "build-wheel", - "--allow-compressed", - "--output-fd", "1", - "--pyproject-toml", str(tmp_path / "pyproject.toml"), - "--sysroot", str(tmp_path), - "--wheel-dir", str(tmp_path)] + - (["--rewrite-prefix-from", prefix_from] - if prefix_from is not None else []) + - (["--rewrite-prefix-to", prefix_to] - if prefix_to is not None else [])) + assert 0 == main(["", "build-wheel", + "--allow-compressed", + "--output-fd", "1", + "--pyproject-toml", str(tmp_path / "pyproject.toml"), + "--sysroot", str(tmp_path), + "--wheel-dir", str(tmp_path)] + + (["--prefix", prefix] if prefix is not None else [])) assert "data.json\n" == capfd.readouterr().out with open(tmp_path / "data.json", "r") as f: