|
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,48 @@ 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 | + if not overwrite: |
| 1861 | + io.write_line("") |
| 1862 | + |
| 1863 | + requires = [ |
| 1864 | + f"<c1>{requirement}</c1>" |
| 1865 | + for requirement in poetry.pyproject.build_system.requires |
| 1866 | + ] |
| 1867 | + |
| 1868 | + io.overwrite( |
| 1869 | + "<b>Preparing</b> build environment with build-system requirements" |
| 1870 | + f" {', '.join(requires)}" |
| 1871 | + ) |
| 1872 | + venv.run_pip( |
| 1873 | + "install", |
| 1874 | + "--disable-pip-version-check", |
| 1875 | + "--ignore-installed", |
| 1876 | + *poetry.pyproject.build_system.requires, |
| 1877 | + ) |
| 1878 | + |
| 1879 | + if overwrite: |
| 1880 | + io.write_line("") |
| 1881 | + |
| 1882 | + yield venv |
| 1883 | + else: |
| 1884 | + yield env |
| 1885 | + |
| 1886 | + |
1842 | 1887 | class MockEnv(NullEnv): |
1843 | 1888 | def __init__( |
1844 | 1889 | self, |
|
0 commit comments