From add982918cbad9d1bfe09661429ee4948bd0026e Mon Sep 17 00:00:00 2001 From: Arun Babu Neelicattu Date: Mon, 10 Aug 2020 16:15:06 +0200 Subject: [PATCH] Support build dependencies Resolves: #2789 --- poetry/console/commands/build.py | 13 +++++++--- poetry/installation/base_installer.py | 4 +++ poetry/installation/installer.py | 37 +++++++++++++++++++++++++++ poetry/puzzle/solver.py | 2 ++ 4 files changed, 53 insertions(+), 3 deletions(-) diff --git a/poetry/console/commands/build.py b/poetry/console/commands/build.py index 118fb210c53..073044698a9 100644 --- a/poetry/console/commands/build.py +++ b/poetry/console/commands/build.py @@ -1,9 +1,9 @@ from cleo import option -from .env_command import EnvCommand +from poetry.console.commands.installer_command import InstallerCommand -class BuildCommand(EnvCommand): +class BuildCommand(InstallerCommand): name = "build" description = "Builds a package, as a tarball and a wheel by default." @@ -33,4 +33,11 @@ def handle(self): ) builder = Builder(self.poetry) - builder.build(fmt) + + executable = None + if self.poetry.package.build_requires: + # ensure build requirements are available if specified + self.installer.categories({"build"}).run() + executable = self.installer.env.python + + builder.build(fmt, executable=executable) diff --git a/poetry/installation/base_installer.py b/poetry/installation/base_installer.py index 1e068d076cd..de8b0086d9a 100644 --- a/poetry/installation/base_installer.py +++ b/poetry/installation/base_installer.py @@ -1,4 +1,8 @@ class BaseInstaller: + @property + def env(self): + return getattr(self, "_env", None) + def install(self, package): raise NotImplementedError diff --git a/poetry/installation/installer.py b/poetry/installation/installer.py index f0c9a62d65d..36878da225a 100644 --- a/poetry/installation/installer.py +++ b/poetry/installation/installer.py @@ -1,3 +1,4 @@ +from typing import Iterable from typing import List from typing import Optional from typing import Union @@ -11,6 +12,7 @@ from poetry.repositories import Pool from poetry.repositories import Repository from poetry.repositories.installed_repository import InstalledRepository +from poetry.utils.env import Env from poetry.utils.extras import get_extra_package_names from poetry.utils.helpers import canonicalize_name @@ -47,10 +49,12 @@ def __init__( self._verbose = False self._write_lock = True self._dev_mode = True + self._build_mode = True self._execute_operations = True self._lock = False self._whitelist = [] + self._categories = set() self._extras = [] @@ -66,6 +70,10 @@ def __init__( self._installed_repository = installed + @property + def env(self): # type: () -> Env + return self._env + @property def executor(self): return self._executor @@ -132,6 +140,14 @@ def dev_mode(self, dev_mode=True): # type: (bool) -> Installer def is_dev_mode(self): # type: () -> bool return self._dev_mode + def build_mode(self, build_mode=True): # type: (bool) -> Installer + self._build_mode = build_mode + + return self + + def is_build_mode(self): # type: () -> bool + return self._build_mode or self._dev_mode + def update(self, update=True): # type: (bool) -> Installer self._update = update @@ -163,6 +179,13 @@ def whitelist(self, packages): # type: (dict) -> Installer return self + def categories( + self, categories=None + ): # type: (Optional[Iterable[str]]) -> Installer + self._categories = {category for category in categories or []} + + return self + def extras(self, extras): # type: (list) -> Installer self._extras = extras @@ -241,6 +264,10 @@ def _do_install(self, local_repo): root = root.clone() del root.dev_requires[:] + if not self.is_build_mode(): + root = root.clone() + del root.build_requires[:] + if self._io.is_verbose(): self._io.write_line("") self._io.write_line( @@ -455,6 +482,8 @@ def _get_operations_from_lock( is_installed = True if locked.category == "dev" and not self.is_dev_mode(): ops.append(Uninstall(locked)) + elif locked.category == "build" and not self.is_build_mode(): + ops.append(Uninstall(locked)) elif locked.optional and locked.name not in extra_packages: # Installed but optional and not requested in extras ops.append(Uninstall(locked)) @@ -506,11 +535,19 @@ def _filter_operations( if package.name not in extra_packages: op.skip("Not required") + if self._categories and package.category not in self._categories: + op.skip("Category ({}) not enabled".format(package.category)) + # If the package is a dev package and dev packages # are not requested, we skip it if package.category == "dev" and not self.is_dev_mode(): op.skip("Dev dependencies not requested") + # If the package is a build package and build packages + # are not requested, we skip it + if package.category == "build" and not self.is_build_mode(): + op.skip("Build dependencies not requested") + def _get_extra_packages(self, repo): # type: (Repository) -> List[str] """ Returns all package names required by extras. diff --git a/poetry/puzzle/solver.py b/poetry/puzzle/solver.py index 386d8f95a7f..5a82b47ab62 100644 --- a/poetry/puzzle/solver.py +++ b/poetry/puzzle/solver.py @@ -338,6 +338,8 @@ def _get_tags_for_package(self, package, graph, depth=0): if "main" in categories: category = "main" + elif "build" in categories: + category = "build" else: category = "dev"