Skip to content

gh-72327: Suggest using system terminal for pip install in PyREPL #136328

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
15 changes: 14 additions & 1 deletion Lib/_pyrepl/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import linecache
from dataclasses import dataclass, field
import os.path
import re
import sys


Expand Down Expand Up @@ -195,7 +196,19 @@ def runsource(self, source, filename="<input>", symbol="single"):
ast.PyCF_ONLY_AST,
incomplete_input=False,
)
except (SyntaxError, OverflowError, ValueError):
except SyntaxError as e:
# If it looks like pip install was entered (a common beginner
# mistake), provide a hint to use the system command prompt.
if re.match(r"^\s*(py(thon3?)? -m pip|pip3?) install.*", source):
Copy link
Contributor

@ncoghlan ncoghlan Jul 14, 2025

Choose a reason for hiding this comment

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

Suggested change
if re.match(r"^\s*(py(thon3?)? -m pip|pip3?) install.*", source):
if re.match(r"^\s*(pip3?|py(thon3?)? -m pip) install.*", source):

Pretty sure that keeps the overall regex meaning the same, while making the optional suffix handling style more internally consistent.

Edit: changed the suggestion to flip the order of the branches, since my first suggestion of removing the pattern alternation entirely was wrong (as per the comments below)

Copy link

@adqm adqm Jul 14, 2025

Choose a reason for hiding this comment

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

I think this would actually change the meaning of the regex, and that the updated version won't match a regular pip install foo, only ones that use the python3 -m pip form. The | in the original regex isn't saying "pip or pip3" for that one little part, but rather that the whole parenthesized bit there must match "py(thon3?)? -m pip or pip3?".

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, you're right, I always forget how broad the scope of | is when mentally parsing regexes.

Copy link
Contributor

Choose a reason for hiding this comment

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

Reworked the suggestion to instead be to put the simpler branch first. I don't think that's a merge blocker though.

e.add_note(
"The Python package manager (pip) can only be used"
" outside of the Python REPL.\n"
"Try the 'pip' command in a separate terminal or"
" command prompt."
)
self.showsyntaxerror(filename, source=source)
return False
except (OverflowError, ValueError):
self.showsyntaxerror(filename, source=source)
return False
if tree.body:
Expand Down
11 changes: 11 additions & 0 deletions Lib/test/test_pyrepl/test_pyrepl.py
Original file line number Diff line number Diff line change
Expand Up @@ -1757,3 +1757,14 @@ def test_showrefcount(self):
output, _ = self.run_repl("1\n1+2\nexit()\n", cmdline_args=['-Xshowrefcount'], env=env)
matches = re.findall(r'\[-?\d+ refs, \d+ blocks\]', output)
self.assertEqual(len(matches), 3)

def test_detect_pip_usage_in_repl(self):
for pip_cmd in ("pip", "pip3", "python -m pip", "python3 -m pip"):
with self.subTest(pip_cmd=pip_cmd):
output, exit_code = self.run_repl([f"{pip_cmd} install sampleproject", "exit"])
self.assertIn("SyntaxError", output)
hint = (
"The Python package manager (pip) can only be used"
" outside of the Python REPL"
)
self.assertIn(hint, output)
2 changes: 2 additions & 0 deletions Misc/ACKS
Original file line number Diff line number Diff line change
Expand Up @@ -1742,6 +1742,7 @@ Joel Shprentz
Yue Shuaijie
Jaysinh Shukla
Terrel Shumway
Richard Si
Eric Siegerman
Reilly Tucker Siemens
Paul Sijben
Expand Down Expand Up @@ -1986,6 +1987,7 @@ Olivier Vielpeau
Kannan Vijayan
Kurt Vile
Norman Vine
Tom Viner
Pauli Virtanen
Frank Visser
Long Vo
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Suggest using the system command prompt when ``pip install`` is typed into
the REPL. Patch by Tom Viner, Richard Si, and Brian Schubert.
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy