Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 10 additions & 3 deletions poetry/console/commands/build.py
Original file line number Diff line number Diff line change
@@ -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."
Expand Down Expand Up @@ -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)
4 changes: 4 additions & 0 deletions poetry/installation/base_installer.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
class BaseInstaller:
@property
def env(self):
return getattr(self, "_env", None)

def install(self, package):
raise NotImplementedError

Expand Down
37 changes: 37 additions & 0 deletions poetry/installation/installer.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from typing import Iterable
from typing import List
from typing import Optional
from typing import Union
Expand All @@ -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

Expand Down Expand Up @@ -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 = []

Expand All @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 2 additions & 0 deletions poetry/puzzle/solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ classifiers = [
[tool.poetry.dependencies]
python = "~2.7 || ^3.5"

poetry-core = "^1.0.0a9"
poetry-core = { git = "https://github.com/abn/poetry-core.git", branch = "support-build-system-requires"}
cleo = "^0.8.1"
clikit = "^0.6.2"
crashtest = { version = "^0.3.0", python = "^3.6" }
Expand Down
25 changes: 1 addition & 24 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,19 @@
import shutil
import tempfile

from typing import Any
from typing import Dict

import httpretty
import pytest

from poetry.config.config import Config as BaseConfig
from poetry.config.dict_config_source import DictConfigSource
from poetry.inspection.info import PackageInfo
from poetry.utils._compat import Path
from poetry.utils.env import EnvManager
from poetry.utils.env import VirtualEnv
from tests.helpers import Config
from tests.helpers import mock_clone
from tests.helpers import mock_download


class Config(BaseConfig):
def get(self, setting_name, default=None): # type: (str, Any) -> Any
self.merge(self._config_source.config)
self.merge(self._auth_config_source.config)

return super(Config, self).get(setting_name, default=default)

def raw(self): # type: () -> Dict[str, Any]
self.merge(self._config_source.config)
self.merge(self._auth_config_source.config)

return super(Config, self).raw()

def all(self): # type: () -> Dict[str, Any]
self.merge(self._config_source.config)
self.merge(self._auth_config_source.config)

return super(Config, self).all()


@pytest.fixture
def config_source():
source = DictConfigSource()
Expand Down
24 changes: 2 additions & 22 deletions tests/console/commands/test_add.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,16 @@

import pytest

from cleo.testers import CommandTester

from poetry.core.semver import Version
from poetry.installation.installer import Installer
from poetry.repositories.legacy_repository import LegacyRepository
from poetry.utils._compat import Path
from tests.helpers import get_dependency
from tests.helpers import get_package


@pytest.fixture()
def tester(app, poetry, config, executor, env):
tester = CommandTester(app.find("add"))

executor._io = tester.io

installer = Installer(
tester.io,
env,
poetry.package,
poetry.locker,
poetry.pool,
config,
executor=executor,
)
installer.use_executor(True)
tester._command.set_installer(installer)
tester._command.set_env(env)

return tester
def tester(poetry, app, make_installer_command_tester):
return make_installer_command_tester(poetry, "add", app)


@pytest.fixture()
Expand Down
83 changes: 83 additions & 0 deletions tests/console/commands/test_build.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import re

import pytest

from tests.helpers import get_package


@pytest.fixture
def command_tester_with_build_requires(
repo, make_poetry, make_installer_command_tester
):
repo.add_package(get_package("cython", "0.29.6"))
poetry = make_poetry("project_with_build_system_requires")
return make_installer_command_tester(poetry, "build")


@pytest.fixture
def command_tester(project_directory, make_poetry, make_installer_command_tester):
return make_installer_command_tester(make_poetry(project_directory), "build")


def test_build_project_complete(command_tester):
tester = command_tester
command_tester.execute()

assert tester._command.installer.executor.installations_count == 0

output = tester.io.fetch_output()

assert "Writing lock file" not in output
assert "Building sdist" in output
assert "Built simple-project-1.2.3.tar.gz" in output
assert "Building wheel" in output
assert re.search(r"Built simple_project-1\.2\.3-.*\.whl", output) is not None


def test_build_project_sdist(command_tester):
tester = command_tester
command_tester.execute("-f sdist")

assert tester._command.installer.executor.installations_count == 0

output = tester.io.fetch_output()

assert "Writing lock file" not in output
assert "Building sdist" in output
assert "Built simple-project-1.2.3.tar.gz" in output
assert "Building wheel" not in output
assert re.search(r"Built simple_project-1\.2\.3-.*\.whl", output) is None


def test_build_project_wheel(command_tester):
tester = command_tester
command_tester.execute("-f wheel")

assert tester._command.installer.executor.installations_count == 0

output = tester.io.fetch_output()

assert "Writing lock file" not in output
assert "Building sdist" not in output
assert "Built simple-project-1.2.3.tar.gz" not in output
assert "Building wheel" in output
assert re.search(r"Built simple_project-1\.2\.3-.*\.whl", output) is not None


def test_build_project_with_build_requires(command_tester_with_build_requires):
tester = command_tester_with_build_requires
tester.execute()

assert tester._command.installer.executor.installations_count == 1

package = tester._command.installer.executor._installs[0]
assert package.name == "cython"
assert package.version.text == "0.29.6"

output = tester.io.fetch_output()

assert "Writing lock file" in output
assert "Building sdist" in output
assert "Built project-1.2.3.tar.gz" in output
assert "Building wheel" in output
assert re.search(r"Built project-1\.2\.3-.*\.whl", output) is not None
4 changes: 2 additions & 2 deletions tests/console/commands/test_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
from poetry.repositories.pool import Pool
from tests.helpers import get_package

from ..conftest import Application
from ..conftest import Locker
from ..conftest import Path
from ..helpers import Application
from ..helpers import Locker


PYPROJECT_CONTENT = """\
Expand Down
Loading