Skip to content

Commit 6a73f4e

Browse files
committed
Support build dependencies
Resolves: #2789
1 parent 79fa04a commit 6a73f4e

4 files changed

Lines changed: 53 additions & 3 deletions

File tree

poetry/console/commands/build.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
from cleo import option
22

3-
from .env_command import EnvCommand
3+
from poetry.console.commands.installer_command import InstallerCommand
44

55

6-
class BuildCommand(EnvCommand):
6+
class BuildCommand(InstallerCommand):
77

88
name = "build"
99
description = "Builds a package, as a tarball and a wheel by default."
@@ -33,4 +33,11 @@ def handle(self):
3333
)
3434

3535
builder = Builder(self.poetry)
36-
builder.build(fmt)
36+
37+
executable = None
38+
if self.poetry.package.build_requires:
39+
# ensure build requirements are available if specified
40+
self.installer.categories({"build"}).run()
41+
executable = self.installer.env.python
42+
43+
builder.build(fmt, executable=executable)

poetry/installation/base_installer.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
class BaseInstaller:
2+
@property
3+
def env(self):
4+
return getattr(self, "_env", None)
5+
26
def install(self, package):
37
raise NotImplementedError
48

poetry/installation/installer.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from typing import Iterable
12
from typing import List
23
from typing import Optional
34
from typing import Union
@@ -11,6 +12,7 @@
1112
from poetry.repositories import Pool
1213
from poetry.repositories import Repository
1314
from poetry.repositories.installed_repository import InstalledRepository
15+
from poetry.utils.env import Env
1416
from poetry.utils.extras import get_extra_package_names
1517
from poetry.utils.helpers import canonicalize_name
1618

@@ -47,10 +49,12 @@ def __init__(
4749
self._verbose = False
4850
self._write_lock = True
4951
self._dev_mode = True
52+
self._build_mode = True
5053
self._execute_operations = True
5154
self._lock = False
5255

5356
self._whitelist = []
57+
self._categories = set()
5458

5559
self._extras = []
5660

@@ -66,6 +70,10 @@ def __init__(
6670

6771
self._installed_repository = installed
6872

73+
@property
74+
def env(self): # type: () -> Env
75+
return self._env
76+
6977
@property
7078
def executor(self):
7179
return self._executor
@@ -132,6 +140,14 @@ def dev_mode(self, dev_mode=True): # type: (bool) -> Installer
132140
def is_dev_mode(self): # type: () -> bool
133141
return self._dev_mode
134142

143+
def build_mode(self, build_mode=True): # type: (bool) -> Installer
144+
self._build_mode = build_mode
145+
146+
return self
147+
148+
def is_build_mode(self): # type: () -> bool
149+
return self._build_mode or self._dev_mode
150+
135151
def update(self, update=True): # type: (bool) -> Installer
136152
self._update = update
137153

@@ -163,6 +179,13 @@ def whitelist(self, packages): # type: (dict) -> Installer
163179

164180
return self
165181

182+
def categories(
183+
self, categories=None
184+
): # type: (Optional[Iterable[str]]) -> Installer
185+
self._categories = {category for category in categories or []}
186+
187+
return self
188+
166189
def extras(self, extras): # type: (list) -> Installer
167190
self._extras = extras
168191

@@ -241,6 +264,10 @@ def _do_install(self, local_repo):
241264
root = root.clone()
242265
del root.dev_requires[:]
243266

267+
if not self.is_build_mode():
268+
root = root.clone()
269+
del root.build_requires[:]
270+
244271
if self._io.is_verbose():
245272
self._io.write_line("")
246273
self._io.write_line(
@@ -455,6 +482,8 @@ def _get_operations_from_lock(
455482
is_installed = True
456483
if locked.category == "dev" and not self.is_dev_mode():
457484
ops.append(Uninstall(locked))
485+
elif locked.category == "build" and not self.is_build_mode():
486+
ops.append(Uninstall(locked))
458487
elif locked.optional and locked.name not in extra_packages:
459488
# Installed but optional and not requested in extras
460489
ops.append(Uninstall(locked))
@@ -506,11 +535,19 @@ def _filter_operations(
506535
if package.name not in extra_packages:
507536
op.skip("Not required")
508537

538+
if self._categories and package.category not in self._categories:
539+
op.skip("Category ({}) not enabled".format(package.category))
540+
509541
# If the package is a dev package and dev packages
510542
# are not requested, we skip it
511543
if package.category == "dev" and not self.is_dev_mode():
512544
op.skip("Dev dependencies not requested")
513545

546+
# If the package is a build package and build packages
547+
# are not requested, we skip it
548+
if package.category == "build" and not self.is_build_mode():
549+
op.skip("Build dependencies not requested")
550+
514551
def _get_extra_packages(self, repo): # type: (Repository) -> List[str]
515552
"""
516553
Returns all package names required by extras.

poetry/puzzle/solver.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,8 @@ def _get_tags_for_package(self, package, graph, depth=0):
338338

339339
if "main" in categories:
340340
category = "main"
341+
elif "build" in categories:
342+
category = "build"
341343
else:
342344
category = "dev"
343345

0 commit comments

Comments
 (0)