Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 2 additions & 1 deletion .github/workflows/mypy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ jobs:
persist-credentials: false
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.13"
python-version: "3.15"
allow-prereleases: true
cache: pip
cache-dependency-path: Tools/requirements-dev.txt
- run: pip install -r Tools/requirements-dev.txt
Expand Down
2 changes: 1 addition & 1 deletion Lib/difflib.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@
'Differ','IS_CHARACTER_JUNK', 'IS_LINE_JUNK', 'context_diff',
'unified_diff', 'diff_bytes', 'HtmlDiff', 'Match']

from _colorize import can_colorize, get_theme
from heapq import nlargest as _nlargest
from collections import namedtuple as _namedtuple
from types import GenericAlias
lazy from _colorize import can_colorize, get_theme

Match = _namedtuple('Match', 'a b size')

Expand Down
4 changes: 2 additions & 2 deletions Lib/doctest.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ def _test():
import unittest
from io import StringIO, TextIOWrapper, BytesIO
from collections import namedtuple
import _colorize # Used in doctests
from _colorize import ANSIColors, can_colorize
lazy import _colorize # Used in doctests
lazy from _colorize import ANSIColors, can_colorize


class TestResults(namedtuple('TestResults', 'failed attempted')):
Expand Down
2 changes: 1 addition & 1 deletion Lib/profiling/sampling/live_collector/collector.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import sys
import sysconfig
import time
import _colorize
lazy import _colorize

from ..collector import Collector, extract_lineno
from ..constants import (
Expand Down
2 changes: 1 addition & 1 deletion Lib/profiling/sampling/pstats_collector.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import collections
import marshal
import pstats
lazy from _colorize import ANSIColors

from _colorize import ANSIColors
from .collector import Collector, extract_lineno
from .constants import MICROSECONDS_PER_SECOND, PROFILING_MODE_CPU

Expand Down
2 changes: 1 addition & 1 deletion Lib/profiling/sampling/sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import sysconfig
import time
from collections import deque
from _colorize import ANSIColors
lazy from _colorize import ANSIColors

from .pstats_collector import PstatsCollector
from .stack_collector import CollapsedStackCollector, FlamegraphCollector
Expand Down
8 changes: 8 additions & 0 deletions Lib/test/test_difflib.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import difflib
from test import support
from test.support import findfile, force_colorized
from test.support.import_helper import ensure_lazy_imports
import unittest
import doctest
import sys
Expand Down Expand Up @@ -644,6 +646,12 @@ def setUpModule():
difflib.HtmlDiff._default_prefix = 0


class LazyImportTest(unittest.TestCase):
@support.cpython_only
def test_lazy_import(self):
ensure_lazy_imports("difflib", {"_colorize"})


def load_tests(loader, tests, pattern):
tests.addTest(doctest.DocTestSuite(difflib))
return tests
Expand Down
8 changes: 7 additions & 1 deletion Lib/test/test_traceback.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
requires_subprocess, os_helper)
from test.support.os_helper import TESTFN, temp_dir, unlink
from test.support.script_helper import assert_python_ok, assert_python_failure, make_script
from test.support.import_helper import forget
from test.support.import_helper import ensure_lazy_imports, forget
from test.support import force_not_colorized, force_not_colorized_test_class

import json
Expand Down Expand Up @@ -5632,5 +5632,11 @@ def test_suggestion_still_works_for_non_lazy_attributes(self):
self.assertNotIn(b"BAR_MODULE_LOADED", stdout)


class LazyImportTest(unittest.TestCase):
@support.cpython_only
def test_lazy_import(self):
ensure_lazy_imports("traceback", {"_colorize"})


if __name__ == "__main__":
unittest.main()
50 changes: 40 additions & 10 deletions Lib/traceback.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
import io
import importlib.util
import pathlib
import _colorize

from contextlib import suppress
lazy import _colorize

try:
from _missing_stdlib_info import _MISSING_STDLIB_MODULE_MESSAGES
Expand All @@ -32,6 +32,36 @@
'FrameSummary', 'StackSummary', 'TracebackException',
'walk_stack', 'walk_tb', 'print_list']


