Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop poetry's dependency on pip and setuptools in project virtual environment #2826

Merged
merged 8 commits into from
Mar 23, 2021

Conversation

abn
Copy link
Member

@abn abn commented Aug 17, 2020

An initial attempt at using the embedded pip wheel from virtualenv package directly. This avoids the need for any critical packages in the project's virtual environment.

Resolves: #1584

Testing this pull request

Since this is a fundamental shift in how we setup virtual environments, testing a broad range of use cases would be great.

Using pipx

pipx install --suffix=@2826 'poetry @ git+https://github.com/python-poetry/poetry.git@refs/pull/2826/head'

Once this is done, you can use this version of poetry as shown here.

poetry@2826 new foobar
pushd foobar
poetry@2826 add pycowsay
poetry@2826 run pycowsay

If you want to do a pip list, there exists a convinience wrapper that will use the embedded pip if the environment does not contain one.

$ poetry@2826 run pip list
Package        Version
-------------- -------
attrs          20.3.0
more-itertools 8.7.0
packaging      20.9
pluggy         0.13.1
py             1.10.0
pycowsay       0.0.0.1
pyparsing      2.4.7
pytest         5.4.3
wcwidth        0.2.5

You will notice here that none of wheel, setuptools nor pip exists in the virtual environment.

Using a container (podman | docker)

podman run --rm -i --entrypoint bash python:3.8 <<EOF
set -xe
python -m pip install -q git+https://github.com/python-poetry/poetry.git@refs/pull/2826/head
poetry new foobar
pushd foobar
poetry add pycowsay
poetry run pip list
EOF

@abn abn requested a review from a team August 17, 2020 23:04
@abn abn force-pushed the curious/pip branch 5 times, most recently from 76d47e7 to 708ce02 Compare August 18, 2020 13:09
@abn abn marked this pull request as ready for review September 28, 2020 18:48
@abn abn force-pushed the curious/pip branch 2 times, most recently from 07b8a15 to 63ffa17 Compare September 28, 2020 19:15
@abn abn changed the title Drop pip from critical packages in project venv Drop poetry's dependency on pip and setuptools in project virtualenvironment Sep 29, 2020
@abn abn force-pushed the curious/pip branch 4 times, most recently from a5ea0fa to 489359a Compare September 29, 2020 12:38
@abn abn changed the title Drop poetry's dependency on pip and setuptools in project virtualenvironment Drop poetry's dependency on pip and setuptools in project virtual environment Sep 29, 2020
@mikenerone
Copy link

Some sort of approach to let me lock pip, setuptools, and wheel for my own project is pretty important to me. Either removing Poetry's dependence on them as this branch does, or a config syntax that lets me bless overrides of Poetry's norms, or something. Right now, my team's dev environments are broken by default because the installed deps don't match the requirements in the package metadata. We workaround it for the moment with poetry run pip install ... (and the versions we need seem to work fine for Poetry), but it would be much, much better if these package deps could be treated per normal.

@gsemet
Copy link

gsemet commented Sep 30, 2020

We are dealing with exactly the same issue using pipenv, it always wants the latest version even if it breaks something. Please ensure at least to let the ability of user to freeze the version somehow. Ideally yes, it would use its own, independent setuptools/wheel, but for some complex projets that needs certain version of setuptools, especially with the version 50.x breaking much stuff with pyinstaller packaging, I am looking to a better alternative than p[ipenv|oetry] run pip install 'setuptools<50'

@abn
Copy link
Member Author

abn commented Sep 30, 2020

@gsemet can you provide a bit more context please? This change only means that poetry's use is isolated to specific versions of pip/setuptools and decoupled. If your project depends on it, you can specify it as either a dev-dependency or build-system.requires. PEP 517 builds still take place in isolated environments, this means the build-system.requires of the project will be respected.

@gsemet
Copy link

gsemet commented Sep 30, 2020

Yes, this change is actually what i would to see. I am using poetry on my newer projects and does not face yet this issue I have on older projects still using pipenv. Pipenv always updates to the latest setuptools available on pypi within the project's virtualenv (also pip and wheels packages), and it occurs several times that the new version broke something. For reproductibility, there should not be these "moving" parts.

