Skip to content

Commit

Permalink
Add sdist metadata extractor
Browse files Browse the repository at this point in the history
Signed-off-by: Bernát Gábor <gaborjbernat@gmail.com>
  • Loading branch information
gaborbernat committed Sep 25, 2021
1 parent f4b0ea5 commit 87ec3d8
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 32 deletions.
10 changes: 5 additions & 5 deletions src/tox/pytest.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,19 +301,19 @@ def enable_pep517_backend_coverage() -> Iterator[None]: # noqa: PT004
yield # pragma: no cover
return # pragma: no cover
# the COV_ env variables needs to be passed on for the PEP-517 backend
from tox.tox_env.python.virtual_env.package.pep517 import Pep517VirtualEnvPackage
from tox.tox_env.python.virtual_env.package.pep517 import Pep517VirtualEnvPackager

def default_pass_env(self: Pep517VirtualEnvPackage) -> List[str]:
def default_pass_env(self: Pep517VirtualEnvPackager) -> List[str]:
result = previous(self)
result.append("COV_*")
return result

previous = Pep517VirtualEnvPackage._default_pass_env
previous = Pep517VirtualEnvPackager._default_pass_env
try:
Pep517VirtualEnvPackage._default_pass_env = default_pass_env # type: ignore
Pep517VirtualEnvPackager._default_pass_env = default_pass_env # type: ignore
yield
finally:
Pep517VirtualEnvPackage._default_pass_env = previous # type: ignore
Pep517VirtualEnvPackager._default_pass_env = previous # type: ignore


