Skip to content
Open
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/_pyrepl/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
from __future__ import annotations

import os
import _colorize

from abc import ABC, abstractmethod
import ast
Expand All @@ -30,6 +29,7 @@
import re
import sys
from typing import TYPE_CHECKING
lazy import _colorize

from .render import RenderedScreen
from .trace import trace
Expand Down
3 changes: 2 additions & 1 deletion Lib/_pyrepl/fancycompleter.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
#
# All Rights Reserved
"""Colorful tab completion for Python prompt"""
from _colorize import ANSIColors, get_colors, get_theme
import rlcompleter
import keyword
import types
lazy from _colorize import ANSIColors, get_colors, get_theme


class Completer(rlcompleter.Completer):
"""
Expand Down
2 changes: 1 addition & 1 deletion Lib/_pyrepl/reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@
from __future__ import annotations

import sys
import _colorize

from contextlib import contextmanager
from dataclasses import dataclass, field, fields, replace
from typing import Self
lazy import _colorize

from . import commands, console, input
from .content import (
Expand Down
2 changes: 1 addition & 1 deletion Lib/_pyrepl/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
import token as T
import tokenize
import unicodedata
import _colorize

from collections import deque
from dataclasses import dataclass
from io import StringIO
from tokenize import TokenInfo as TI
from typing import Iterable, Iterator, Match, NamedTuple, Self
lazy import _colorize

from .types import CharBuffer, CharWidths
from .trace import trace
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/json/tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import json
import re
import sys
from _colorize import get_theme, can_colorize
lazy from _colorize import get_theme, can_colorize


# The string we are colorizing is valid JSON,
Expand Down
2 changes: 1 addition & 1 deletion Lib/pdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,11 +96,11 @@
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

try:
import _pyrepl.utils
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
6 changes: 4 additions & 2 deletions Lib/sqlite3/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,21 @@
from argparse import ArgumentParser
from code import InteractiveConsole
from textwrap import dedent
from _colorize import get_theme, theme_no_color
lazy from _colorize import get_theme, theme_no_color

from ._completer import completer


def execute(c, sql, suppress_errors=True, theme=theme_no_color):
def execute(c, sql, suppress_errors=True, theme=None):
"""Helper that wraps execution of SQL code.

This is used both by the REPL and by direct execution from the CLI.

'c' may be a cursor or a connection.
'sql' is the SQL string to execute.
"""
if theme is None:
theme = theme_no_color

try:
for row in c.execute(sql):
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
7 changes: 7 additions & 0 deletions Lib/test/test_json/test_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from test import support
from test.support import force_colorized, force_not_colorized, os_helper
from test.support.import_helper import ensure_lazy_imports
from test.support.script_helper import assert_python_ok

from _colorize import get_theme
Expand Down Expand Up @@ -334,5 +335,11 @@ class TestTool(TestMain):
module = 'json.tool'


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


if __name__ == "__main__":
unittest.main()
8 changes: 7 additions & 1 deletion Lib/test/test_pdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
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
Expand Down Expand Up @@ -5306,5 +5306,11 @@ def tearDown(test):
return tests


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


if __name__ == '__main__':
unittest.main()
8 changes: 7 additions & 1 deletion Lib/test/test_sqlite3/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@
import os

from sqlite3.__main__ import main as cli
from test.support.import_helper import import_module
from test.support.import_helper import ensure_lazy_imports, import_module
from test.support.os_helper import TESTFN, unlink
from test.support.pty_helper import run_pty
from test.support import (
captured_stdout,
captured_stderr,
captured_stdin,
cpython_only,
force_not_colorized_test_class,
requires_subprocess,
verbose,
Expand Down Expand Up @@ -437,6 +438,11 @@ def test_complete_no_input(self):
raise


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


if __name__ == "__main__":
unittest.main()
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 @@ -5543,5 +5543,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 @@ -1336,9 +1366,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 @@ -1486,9 +1516,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