class _ShutdownTheme:
Comment thread
hugovk marked this conversation as resolved.
"""Empty stand-in if `_colorize` cannot be imported during late shutdown."""
def __getattr__(self, _): return self
def __getitem__(self, _): return ""
def __format__(self, _): return ""
def __str__(self): return ""
def __add__(self, other): return other
__radd__ = __add__
Comment thread
picnixz marked this conversation as resolved.


_shutdown_theme = _ShutdownTheme()


def _safe_get_theme(*, force_color=False, force_no_color=False):
try:
return _colorize.get_theme(
force_color=force_color, force_no_color=force_no_color
)
except ImportError:
return _shutdown_theme

Comment thread
hugovk marked this conversation as resolved.

def _safe_can_colorize(*, file=None):
try:
return _colorize.can_colorize(file=file)
except ImportError:
return False


#
# Formatting and printing lists of traceback lines.
#
Expand Down Expand Up @@ -151,7 +181,7 @@ def print_exception(exc, /, value=_sentinel, tb=_sentinel, limit=None, \
def _print_exception_bltin(exc, file=None, /):
if file is None:
file = sys.stderr if sys.stderr is not None else sys.__stderr__
colorize = _colorize.can_colorize(file=file)
colorize = _safe_can_colorize(file=file)
return print_exception(exc, limit=BUILTIN_EXCEPTION_LIMIT, file=file, colorize=colorize)


Expand Down Expand Up @@ -199,9 +229,9 @@ def _format_final_exc_line(etype, value, *, insert_final_newline=True, colorize=
valuestr = _safe_string(value, 'exception')
end_char = "\n" if insert_final_newline else ""
if colorize:
theme = _colorize.get_theme(force_color=True).traceback
theme = _safe_get_theme(force_color=True).traceback
else:
theme = _colorize.get_theme(force_no_color=True).traceback
theme = _safe_get_theme(force_no_color=True).traceback
if value is None or not valuestr:
line = f"{theme.type}{etype}{theme.reset}{end_char}"
else:
Expand Down Expand Up @@ -555,9 +585,9 @@ def format_frame_summary(self, frame_summary, **kwargs):
if frame_summary.filename.startswith("<stdin-") and frame_summary.filename.endswith('>'):
filename = "<stdin>"
if colorize:
theme = _colorize.get_theme(force_color=True).traceback
theme = _safe_get_theme(force_color=True).traceback
else:
theme = _colorize.get_theme(force_no_color=True).traceback
theme = _safe_get_theme(force_no_color=True).traceback
row.append(
' File {}"{}"{}, line {}{}{}, in {}{}{}\n'.format(
theme.filename,
Expand Down Expand Up @@ -1344,9 +1374,9 @@ def format_exception_only(self, *, show_group=False, _depth=0, **kwargs):
"""
colorize = kwargs.get("colorize", False)
if colorize:
theme = _colorize.get_theme(force_color=True).traceback
theme = _safe_get_theme(force_color=True).traceback
else:
theme = _colorize.get_theme(force_no_color=True).traceback
theme = _safe_get_theme(force_no_color=True).traceback

indent = 3 * _depth * ' '
if not self._have_exc_type:
Expand Down Expand Up @@ -1494,9 +1524,9 @@ def _format_syntax_error(self, stype, **kwargs):
# Show exactly where the problem was found.
colorize = kwargs.get("colorize", False)
if colorize:
theme = _colorize.get_theme(force_color=True).traceback
theme = _safe_get_theme(force_color=True).traceback
else:
theme = _colorize.get_theme(force_no_color=True).traceback
theme = _safe_get_theme(force_no_color=True).traceback
filename_suffix = ''
if self.lineno is not None:
yield ' File {}"{}"{}, line {}{}{}\n'.format(
Expand Down
3 changes: 1 addition & 2 deletions Lib/unittest/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@
import time
import warnings

from _colorize import get_theme

from . import result
from .case import _SubTest
from .signals import registerResult
lazy from _colorize import get_theme

__unittest = True

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Lazily import :mod:`!_colorize`. Patch by Hugo van Kemenade.
Loading