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

Adopting "working" scheme for every run #4575

Open
pradyunsg opened this issue Jun 27, 2017 · 28 comments
Open

Adopting "working" scheme for every run #4575

pradyunsg opened this issue Jun 27, 2017 · 28 comments
Labels
C: user scheme Handling of packages in user-specific directories state: awaiting PR Feature discussed, PR is needed type: enhancement Improvements to functionality type: refactor Refactoring code UX User experience related

Comments

@pradyunsg
Copy link
Member

Just carrying over my idea in #1056 (comment), for proper dedicated discussion.

AFAIK, there are 3 possible schemes for packages:

  • "system" - for system/global packages (--system)
  • "user" - for packages installed in user space (--user)
  • "local" - for virtualenv packages (--local)

pip enforces a "working" scheme on every run. Outside a virtualenv, the default working scheme would be "system" (It should really be "user", that's another issue #1668). Inside a virtualenv, the default working scheme should be "local". Passing --system or --user or --local overrides the working scheme.

Only packages in the same scheme as the working scheme can be modified. By modifying, I mean installing or uninstalling a package. Trying to modify a package in a different scheme is not allowed and pip would print a message and error out.

So, modifying a package in system scheme with a "user" working scheme is not allowed. Nor is modifing a package in user scheme with a "system" working scheme. Niether are the other permutations with "local".

I think this results in a pretty simple behaviour model.

As @ncoghlan pointed out, this would need some logic to understand that user installs shadow system ones. Also, I would slightly change this to spell it like --scheme {global,user,venv} because I like how this signifies exclusiveness of the behaviours better than plain flags do and is consistent with some internal configuration stuff.

Additionally, while doing this:

/ping @dstufft @pfmoore

@pradyunsg pradyunsg added the state: needs discussion This needs some more discussion label Jun 27, 2017
@pradyunsg pradyunsg self-assigned this Jun 27, 2017
@pradyunsg pradyunsg added type: enhancement Improvements to functionality C: user scheme Handling of packages in user-specific directories labels Jun 27, 2017
@pradyunsg
Copy link
Member Author

I would slightly change this to spell it like --scheme {global,user,venv}

Oh, and this would let you set a default scheme for yourself using the configuration toolchain.

@pradyunsg
Copy link
Member Author

@dstufft @pfmoore I would like to know what you think about this. :)

@pfmoore
Copy link
Member

pfmoore commented Jun 30, 2017

In principle this sounds like a reasonable thing to do - but I'm afraid I've got some personal priorities at the moment that mean I don't really have time to think through the implications.

So count me as in favour in principle, but not really able to provide a detailed review at the moment, sorry.

@pradyunsg
Copy link
Member Author

Cool. Thanks! :)

@ncoghlan
Copy link
Member

ncoghlan commented Jul 4, 2017

Just noting that I briefly thought that --scheme may not be a good name for this option, due to the potential collision with the concept of installation schemes in sysconfig: https://docs.python.org/3/library/sysconfig.html#installation-paths

However, I subsequently realised that these uses are actually the same use case - the new pip level option is just a helper to select the desired scheme without having to specify the exact platform appropriate scheme name as defined in sysconfig.

@pradyunsg
Copy link
Member Author

pradyunsg commented Jul 5, 2017

Linking to #2418 since I somehow always forget there was an attempt at making --user behaviour default.


concept of installation schemes in sysconfig

This is, actually, nice that the names here and there match. :)

@tuukkamustonen
Copy link

This came up in #4809 where I suggested being able to pip list only packges related to one scope (now it combines both system and user packages, making it impossible to say which package comes from where).

@pradyunsg
Copy link
Member Author

I've gone ahead and made a PR for this -- #4871.

Thoughts @dstufft, @xavfernandez?