So yes, I am pretty much very interesting is seeing the right behavior in poetry, and maybe it already does it: poetry either vendors its own setuptools/wheel package so that they change with poetry updates, but if my package wants some specific version of setuptools for any reason, it should not cause any incompatibility with poetry. From out point of view, setuptools, pip and wheels are 3 packages like any others.

TL;DR: I need to update to poetry, it seems like you already do the right thing :)

@abn
Copy link
Member Author

abn commented Sep 30, 2020

@gsemet ah, I think I misunderstood your first message. Glad that this is something that is useful. However, do note that poetry today treats setuptools, pip and wheel as "unsafe" packages in the environment. This means that, while, we do not explicitly update these versions, they cannot be managed by project.

This is what I (putting on my poetry user hat), want to change in this PR.

Poetry (putting on my maintainer hat again), has been gradually reducing reliance on pip and setuptools. Right now, we only use pip for wheel installations (wheels poetry downloads) and editable installs pip install -e /path/to/something. The reliance on setuptools is a side-effect of supporting editable dependency installations.

@gsemet
Copy link

gsemet commented Sep 30, 2020

So, I hope this PR lands in the next version of poetry :)

@apollo13
Copy link
Contributor

apollo13 commented Oct 8, 2020

I just saw this PR. This would be a huge improvement for us if it ends up fixing #1584 -- Thank you for your work on this @abn

Copy link
Contributor

@apollo13 apollo13 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@abn Looking mostly good so far. I have left a few question, would be glad if you could get back on those.

poetry/installation/pip_installer.py Outdated Show resolved Hide resolved
poetry/installation/pip_installer.py Outdated Show resolved Hide resolved
poetry/utils/env.py Outdated Show resolved Hide resolved
poetry/utils/env.py Show resolved Hide resolved
abn added 2 commits March 21, 2021 13:23
Use embedded pip wheel from virtualenv package. This avoids the need
for pip to be a critical package in the project's virtual environment.
@abn abn deleted the curious/pip branch March 23, 2021 15:17
@sdispater
Copy link
Member

@abn

This is a solved problem and we should really use https://github.com/pypa/pep517

