← baseline_full_v2

rich_4070

failed NO_PATCH NO_PATCH UNSUBMITTED empty_patch(None) · None tool calls · 0 s · Textualize/rich

Task input

perf: reduce Console and RichHandler import time by deferring unused imports

## E2E Results

| Import | master | This PR | Speedup |
|---|---|---|---|
| `from rich.console import Console` | 78.1ms | 52.2ms | **1.50x faster** |
| `from rich.logging import RichHandler` | 99.4ms | 56.9ms | **1.75x faster** |
| `import rich` | 18.2ms | 18.3ms | (already lean) |

## Summary

Defer module-level imports that are only needed in specific code paths, move annotation-only imports to `TYPE_CHECKING`, and remove dead code:

| File | Change | Savings |
|---|---|---|
| `logging.py` | Defer `Traceback` to `emit()` (only when `rich_tracebacks=True`) | ~20ms |
| `logging.py` | `from __future__ import annotations` + `TYPE_CHECKING` for `Console`, `ConsoleRenderable`, `Highlighter`, `FormatTimeCallable` | ~6ms |
| `logging.py` | Replace `pathlib.Path` → `os.path.basename` (also a minor runtime win) | ~4-5ms |
| `console.py` | Eliminate `import inspect`; replace `isclass` → `isinstance(x, type)`, `currentframe` → `sys._getframe` | ~10ms |
| `console.py` | Defer `pretty` to `Console.print()` | ~3-5ms |
| `console.py` | Defer `scope` to `Console.log()` (only when `log_locals=True`) | ~3-5ms |
| `console.py` | Defer `getpass` to `Console.input()` (only when `password=True`) | ~2ms |
| `console.py` | Defer `html.escape` and `zlib` to export methods | ~2.3ms |
| `console.py` | Remove dead `_svg_hash` function (unused since 113997ac, fixes latent NameError) | cleanup |
| `segment.py` | Remove dead `logging` import (`getLogger` assigned but never used) | ~2-3ms |
| `theme.py` | Defer `configparser` to `Theme.from_file()` | ~1.5ms |
| `syntax.py` | Move `Console`, `ConsoleOptions`, `JustifyMethod`, `RenderResult` to `TYPE_CHECKING` | eliminates console.py from syntax import chain |
| `protocol.py` | Replace `from inspect import isclass` → `isinstance(x, type)` | prepares for dataclasses removal |
| `repr.py` | Defer `import inspect` to `auto_rich_repr()` | prepares for dataclasses removal |

All deferred imports are still available at runtime — they're loaded when the code path that needs them is actually hit. The `TYPE_CHECKING` imports are annotation-only and never needed at runtime (files use `from __future__ import annotations`).

## Benchmarks

Environment: Standard_D2s_v5 (non-burstable), CPython 3.13.13, hyperfine --min-runs 30

### Per-module breakdown (this PR)

| Module | Time |
|---|---|
| `import rich` | 18.2ms |
| `Console` | 52.5ms |
| `RichHandler` | 56.4ms |
| `Syntax` | 64.7ms |
| `Traceback` | 92.5ms |
| `Markdown` | 103.0ms |

## Motivation

pip vendors Rich, and `Console`/`RichHandler` are imported on every `pip` invocation. These savings directly improve startup time for pip and every other tool that imports Rich.

## Testing

- `pytest tests/` — 952 passed, 25 skipped
- `mypy -p rich --no-incremental` — no issues
- `black --check` — passes

## Disclosure

This PR was developed with AI assistance (codeflash-agent). Benchmarked in a controlled environment (dedicated non-burstable Azure VM). All tests verified across multiple Python implementations.

Tool calls (0)

#ToolArgumentsResult
No trace captured.

Test output

show
..........................................F
=================================== FAILURES ===================================
_____________________________ test_input_password ______________________________

prompt = '', stream = None

    def unix_getpass(prompt='Password: ', stream=None):
        """Prompt for a password, with echo turned off.
    
        Args:
          prompt: Written on stream to ask for the input.  Default: 'Password: '
          stream: A writable file object to display the prompt.  Defaults to
                  the tty.  If no tty is available defaults to sys.stderr.
        Returns:
          The seKr3t input.
        Raises:
          EOFError: If our input tty or stdin was closed.
          GetPassWarning: When we were unable to turn echo off on the input.
    
        Always restores terminal settings before returning.
        """
        passwd = None
        with contextlib.ExitStack() as stack:
            try:
                # Always try reading and writing directly on the tty first.