class ToxRunOutcome:
Expand Down
1 change: 1 addition & 0 deletions src/tox/session/cmd/run/single.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,5 +114,6 @@ def run_command_set(tox_env: ToxEnv, key: str, cwd: Path, ignore_errors: bool, o

__all__ = (
"run_one",
"run_command_set",
"ToxEnvRunResult",
)
28 changes: 24 additions & 4 deletions src/tox/tox_env/python/virtual_env/package/cmd_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from io import TextIOWrapper
from os import PathLike
from pathlib import Path
from typing import List, Optional, Set, cast
from typing import Generator, Iterator, List, Optional, Set, Tuple, cast
from zipfile import ZipFile

from packaging.requirements import Requirement
Expand All @@ -15,13 +15,16 @@
from tox.execute import Outcome
from tox.plugin import impl
from tox.session.cmd.run.single import run_command_set
from tox.tox_env.api import ToxEnvCreateArgs
from tox.tox_env.errors import Fail
from tox.tox_env.package import Package
from tox.tox_env.package import Package, PackageToxEnv
from tox.tox_env.python.package import PythonPackageToxEnv, SdistPackage, WheelPackage
from tox.tox_env.python.pip.req_file import PythonDeps
from tox.tox_env.python.virtual_env.api import VirtualEnv
from tox.tox_env.register import ToxEnvRegister
from tox.tox_env.runner import RunToxEnv

from .pep517 import Pep517VirtualEnvPackager
from .util import dependencies_with_extras

if sys.version_info >= (3, 8):
Expand All @@ -31,6 +34,10 @@


class VirtualEnvCmdBuilder(PythonPackageToxEnv, VirtualEnv):
def __init__(self, create_args: ToxEnvCreateArgs) -> None:
super().__init__(create_args)
self._sdist_meta_tox_env: Optional[Pep517VirtualEnvPackager] = None

@staticmethod
def id() -> str:
return "virtualenv-cmd-builder"
Expand Down Expand Up @@ -109,10 +116,23 @@ def extract_install_info(self, for_env: EnvConfigSet, path: Path) -> List[Packag
work_dir.mkdir()
with tarfile.open(str(path), "r:gz") as tar:
tar.extractall(path=str(work_dir))
deps: List[Requirement] = [] # builder.get_package_dependencies() # use PEP-517 to generate the metadata
assert self._sdist_meta_tox_env is not None # the register run env is guaranteed to be called before this
with self._sdist_meta_tox_env.display_context(self._has_display_suspended):
self._sdist_meta_tox_env.root = next(work_dir.iterdir()) # contains a single egg info folder
deps = self._sdist_meta_tox_env.get_package_dependencies()
package = SdistPackage(path, dependencies_with_extras(deps, extras))
return [package]

def register_run_env(self, run_env: RunToxEnv) -> Generator[Tuple[str, str], PackageToxEnv, None]:
yield from super().register_run_env(run_env)
# in case the outcome is a sdist we'll use this to find out its metadata
result = yield f"{self.conf.name}_sdist_meta", Pep517VirtualEnvPackager.id()
self._sdist_meta_tox_env = cast(Pep517VirtualEnvPackager, result)

def child_pkg_envs(self, run_conf: EnvConfigSet) -> Iterator[PackageToxEnv]: # noqa: U100
if self._sdist_meta_tox_env is not None:
yield self._sdist_meta_tox_env


class WheelDistribution(Distribution): # type: ignore # cannot subclass has type Any
def __init__(self, wheel: Path) -> None:
Expand All @@ -135,7 +155,7 @@ def read_text(self, filename: str) -> Optional[str]:
except KeyError:
return None

def locate_file(self, path: str) -> PathLike[str]:
def locate_file(self, path: str) -> "PathLike[str]":
return self._wheel / path # pragma: no cover # not used by us, but part of the ABC


Expand Down
20 changes: 13 additions & 7 deletions src/tox/tox_env/python/virtual_env/package/pep517.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,13 @@ def out_err(self) -> Tuple[str, str]:
return status.outcome.out_err()


class Pep517VirtualEnvPackage(PythonPackageToxEnv, VirtualEnv):
class Pep517VirtualEnvPackager(PythonPackageToxEnv, VirtualEnv):
"""local file system python virtual environment via the virtualenv package"""

def __init__(self, create_args: ToxEnvCreateArgs) -> None:
super().__init__(create_args)
self._root: Path = self.conf["package_root"]
self._frontend = Pep517VirtualEnvFrontend(self._root, self)
self.root: Path = self.conf["package_root"]
self._frontend_private: Optional[Pep517VirtualEnvFrontend] = None
self.builds: Set[str] = set()
self._distribution_meta: Optional[PathDistribution] = None
self._package_dependencies: Optional[List[Requirement]] = None
Expand All @@ -82,6 +82,12 @@ def __init__(self, create_args: ToxEnvCreateArgs) -> None:
def id() -> str:
return "virtualenv-pep-517"

@property
def _frontend(self) -> "Pep517VirtualEnvFrontend":
if self._frontend_private is None:
self._frontend_private = Pep517VirtualEnvFrontend(self.root, self)
return self._frontend_private

def register_config(self) -> None:
super().register_config()
self.conf.add_config(
Expand Down Expand Up @@ -116,7 +122,7 @@ def _setup_env(self) -> None:
if "wheel" in self.builds:
build_requires = self._frontend.get_requires_for_build_wheel().requires
self.installer.install(build_requires, PythonPackageToxEnv.__name__, "requires_for_build_wheel")
if "sdist" in self.builds:
if "sdist" in self.builds or "external" in self.builds:
build_requires = self._frontend.get_requires_for_build_sdist().requires
self.installer.install(build_requires, PythonPackageToxEnv.__name__, "requires_for_build_sdist")

Expand All @@ -141,7 +147,7 @@ def perform_packaging(self, for_env: EnvConfigSet) -> List[Package]:
w_env = self._wheel_build_envs.get(for_env["wheel_build_env"])
if w_env is not None and w_env is not self:
with w_env.display_context(self._has_display_suspended):
reqs = w_env.get_package_dependencies() if isinstance(w_env, Pep517VirtualEnvPackage) else []
reqs = w_env.get_package_dependencies() if isinstance(w_env, Pep517VirtualEnvPackager) else []
if reqs is None:
reqs = self.get_package_dependencies()

Expand Down Expand Up @@ -196,7 +202,7 @@ def requires(self) -> Tuple[Requirement, ...]:


class Pep517VirtualEnvFrontend(Frontend):
def __init__(self, root: Path, env: Pep517VirtualEnvPackage) -> None:
def __init__(self, root: Path, env: Pep517VirtualEnvPackager) -> None:
super().__init__(*Frontend.create_args_from_folder(root))
self._tox_env = env
self._backend_executor_: Optional[LocalSubProcessPep517Executor] = None
Expand Down Expand Up @@ -271,4 +277,4 @@ def _wheel_directory(self) -> Iterator[Path]:

@impl
def tox_register_tox_env(register: ToxEnvRegister) -> None:
register.add_package_env(Pep517VirtualEnvPackage)
register.add_package_env(Pep517VirtualEnvPackager)
2 changes: 1 addition & 1 deletion src/tox/util/pep517/frontend.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def __init__(
self._backend_paths = backend_paths
self._backend_module = backend_module
self._backend_obj = backend_obj
self.requires = requires
self.requires: Tuple[Requirement, ...] = requires
self._reuse_backend = reuse_backend

@classmethod
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,10 @@ def test_tox_install_pkg_wheel(tox_project: ToxProjectCreator, pkg_with_extras_p
result = proj.run("r", "-e", "py", "--installpkg", str(pkg_with_extras_project_wheel))
result.assert_success()
calls = [(i[0][0].conf.name, i[0][3].run_id, i[0][3].cmd[5:]) for i in execute_calls.call_args_list]
deps = ["black>=3", "colorama>=0.4.3", "flake8", "platformdirs>=2.1", "sphinx-rtd-theme<1,>=0.4.3", "sphinx>=3"]
expected = [
(
"py",
"install_package_deps",
["black>=3", "colorama>=0.4.3", "flake8", "platformdirs>=2.1", "sphinx-rtd-theme<1,>=0.4.3", "sphinx>=3"],
),
(
"py",
"install_package",
["--force-reinstall", "--no-deps", str(pkg_with_extras_project_wheel)],
),
("py", "install_package_deps", deps),
("py", "install_package", ["--force-reinstall", "--no-deps", str(pkg_with_extras_project_wheel)]),
]
assert calls == expected

Expand All @@ -46,10 +39,20 @@ def pkg_with_extras_project_sdist(


def test_tox_install_pkg_sdist(tox_project: ToxProjectCreator, pkg_with_extras_project_sdist: Path) -> None:
proj = tox_project({"tox.ini": "[testenv]"})
pytest.skip("not yet ready")
proj = tox_project({"tox.ini": "[testenv]\nextras=docs,format"})
execute_calls = proj.patch_execute(lambda r: 0 if "install" in r.run_id else None)
result = proj.run("r", "-e", "py", "--installpkg", str(pkg_with_extras_project_sdist))
result.assert_success()
calls = [(i[0][0].conf.name, i[0][3].run_id, i[0][3].cmd[5:]) for i in execute_calls.call_args_list]
deps = ["black>=3", "colorama>=0.4.3", "flake8", "platformdirs>=2.1", "sphinx-rtd-theme<1,>=0.4.3", "sphinx>=3"]
assert calls == [
(".pkg_external_sdist_meta", "install_requires", ["setuptools", "wheel"]),
(".pkg_external_sdist_meta", "get_requires_for_build_sdist", []),
(".pkg_external_sdist_meta", "prepare_metadata_for_build_wheel", []),
("py", "install_package_deps", deps),
("py", "install_package", ["--force-reinstall", "--no-deps", str(pkg_with_extras_project_sdist)]),
(".pkg_external_sdist_meta", "_exit", []),
]


@pytest.mark.parametrize("mode", ["p", "le"]) # no need for r as is tested above
Expand Down
4 changes: 2 additions & 2 deletions tests/tox_env/python/virtual_env/test_setuptools.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from tox.pytest import ToxProjectCreator
from tox.tox_env.python.package import WheelPackage
from tox.tox_env.python.virtual_env.package.pep517 import Pep517VirtualEnvPackage
from tox.tox_env.python.virtual_env.package.pep517 import Pep517VirtualEnvPackager


@pytest.mark.integration()
Expand All @@ -32,7 +32,7 @@ def test_setuptools_package(
tox_env = outcome.state.tox_env("py")

(package_env,) = list(tox_env.package_envs)
assert isinstance(package_env, Pep517VirtualEnvPackage)
assert isinstance(package_env, Pep517VirtualEnvPackager)
packages = package_env.perform_packaging(tox_env.conf)
assert len(packages) == 1
package = packages[0]
Expand Down
1 change: 0 additions & 1 deletion whitelist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ contnode
copytree
cov
cpus
creationflags
creq
crypto
ctrl
Expand Down

0 comments on commit 87ec3d8

Please sign in to comment.