diff --git a/Lib/argparse.py b/Lib/argparse.py index 42891516b3bb2a..f8739d031e01c5 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -87,12 +87,17 @@ import os as _os -import re as _re import sys as _sys -from gettext import gettext as _ -from gettext import ngettext lazy import _colorize +lazy import copy +lazy import difflib +lazy import re as _re +lazy import shutil +lazy import textwrap +lazy import warnings +lazy from gettext import gettext as _ +lazy from gettext import ngettext SUPPRESS = '==SUPPRESS==' @@ -143,10 +148,8 @@ def _copy_items(items): return [] # The copy module is used only in the 'append' and 'append_const' # actions, and it is needed only when the default value isn't a list. - # Delay its import for speeding up the common case. if type(items) is list: return items[:] - import copy return copy.copy(items) @@ -186,7 +189,6 @@ def __init__( ): # default setting for width if width is None: - import shutil width = shutil.get_terminal_size().columns width -= 2 @@ -773,9 +775,6 @@ def _iter_indented_subactions(self, action): def _split_lines(self, text, width): text = self._whitespace_matcher.sub(' ', text).strip() - # The textwrap module is used only for formatting help. - # Delay its import for speeding up the common usage of argparse. - import textwrap decolored = self._decolor(text) if decolored == text: return textwrap.wrap(text, width) @@ -808,7 +807,6 @@ def _split_lines(self, text, width): def _fill_text(self, text, width, indent): text = self._whitespace_matcher.sub(' ', text).strip() - import textwrap return textwrap.fill(text, width, initial_indent=indent, subsequent_indent=indent) @@ -1486,7 +1484,6 @@ class FileType(object): """ def __init__(self, mode='r', bufsize=-1, encoding=None, errors=None): - import warnings warnings.warn( "FileType is deprecated. Simply open files after parsing arguments.", category=PendingDeprecationWarning, @@ -1893,7 +1890,6 @@ class _ArgumentGroup(_ActionsContainer): def __init__(self, container, title=None, description=None, **kwargs): if 'prefix_chars' in kwargs: - import warnings depr_msg = ( "The use of the undocumented 'prefix_chars' parameter in " "ArgumentParser.add_argument_group() is deprecated." @@ -2824,7 +2820,6 @@ def _check_value(self, action, value): if self.suggest_on_error and isinstance(value, str): if all(isinstance(choice, str) for choice in action.choices): - import difflib suggestions = difflib.get_close_matches(value, action.choices, 1) if suggestions: args['closest'] = suggestions[0] @@ -2964,8 +2959,6 @@ def _warning(self, message): def __getattr__(name): if name == "__version__": - from warnings import _deprecated - - _deprecated("__version__", remove=(3, 20)) + warnings._deprecated("__version__", remove=(3, 20)) return "1.1" # Do not change raise AttributeError(f"module {__name__!r} has no attribute {name!r}") diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index fbeb933841129e..442cbb1aaadfe3 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -3,7 +3,6 @@ import _colorize import contextlib import functools -import inspect import io import operator import os @@ -12,6 +11,7 @@ import sys import textwrap import tempfile +import types import unittest import argparse import warnings @@ -85,6 +85,8 @@ class TestLazyImports(unittest.TestCase): "_colorize", "copy", "difflib", + "gettext", + "re", "shutil", "textwrap", "warnings", @@ -99,7 +101,7 @@ def test_create_parser(self): # Test imports are still unused after # creating a parser create_parser = "argparse.ArgumentParser()" - imported_modules = {"shutil"} + imported_modules = {"gettext", "re", "shutil"} import_helper.ensure_lazy_imports( "argparse", @@ -114,7 +116,7 @@ def test_add_subparser(self): parser.add_subparsers(dest='command', required=False) """ ) - imported_modules = {"shutil"} + imported_modules = {"gettext", "re", "shutil"} import_helper.ensure_lazy_imports( "argparse", @@ -132,7 +134,7 @@ def test_parse_args(self): parser.parse_args(['BAR', '--foo', 'FOO']) """ ) - imported_modules = {"shutil"} + imported_modules = {"gettext", "re", "shutil"} import_helper.ensure_lazy_imports( "argparse", self.LAZY_IMPORTS - imported_modules, @@ -7098,7 +7100,10 @@ def test_all_exports_everything_but_modules(self): name for name, value in vars(argparse).items() if not (name.startswith("_") or name == 'ngettext') - if not inspect.ismodule(value) + if not isinstance( + value, + (types.ModuleType, types.LazyImportType), + ) ] self.assertEqual(sorted(items), sorted(argparse.__all__)) diff --git a/Misc/NEWS.d/next/Library/2026-07-24-17-02-46.gh-issue-154638.7YnFHH.rst b/Misc/NEWS.d/next/Library/2026-07-24-17-02-46.gh-issue-154638.7YnFHH.rst new file mode 100644 index 00000000000000..91c22640deba6b --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-07-24-17-02-46.gh-issue-154638.7YnFHH.rst @@ -0,0 +1 @@ +Improve import time of :mod:`argparse` by lazily importing several dependencies.