>               fd = os.open('/dev/tty', os.O_RDWR|os.O_NOCTTY)
E               OSError: [Errno 6] Device not configured: '/dev/tty'

/Users/jp/.local/share/uv/python/cpython-3.13.15-macos-aarch64-none/lib/python3.13/getpass.py:47: OSError

During handling of the above exception, another exception occurred:

prompt = '', stream = None

    def unix_getpass(prompt='Password: ', stream=None):
        """Prompt for a password, with echo turned off.
    
        Args:
          prompt: Written on stream to ask for the input.  Default: 'Password: '
          stream: A writable file object to display the prompt.  Defaults to
                  the tty.  If no tty is available defaults to sys.stderr.
        Returns:
          The seKr3t input.
        Raises:
          EOFError: If our input tty or stdin was closed.
          GetPassWarning: When we were unable to turn echo off on the input.
    
        Always restores terminal settings before returning.
        """
        passwd = None
        with contextlib.ExitStack() as stack:
            try:
                # Always try reading and writing directly on the tty first.
                fd = os.open('/dev/tty', os.O_RDWR|os.O_NOCTTY)
                tty = io.FileIO(fd, 'w+')
                stack.enter_context(tty)
                input = io.TextIOWrapper(tty)
                stack.enter_context(input)
                if not stream:
                    stream = input
            except OSError:
                # If that fails, see if stdin can be controlled.
                stack.close()
                try:
>                   fd = sys.stdin.fileno()
E                   io.UnsupportedOperation: redirected stdin is pseudofile, has no fileno()

/Users/jp/.local/share/uv/python/cpython-3.13.15-macos-aarch64-none/lib/python3.13/getpass.py:58: UnsupportedOperation

During handling of the above exception, another exception occurred:

monkeypatch = <_pytest.monkeypatch.MonkeyPatch object at 0x106ad6200>
capsys = <_pytest.capture.CaptureFixture object at 0x106870b90>

    def test_input_password(monkeypatch, capsys) -> None:
        def fake_input(prompt, stream=None):
            console.file.write(prompt)
            return "bar"
    
        import getpass
    
        monkeypatch.setattr(getpass, "getpass", fake_input)
        console = Console()
>       user_input = console.input(prompt="foo:", password=True)

tests/test_console.py:407: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
rich/console.py:2169: in input
    result = getpass("", stream=stream)
/Users/jp/.local/share/uv/python/cpython-3.13.15-macos-aarch64-none/lib/python3.13/getpass.py:61: in unix_getpass
    passwd = fallback_getpass(prompt, stream)
/Users/jp/.local/share/uv/python/cpython-3.13.15-macos-aarch64-none/lib/python3.13/getpass.py:126: in fallback_getpass
    return _raw_input(prompt, stream)
/Users/jp/.local/share/uv/python/cpython-3.13.15-macos-aarch64-none/lib/python3.13/getpass.py:146: in _raw_input
    line = input.readline()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <_pytest.capture.DontReadFromInput object at 0x106811550>, size = -1

    def read(self, size: int = -1) -> str:
>       raise OSError(
            "pytest: reading from stdin while output is captured!  Consider using `-s`."
        )
E       OSError: pytest: reading from stdin while output is captured!  Consider using `-s`.

/Users/jp/repos/kaggle-gemini-coding-agent-post-training/.envs/rich/lib/python3.13/site-packages/_pytest/capture.py:209: OSError
----------------------------- Captured stdout call -----------------------------
foo:
----------------------------- Captured stderr call -----------------------------
Warning: Password input may be echoed.
=============================== warnings summary ===============================
test_console.py::test_input_password
  /Users/jp/.local/share/uv/python/cpython-3.13.15-macos-aarch64-none/lib/python3.13/getpass.py:61: GetPassWarning: Can not control echo on the terminal.
    passwd = fallback_getpass(prompt, stream)

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!!
1 failed, 42 passed, 1 warning in 0.31s