Skip to content

Commit bc55687

Browse files
committed
Use lazy imports in pdb, bdb, code
1 parent eb08902 commit bc55687

7 files changed

Lines changed: 70 additions & 34 deletions

File tree

Lib/bdb.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
"""Debugger basics"""
22

3-
import fnmatch
4-
import sys
5-
import threading
63
import os
7-
import weakref
4+
import sys
85
from contextlib import contextmanager
96
from inspect import CO_GENERATOR, CO_COROUTINE, CO_ASYNC_GENERATOR
7+
lazy import fnmatch
8+
lazy import threading
9+
lazy import weakref
1010

1111
__all__ = ["BdbQuit", "Bdb", "Breakpoint"]
1212

Lib/code.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77

88
import builtins
99
import sys
10-
import traceback
1110
from codeop import CommandCompiler, compile_command
11+
lazy import traceback
1212

1313
__all__ = ["InteractiveInterpreter", "InteractiveConsole", "interact",
1414
"compile_command"]

Lib/pdb.py

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -67,45 +67,44 @@
6767

6868
import os
6969
import io
70-
import re
7170
import sys
7271
import cmd
73-
import bdb
7472
import dis
73+
import bdb
7574
import code
76-
import glob
77-
import json
7875
import stat
7976
import token
8077
import types
8178
import atexit
8279
import codeop
83-
import pprint
84-
import signal
85-
import socket
8680
import typing
87-
import asyncio
8881
import inspect
89-
import weakref
9082
import builtins
91-
import tempfile
92-
import textwrap
93-
import tokenize
9483
import itertools
95-
import traceback
9684
import linecache
97-
import selectors
98-
import threading
99-
import _colorize
10085

10186
from contextlib import ExitStack, closing, contextmanager
10287
from types import CodeType
10388
from warnings import deprecated
10489

105-
try:
106-
import _pyrepl.utils
107-
except ModuleNotFoundError:
108-
_pyrepl = None
90+
lazy import _colorize
91+
lazy import argparse
92+
lazy import asyncio
93+
lazy import glob
94+
lazy import json
95+
lazy import pprint
96+
lazy import re
97+
lazy import runpy
98+
lazy import selectors
99+
lazy import shlex
100+
lazy import signal
101+
lazy import socket
102+
lazy import tempfile
103+
lazy import textwrap
104+
lazy import threading
105+
lazy import tokenize
106+
lazy import traceback
107+
lazy import weakref
109108

110109

111110
class Restart(Exception):
@@ -246,7 +245,6 @@ class _ModuleTarget(_ExecutableTarget):
246245
def __init__(self, target):
247246
self._target = target
248247

249-
import runpy
250248
try:
251249
_, self._spec, self._code = runpy._get_module_details(self._target)
252250
except ImportError as e:
@@ -281,8 +279,6 @@ def namespace(self):
281279

282280
class _ZipTarget(_ExecutableTarget):
283281
def __init__(self, target):
284-
import runpy
285-
286282
self._target = os.path.realpath(target)
287283
sys.path.insert(0, self._target)
288284
try:
@@ -465,6 +461,7 @@ def complete(self, text, state):
465461
return None
466462

467463
def gen_colors(self, buffer):
464+
import _pyrepl.utils
468465
from _pyrepl.utils import ColorSpan, Span
469466

470467
if not buffer.strip():
@@ -1266,7 +1263,11 @@ def handle_command_def(self, line):
12661263
return False
12671264

