Skip to content

Commit 814db9a

Browse files
committed
Merge remote-tracking branch 'upstream/main' into tuple_hash_cache2
2 parents c4fb543 + 3a09986 commit 814db9a

39 files changed

+1064
-303
lines changed

Include/internal/pycore_optimizer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ typedef struct _jit_opt_tuple {
202202

203203
typedef struct {
204204
uint8_t tag;
205-
bool not;
205+
bool invert;
206206
uint16_t value;
207207
} JitOptTruthiness;
208208

Lib/_colorize.py

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,64 @@
1+
from __future__ import annotations
12
import io
23
import os
34
import sys
45

56
COLORIZE = True
67

8+
# types
9+
if False:
10+
from typing import IO
11+
712

813
class ANSIColors:
9-
BACKGROUND_YELLOW = "\x1b[43m"
10-
BOLD_GREEN = "\x1b[1;32m"
11-
BOLD_MAGENTA = "\x1b[1;35m"
12-
BOLD_RED = "\x1b[1;31m"
14+
RESET = "\x1b[0m"
15+
1316
BLACK = "\x1b[30m"
17+
BLUE = "\x1b[34m"
18+
CYAN = "\x1b[36m"
1419
GREEN = "\x1b[32m"
15-
GREY = "\x1b[90m"
1620
MAGENTA = "\x1b[35m"
1721
RED = "\x1b[31m"
18-
RESET = "\x1b[0m"
22+
WHITE = "\x1b[37m" # more like LIGHT GRAY
1923
YELLOW = "\x1b[33m"
2024

25+
BOLD_BLACK = "\x1b[1;30m" # DARK GRAY
26+
BOLD_BLUE = "\x1b[1;34m"
27+
BOLD_CYAN = "\x1b[1;36m"
28+
BOLD_GREEN = "\x1b[1;32m"
29+
BOLD_MAGENTA = "\x1b[1;35m"
30+
BOLD_RED = "\x1b[1;31m"
31+
BOLD_WHITE = "\x1b[1;37m" # actual WHITE
32+
BOLD_YELLOW = "\x1b[1;33m"
33+
34+
# intense = like bold but without being bold
35+
INTENSE_BLACK = "\x1b[90m"
36+
INTENSE_BLUE = "\x1b[94m"
37+
INTENSE_CYAN = "\x1b[96m"
38+
INTENSE_GREEN = "\x1b[92m"
39+
INTENSE_MAGENTA = "\x1b[95m"
40+
INTENSE_RED = "\x1b[91m"
41+
INTENSE_WHITE = "\x1b[97m"
42+
INTENSE_YELLOW = "\x1b[93m"
43+
44+
BACKGROUND_BLACK = "\x1b[40m"
45+
BACKGROUND_BLUE = "\x1b[44m"
46+
BACKGROUND_CYAN = "\x1b[46m"
47+
BACKGROUND_GREEN = "\x1b[42m"
48+
BACKGROUND_MAGENTA = "\x1b[45m"
49+
BACKGROUND_RED = "\x1b[41m"
50+
BACKGROUND_WHITE = "\x1b[47m"
51+
BACKGROUND_YELLOW = "\x1b[43m"
52+
53+
INTENSE_BACKGROUND_BLACK = "\x1b[100m"
54+
INTENSE_BACKGROUND_BLUE = "\x1b[104m"
55+
INTENSE_BACKGROUND_CYAN = "\x1b[106m"
56+
INTENSE_BACKGROUND_GREEN = "\x1b[102m"
57+
INTENSE_BACKGROUND_MAGENTA = "\x1b[105m"
58+
INTENSE_BACKGROUND_RED = "\x1b[101m"
59+
INTENSE_BACKGROUND_WHITE = "\x1b[107m"
60+
INTENSE_BACKGROUND_YELLOW = "\x1b[103m"
61+
2162

2263
NoColors = ANSIColors()
2364

@@ -26,14 +67,16 @@ class ANSIColors:
2667
setattr(NoColors, attr, "")
2768

2869

29-
def get_colors(colorize: bool = False, *, file=None) -> ANSIColors:
70+
def get_colors(
71+
colorize: bool = False, *, file: IO[str] | IO[bytes] | None = None
72+
) -> ANSIColors:
3073
if colorize or can_colorize(file=file):
3174
return ANSIColors()
3275
else:
3376
return NoColors
3477

3578

36-
def can_colorize(*, file=None) -> bool:
79+
def can_colorize(*, file: IO[str] | IO[bytes] | None = None) -> bool:
3780
if file is None:
3881
file = sys.stdout
3982

@@ -66,4 +109,4 @@ def can_colorize(*, file=None) -> bool:
66109
try:
67110
return os.isatty(file.fileno())
68111
except io.UnsupportedOperation:
69-
return file.isatty()
112+
return hasattr(file, "isatty") and file.isatty()

Lib/_pydatetime.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ def _check_date_fields(year, month, day):
576576
raise ValueError(f"month must be in 1..12, not {month}")
577577
dim = _days_in_month(year, month)
578578
if not 1 <= day <= dim:
579-
raise ValueError(f"day must be in 1..{dim}, not {day}")
579+
raise ValueError(f"day {day} must be in range 1..{dim} for month {month} in year {year}")
580580
return year, month, day
581581

582582
def _check_time_fields(hour, minute, second, microsecond, fold):

Lib/_pyrepl/commands.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ def do(self) -> None:
456456
class show_history(Command):
457457
def do(self) -> None:
458458
from .pager import get_pager
459-
from site import gethistoryfile # type: ignore[attr-defined]
459+
from site import gethistoryfile
460460

461461
history = os.linesep.join(self.reader.history[:])
462462
self.reader.console.restore()

Lib/_pyrepl/console.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
from __future__ import annotations
2121

22-
import _colorize # type: ignore[import-not-found]
22+
import _colorize
2323

2424
from abc import ABC, abstractmethod
2525
import ast
@@ -162,7 +162,7 @@ def __init__(
162162
*,
163163
local_exit: bool = False,
164164
) -> None:
165-
super().__init__(locals=locals, filename=filename, local_exit=local_exit) # type: ignore[call-arg]
165+
super().__init__(locals=locals, filename=filename, local_exit=local_exit)
166166
self.can_colorize = _colorize.can_colorize()
167167

168168
def showsyntaxerror(self, filename=None, **kwargs):

Lib/_pyrepl/mypy.ini

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44

55
[mypy]
66
files = Lib/_pyrepl
7+
mypy_path = $MYPY_CONFIG_FILE_DIR/../../Misc/mypy
78
explicit_package_bases = True
8-
python_version = 3.12
9+
python_version = 3.13
910
platform = linux
1011
pretty = True
1112

@@ -22,3 +23,7 @@ check_untyped_defs = False
2223
# Various internal modules that typeshed deliberately doesn't have stubs for:
2324
[mypy-_abc.*,_opcode.*,_overlapped.*,_testcapi.*,_testinternalcapi.*,test.*]
2425
ignore_missing_imports = True
26+
27+
# Other untyped parts of the stdlib
28+
[mypy-idlelib.*]
29+
ignore_missing_imports = True

Lib/_pyrepl/reader.py

Lines changed: 10 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@
2626
from contextlib import contextmanager
2727
from dataclasses import dataclass, field, fields
2828
import unicodedata
29-
from _colorize import can_colorize, ANSIColors # type: ignore[import-not-found]
29+
from _colorize import can_colorize, ANSIColors
3030

3131

3232
from . import commands, console, input
33-
from .utils import ANSI_ESCAPE_SEQUENCE, wlen, str_width
33+
from .utils import wlen, unbracket, str_width
3434
from .trace import trace
3535

3636

@@ -421,42 +421,15 @@ def calc_screen(self) -> list[str]:
421421

422422
@staticmethod
423423
def process_prompt(prompt: str) -> tuple[str, int]:
424-
"""Process the prompt.
424+
r"""Return a tuple with the prompt string and its visible length.
425425
426-
This means calculate the length of the prompt. The character \x01
427-
and \x02 are used to bracket ANSI control sequences and need to be
428-
excluded from the length calculation. So also a copy of the prompt
429-
is returned with these control characters removed."""
430-
431-
# The logic below also ignores the length of common escape
432-
# sequences if they were not explicitly within \x01...\x02.
433-
# They are CSI (or ANSI) sequences ( ESC [ ... LETTER )
434-
435-
# wlen from utils already excludes ANSI_ESCAPE_SEQUENCE chars,
436-
# which breaks the logic below so we redefine it here.
437-
def wlen(s: str) -> int:
438-
return sum(str_width(i) for i in s)
439-
440-
out_prompt = ""
441-
l = wlen(prompt)
442-
pos = 0
443-
while True:
444-
s = prompt.find("\x01", pos)
445-
if s == -1:
446-
break
447-
e = prompt.find("\x02", s)
448-
if e == -1:
449-
break
450-
# Found start and end brackets, subtract from string length
451-
l = l - (e - s + 1)
452-
keep = prompt[pos:s]
453-
l -= sum(map(wlen, ANSI_ESCAPE_SEQUENCE.findall(keep)))
454-
out_prompt += keep + prompt[s + 1 : e]
455-
pos = e + 1
456-
keep = prompt[pos:]
457-
l -= sum(map(wlen, ANSI_ESCAPE_SEQUENCE.findall(keep)))
458-
out_prompt += keep
459-
return out_prompt, l
426+
The prompt string has the zero-width brackets recognized by shells
427+
(\x01 and \x02) removed. The length ignores anything between those
428+
brackets as well as any ANSI escape sequences.
429+
"""
430+
out_prompt = unbracket(prompt, including_content=False)
431+
visible_prompt = unbracket(prompt, including_content=True)
432+
return out_prompt, wlen(visible_prompt)
460433

461434
def bow(self, p: int | None = None) -> int:
462435
"""Return the 0-based index of the word break preceding p most

Lib/_pyrepl/readline.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
from dataclasses import dataclass, field
3333

3434
import os
35-
from site import gethistoryfile # type: ignore[attr-defined]
35+
from site import gethistoryfile
3636
import sys
3737
from rlcompleter import Completer as RLCompleter
3838

Lib/_pyrepl/utils.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,36 @@
33
import functools
44

55
ANSI_ESCAPE_SEQUENCE = re.compile(r"\x1b\[[ -@]*[A-~]")
6+
ZERO_WIDTH_BRACKET = re.compile(r"\x01.*?\x02")
7+
ZERO_WIDTH_TRANS = str.maketrans({"\x01": "", "\x02": ""})
68

79

810
@functools.cache
911
def str_width(c: str) -> int:
1012
if ord(c) < 128:
1113
return 1
1214
w = unicodedata.east_asian_width(c)
13-
if w in ('N', 'Na', 'H', 'A'):
15+
if w in ("N", "Na", "H", "A"):
1416
return 1
1517
return 2
1618

1719

1820
def wlen(s: str) -> int:
19-
if len(s) == 1 and s != '\x1a':
21+
if len(s) == 1 and s != "\x1a":
2022
return str_width(s)
2123
length = sum(str_width(i) for i in s)
2224
# remove lengths of any escape sequences
2325
sequence = ANSI_ESCAPE_SEQUENCE.findall(s)
24-
ctrl_z_cnt = s.count('\x1a')
26+
ctrl_z_cnt = s.count("\x1a")
2527
return length - sum(len(i) for i in sequence) + ctrl_z_cnt
28+
29+
30+
def unbracket(s: str, including_content: bool = False) -> str:
31+
r"""Return `s` with \001 and \002 characters removed.
32+
33+
If `including_content` is True, content between \001 and \002 is also
34+
stripped.
35+
"""
36+
if including_content:
37+
return ZERO_WIDTH_BRACKET.sub("", s)
38+
return s.translate(ZERO_WIDTH_TRANS)

Lib/bdb.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,12 @@ def dispatch_call(self, frame, arg):
342342
self.botframe = frame.f_back # (CT) Note that this may also be None!
343343
return self.trace_dispatch
344344
if not (self.stop_here(frame) or self.break_anywhere(frame)):
345-
# No need to trace this function
345+
# We already know there's no breakpoint in this function
346+
# If it's a next/until/return command, we don't need any CALL event
347+
# and we don't need to set the f_trace on any new frame.
348+
# If it's a step command, it must either hit stop_here, or skip the
349+
# whole module. Either way, we don't need the CALL event here.
350+
self.disable_current_event()
346351
return # None
347352
# Ignore call events in generator except when stepping.
348353
if self.stopframe and frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS:

0 commit comments

Comments
 (0)