https://github.com/python/cpython/commit/8288f3693f50058ad9b9fe04e01f5dad902d8bad
commit: 8288f3693f50058ad9b9fe04e01f5dad902d8bad
branch: main
author: Tian Gao <[email protected]>
committer: gaogaotiantian <[email protected]>
date: 2025-09-26T22:17:02+08:00
summary:
gh-139289: Lazy import rlcompleter to fix the refleak (#139305)
files:
A Misc/NEWS.d/next/Library/2025-09-24-14-17-34.gh-issue-139289.Vmk25k.rst
M Lib/pdb.py
M Lib/test/test_pyclbr.py
diff --git a/Lib/pdb.py b/Lib/pdb.py
index fd48882e28fe7c..f695a39332e461 100644
--- a/Lib/pdb.py
+++ b/Lib/pdb.py
@@ -364,14 +364,6 @@ def __init__(self, completekey='tab', stdin=None,
stdout=None, skip=None,
except ImportError:
pass
- # GH-138860
- # We need to lazy-import rlcompleter to avoid deadlock
- # We cannot import it during self.complete* methods because importing
- # rlcompleter for the first time will overwrite readline's completer
- # So we import it here and save the Completer class
- from rlcompleter import Completer
- self.RlCompleter = Completer
-
self.allow_kbdint = False
self.nosigint = nosigint
# Consider these characters as part of the command so when the users
type
@@ -1100,6 +1092,31 @@ def set_convenience_variable(self, frame, name, value):
# Generic completion functions. Individual complete_foo methods can be
# assigned below to one of these functions.
+ @property
+ def rlcompleter(self):
+ """Return the `Completer` class from `rlcompleter`, while avoiding the
+ side effects of changing the completer from `import rlcompleter`.
+
+ This is a compromise between GH-138860 and GH-139289. If GH-139289 is
+ fixed, then we don't need this and we can just `import rlcompleter` in
+ `Pdb.__init__`.
+ """
+ if not hasattr(self, "_rlcompleter"):
+ try:
+ import readline
+ except ImportError:
+ # readline is not available, just get the Completer
+ from rlcompleter import Completer
+ self._rlcompleter = Completer
+ else:
+ # importing rlcompleter could have side effect of changing
+ # the current completer, we need to restore it
+ prev_completer = readline.get_completer()
+ from rlcompleter import Completer
+ self._rlcompleter = Completer
+ readline.set_completer(prev_completer)
+ return self._rlcompleter
+
def completenames(self, text, line, begidx, endidx):
# Overwrite completenames() of cmd so for the command completion,
# if no current command matches, check for expressions as well
@@ -1196,7 +1213,7 @@ def completedefault(self, text, line, begidx, endidx):
state = 0
matches = []
- completer = self.RlCompleter(self.curframe.f_globals |
self.curframe.f_locals)
+ completer = self.rlcompleter(self.curframe.f_globals |
self.curframe.f_locals)
while (match := completer.complete(text, state)) is not None:
matches.append(match)
state += 1
@@ -1211,7 +1228,7 @@ def _enable_rlcompleter(self, ns):
return
try:
- completer = self.RlCompleter(ns)
+ completer = self.rlcompleter(ns)
old_completer = readline.get_completer()
readline.set_completer(completer.complete)
yield
diff --git a/Lib/test/test_pyclbr.py b/Lib/test/test_pyclbr.py
index bce68e6cd7a57e..79ef178f3807f4 100644
--- a/Lib/test/test_pyclbr.py
+++ b/Lib/test/test_pyclbr.py
@@ -250,7 +250,7 @@ def test_others(self):
'pdb',
# pyclbr does not handle elegantly `typing` or properties
ignore=('Union', '_ModuleTarget', '_ScriptTarget',
'_ZipTarget', 'curframe_locals',
- '_InteractState'),
+ '_InteractState', 'rlcompleter'),
)
cm('pydoc', ignore=('input', 'output',)) # properties
diff --git
a/Misc/NEWS.d/next/Library/2025-09-24-14-17-34.gh-issue-139289.Vmk25k.rst
b/Misc/NEWS.d/next/Library/2025-09-24-14-17-34.gh-issue-139289.Vmk25k.rst
new file mode 100644
index 00000000000000..04162619cf218b
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-09-24-14-17-34.gh-issue-139289.Vmk25k.rst
@@ -0,0 +1 @@
+Do a real lazy-import on :mod:`rlcompleter` in :mod:`pdb` and restore the
existing completer after importing :mod:`rlcompleter`.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]