12681265
def _colorize_code(self, code):
1269-
if self.colorize and _pyrepl:
1266+
if self.colorize:
1267+
try:
1268+
import _pyrepl.utils
1269+
except ModuleNotFoundError:
1270+
return code
12701271
colors = list(_pyrepl.utils.gen_colors(code))
12711272
chars, _ = _pyrepl.utils.disp_str(code, colors=colors, force_color=True)
12721273
code = "".join(chars)
@@ -2084,7 +2085,6 @@ def do_run(self, arg):
20842085
'e.g. "python -m pdb myscript.py"')
20852086
return
20862087
if arg:
2087-
import shlex
20882088
argv0 = sys.argv[0:1]
20892089
try:
20902090
sys.argv = shlex.split(arg)
@@ -3778,9 +3778,7 @@ def parse_args():
37783778
# "python -m pdb -m foo -p 1" should pass "-p 1" to "foo".
37793779
# "python -m pdb foo.py -m bar" should pass "-m bar" to "foo.py".
37803780
# "python -m pdb -m foo -m bar" should pass "-m bar" to "foo".
3781-
# This require some customized parsing logic to find the actual debug target.
3782-
3783-
import argparse
3781+
# This requires some customized parsing logic to find the actual debug target.
37843782

37853783
parser = argparse.ArgumentParser(
37863784
usage="%(prog)s [-h] [-c command] (-m module | -p pid | pyfile) [args ...]",

Lib/test/test_bdb.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
import linecache
5858
from contextlib import contextmanager
5959
from itertools import islice, repeat
60+
from test.support import cpython_only
6061
from test.support import import_helper
6162
from test.support import os_helper
6263
from test.support import patch_list
@@ -1232,6 +1233,10 @@ def test_next_to_botframe(self):
12321233

12331234

12341235
class TestRegressions(unittest.TestCase):
1236+
@cpython_only
1237+
def test_lazy_import(self):
1238+
import_helper.ensure_lazy_imports("bdb", {"fnmatch", "threading", "weakref"})
1239+
12351240
def test_format_stack_entry_no_lineno(self):
12361241
# See gh-101517
12371242
self.assertIn('Warning: lineno is None',

Lib/test/test_code_module.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from textwrap import dedent
66
from contextlib import ExitStack
77
from unittest import mock
8+
from test.support import cpython_only
89
from test.support import force_not_colorized_test_class
910
from test.support import import_helper
1011

@@ -38,6 +39,10 @@ def setUp(self):
3839
self.console = code.InteractiveConsole()
3940
self.mock_sys()
4041

42+
@cpython_only
43+
def test_lazy_import(self):
44+
import_helper.ensure_lazy_imports("code", {"traceback"})
45+
4146
def test_ps1(self):
4247
self.infunc.side_effect = [
4348
"import code",

Lib/test/test_pdb.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from io import StringIO
2323
from test import support
2424
from test.support import has_socket_support, os_helper
25-
from test.support.import_helper import import_module
25+
from test.support.import_helper import ensure_lazy_imports, import_module
2626
from test.support.pty_helper import run_pty, FakeInput
2727
from test.support.script_helper import kill_python
2828
from unittest.mock import patch
@@ -3529,6 +3529,32 @@ class PdbTestCase(unittest.TestCase):
35293529
def tearDown(self):
35303530
os_helper.unlink(os_helper.TESTFN)
35313531

3532+
@support.cpython_only
3533+
def test_lazy_import(self):
3534+
ensure_lazy_imports(
3535+
"pdb",
3536+
{
3537+
"_colorize",
3538+
"argparse",
3539+
"asyncio",
3540+
"glob",
3541+
"json",
3542+
"pprint",
3543+
"re",
3544+
"runpy",
3545+
"selectors",
3546+
"shlex",
3547+
"signal",
3548+
"socket",
3549+
"tempfile",
3550+
"textwrap",
3551+
"threading",
3552+
"tokenize",
3553+
"traceback",
3554+
"weakref",
3555+
},
3556+
)
3557+
35323558
@unittest.skipIf(sys.flags.safe_path,
35333559
'PYTHONSAFEPATH changes default sys.path')
35343560
def _run_pdb(self, pdb_args, commands,
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Improve import time of :mod:`pdb`, :mod:`bdb` and :mod:`code` by lazily
2+
importing several dependencies.

0 commit comments

Comments
 (0)