Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
20 changes: 20 additions & 0 deletions Lib/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,22 @@ def setcopyright():
files, dirs)


def _register_detect_pip_usage_in_repl():
old_excepthook = sys.excepthook

def detect_pip_usage_in_repl(typ, value, traceback):
old_excepthook(typ, value, traceback)
if typ is SyntaxError and (
"pip install" in value.text or "pip3 install" in value.text
):
print("\nThe Python package manager (pip) can only be used from"
" outside of Python.\nPlease try the `pip` command in a"
" separate terminal or command prompt.",
file=sys.stderr)

sys.excepthook = detect_pip_usage_in_repl


def sethelper():
builtins.help = _sitebuiltins._Helper()

Expand Down Expand Up @@ -558,6 +574,10 @@ def main():
setquit()
setcopyright()
sethelper()
# Detect REPL by prompt, -i flag or PYTHONINSPECT env var being set.
if getattr(sys, 'ps1',
sys.flags.interactive or os.environ.get('PYTHONINSPECT')):
_register_detect_pip_usage_in_repl()
if not sys.flags.isolated:
enablerlcompleter()
execsitecustomize()
Expand Down
27 changes: 27 additions & 0 deletions Lib/test/test_site.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import test.support
from test.support import captured_stderr, TESTFN, EnvironmentVarGuard
import builtins
import io
import os
import sys
import re
Expand Down Expand Up @@ -454,6 +455,32 @@ def test_license_exists_at_url(self):
self.assertEqual(code, 200, msg="Can't find " + url)


class DetectPipUsageInReplTests(unittest.TestCase):
def setUp(self):
self.old_excepthook = sys.excepthook
site._register_detect_pip_usage_in_repl()
self.save_stderr = sys.stderr

def tearDown(self):
sys.stderr = self.save_stderr
sys.excepthook = self.old_excepthook

def test_detect_pip_usage_in_repl(self):
for pip_cmd in [
'pip install a', 'pip3 install b', 'python -m pip install c'
]:
with self.subTest(pip_cmd=pip_cmd):
stream = io.StringIO()
sys.stderr = stream

try:
exec(pip_cmd, {}, {})
except SyntaxError as exc:
sys.excepthook(SyntaxError, exc, exc.__traceback__)

self.assertIn("the `pip` command", stream.getvalue())


class StartupImportTests(unittest.TestCase):

def test_startup_imports(self):
Expand Down
1 change: 1 addition & 0 deletions Misc/ACKS
Original file line number Diff line number Diff line change
Expand Up @@ -1826,3 +1826,4 @@ Jelle Zijlstra
Gennadiy Zlobin
Doug Zongker
Peter Åstrand
Tom Viner
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Give better errors for `pip install` command typed into the REPL.