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
22 changes: 22 additions & 0 deletions docs/docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ cache-dir = "/path/to/cache/directory"
virtualenvs.create = true
virtualenvs.in-project = null
virtualenvs.options.always-copy = true
virtualenvs.options.no-pip = true
virtualenvs.options.no-setuptools = false
virtualenvs.options.no-wheel = false
virtualenvs.options.system-site-packages = false
virtualenvs.path = "{cache-dir}/virtualenvs" # /path/to/cache/directory/virtualenvs
```
Expand Down Expand Up @@ -146,6 +149,25 @@ Defaults to `{cache-dir}/virtualenvs` (`{cache-dir}\virtualenvs` on Windows).
If set to `true` the `--always-copy` parameter is passed to `virtualenv` on creation of the venv. Thus all needed files are copied into the venv instead of symlinked.
Defaults to `false`.

### `virtualenvs.options.no-pip`: boolean

If set to `true` the `--no-pip` parameter is passed to `virtualenv` on creation of the venv. Thus all needed files are copied into the venv instead of symlinked.
Defaults to `false`.

!!!note

If set to `true`, `poetry run pip` will use pip embedded in poetry's virtualenv dependency.

### `virtualenvs.options.no-setuptools`: boolean

If set to `true` the `--no-setuptools` parameter is passed to `virtualenv` on creation of the venv. Thus all needed files are copied into the venv instead of symlinked.
Defaults to `false`.

### `virtualenvs.options.no-wheel`: boolean

If set to `true` the `--no-wheel parameter is passed to `virtualenv` on creation of the venv. Thus all needed files are copied into the venv instead of symlinked.
Defaults to `false`.

### `virtualenvs.options.system-site-packages`: boolean

Give the virtual environment access to the system site-packages directory.
Expand Down
40 changes: 20 additions & 20 deletions poetry.lock

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

11 changes: 10 additions & 1 deletion poetry/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,13 @@ class Config:
"create": True,
"in-project": None,
"path": os.path.join("{cache-dir}", "virtualenvs"),
"options": {"always-copy": False, "system-site-packages": False},
"options": {
"always-copy": False,
"system-site-packages": False,
"no-pip": False,
"no-setuptools": False,
"no-wheel": False,
},
},
"experimental": {"new-installer": True},
"installer": {"parallel": True},
Expand Down Expand Up @@ -139,6 +145,9 @@ def _get_normalizer(self, name: str) -> Callable:
"virtualenvs.in-project",
"virtualenvs.options.always-copy",
"virtualenvs.options.system-site-packages",
"virtualenvs.options.no-pip",
"virtualenvs.options.no-setuptools",
"virtualenvs.options.no-wheel",
"installer.parallel",
}:
return boolean_normalizer
Expand Down
15 changes: 15 additions & 0 deletions poetry/console/commands/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,21 @@ def unique_config_values(self) -> Dict[str, Tuple[Any, Any, Any]]:
boolean_normalizer,
False,
),
"virtualenvs.options.no-pip": (
boolean_validator,
boolean_normalizer,
False,
),
"virtualenvs.options.no-setuptools": (
boolean_validator,
boolean_normalizer,
False,
),
"virtualenvs.options.no-wheel": (
boolean_validator,
boolean_normalizer,
False,
),
"virtualenvs.path": (
str,
lambda val: str(Path(val)),
Expand Down
13 changes: 11 additions & 2 deletions poetry/console/commands/debug/resolve.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,14 @@ def handle(self) -> Optional[int]:

pool = self.poetry.pool

solver = Solver(package, pool, Repository(), Repository(), self._io)
solver = Solver(
package,
pool,
Repository(),
Repository(),
self._io,
config=self.poetry.config,
)

ops = solver.solve()

Expand Down Expand Up @@ -121,7 +128,9 @@ def handle(self) -> Optional[int]:

pool.add_repository(locked_repository)

solver = Solver(package, pool, Repository(), Repository(), NullIO())
solver = Solver(
package, pool, Repository(), Repository(), NullIO(), poetry=self.poetry
)
with solver.use_environment(env):
ops = solver.solve()

Expand Down
1 change: 1 addition & 0 deletions poetry/console/commands/show.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ def handle(self) -> Optional[int]:
installed=Repository(),
locked=locked_repo,
io=NullIO(),
config=self.poetry.config,
)
solver.provider.load_deferred(False)
with solver.use_environment(self.env):
Expand Down
8 changes: 7 additions & 1 deletion poetry/installation/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,13 @@ def _download_link(self, operation: Union[Install, Update], link: Link) -> Link:
archive = self._chef.prepare(archive)

