gh-154675: Use lazy imports in pdb, bdb, code (#156567)

This commit is contained in:
Hugo van Kemenade authored and GitHub committed 2026-10-21 10:35:49 +03:00
1 parent b577a5403a
commit 00348beb67
7 files changed
+69 -34

No files matched your search

+4 -4
View File
@@ -1,12 +1,12 @@
"""Debugger basics"""
import fnmatch
import sys
import threading
import os
import weakref
import sys
from contextlib import contextmanager
from inspect import CO_GENERATOR, CO_COROUTINE, CO_ASYNC_GENERATOR
lazy import fnmatch
lazy import threading
lazy import weakref
__all__ = ["BdbQuit", "Bdb", "Breakpoint"]
+1 -1
View File
@@ -7,8 +7,8 @@
import builtins
import sys
import traceback
from codeop import CommandCompiler, compile_command
lazy import traceback
__all__ = ["InteractiveInterpreter", "InteractiveConsole", "interact",
"compile_command"]
+25 -28
View File
@@ -67,46 +67,44 @@ Debugger commands
import os
import io
import re
import sys
import cmd
import bdb
import dis
import bdb
import code
import glob
import json
import stat
import token
import types
import atexit
import codeop
import pprint
import signal
import socket
import typing
import inspect
import weakref
import builtins
import tempfile
import textwrap
import tokenize
import itertools
import traceback
import linecache
import selectors
import threading
import _colorize
from contextlib import ExitStack, closing, contextmanager
from types import CodeType
from warnings import deprecated
lazy import _colorize
lazy import argparse
lazy import asyncio
try:
import _pyrepl.utils
except ModuleNotFoundError:
_pyrepl = None
lazy import glob
lazy import json
lazy import pprint
lazy import re
lazy import runpy
lazy import selectors
lazy import shlex
lazy import signal
lazy import socket
lazy import tempfile
lazy import textwrap
lazy import threading
lazy import tokenize
lazy import traceback
lazy import weakref
class Restart(Exception):
@@ -247,7 +245,6 @@ class _ModuleTarget(_ExecutableTarget):
def __init__(self, target):
self._target = target
import runpy
try:
_, self._spec, self._code = runpy._get_module_details(self._target)
except ImportError as e:
@@ -282,8 +279,6 @@ class _ModuleTarget(_ExecutableTarget):
class _ZipTarget(_ExecutableTarget):
def __init__(self, target):
import runpy
self._target = os.path.realpath(target)
sys.path.insert(0, self._target)
try:
@@ -466,6 +461,7 @@ class PdbPyReplInput:
return None
def gen_colors(self, buffer):
import _pyrepl.utils
from _pyrepl.utils import ColorSpan, Span
if not buffer.strip():
@@ -1271,7 +1267,11 @@ class Pdb(bdb.Bdb, cmd.Cmd):
return False
def _colorize_code(self, code):
if self.colorize and _pyrepl:
if self.colorize:
try:
import _pyrepl.utils
except ModuleNotFoundError:
return code
colors = list(_pyrepl.utils.gen_colors(code))
chars, _ = _pyrepl.utils.disp_str(code, colors=colors, force_color=True)
code = "".join(chars)
@@ -2089,7 +2089,6 @@ class Pdb(bdb.Bdb, cmd.Cmd):
'e.g. "python -m pdb myscript.py"')
return
if arg:
import shlex
argv0 = sys.argv[0:1]
try:
sys.argv = shlex.split(arg)
@@ -3787,9 +3786,7 @@ def parse_args():
# "python -m pdb -m foo -p 1" should pass "-p 1" to "foo".
# "python -m pdb foo.py -m bar" should pass "-m bar" to "foo.py".
# "python -m pdb -m foo -m bar" should pass "-m bar" to "foo".
# This require some customized parsing logic to find the actual debug target.
import argparse
# This requires some customized parsing logic to find the actual debug target.
parser = argparse.ArgumentParser(
usage="%(prog)s [-h] [-c command] (-m module | -p pid | pyfile) [args ...]",
+5
View File
@@ -57,6 +57,7 @@ import importlib
import linecache
from contextlib import contextmanager
from itertools import islice, repeat
from test.support import cpython_only
from test.support import import_helper
from test.support import os_helper
from test.support import patch_list
@@ -1243,6 +1244,10 @@ class IssuesTestCase(BaseTestCase):
class TestRegressions(unittest.TestCase):
@cpython_only
def test_lazy_import(self):
import_helper.ensure_lazy_imports("bdb", {"fnmatch", "threading", "weakref"})
def test_format_stack_entry_no_lineno(self):
# See gh-101517
self.assertIn('Warning: lineno is None',
+5
View File
@@ -5,6 +5,7 @@ import unittest
from textwrap import dedent
from contextlib import ExitStack
from unittest import mock
from test.support import cpython_only
from test.support import force_not_colorized_test_class
from test.support import import_helper
@@ -38,6 +39,10 @@ class TestInteractiveConsole(unittest.TestCase, MockSys):
self.console = code.InteractiveConsole()
self.mock_sys()
@cpython_only
def test_lazy_import(self):
import_helper.ensure_lazy_imports("code", {"traceback"})
def test_ps1(self):
self.infunc.side_effect = [
"import code",
+27 -1
View File
@@ -22,7 +22,7 @@ from contextlib import ExitStack, redirect_stdout
from io import StringIO
from test import support
from test.support import has_socket_support, os_helper
from test.support.import_helper import import_module
from test.support.import_helper import ensure_lazy_imports, import_module
from test.support.pty_helper import run_pty, FakeInput
from test.support.script_helper import kill_python
from unittest.mock import patch
@@ -3558,6 +3558,32 @@ class PdbTestCase(unittest.TestCase):
def tearDown(self):
os_helper.unlink(os_helper.TESTFN)
@support.cpython_only
def test_lazy_import(self):
ensure_lazy_imports(
"pdb",
{
"_colorize",
"argparse",
"asyncio",
"glob",
"json",
"pprint",
"re",
"runpy",
"selectors",
"shlex",
"signal",
"socket",
"tempfile",
"textwrap",
"threading",
"tokenize",
"traceback",
"weakref",
},
)
@unittest.skipIf(sys.flags.safe_path,
'PYTHONSAFEPATH changes default sys.path')
def _run_pdb(self, pdb_args, commands,
@@ -0,0 +1,2 @@
Improve import time of :mod:`pdb`, :mod:`bdb` and :mod:`code` by lazily
importing several dependencies.