Well, not really, since pep517 makes subprocess calls to pip (https://github.com/pypa/pep517/blob/master/pep517/envbuild.py#L98) which we want to avoid. It also doesn't have reusable environments, i.e. you need to create a brand new environment for each sdist which is costly.

That's why I said it's no small task to make it pip agnostic.

@apollo13
Copy link
Contributor

apollo13 commented Mar 23, 2021

It seems as if https://github.com/pypa/build would be a pep517 compatible installer that doesn't utilize pip at all -- at least that is what a quick look through the source suggested.

EDIT:// That might have been to fast: https://github.com/pypa/build/blob/main/src/build/env.py#L157-L168

@abn
Copy link
Member Author

abn commented Mar 23, 2021

At present it does use pip, see https://github.com/pypa/build/blob/2c1da830f214580e8e4b94e4c88345963fa32d2e/src/build/env.py#L157-L170

That said, if we do have support for wheel installations, and access to setuptools wheels (bundled via virtualenv), I suspect doing so will only require poetry to override the build lib implementation to use poetry's own wheel installation. But I can see what you mean by it not being a simple task. Although, I would definitely have to ask if that is worthwhile for poetry to implement and manage. Additionally, the "new environment" for each sdist is probably a good thing to be honest as it ensures build isolation. I doubt that will be an issue if you have local caching available.

@TBBle
Copy link
Contributor

TBBle commented Mar 23, 2021

You don't actually override pypa/build's env-setup, since the caller is the one calling it, i.e. pip is only sub-called by IsolatedEnvBuilder.install from _build_in_isolated_env in __main__.py which is part of the CLI for the pypa/build package:

def _build_in_isolated_env(builder, outdir, distributions, config_settings):
    # type: (ProjectBuilder, str, List[str], ConfigSettings) -> None
    for distribution in distributions:
        with IsolatedEnvBuilder() as env:
            builder.python_executable = env.executable
            builder.scripts_dir = env.scripts_dir
            # first install the build dependencies
            env.install(builder.build_dependencies)
            # then get the extra required dependencies from the backend (which was installed in the call above :P)
            env.install(builder.get_dependencies(distribution))
            builder.build(distribution, outdir, config_settings)

So you just want to create a venv with the necessary dependencies yourself, and do this (_build_in_current_envfrom __main__.py, this is the --no-isolation path for their CLI tool)

def _build_in_current_env(builder, outdir, distributions, config_settings, skip_dependencies=False):
    # type: (ProjectBuilder, str, List[str], ConfigSettings, bool) -> None
    for dist in distributions:
        if not skip_dependencies:
            missing = builder.check_dependencies(dist)
            if missing:
                _error(
                    'Missing dependencies:'
                    + ''.join('\n\t' + dep for deps in missing for dep in (deps[0], _format_dep_chain(deps[1:])) if dep)
                )

        builder.build(dist, outdir, config_settings)

So for Poetry, I expect that if we want to use pypb/build, we just populate a venv as we do now, and use pypa/build's ProjectBuilder(srcdir) (builder above, this wraps/exposes the PEP-517 hooks) to build the wheel we need using that venv.

This also puts Poetry directly in control of whether it uses a single scratch venv to build all necessary wheels for the "real" project venv, or uses an isolated venv for each wheel, or some other combination thereof.

@bmw
Copy link

bmw commented Apr 8, 2021

I'm eagerly awaiting this change as a resolution to #1584. When do people expect this PR to be included in a release?

@abn
Copy link
Member Author

abn commented Apr 8, 2021

@bmw the next planned release is 1.2.0a0, which should be landing in the next month or so. In the meantime, you can use the version from master.

pipx install --force --suffix=@master 'poetry @ git+https://github.com/python-poetry/poetry.git@master'

abn added a commit to abn/poetry that referenced this pull request Apr 11, 2021
This change introduces the following configuration options:

- `virtualenvs.options.no-pip` (Default: `false`)
- `virtualenvs.options.no-wheel` (Default: `false`)
- `virtualenvs.options.no-setuptools` (Default: `false`)

With these options, we allow, the user to control the inclusion of
`pip`, `wheel` and `setuptools` packages in new virtual environments.
The defaults used retain existing behaviour as of `1.1.5`.

In addition the following now holds true.

- projects can define `pip`, `wheel` and `setuptools` as dependencies
- if any of these packages are in the project's dependency tree, poetry
  will manage their versions
- all poetry internal commands will use pip embedded in virtualenv
  irrespective of pip beig available in the environment
- if `poetry run pip` is executed, pip installed in the virtualenv will
  be prioritsed
- `poetry install --remove-untracked` will ignore these packages if
  they are not present in the project's dependency tree

Relates-to: python-poetry#2826
Relates-to: python-poetry#3916
abn added a commit to abn/poetry that referenced this pull request Apr 13, 2021
This change introduces the following configuration options:

- `virtualenvs.options.no-pip` (Default: `false`)
- `virtualenvs.options.no-wheel` (Default: `false`)
- `virtualenvs.options.no-setuptools` (Default: `false`)

With these options, we allow, the user to control the inclusion of
`pip`, `wheel` and `setuptools` packages in new virtual environments.
The defaults used retain existing behaviour as of `1.1.5`.

In addition the following now holds true.

- projects can define `pip`, `wheel` and `setuptools` as dependencies
- if any of these packages are in the project's dependency tree, poetry
  will manage their versions
- all poetry internal commands will use pip embedded in virtualenv
  irrespective of pip beig available in the environment
- if `poetry run pip` is executed, pip installed in the virtualenv will
  be prioritsed
- `poetry install --remove-untracked` will ignore these packages if
  they are not present in the project's dependency tree

Relates-to: python-poetry#2826
Relates-to: python-poetry#3916
@sdispater sdispater mentioned this pull request Apr 23, 2021
abn added a commit to abn/poetry that referenced this pull request Apr 27, 2021
This change introduces the following configuration options:

- `virtualenvs.options.no-pip` (Default: `false`)
- `virtualenvs.options.no-wheel` (Default: `false`)
- `virtualenvs.options.no-setuptools` (Default: `false`)

With these options, we allow, the user to control the inclusion of
`pip`, `wheel` and `setuptools` packages in new virtual environments.
The defaults used retain existing behaviour as of `1.1.5`.

In addition the following now holds true.

- projects can define `pip`, `wheel` and `setuptools` as dependencies
- if any of these packages are in the project's dependency tree, poetry
  will manage their versions
- all poetry internal commands will use pip embedded in virtualenv
  irrespective of pip beig available in the environment
- if `poetry run pip` is executed, pip installed in the virtualenv will
  be prioritsed
- `poetry install --remove-untracked` will ignore these packages if
  they are not present in the project's dependency tree

Relates-to: python-poetry#2826
Relates-to: python-poetry#3916
abn added a commit to abn/poetry that referenced this pull request Apr 28, 2021
This change introduces the following configuration options:

- `virtualenvs.options.no-pip` (Default: `false`)
- `virtualenvs.options.no-wheel` (Default: `false`)
- `virtualenvs.options.no-setuptools` (Default: `false`)

With these options, we allow, the user to control the inclusion of
`pip`, `wheel` and `setuptools` packages in new virtual environments.
The defaults used retain existing behaviour as of `1.1.5`.

In addition the following now holds true.

- projects can define `pip`, `wheel` and `setuptools` as dependencies
- if any of these packages are in the project's dependency tree, poetry
  will manage their versions
- all poetry internal commands will use pip embedded in virtualenv
  irrespective of pip beig available in the environment
- if `poetry run pip` is executed, pip installed in the virtualenv will
  be prioritsed
- `poetry install --remove-untracked` will ignore these packages if
  they are not present in the project's dependency tree

Relates-to: python-poetry#2826
Relates-to: python-poetry#3916
abn added a commit to abn/poetry that referenced this pull request Apr 29, 2021
This change introduces the following configuration options:

- `virtualenvs.options.no-pip` (Default: `false`)
- `virtualenvs.options.no-wheel` (Default: `false`)
- `virtualenvs.options.no-setuptools` (Default: `false`)

With these options, we allow, the user to control the inclusion of
`pip`, `wheel` and `setuptools` packages in new virtual environments.
The defaults used retain existing behaviour as of `1.1.5`.

In addition the following now holds true.

- projects can define `pip`, `wheel` and `setuptools` as dependencies
- if any of these packages are in the project's dependency tree, poetry
  will manage their versions
- all poetry internal commands will use pip embedded in virtualenv
  irrespective of pip beig available in the environment
- if `poetry run pip` is executed, pip installed in the virtualenv will
  be prioritsed
- `poetry install --remove-untracked` will ignore these packages if
  they are not present in the project's dependency tree

Relates-to: python-poetry#2826
Relates-to: python-poetry#3916
abn added a commit to abn/poetry that referenced this pull request Apr 30, 2021
For project virtual environments, default to enabling pip, setuptools
and wheel packages to retain existing stable behaviour to prevent
unexpected breakages caused by development environments making
assumptions of base package availability in virtual environments.

Poetry itself does not require the use of these packages and will
execute correctly within environments that do not have these packages.

This change retains the ability to manage these packages as direct
project dependency as introduced in python-poetry#2826. All poetry internal
execution of pip is retaining the use of the wheel embedded within
the virtualenv package used by poetry.

In cases where a one of these reserved packages are being managed as a
project dependency, the will be treated as any other project
dependency. Executing `poetry install --remove-untracked` will not
remove any of these reserved packages. However, `poetry add pip` and
`poetry remove pip` will trigger the update and removal of `pip`
respectively.

Relates-to: python-poetry#2826
Relates-to: python-poetry#3916
abn added a commit to abn/poetry that referenced this pull request Apr 30, 2021
For project virtual environments, default to enabling pip, setuptools
and wheel packages to retain existing stable behaviour to prevent
unexpected breakages caused by development environments making
assumptions of base package availability in virtual environments.

Poetry itself does not require the use of these packages and will
execute correctly within environments that do not have these packages.

This change retains the ability to manage these packages as direct
project dependency as introduced in python-poetry#2826. All poetry internal
execution of pip is retaining the use of the wheel embedded within
the virtualenv package used by poetry.

In cases where a one of these reserved packages are being managed as a
project dependency, the will be treated as any other project
dependency. Executing `poetry install --remove-untracked` will not
remove any of these reserved packages. However, `poetry add pip` and
`poetry remove pip` will trigger the update and removal of `pip`
respectively.

Relates-to: python-poetry#2826
Relates-to: python-poetry#3916
Copy link

github-actions bot commented Mar 1, 2024

This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 1, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area/venv Related to virtualenv management
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Poetry export does not include setuptools even when it is a direct dependency.
8 participants