|
20 | 20 | from typing import ContextManager
|
21 | 21 | from typing import Iterable
|
22 | 22 | from typing import Iterator
|
| 23 | +from typing import TypeVar |
23 | 24 |
|
24 | 25 | import packaging.tags
|
25 | 26 | import tomlkit
|
|
30 | 31 | from packaging.tags import interpreter_name
|
31 | 32 | from packaging.tags import interpreter_version
|
32 | 33 | from packaging.tags import sys_tags
|
| 34 | +from poetry.core.poetry import Poetry |
33 | 35 | from poetry.core.semver.helpers import parse_constraint
|
34 | 36 | from poetry.core.semver.version import Version
|
35 | 37 | from poetry.core.toml.file import TOMLFile
|
|
50 | 52 | from cleo.io.io import IO
|
51 | 53 | from poetry.core.version.markers import BaseMarker
|
52 | 54 |
|
53 |
| - from poetry.poetry import Poetry |
| 55 | + |
| 56 | +P = TypeVar("P", bound=Poetry) |
54 | 57 |
|
55 | 58 |
|
56 | 59 | GET_SYS_TAGS = f"""
|
@@ -494,7 +497,7 @@ class EnvManager:
|
494 | 497 |
|
495 | 498 | ENVS_FILE = "envs.toml"
|
496 | 499 |
|
497 |
| - def __init__(self, poetry: Poetry) -> None: |
| 500 | + def __init__(self, poetry: P) -> None: |
498 | 501 | self._poetry = poetry
|
499 | 502 |
|
500 | 503 | def _full_python_path(self, python: str) -> str:
|
@@ -1839,6 +1842,46 @@ def ephemeral_environment(
|
1839 | 1842 | yield VirtualEnv(venv_dir, venv_dir)
|
1840 | 1843 |
|
1841 | 1844 |
|
| 1845 | +@contextmanager |
| 1846 | +def build_environment( |
| 1847 | + poetry: P, env: Env | None = None, io: IO | None = None |
| 1848 | +) -> Iterator[Env]: |
| 1849 | + """ |
| 1850 | + If a build script is specified for the project, there could be additional build |
| 1851 | + time dependencies, eg: cython, setuptools etc. In these cases, we create an |
| 1852 | + ephemeral build environment with all requirements specified under |
| 1853 | + `build-system.requires` and return this. Otherwise, the given default project |
| 1854 | + environment is returned. |
| 1855 | + """ |
| 1856 | + if not env or poetry.package.build_script: |
| 1857 | + with ephemeral_environment(executable=env.python if env else None) as venv: |
| 1858 | + overwrite = io and io.output.is_decorated() and not io.is_debug() |
| 1859 | + if io: |
| 1860 | + requires = map( |
| 1861 | + lambda r: f"<c1>{r}</c1>", poetry.pyproject.build_system.requires |
| 1862 | + ) |
| 1863 | + if not overwrite: |
| 1864 | + io.write_line("") |
| 1865 | + |
| 1866 | + io.overwrite( |
| 1867 | + "<b>Preparing</b> build environment with build-system requirements" |
| 1868 | + f" {', '.join(requires)}" |
| 1869 | + ) |
| 1870 | + venv.run_pip( |
| 1871 | + "install", |
| 1872 | + "--disable-pip-version-check", |
| 1873 | + "--ignore-installed", |
| 1874 | + *poetry.pyproject.build_system.requires, |
| 1875 | + ) |
| 1876 | + |
| 1877 | + if overwrite: |
| 1878 | + io.write_line("") |
| 1879 | + |
| 1880 | + yield venv |
| 1881 | + else: |
| 1882 | + yield env |
| 1883 | + |
| 1884 | + |
1842 | 1885 | class MockEnv(NullEnv):
|
1843 | 1886 | def __init__(
|
1844 | 1887 | self,
|
|
0 commit comments