if package.files:
archive_hash = "sha256:" + FileDependency(package.name, archive).hash()
archive_hash = (
"sha256:"
+ FileDependency(
package.name,
Path(archive.path) if isinstance(archive, Link) else archive,
).hash()
)
if archive_hash not in {f["hash"] for f in package.files}:
raise RuntimeError(
f"Invalid hash for {package} using archive {archive.name}"
Expand Down
4 changes: 4 additions & 0 deletions poetry/installation/installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ def __init__(
installed = self._get_installed()

self._installed_repository = installed
self._poetry_config = config

@property
def executor(self) -> Executor:
Expand Down Expand Up @@ -209,6 +210,7 @@ def _do_refresh(self) -> int:
locked_repository,
locked_repository,
self._io,
config=self._poetry_config,
)

ops = solver.solve(use_latest=[])
Expand Down Expand Up @@ -247,6 +249,7 @@ def _do_install(self, local_repo: Repository) -> int:
locked_repository,
self._io,
remove_untracked=self._remove_untracked,
config=self._poetry_config,
)

ops = solver.solve(use_latest=self._whitelist)
Expand Down Expand Up @@ -316,6 +319,7 @@ def _do_install(self, local_repo: Repository) -> int:
locked_repository,
NullIO(),
remove_untracked=self._remove_untracked,
config=self._poetry_config,
)
# Everything is resolved at this point, so we no longer need
# to load deferred dependencies (i.e. VCS, URL and path dependencies)
Expand Down
28 changes: 24 additions & 4 deletions poetry/puzzle/solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@


if TYPE_CHECKING:
from poetry.config.config import Config
from poetry.core.packages.dependency import Dependency
from poetry.core.packages.directory_dependency import DirectoryDependency
from poetry.core.packages.file_dependency import FileDependency
Expand All @@ -49,6 +50,7 @@ def __init__(
io: IO,
remove_untracked: bool = False,
provider: Optional[Provider] = None,
config: Optional["Config"] = None,
):
self._package = package
self._pool = pool
Expand All @@ -63,10 +65,30 @@ def __init__(
self._overrides = []
self._remove_untracked = remove_untracked

self._poetry_config = config
self._preserved_package_names = None

@property
def provider(self) -> Provider:
return self._provider

@property
def preserved_package_names(self):
if self._preserved_package_names is None:
self._preserved_package_names = {
self._package.name,
*Provider.UNSAFE_PACKAGES,
}
if self._poetry_config is not None:
deps = {package.name for package in self._locked.packages}

for name in {"pip", "wheel", "setuptools"}:
if not self._poetry_config.get(f"virtualenvs.options.no-{name}"):
if name not in deps:
self._preserved_package_names.add(name)

return self._preserved_package_names

@contextmanager
def use_environment(self, env: Env) -> None:
with self.provider.use_environment(env):
Expand Down Expand Up @@ -190,11 +212,9 @@ def solve(self, use_latest: List[str] = None) -> List["OperationTypes"]:
locked_names = {locked.name for locked in self._locked.packages}

for installed in self._installed.packages:
if installed.name == self._package.name:
continue
if installed.name in Provider.UNSAFE_PACKAGES:
# Never remove pip, setuptools etc.
if installed.name in self.preserved_package_names:
continue

if installed.name not in locked_names:
operations.append(Uninstall(installed))

Expand Down
Loading