diff --git a/poetry.lock b/poetry.lock index 81bff637e44..7a480f091a6 100644 --- a/poetry.lock +++ b/poetry.lock @@ -687,7 +687,7 @@ category = "main" description = "Core utilities for Poetry" name = "poetry-core" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = "~2.7 || ^3.5" version = "1.0.0a9" [package.dependencies] @@ -697,6 +697,10 @@ importlib-metadata = {version = ">=1.7.0,<2.0.0", markers = "python_version >= \ pathlib2 = {version = ">=2.3.5,<3.0.0", markers = "python_version >= \"2.7\" and python_version < \"2.8\""} typing = {version = ">=3.7.4.1,<4.0.0.0", markers = "python_version >= \"2.7\" and python_version < \"2.8\""} +[package.source] +reference = "0658ad01a805310d1fc96891dae3e9b7a420727c" +type = "git" +url = "https://github.com/abn/poetry-core.git" [[package]] category = "dev" description = "A framework for managing and maintaining multi-language pre-commit hooks." @@ -1160,7 +1164,7 @@ docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] testing = ["pathlib2", "unittest2", "jaraco.itertools", "func-timeout"] [metadata] -content-hash = "20c1d02c76ead833a0b43da34477554bdb262f20fd1b7a8b530a5bf551cd9d4a" +content-hash = "cc8c9da62ac7663cb2192ebcf38a9afdc4c98cc50cfa49c398d6f45eae035e77" lock-version = "1.1" python-versions = "~2.7 || ^3.5" @@ -1437,6 +1441,11 @@ markupsafe = [ {file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6"}, {file = "MarkupSafe-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2"}, {file = "MarkupSafe-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c"}, + {file = "MarkupSafe-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15"}, + {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2"}, + {file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42"}, + {file = "MarkupSafe-1.1.1-cp38-cp38-win32.whl", hash = "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b"}, + {file = "MarkupSafe-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"}, {file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"}, ] mkdocs = [ @@ -1511,10 +1520,7 @@ pluggy = [ {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, ] -poetry-core = [ - {file = "poetry-core-1.0.0a9.tar.gz", hash = "sha256:f08e9829fd06609ca5615faa91739b589eb71e025a6aaf7ddffb698676eb7c8c"}, - {file = "poetry_core-1.0.0a9-py2.py3-none-any.whl", hash = "sha256:79a63629ae44533ba9aa828e0eff0002c61b3af5fc9bec212e006cc643f4eb19"}, -] +poetry-core = [] pre-commit = [ {file = "pre_commit-2.6.0-py2.py3-none-any.whl", hash = "sha256:e8b1315c585052e729ab7e99dcca5698266bedce9067d21dc909c23e3ceed626"}, {file = "pre_commit-2.6.0.tar.gz", hash = "sha256:1657663fdd63a321a4a739915d7d03baedd555b25054449090f97bb0cb30a915"}, @@ -1603,7 +1609,6 @@ regex = [ {file = "regex-2020.7.14-cp38-cp38-manylinux1_i686.whl", hash = "sha256:5ea81ea3dbd6767873c611687141ec7b06ed8bab43f68fad5b7be184a920dc99"}, {file = "regex-2020.7.14-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:bbb332d45b32df41200380fff14712cb6093b61bd142272a10b16778c418e98e"}, {file = "regex-2020.7.14-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:c11d6033115dc4887c456565303f540c44197f4fc1a2bfb192224a301534888e"}, - {file = "regex-2020.7.14-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:75aaa27aa521a182824d89e5ab0a1d16ca207318a6b65042b046053cfc8ed07a"}, {file = "regex-2020.7.14-cp38-cp38-win32.whl", hash = "sha256:d6cff2276e502b86a25fd10c2a96973fdb45c7a977dca2138d661417f3728341"}, {file = "regex-2020.7.14-cp38-cp38-win_amd64.whl", hash = "sha256:7a2dd66d2d4df34fa82c9dc85657c5e019b87932019947faece7983f2089a840"}, {file = "regex-2020.7.14.tar.gz", hash = "sha256:3a3af27a8d23143c49a3420efe5b3f8cf1a48c6fc8bc6856b03f638abc1833bb"}, 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" diff --git a/pyproject.toml b/pyproject.toml index 5ef380e92e1..33ff82b9a1a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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" } diff --git a/tests/conftest.py b/tests/conftest.py index 08d4641b47c..098cf0df852 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -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() diff --git a/tests/console/commands/test_add.py b/tests/console/commands/test_add.py index 14b99842231..7cd987cb134 100644 --- a/tests/console/commands/test_add.py +++ b/tests/console/commands/test_add.py @@ -5,10 +5,7 @@ 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 @@ -16,25 +13,8 @@ @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() diff --git a/tests/console/commands/test_build.py b/tests/console/commands/test_build.py new file mode 100644 index 00000000000..f4d9781f2f6 --- /dev/null +++ b/tests/console/commands/test_build.py @@ -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 diff --git a/tests/console/commands/test_export.py b/tests/console/commands/test_export.py index 65d4927916d..b6e2e4e58f2 100644 --- a/tests/console/commands/test_export.py +++ b/tests/console/commands/test_export.py @@ -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 = """\ diff --git a/tests/console/conftest.py b/tests/console/conftest.py index 034e47207f5..582471f5223 100644 --- a/tests/console/conftest.py +++ b/tests/console/conftest.py @@ -1,65 +1,28 @@ import os import re +import shutil import pytest from cleo import ApplicationTester +from cleo import CommandTester -from poetry.console import Application as BaseApplication -from poetry.core.masonry.utils.helpers import escape_name -from poetry.core.masonry.utils.helpers import escape_version -from poetry.core.packages.utils.link import Link from poetry.factory import Factory -from poetry.installation.executor import Executor as BaseExecutor +from poetry.installation import Installer from poetry.installation.noop_installer import NoopInstaller from poetry.io.null_io import NullIO -from poetry.packages import Locker as BaseLocker -from poetry.poetry import Poetry as BasePoetry from poetry.repositories import Pool from poetry.repositories import Repository as BaseRepository -from poetry.repositories.exceptions import PackageNotFound from poetry.utils._compat import Path from poetry.utils.env import MockEnv -from poetry.utils.toml_file import TomlFile +from tests.console.helpers import Application +from tests.console.helpers import Locker +from tests.console.helpers import Repository +from tests.helpers import Executor +from tests.helpers import fixture from tests.helpers import mock_clone -class Executor(BaseExecutor): - def __init__(self, *args, **kwargs): - super(Executor, self).__init__(*args, **kwargs) - - self._installs = [] - self._updates = [] - self._uninstalls = [] - - @property - def installations(self): - return self._installs - - @property - def updates(self): - return self._updates - - @property - def removals(self): - return self._uninstalls - - def _do_execute_operation(self, operation): - super(Executor, self)._do_execute_operation(operation) - - if not operation.skipped: - getattr(self, "_{}s".format(operation.job_type)).append(operation.package) - - def _execute_install(self, operation): - return 0 - - def _execute_update(self, operation): - return 0 - - def _execute_remove(self, operation): - return 0 - - @pytest.fixture() def installer(): return NoopInstaller() @@ -114,104 +77,66 @@ def setup(mocker, installer, installed, config, env): os.environ.update(environ) -class Application(BaseApplication): - def __init__(self, poetry): - super(Application, self).__init__() - - self._poetry = poetry - - def reset_poetry(self): - poetry = self._poetry - self._poetry = Factory().create_poetry(self._poetry.file.path.parent) - self._poetry.set_pool(poetry.pool) - self._poetry.set_config(poetry.config) - self._poetry.set_locker( - Locker(poetry.locker.lock.path, self._poetry.local_config) - ) - - -class Locker(BaseLocker): - def __init__(self, lock, local_config): - self._lock = TomlFile(lock) - self._local_config = local_config - self._lock_data = None - self._content_hash = self._get_content_hash() - self._locked = False - self._lock_data = None - self._write = False - - def write(self, write=True): - self._write = write - - def is_locked(self): - return self._locked - - def locked(self, is_locked=True): - self._locked = is_locked - - return self - - def mock_lock_data(self, data): - self.locked() - - self._lock_data = data +@pytest.fixture +def repo(http): + http.register_uri( + http.GET, re.compile("^https?://foo.bar/(.+?)$"), + ) + return Repository(name="foo") - def is_fresh(self): - return True - def _write_lock_data(self, data): - if self._write: - super(Locker, self)._write_lock_data(data) - self._locked = True - return +@pytest.fixture +def project_directory(): + return "simple_project" - self._lock_data = data +@pytest.fixture +def make_poetry(tmp_dir, repo, config): + def make_poetry_from_fixture_name(name): + src = fixture(name) + dst = Path(tmp_dir) / name + shutil.copytree(src.as_posix(), dst.as_posix()) -class Poetry(BasePoetry): - def __init__(self, file, local_config, package, locker, config): - self._file = TomlFile(file) - self._package = package - self._local_config = local_config - self._locker = Locker(locker.lock.path, locker._local_config) - self._config = config + poetry = Factory().create_poetry(dst) + poetry.set_locker(Locker(poetry.locker.lock.path, poetry.locker._local_config)) + poetry.set_config(config) - # Configure sources - self._pool = Pool() + pool = Pool() + pool.add_repository(repo) + poetry.set_pool(pool) + return poetry -class Repository(BaseRepository): - def find_packages( - self, name, constraint=None, extras=None, allow_prereleases=False - ): - packages = super(Repository, self).find_packages( - name, constraint, extras, allow_prereleases - ) - if len(packages) == 0: - raise PackageNotFound("Package [{}] not found.".format(name)) - return packages - - def find_links_for_package(self, package): - return [ - Link( - "https://foo.bar/files/{}-{}-py2.py3-none-any.whl".format( - escape_name(package.name), escape_version(package.version.text) - ) - ) - ] + return make_poetry_from_fixture_name @pytest.fixture -def repo(http): - http.register_uri( - http.GET, re.compile("^https?://foo.bar/(.+?)$"), - ) - return Repository(name="foo") +def make_installer_command_tester(config, executor, env): + def make_tester(poetry, command, app=None): + if app is None: + app = Application(poetry) + app.config.set_terminate_after_run(False) + + tester = CommandTester(app.find(command)) + + 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 -@pytest.fixture -def project_directory(): - return "simple_project" + yield make_tester @pytest.fixture diff --git a/tests/console/helpers.py b/tests/console/helpers.py new file mode 100644 index 00000000000..b0f845c6500 --- /dev/null +++ b/tests/console/helpers.py @@ -0,0 +1,84 @@ +from poetry.console import Application as BaseApplication +from poetry.core.masonry.utils.helpers import escape_name +from poetry.core.masonry.utils.helpers import escape_version +from poetry.core.packages import Link +from poetry.factory import Factory +from poetry.packages import Locker as BaseLocker +from poetry.repositories import Repository as BaseRepository +from poetry.repositories.exceptions import PackageNotFound +from poetry.utils.toml_file import TomlFile + + +class Application(BaseApplication): + def __init__(self, poetry): + super(Application, self).__init__() + + self._poetry = poetry + + def reset_poetry(self): + poetry = self._poetry + self._poetry = Factory().create_poetry(self._poetry.file.path.parent) + self._poetry.set_pool(poetry.pool) + self._poetry.set_config(poetry.config) + self._poetry.set_locker( + Locker(poetry.locker.lock.path, self._poetry.local_config) + ) + + +class Locker(BaseLocker): + def __init__(self, lock, local_config): + self._lock = TomlFile(lock) + self._local_config = local_config + self._lock_data = None + self._content_hash = self._get_content_hash() + self._locked = False + self._lock_data = None + self._write = False + + def write(self, write=True): + self._write = write + + def is_locked(self): + return self._locked + + def locked(self, is_locked=True): + self._locked = is_locked + + return self + + def mock_lock_data(self, data): + self.locked() + + self._lock_data = data + + def is_fresh(self): + return True + + def _write_lock_data(self, data): + if self._write: + super(Locker, self)._write_lock_data(data) + self._locked = True + return + + self._lock_data = data + + +class Repository(BaseRepository): + def find_packages( + self, name, constraint=None, extras=None, allow_prereleases=False + ): + packages = super(Repository, self).find_packages( + name, constraint, extras, allow_prereleases + ) + if len(packages) == 0: + raise PackageNotFound("Package [{}] not found.".format(name)) + return packages + + def find_links_for_package(self, package): + return [ + Link( + "https://foo.bar/files/{}-{}-py2.py3-none-any.whl".format( + escape_name(package.name), escape_version(package.version.text) + ) + ) + ] diff --git a/tests/fixtures/project_with_build_system_requires/README.rst b/tests/fixtures/project_with_build_system_requires/README.rst new file mode 100644 index 00000000000..f7fe15470f9 --- /dev/null +++ b/tests/fixtures/project_with_build_system_requires/README.rst @@ -0,0 +1,2 @@ +My Package +========== diff --git a/tests/fixtures/project_with_build_system_requires/build.py b/tests/fixtures/project_with_build_system_requires/build.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/fixtures/project_with_build_system_requires/project/__init__.py b/tests/fixtures/project_with_build_system_requires/project/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/fixtures/project_with_build_system_requires/pyproject.toml b/tests/fixtures/project_with_build_system_requires/pyproject.toml new file mode 100644 index 00000000000..65f884a70ba --- /dev/null +++ b/tests/fixtures/project_with_build_system_requires/pyproject.toml @@ -0,0 +1,19 @@ +[tool.poetry] +name = "project" +version = "1.2.3" +description = "Some description." +authors = [] +license = "MIT" + +[tool.poetry.build] +script = "build.py" +generate-setup-file = false + +[tool.poetry.dependencies] +python = "^3.7" + +[build-system] +requires = [ + "poetry-core", + "Cython>=0.29.6", +] diff --git a/tests/helpers.py b/tests/helpers.py index 0dd7ce312e5..01c1a485e69 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -1,9 +1,14 @@ import os import shutil +from typing import Any +from typing import Dict + +from poetry.config.config import Config as BaseConfig from poetry.core.packages import Dependency from poetry.core.packages import Package from poetry.core.vcs.git import ParsedUrl +from poetry.installation.executor import Executor as BaseExecutor from poetry.utils._compat import PY2 from poetry.utils._compat import WINDOWS from poetry.utils._compat import Path @@ -13,6 +18,26 @@ FIXTURE_PATH = Path(__file__).parent / "fixtures" +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() + + def get_package(name, version): return Package(name, version) @@ -88,3 +113,39 @@ def mock_download(url, dest, **__): fixture = fixtures / parts.path.lstrip("/") copy_or_symlink(fixture, Path(dest)) + + +class Executor(BaseExecutor): + def __init__(self, *args, **kwargs): + super(Executor, self).__init__(*args, **kwargs) + + self._installs = [] + self._updates = [] + self._uninstalls = [] + + @property + def installations(self): + return self._installs + + @property + def updates(self): + return self._updates + + @property + def removals(self): + return self._uninstalls + + def _do_execute_operation(self, operation): + super(Executor, self)._do_execute_operation(operation) + + if not operation.skipped: + getattr(self, "_{}s".format(operation.job_type)).append(operation.package) + + def _execute_install(self, operation): + return 0 + + def _execute_update(self, operation): + return 0 + + def _execute_remove(self, operation): + return 0 diff --git a/tests/installation/test_installer.py b/tests/installation/test_installer.py index 88103e7c323..067f18ee977 100644 --- a/tests/installation/test_installer.py +++ b/tests/installation/test_installer.py @@ -8,7 +8,6 @@ from poetry.core.packages import ProjectPackage from poetry.installation import Installer as BaseInstaller -from poetry.installation.executor import Executor as BaseExecutor from poetry.installation.noop_installer import NoopInstaller from poetry.packages import Locker as BaseLocker from poetry.repositories import Pool @@ -19,6 +18,7 @@ from poetry.utils.env import MockEnv from poetry.utils.env import NullEnv from poetry.utils.toml_file import TomlFile +from tests.helpers import Executor from tests.helpers import get_dependency from tests.helpers import get_package from tests.repositories.test_legacy_repository import ( @@ -35,42 +35,6 @@ def _get_installer(self): return NoopInstaller() -class Executor(BaseExecutor): - def __init__(self, *args, **kwargs): - super(Executor, self).__init__(*args, **kwargs) - - self._installs = [] - self._updates = [] - self._uninstalls = [] - - @property - def installations(self): - return self._installs - - @property - def updates(self): - return self._updates - - @property - def removals(self): - return self._uninstalls - - def _do_execute_operation(self, operation): - super(Executor, self)._do_execute_operation(operation) - - if not operation.skipped: - getattr(self, "_{}s".format(operation.job_type)).append(operation.package) - - def _execute_install(self, operation): - return 0 - - def _execute_update(self, operation): - return 0 - - def _execute_uninstall(self, operation): - return 0 - - class CustomInstalledRepository(InstalledRepository): @classmethod def load(cls, env): diff --git a/tests/puzzle/test_solver.py b/tests/puzzle/test_solver.py index a3678c43bd4..c3540a36591 100644 --- a/tests/puzzle/test_solver.py +++ b/tests/puzzle/test_solver.py @@ -902,12 +902,14 @@ def test_solver_can_resolve_git_dependencies(solver, repo, package): ops = solver.solve() + demo = get_package("demo", "0.1.2") + demo.source_type = "git" + demo.source_url = "https://github.com/demo/demo.git" + demo.source_reference = "9cf87a285a2d3fbb0b9fa621997b3acc3631ed24" + check_solver_result( ops, - [ - {"job": "install", "package": pendulum}, - {"job": "install", "package": get_package("demo", "0.1.2")}, - ], + [{"job": "install", "package": pendulum}, {"job": "install", "package": demo}], ) op = ops[1] @@ -928,12 +930,17 @@ def test_solver_can_resolve_git_dependencies_with_extras(solver, repo, package): ops = solver.solve() + demo = get_package("demo", "0.1.2") + demo.source_type = "git" + demo.source_url = "https://github.com/demo/demo.git" + demo.source_reference = "9cf87a285a2d3fbb0b9fa621997b3acc3631ed24" + check_solver_result( ops, [ {"job": "install", "package": cleo}, {"job": "install", "package": pendulum}, - {"job": "install", "package": get_package("demo", "0.1.2")}, + {"job": "install", "package": demo}, ], ) @@ -949,7 +956,12 @@ def test_solver_can_resolve_git_dependencies_with_ref(solver, repo, package, ref repo.add_package(pendulum) repo.add_package(cleo) - git_config = {"git": "https://github.com/demo/demo.git"} + demo = get_package("demo", "0.1.2") + demo.source_type = "git" + demo.source_url = "https://github.com/demo/demo.git" + demo.source_reference = "9cf87a285a2d3fbb0b9fa621997b3acc3631ed24" + + git_config = {demo.source_type: demo.source_url} git_config.update(ref) package.add_dependency("demo", git_config) @@ -957,10 +969,7 @@ def test_solver_can_resolve_git_dependencies_with_ref(solver, repo, package, ref check_solver_result( ops, - [ - {"job": "install", "package": pendulum}, - {"job": "install", "package": get_package("demo", "0.1.2")}, - ], + [{"job": "install", "package": pendulum}, {"job": "install", "package": demo}], ) op = ops[1] @@ -1206,25 +1215,26 @@ def test_solver_git_dependencies_update(solver, repo, package, installed): repo.add_package(pendulum) repo.add_package(cleo) - demo = get_package("demo", "0.1.2") - demo.source_type = "git" - demo.source_url = "https://github.com/demo/demo.git" - demo.source_reference = "123456" - installed.add_package(demo) + demo_installed = get_package("demo", "0.1.2") + demo_installed.source_type = "git" + demo_installed.source_url = "https://github.com/demo/demo.git" + demo_installed.source_reference = "123456" + installed.add_package(demo_installed) package.add_dependency("demo", {"git": "https://github.com/demo/demo.git"}) ops = solver.solve() + demo = get_package("demo", "0.1.2") + demo.source_type = "git" + demo.source_url = "https://github.com/demo/demo.git" + demo.source_reference = "9cf87a285a2d3fbb0b9fa621997b3acc3631ed24" + check_solver_result( ops, [ {"job": "install", "package": pendulum}, - { - "job": "update", - "from": get_package("demo", "0.1.2"), - "to": get_package("demo", "0.1.2"), - }, + {"job": "update", "from": demo_installed, "to": demo}, ], ) @@ -1256,11 +1266,7 @@ def test_solver_git_dependencies_update_skipped(solver, repo, package, installed ops, [ {"job": "install", "package": pendulum}, - { - "job": "install", - "package": get_package("demo", "0.1.2"), - "skipped": True, - }, + {"job": "install", "package": demo, "skipped": True}, ], ) @@ -1289,11 +1295,7 @@ def test_solver_git_dependencies_short_hash_update_skipped( ops, [ {"job": "install", "package": pendulum}, - { - "job": "install", - "package": get_package("demo", "0.1.2"), - "skipped": True, - }, + {"job": "install", "package": demo, "skipped": True}, ], ) @@ -1315,12 +1317,13 @@ def test_solver_can_resolve_directory_dependencies(solver, repo, package): ops = solver.solve() + demo = get_package("demo", "0.1.2") + demo.source_type = "directory" + demo.source_url = path + check_solver_result( ops, - [ - {"job": "install", "package": pendulum}, - {"job": "install", "package": get_package("demo", "0.1.2")}, - ], + [{"job": "install", "package": pendulum}, {"job": "install", "package": demo}], ) op = ops[1] @@ -1350,12 +1353,16 @@ def test_solver_can_resolve_directory_dependencies_with_extras(solver, repo, pac ops = solver.solve() + demo = get_package("demo", "0.1.2") + demo.source_type = "directory" + demo.source_url = path + check_solver_result( ops, [ {"job": "install", "package": cleo}, {"job": "install", "package": pendulum}, - {"job": "install", "package": get_package("demo", "0.1.2")}, + {"job": "install", "package": demo}, ], ) @@ -1382,12 +1389,13 @@ def test_solver_can_resolve_sdist_dependencies(solver, repo, package): ops = solver.solve() + demo = get_package("demo", "0.1.0") + demo.source_type = "file" + demo.source_url = path + check_solver_result( ops, - [ - {"job": "install", "package": pendulum}, - {"job": "install", "package": get_package("demo", "0.1.0")}, - ], + [{"job": "install", "package": pendulum}, {"job": "install", "package": demo}], ) op = ops[1] @@ -1415,12 +1423,16 @@ def test_solver_can_resolve_sdist_dependencies_with_extras(solver, repo, package ops = solver.solve() + demo = get_package("demo", "0.1.0") + demo.source_type = "file" + demo.source_url = path + check_solver_result( ops, [ {"job": "install", "package": cleo}, {"job": "install", "package": pendulum}, - {"job": "install", "package": get_package("demo", "0.1.0")}, + {"job": "install", "package": demo}, ], ) @@ -1447,12 +1459,13 @@ def test_solver_can_resolve_wheel_dependencies(solver, repo, package): ops = solver.solve() + demo = get_package("demo", "0.1.0") + demo.source_type = "file" + demo.source_url = path + check_solver_result( ops, - [ - {"job": "install", "package": pendulum}, - {"job": "install", "package": get_package("demo", "0.1.0")}, - ], + [{"job": "install", "package": pendulum}, {"job": "install", "package": demo}], ) op = ops[1] @@ -1480,12 +1493,16 @@ def test_solver_can_resolve_wheel_dependencies_with_extras(solver, repo, package ops = solver.solve() + demo = get_package("demo", "0.1.0") + demo.source_type = "file" + demo.source_url = path + check_solver_result( ops, [ {"job": "install", "package": cleo}, {"job": "install", "package": pendulum}, - {"job": "install", "package": get_package("demo", "0.1.0")}, + {"job": "install", "package": demo}, ], )