-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Add a --python option #11320
Add a --python option #11320
Conversation
Virtualenv and tox have a pretty sophisticated mechanism for supporting names like In reality, I would expect the
For case (1), we need to point at the environment's interpreter. A path (absolute or relative) to that interpreter is probably perfectly sufficient. We might want to allow a shortcut of pointing to the virtualenv (a directory containing either For case (2), we might also want to point at the currently active interpreter. Allowing an alias of "py" or "python", would cover this. We'd need to smooth over platform differences here, but that's a minor point. Note that I don't think we should try to detect when pip is run via pipx, and automatically supply Basically, let's keep it simple until we get some actual use cases. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! A couple of total nit-picks.
src/pip/_internal/cli/main_parser.py
Outdated
# TODO: On Windows, `--python .venv/Scripts/python` won't pass the | ||
# exists() check (no .exe extension supplied). But it's pretty | ||
# obvious what the user intends. Should we allow this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could do this without too much fuss with
directory, filename = os.path.split(python)
if shutil.which(filename, path=directory) is not None:
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the shutil.which
docs,
On Windows, the current directory is always prepended to the path whether or not you use the default or provide your own
That could give weird false positives (for example, we have a python.exe
in the CWD, and we do --python=.venv/python.exe
).
On reflection, I think this is too much effort, and we should just expect the user to supply the .exe
(i.e., provide the name of a file that exists). I suspect most people will use autocomplete anyway, if they are entering the path by hand.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm on board with this. Thanks for this work!
Ah, another thing: I tried |
Ouch, that's not a usage I'd expected ( So how about the following:
I don't mind making Also, do we have a machine readable definition of what Python versions pip supports? I guess I could get it via |
Eh eh, just me trying to do end-user-ish things :) But what's wrong with not having a virtual environment? |
Nothing at all, but I view "provide a directory name" as a shortcut for "provide a virtual environment". If you don't have a virtual environment, just supply the executable name1. In the docs, I've explicitly said that what you can pass is "the path to a virtual environment", not a general directory. Footnotes
|
Maybe we should check for |
a599e92
to
263b562
Compare
Can anyone shed any light on why the github actions Ubuntu runner is showing a bunch of packages present in a newly-created Hmm. Why the heck does the venv
If anyone has any suggestions, either on what might be happening or how to debug this further, I'd be really grateful. |
I could of course weaken the test, to not assert that the environment is empty before and after, but that seems bad - a major point here is that the environment doesn't need anything in it 🙁 |
db42458
to
dde2b17
Compare
Hmm, is this somehow related to the (accurately named, IMO 🙂) setuptools |
That's quite a substantial change, and not just to the version check code. I don't want to simply accept that without consensus from @pypa/pip-committers that we're OK requiring the limitation to Python 2 compatible syntax in Personally, I'm rather aggressively against catering for Python 2, so my instinct is to reject it. But I know that's an extreme view, so I'd like to mitigate it by getting other people to tell me I'm wrong 🙂 On the other hand, I do like the simplification you made to the version check - I was being far too clever for my own good there. I'll happily accept that regardless of the question over Python 2. (Don't worry about changing your PR, I'll cherry-pick the bits we agree on by hand if needed). |
It's the solution I found to avoid an ugly syntax error stack trace when running |
If we restrict the option to only supporting virtual environments, we can introspect However, |
One specific issue I have is that I don't see any way to easily test that we keep to Python 2 compatible syntax. I guess we could add a Python 2 CI test, but I'd prefer a lint check that we can run locally (i.e. without needing Python 2 installed...) Personally, I don't even remember what counts as Python 2 compatible these days... |
Thinking some more about this, though, the main changes for Python 2 compatibility are removing type annotations in favour of It makes me somewhat sad that I find the version without type annotations a lot more readable than the annotated version... |
src/pip/__pip-runner__.py
Outdated
def check_python_version() -> None: | ||
# Import here to ensure the imports happen after the sys.meta_path change. | ||
from pip._vendor.packaging.specifiers import SpecifierSet | ||
from pip._vendor.packaging.version import Version | ||
|
||
py_ver = Version("{0.major}.{0.minor}.{0.micro}".format(sys.version_info)) | ||
if py_ver not in SpecifierSet(PYTHON_REQUIRES): | ||
raise SystemExit( | ||
f"This version of pip does not support python {py_ver} " | ||
f"(requires {PYTHON_REQUIRES})" | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
def check_python_version() -> None: | |
# Import here to ensure the imports happen after the sys.meta_path change. | |
from pip._vendor.packaging.specifiers import SpecifierSet | |
from pip._vendor.packaging.version import Version | |
py_ver = Version("{0.major}.{0.minor}.{0.micro}".format(sys.version_info)) | |
if py_ver not in SpecifierSet(PYTHON_REQUIRES): | |
raise SystemExit( | |
f"This version of pip does not support python {py_ver} " | |
f"(requires {PYTHON_REQUIRES})" | |
) | |
def check_python_version() -> None: | |
if sys.version_info < (3, 7): | |
raise SystemExit( | |
f"This version of pip requires Python 3.7+. You have:\n" | |
f"{sys.version}" | |
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We aren't going to get more complicated anytime in the future, so I wouldn't bother with trying to be fully flexible here TBH.
FWIW, I think we should omit all the changes to the pip-runner from this PR, and make them in a separate follow up. It's a valid point that we should present a better error message -- but that's auxilary to the main functionality change in this PR and there's no reason to block the rest of the discussion on handling the edge case of unsupported Python versions with the runner (even though, yes, I admit we'll hit that and should improve that). :) |
That's an excellent idea. I've done that, and added #11342 for the runner change. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A small update to the doc, otherwise looks good to me.
Fixed, thanks. |
OK, I believe that's all the review comments addressed. Unless anyone flags any last minute objections, I'll merge this at the weekend. |
This is an initial draft for a
--python
option for pip, that runs pip with a specified Python interpreter.To do:
_get_runnable_pip
should probably be moved somewhere more general)The use of an environment variable to stop infinitely creating new subprocesses feels OK to me, but is there a better way? Stripping the
--python
option out of the command line is probably impractical (i.e., even more risk of missing something and fork-bombing the user's machine 🙁).