Maybe Barry Warsaw (his name's on the Debian patch to pip; #1668 would be fixed as a part of that PR) should be pinged for this discussion?

@piotr-dobrogost
Copy link

How does --target mode of operation relate to schemes? It feels like --target essentially is another type of scheme and treating it as such would potentially solve many bugs pertaining to --target option.

@pradyunsg pradyunsg added the type: refactor Refactoring code label Aug 1, 2018
@nanonyme
Copy link

nanonyme commented Mar 7, 2019

I personally think that fallback logic is too complicated. If you're operating under a badly configured distro, use virtualenv.

@ssbarnea
Copy link
Contributor

ssbarnea commented Mar 7, 2019

@nanonyme The fallback has nothing to do with what you call "badly" configured distro. Here is a very simple use case: you have a bash script that call "pip install foo", which is needed for testing you code. You want to make this script usable regardless if user is inside an virtualenv or not.

The script could be called by tox so it would be inside a virtualenv, it may be called by user outside a virtualenv or by user after the activated a virtualenv.

All these use cases are not only valid but also wild spread. At this moment it requires adding a lot of extra logic inside that bash script in order to detect virtualenv presence and decide which params to give to pip.

I gave the bash script just as an example but in practice users may not even have a script and only a configuration line that accepts a "command to run", something quite common on CI systems (see travis.ini). Those CI systems may run that code inside or outside a virtualenv.

If pip is not able to detect and make use of virtualenv, it make any usage of it much harder because the user would be forced to write wrappers around that code in order to make it work in various contexts. Writing these wrappers is not even possible in some cases (or just hard and ugly due to the need to cope with multiple levels or quoting in order to use bash to implement that missing logic).

@nanonyme
Copy link

nanonyme commented Mar 7, 2019

Basically with above you have

  1. Explicit global, ignore virtualenv
  2. Explicit user, ignore virtualenv
  3. Explicit local, local set to global, virtualenv with fallback to global
  4. Explicit local, local set to user, virtualenv with fallback to user

The fallback sequences are far simpler this way

@chrahunt
Copy link
Member

Not sure if I missed it, how would this interact with the set of packages available for import in a setup.py-based install, or a PEP 517 install using --no-build-isolation?

Also, is the assumption that for determining whether a dependency is already installed we'd have some of these schemes "inherit" the packages from the packages that would be available in another? Like

  • user considers packages in system
  • local considers packages in user and system only if system site packages is enabled
  • system doesn't consider any others
  • target doesn't consider any others (or it may be configurable -I think we've seen use cases going both ways)

@pradyunsg
Copy link
Member Author

pradyunsg commented Sep 21, 2019

No changes on that front. This would only affect how a package is installed / unpacked, not how it's built.

Things that are currently importable at build time, would stay importable -- basically anything that's on sys.path when running.

@pradyunsg
Copy link
Member Author

Poking here for feedback on #7164.

@illume
Copy link
Contributor

illume commented Oct 14, 2019

It looks like @takluyver in #7164 (comment) has a nice plan for stopping some of the damage of defaulting to write to system wide packages. #7002 That should hopefully stop much of the damage experienced by newbies. Thank you, thankyou, thanksssss to all involved! 🎈🎉

@pradyunsg
Copy link
Member Author

(Re?)iterating that this change is still relevant in a post #7002 world, since this is an internal refactoring-related issue in pip.

I'd expect us to start by making refactors to decouple the scheme from the various parts of our codebase (like @chrahunt has started!) and once that's completely/fairly done; we'd start working on the user-facing changes.

@robeke
Copy link

robeke commented Aug 27, 2023

I agree this will hopefully improve the current inconsistent behavior. For example using Python 3.11.3 venv with pip 22.3.1 on Linux, I am able to install a package with the --user option, but if I attempt to uninstall the same package using the same venv/pip, it refuses indicating package is "outside environment" and "Can't uninstall 'mypackage'. No files were found to uninstall." I would expect the uninstall to work given the install was permitted.

@hmkim
Copy link

hmkim commented Sep 12, 2023

If you have a sudo account, use this command.
sudo dnf remove python3-requests

For example, Amazon Linux 2023 have this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C: user scheme Handling of packages in user-specific directories state: awaiting PR Feature discussed, PR is needed type: enhancement Improvements to functionality type: refactor Refactoring code UX User experience related
Projects
None yet
Development

Successfully merging a pull request may close this issue.