+from __future__ import annotations
import io
import os
import sys
COLORIZE = True
+# types
+if False:
+ from typing import IO
+
class ANSIColors:
- BACKGROUND_YELLOW = "\x1b[43m"
- BOLD_GREEN = "\x1b[1;32m"
- BOLD_MAGENTA = "\x1b[1;35m"
- BOLD_RED = "\x1b[1;31m"
+ RESET = "\x1b[0m"
+
BLACK = "\x1b[30m"
+ BLUE = "\x1b[34m"
+ CYAN = "\x1b[36m"
GREEN = "\x1b[32m"
- GREY = "\x1b[90m"
MAGENTA = "\x1b[35m"
RED = "\x1b[31m"
- RESET = "\x1b[0m"
+ WHITE = "\x1b[37m" # more like LIGHT GRAY
YELLOW = "\x1b[33m"
+ BOLD_BLACK = "\x1b[1;30m" # DARK GRAY
+ BOLD_BLUE = "\x1b[1;34m"
+ BOLD_CYAN = "\x1b[1;36m"
+ BOLD_GREEN = "\x1b[1;32m"
+ BOLD_MAGENTA = "\x1b[1;35m"
+ BOLD_RED = "\x1b[1;31m"
+ BOLD_WHITE = "\x1b[1;37m" # actual WHITE
+ BOLD_YELLOW = "\x1b[1;33m"
+
+ # intense = like bold but without being bold
+ INTENSE_BLACK = "\x1b[90m"
+ INTENSE_BLUE = "\x1b[94m"
+ INTENSE_CYAN = "\x1b[96m"
+ INTENSE_GREEN = "\x1b[92m"
+ INTENSE_MAGENTA = "\x1b[95m"
+ INTENSE_RED = "\x1b[91m"
+ INTENSE_WHITE = "\x1b[97m"
+ INTENSE_YELLOW = "\x1b[93m"
+
+ BACKGROUND_BLACK = "\x1b[40m"
+ BACKGROUND_BLUE = "\x1b[44m"
+ BACKGROUND_CYAN = "\x1b[46m"
+ BACKGROUND_GREEN = "\x1b[42m"
+ BACKGROUND_MAGENTA = "\x1b[45m"
+ BACKGROUND_RED = "\x1b[41m"
+ BACKGROUND_WHITE = "\x1b[47m"
+ BACKGROUND_YELLOW = "\x1b[43m"
+
+ INTENSE_BACKGROUND_BLACK = "\x1b[100m"
+ INTENSE_BACKGROUND_BLUE = "\x1b[104m"
+ INTENSE_BACKGROUND_CYAN = "\x1b[106m"
+ INTENSE_BACKGROUND_GREEN = "\x1b[102m"
+ INTENSE_BACKGROUND_MAGENTA = "\x1b[105m"
+ INTENSE_BACKGROUND_RED = "\x1b[101m"
+ INTENSE_BACKGROUND_WHITE = "\x1b[107m"
+ INTENSE_BACKGROUND_YELLOW = "\x1b[103m"
+
NoColors = ANSIColors()
setattr(NoColors, attr, "")
-def get_colors(colorize: bool = False, *, file=None) -> ANSIColors:
+def get_colors(
+ colorize: bool = False, *, file: IO[str] | IO[bytes] | None = None
+) -> ANSIColors:
if colorize or can_colorize(file=file):
return ANSIColors()
else:
return NoColors
-def can_colorize(*, file=None) -> bool:
+def can_colorize(*, file: IO[str] | IO[bytes] | None = None) -> bool:
if file is None:
file = sys.stdout
try:
return os.isatty(file.fileno())
except io.UnsupportedOperation:
- return file.isatty()
+ return hasattr(file, "isatty") and file.isatty()
class show_history(Command):
def do(self) -> None:
from .pager import get_pager
- from site import gethistoryfile # type: ignore[attr-defined]
+ from site import gethistoryfile
history = os.linesep.join(self.reader.history[:])
self.reader.console.restore()
from __future__ import annotations
-import _colorize # type: ignore[import-not-found]
+import _colorize
from abc import ABC, abstractmethod
import ast
*,
local_exit: bool = False,
) -> None:
- super().__init__(locals=locals, filename=filename, local_exit=local_exit) # type: ignore[call-arg]
+ super().__init__(locals=locals, filename=filename, local_exit=local_exit)
self.can_colorize = _colorize.can_colorize()
def showsyntaxerror(self, filename=None, **kwargs):
[mypy]
files = Lib/_pyrepl
+mypy_path = $MYPY_CONFIG_FILE_DIR/../../Misc/mypy
explicit_package_bases = True
-python_version = 3.12
+python_version = 3.13
platform = linux
pretty = True
# Various internal modules that typeshed deliberately doesn't have stubs for:
[mypy-_abc.*,_opcode.*,_overlapped.*,_testcapi.*,_testinternalcapi.*,test.*]
ignore_missing_imports = True
+
+# Other untyped parts of the stdlib
+[mypy-idlelib.*]
+ignore_missing_imports = True
from contextlib import contextmanager
from dataclasses import dataclass, field, fields
import unicodedata
-from _colorize import can_colorize, ANSIColors # type: ignore[import-not-found]
+from _colorize import can_colorize, ANSIColors
from . import commands, console, input
-from .utils import ANSI_ESCAPE_SEQUENCE, wlen, str_width
+from .utils import wlen, unbracket, str_width
from .trace import trace
@staticmethod
def process_prompt(prompt: str) -> tuple[str, int]:
- """Process the prompt.
+ r"""Return a tuple with the prompt string and its visible length.
- This means calculate the length of the prompt. The character \x01
- and \x02 are used to bracket ANSI control sequences and need to be
- excluded from the length calculation. So also a copy of the prompt
- is returned with these control characters removed."""
-
- # The logic below also ignores the length of common escape
- # sequences if they were not explicitly within \x01...\x02.
- # They are CSI (or ANSI) sequences ( ESC [ ... LETTER )
-
- # wlen from utils already excludes ANSI_ESCAPE_SEQUENCE chars,
- # which breaks the logic below so we redefine it here.
- def wlen(s: str) -> int:
- return sum(str_width(i) for i in s)
-
- out_prompt = ""
- l = wlen(prompt)
- pos = 0
- while True:
- s = prompt.find("\x01", pos)
- if s == -1:
- break
- e = prompt.find("\x02", s)
- if e == -1:
- break
- # Found start and end brackets, subtract from string length
- l = l - (e - s + 1)
- keep = prompt[pos:s]
- l -= sum(map(wlen, ANSI_ESCAPE_SEQUENCE.findall(keep)))
- out_prompt += keep + prompt[s + 1 : e]
- pos = e + 1
- keep = prompt[pos:]
- l -= sum(map(wlen, ANSI_ESCAPE_SEQUENCE.findall(keep)))
- out_prompt += keep
- return out_prompt, l
+ The prompt string has the zero-width brackets recognized by shells
+ (\x01 and \x02) removed. The length ignores anything between those
+ brackets as well as any ANSI escape sequences.
+ """
+ out_prompt = unbracket(prompt, including_content=False)
+ visible_prompt = unbracket(prompt, including_content=True)
+ return out_prompt, wlen(visible_prompt)
def bow(self, p: int | None = None) -> int:
"""Return the 0-based index of the word break preceding p most
from dataclasses import dataclass, field
import os
-from site import gethistoryfile # type: ignore[attr-defined]
+from site import gethistoryfile
import sys
from rlcompleter import Completer as RLCompleter
import functools
ANSI_ESCAPE_SEQUENCE = re.compile(r"\x1b\[[ -@]*[A-~]")
+ZERO_WIDTH_BRACKET = re.compile(r"\x01.*?\x02")
+ZERO_WIDTH_TRANS = str.maketrans({"\x01": "", "\x02": ""})
@functools.cache
if ord(c) < 128:
return 1
w = unicodedata.east_asian_width(c)
- if w in ('N', 'Na', 'H', 'A'):
+ if w in ("N", "Na", "H", "A"):
return 1
return 2
def wlen(s: str) -> int:
- if len(s) == 1 and s != '\x1a':
+ if len(s) == 1 and s != "\x1a":
return str_width(s)
length = sum(str_width(i) for i in s)
# remove lengths of any escape sequences
sequence = ANSI_ESCAPE_SEQUENCE.findall(s)
- ctrl_z_cnt = s.count('\x1a')
+ ctrl_z_cnt = s.count("\x1a")
return length - sum(len(i) for i in sequence) + ctrl_z_cnt
+
+
+def unbracket(s: str, including_content: bool = False) -> str:
+ r"""Return `s` with \001 and \002 characters removed.
+
+ If `including_content` is True, content between \001 and \002 is also
+ stripped.
+ """
+ if including_content:
+ return ZERO_WIDTH_BRACKET.sub("", s)
+ return s.translate(ZERO_WIDTH_TRANS)
from _pyrepl.console import Console, Event
from _pyrepl.readline import ReadlineAlikeReader, ReadlineConfig
from _pyrepl.simple_interact import _strip_final_indent
+from _pyrepl.utils import unbracket, ANSI_ESCAPE_SEQUENCE
+
+
+class ScreenEqualMixin:
+ def assert_screen_equal(
+ self, reader: ReadlineAlikeReader, expected: str, clean: bool = False
+ ):
+ actual = clean_screen(reader) if clean else reader.screen
+ expected = expected.split("\n")
+ self.assertListEqual(actual, expected)
def multiline_input(reader: ReadlineAlikeReader, namespace: dict | None = None):
saved = reader.more_lines
try:
reader.more_lines = partial(more_lines, namespace=namespace)
- reader.ps1 = reader.ps2 = ">>>"
- reader.ps3 = reader.ps4 = "..."
+ reader.ps1 = reader.ps2 = ">>> "
+ reader.ps3 = reader.ps4 = "... "
return reader.readline()
finally:
reader.more_lines = saved
yield Event(evt="key", data=c, raw=bytearray(c.encode("utf-8")))
-def clean_screen(screen: Iterable[str]):
+def clean_screen(reader: ReadlineAlikeReader) -> list[str]:
"""Cleans color and console characters out of a screen output.
This is useful for screen testing, it increases the test readability since
it strips out all the unreadable side of the screen.
"""
output = []
- for line in screen:
- if line.startswith(">>>") or line.startswith("..."):
- line = line[3:]
+ for line in reader.screen:
+ line = unbracket(line, including_content=True)
+ line = ANSI_ESCAPE_SEQUENCE.sub("", line)
+ for prefix in (reader.ps1, reader.ps2, reader.ps3, reader.ps4):
+ if line.startswith(prefix):
+ line = line[len(prefix):]
+ break
output.append(line)
- return "\n".join(output).strip()
+ return output
def prepare_reader(console: Console, **kwargs):
prepare_console=partial(prepare_console, width=10),
)
+reader_no_colors = partial(prepare_reader, can_colorize=False)
+reader_force_colors = partial(prepare_reader, can_colorize=True)
+
class FakeConsole(Console):
def __init__(self, events, encoding="utf-8") -> None:
from .support import (
FakeConsole,
+ ScreenEqualMixin,
handle_all_events,
handle_events_narrow_console,
more_lines,
multiline_input,
code_to_events,
- clean_screen,
)
from _pyrepl.console import Event
from _pyrepl.readline import (ReadlineAlikeReader, ReadlineConfig,
self.assertEqual(output, output_code)
-class TestPyReplOutput(TestCase):
+class TestPyReplOutput(ScreenEqualMixin, TestCase):
def prepare_reader(self, events):
console = FakeConsole(events)
config = ReadlineConfig(readline_completer=None)
output = multiline_input(reader)
self.assertEqual(output, "1+1")
- self.assertEqual(clean_screen(reader.screen), "1+1")
+ self.assert_screen_equal(reader, "1+1", clean=True)
def test_get_line_buffer_returns_str(self):
reader = self.prepare_reader(code_to_events("\n"))
reader = self.prepare_reader(events)
output = multiline_input(reader)
- self.assertEqual(output, "def f():\n ...\n ")
- self.assertEqual(clean_screen(reader.screen), "def f():\n ...")
+ expected = "def f():\n ...\n "
+ self.assertEqual(output, expected)
+ self.assert_screen_equal(reader, expected, clean=True)
output = multiline_input(reader)
- self.assertEqual(output, "def g():\n pass\n ")
- self.assertEqual(clean_screen(reader.screen), "def g():\n pass")
+ expected = "def g():\n pass\n "
+ self.assertEqual(output, expected)
+ self.assert_screen_equal(reader, expected, clean=True)
def test_history_navigation_with_up_arrow(self):
events = itertools.chain(
output = multiline_input(reader)
self.assertEqual(output, "1+1")
- self.assertEqual(clean_screen(reader.screen), "1+1")
+ self.assert_screen_equal(reader, "1+1", clean=True)
output = multiline_input(reader)
self.assertEqual(output, "2+2")
- self.assertEqual(clean_screen(reader.screen), "2+2")
+ self.assert_screen_equal(reader, "2+2", clean=True)
output = multiline_input(reader)
self.assertEqual(output, "2+2")
- self.assertEqual(clean_screen(reader.screen), "2+2")
+ self.assert_screen_equal(reader, "2+2", clean=True)
output = multiline_input(reader)
self.assertEqual(output, "1+1")
- self.assertEqual(clean_screen(reader.screen), "1+1")
+ self.assert_screen_equal(reader, "1+1", clean=True)
def test_history_with_multiline_entries(self):
code = "def foo():\nx = 1\ny = 2\nz = 3\n\ndef bar():\nreturn 42\n\n"
output = multiline_input(reader)
output = multiline_input(reader)
output = multiline_input(reader)
- self.assertEqual(
- clean_screen(reader.screen),
- 'def foo():\n x = 1\n y = 2\n z = 3'
- )
- self.assertEqual(output, "def foo():\n x = 1\n y = 2\n z = 3\n ")
+ expected = "def foo():\n x = 1\n y = 2\n z = 3\n "
+ self.assert_screen_equal(reader, expected, clean=True)
+ self.assertEqual(output, expected)
def test_history_navigation_with_down_arrow(self):
output = multiline_input(reader)
self.assertEqual(output, "1+1")
- self.assertEqual(clean_screen(reader.screen), "1+1")
+ self.assert_screen_equal(reader, "1+1", clean=True)
def test_history_search(self):
events = itertools.chain(
output = multiline_input(reader)
self.assertEqual(output, "1+1")
- self.assertEqual(clean_screen(reader.screen), "1+1")
+ self.assert_screen_equal(reader, "1+1", clean=True)
output = multiline_input(reader)
self.assertEqual(output, "2+2")
- self.assertEqual(clean_screen(reader.screen), "2+2")
+ self.assert_screen_equal(reader, "2+2", clean=True)
output = multiline_input(reader)
self.assertEqual(output, "3+3")
- self.assertEqual(clean_screen(reader.screen), "3+3")
+ self.assert_screen_equal(reader, "3+3", clean=True)
output = multiline_input(reader)
self.assertEqual(output, "1+1")
- self.assertEqual(clean_screen(reader.screen), "1+1")
+ self.assert_screen_equal(reader, "1+1", clean=True)
def test_control_character(self):
events = code_to_events("c\x1d\n")
reader = self.prepare_reader(events)
output = multiline_input(reader)
self.assertEqual(output, "c\x1d")
- self.assertEqual(clean_screen(reader.screen), "c")
+ self.assert_screen_equal(reader, "c\x1d", clean=True)
def test_history_search_backward(self):
# Test <page up> history search backward with "imp" input
# search for "imp" in history
output = multiline_input(reader)
self.assertEqual(output, "import os")
- self.assertEqual(clean_screen(reader.screen), "import os")
+ self.assert_screen_equal(reader, "import os", clean=True)
def test_history_search_backward_empty(self):
# Test <page up> history search backward with an empty input
# search backward in history
output = multiline_input(reader)
self.assertEqual(output, "import os")
- self.assertEqual(clean_screen(reader.screen), "import os")
+ self.assert_screen_equal(reader, "import os", clean=True)
class TestPyReplCompleter(TestCase):
from unittest import TestCase
from unittest.mock import MagicMock
-from .support import handle_all_events, handle_events_narrow_console, code_to_events, prepare_reader, prepare_console
+from .support import handle_all_events, handle_events_narrow_console
+from .support import ScreenEqualMixin, code_to_events
+from .support import prepare_reader, prepare_console
from _pyrepl.console import Event
from _pyrepl.reader import Reader
-class TestReader(TestCase):
- def assert_screen_equals(self, reader, expected):
- actual = reader.screen
- expected = expected.split("\n")
- self.assertListEqual(actual, expected)
-
+class TestReader(ScreenEqualMixin, TestCase):
def test_calc_screen_wrap_simple(self):
events = code_to_events(10 * "a")
reader, _ = handle_events_narrow_console(events)
- self.assert_screen_equals(reader, f"{9*"a"}\\\na")
+ self.assert_screen_equal(reader, f"{9*"a"}\\\na")
def test_calc_screen_wrap_wide_characters(self):
events = code_to_events(8 * "a" + "樂")
reader, _ = handle_events_narrow_console(events)
- self.assert_screen_equals(reader, f"{8*"a"}\\\n樂")
+ self.assert_screen_equal(reader, f"{8*"a"}\\\n樂")
def test_calc_screen_wrap_three_lines(self):
events = code_to_events(20 * "a")
reader, _ = handle_events_narrow_console(events)
- self.assert_screen_equals(reader, f"{9*"a"}\\\n{9*"a"}\\\naa")
+ self.assert_screen_equal(reader, f"{9*"a"}\\\n{9*"a"}\\\naa")
def test_calc_screen_prompt_handling(self):
def prepare_reader_keep_prompts(*args, **kwargs):
prepare_reader=prepare_reader_keep_prompts,
)
# fmt: off
- self.assert_screen_equals(
+ self.assert_screen_equal(
reader,
(
">>> if so\\\n"
reader, _ = handle_events_narrow_console(events)
# fmt: off
- self.assert_screen_equals(reader, (
- "def f():\n"
- f" {7*"a"}\\\n"
- "a\n"
- f" {3*"樂"}\\\n"
- "樂樂"
- ))
+ self.assert_screen_equal(
+ reader,
+ (
+ "def f():\n"
+ f" {7*"a"}\\\n"
+ "a\n"
+ f" {3*"樂"}\\\n"
+ "樂樂"
+ ),
+ clean=True,
+ )
# fmt: on
def test_calc_screen_backspace(self):
],
)
reader, _ = handle_all_events(events)
- self.assert_screen_equals(reader, "aa")
+ self.assert_screen_equal(reader, "aa")
def test_calc_screen_wrap_removes_after_backspace(self):
events = itertools.chain(
],
)
reader, _ = handle_events_narrow_console(events)
- self.assert_screen_equals(reader, 9 * "a")
+ self.assert_screen_equal(reader, 9 * "a")
def test_calc_screen_backspace_in_second_line_after_wrap(self):
events = itertools.chain(
],
)
reader, _ = handle_events_narrow_console(events)
- self.assert_screen_equals(reader, f"{9*"a"}\\\na")
+ self.assert_screen_equal(reader, f"{9*"a"}\\\na")
def test_setpos_for_xy_simple(self):
events = code_to_events("11+11")
code = 'flag = "🏳️🌈"'
events = code_to_events(code)
reader, _ = handle_all_events(events)
- self.assert_screen_equals(reader, 'flag = "🏳️\\u200d🌈"')
+ self.assert_screen_equal(reader, 'flag = "🏳️\\u200d🌈"', clean=True)
def test_setpos_from_xy_multiple_lines(self):
# fmt: off
)
reader, _ = handle_all_events(events)
- self.assert_screen_equals(reader, "")
+ self.assert_screen_equal(reader, "")
def test_newline_within_block_trailing_whitespace(self):
# fmt: off
" \n"
" a = 1\n"
" \n"
- " " # HistoricalReader will trim trailing whitespace
+ " " # HistoricalReader will trim trailing whitespace
)
- self.assert_screen_equals(reader, expected)
+ self.assert_screen_equal(reader, expected, clean=True)
self.assertTrue(reader.finished)
def test_input_hook_is_called_if_set(self):
input_hook = MagicMock()
+
def _prepare_console(events):
console = MagicMock()
console.get_event.side_effect = events
def test_keyboard_interrupt_clears_screen(self):
namespace = {"itertools": itertools}
code = "import itertools\nitertools."
- events = itertools.chain(code_to_events(code), [
- Event(evt='key', data='\t', raw=bytearray(b'\t')), # Two tabs for completion
- Event(evt='key', data='\t', raw=bytearray(b'\t')),
- Event(evt='key', data='\x03', raw=bytearray(b'\x03')), # Ctrl-C
- ])
-
- completing_reader = functools.partial(
- prepare_reader,
- readline_completer=rlcompleter.Completer(namespace).complete
+ events = itertools.chain(
+ code_to_events(code),
+ [
+ # Two tabs for completion
+ Event(evt="key", data="\t", raw=bytearray(b"\t")),
+ Event(evt="key", data="\t", raw=bytearray(b"\t")),
+ Event(evt="key", data="\x03", raw=bytearray(b"\x03")), # Ctrl-C
+ ],
)
- reader, _ = handle_all_events(events, prepare_reader=completing_reader)
- self.assertEqual(reader.calc_screen(), code.split("\n"))
+ console = prepare_console(events)
+ reader = prepare_reader(
+ console,
+ readline_completer=rlcompleter.Completer(namespace).complete,
+ )
+ try:
+ # we're not using handle_all_events() here to be able to
+ # follow the KeyboardInterrupt sequence of events. Normally this
+ # happens in simple_interact.run_multiline_interactive_console.
+ while True:
+ reader.handle1()
+ except KeyboardInterrupt:
+ # at this point the completions are still visible
+ self.assertTrue(len(reader.screen) > 2)
+ reader.refresh()
+ # after the refresh, they are gone
+ self.assertEqual(len(reader.screen), 2)
+ self.assert_screen_equal(reader, code, clean=True)
+ else:
+ self.fail("KeyboardInterrupt not raised.")
def test_prompt_length(self):
# Handles simple ASCII prompt
def test_completions_updated_on_key_press(self):
namespace = {"itertools": itertools}
code = "itertools."
- events = itertools.chain(code_to_events(code), [
- Event(evt='key', data='\t', raw=bytearray(b'\t')), # Two tabs for completion
- Event(evt='key', data='\t', raw=bytearray(b'\t')),
- ], code_to_events("a"))
+ events = itertools.chain(
+ code_to_events(code),
+ [
+ # Two tabs for completion
+ Event(evt="key", data="\t", raw=bytearray(b"\t")),
+ Event(evt="key", data="\t", raw=bytearray(b"\t")),
+ ],
+ code_to_events("a"),
+ )
completing_reader = functools.partial(
prepare_reader,
- readline_completer=rlcompleter.Completer(namespace).complete
+ readline_completer=rlcompleter.Completer(namespace).complete,
)
reader, _ = handle_all_events(events, prepare_reader=completing_reader)
def test_key_press_on_tab_press_once(self):
namespace = {"itertools": itertools}
code = "itertools."
- events = itertools.chain(code_to_events(code), [
- Event(evt='key', data='\t', raw=bytearray(b'\t')),
- ], code_to_events("a"))
+ events = itertools.chain(
+ code_to_events(code),
+ [
+ Event(evt="key", data="\t", raw=bytearray(b"\t")),
+ ],
+ code_to_events("a"),
+ )
completing_reader = functools.partial(
prepare_reader,
- readline_completer=rlcompleter.Completer(namespace).complete
+ readline_completer=rlcompleter.Completer(namespace).complete,
)
reader, _ = handle_all_events(events, prepare_reader=completing_reader)
- self.assert_screen_equals(reader, f"{code}a")
+ self.assert_screen_equal(reader, f"{code}a")
def test_pos2xy_with_no_columns(self):
console = prepare_console([])
from unittest import TestCase
from unittest.mock import MagicMock, call, patch, ANY
-from .support import handle_all_events, code_to_events
+from .support import handle_all_events, code_to_events, reader_no_colors
try:
from _pyrepl.console import Event
# fmt: on
events = itertools.chain(code_to_events(code))
- reader, console = handle_events_short_unix_console(events)
+ reader, console = handle_events_short_unix_console(
+ events, prepare_reader=reader_no_colors
+ )
console.height = 2
console.getheightwidth = MagicMock(lambda _: (2, 80))
--- /dev/null
+# Mypy path symlinks
+
+This directory stores symlinks to standard library modules and packages
+that are fully type-annotated and ready to be used in type checking of
+the rest of the stdlib or Tools/ and so on.
+
+Due to most of the standard library being untyped, we prefer not to
+point mypy directly at `Lib/` for type checking. Additionally, mypy
+as a tool does not support shadowing typing-related standard libraries
+like `types`, `typing`, and `collections.abc`.
+
+So instead, we set `mypy_path` to include this directory,
+which only links modules and packages we know are safe to be
+type-checked themselves and used as dependencies.
+
+See `Lib/_pyrepl/mypy.ini` for an example.
\ No newline at end of file
--- /dev/null
+../../Lib/_colorize.py
\ No newline at end of file
--- /dev/null
+../../Lib/_pyrepl
\ No newline at end of file