Skip to content

Commit 8753264

Browse files
Merge branch 'main' of https://github.com/python/cpython into jit-super
2 parents 13aad7b + eab7dbd commit 8753264

27 files changed

Lines changed: 485 additions & 248 deletions

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
repos:
22
- repo: https://github.com/astral-sh/ruff-pre-commit
3-
rev: a27a2e47c7751b639d2b5badf0ef6ff11fee893f # frozen: v0.15.4
3+
rev: e05c5c0818279e5ac248ac9e954431ba58865e61 # frozen: v0.15.7
44
hooks:
55
- id: ruff-check
66
name: Run Ruff (lint) on Platforms/Apple/

Doc/library/itertools.rst

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -850,7 +850,7 @@ and :term:`generators <generator>` which incur interpreter overhead.
850850

851851
def running_mean(iterable):
852852
"Yield the average of all values seen so far."
853-
# running_mean([8.5, 9.5, 7.5, 6.5]) -> 8.5 9.0 8.5 8.0
853+
# running_mean([8.5, 9.5, 7.5, 6.5]) 8.5 9.0 8.5 8.0
854854
return map(truediv, accumulate(iterable), count(1))
855855

856856
def repeatfunc(function, times=None, *args):
@@ -932,10 +932,10 @@ and :term:`generators <generator>` which incur interpreter overhead.
932932
yield element
933933

934934
def unique(iterable, key=None, reverse=False):
935-
"Yield unique elements in sorted order. Supports unhashable inputs."
936-
# unique([[1, 2], [3, 4], [1, 2]]) → [1, 2] [3, 4]
937-
sequenced = sorted(iterable, key=key, reverse=reverse)
938-
return unique_justseen(sequenced, key=key)
935+
"Yield unique elements in sorted order. Supports unhashable inputs."
936+
# unique([[1, 2], [3, 4], [1, 2]]) → [1, 2] [3, 4]
937+
sequenced = sorted(iterable, key=key, reverse=reverse)
938+
return unique_justseen(sequenced, key=key)
939939

940940
def sliding_window(iterable, n):
941941
"Collect data into overlapping fixed-length chunks or blocks."

Doc/whatsnew/3.15.rst

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,17 @@ http.cookies
822822
(Contributed by Nick Burns and Senthil Kumaran in :gh:`92936`.)
823823

824824

825+
http.server
826+
-----------
827+
828+
* The logging of :mod:`~http.server.BaseHTTPRequestHandler`,
829+
as used by the :ref:`command-line interface <http-server-cli>`,
830+
is colored by default.
831+
This can be controlled with :ref:`environment variables
832+
<using-on-controlling-color>`.
833+
(Contributed by Hugo van Kemenade in :gh:`146292`.)
834+
835+
825836
inspect
826837
-------
827838

@@ -1097,6 +1108,10 @@ tarfile
10971108
timeit
10981109
------
10991110

1111+
* The output of the :mod:`timeit` command-line interface is colored by default.
1112+
This can be controlled with
1113+
:ref:`environment variables <using-on-controlling-color>`.
1114+
(Contributed by Hugo van Kemenade in :gh:`146609`.)
11001115
* The command-line interface now colorizes error tracebacks
11011116
by default. This can be controlled with
11021117
:ref:`environment variables <using-on-controlling-color>`.
@@ -1294,6 +1309,25 @@ warnings
12941309
(Contributed by Serhiy Storchaka in :gh:`135801`.)
12951310

12961311

1312+
wave
1313+
----
1314+
1315+
* Added support for IEEE floating-point WAVE audio
1316+
(``WAVE_FORMAT_IEEE_FLOAT``) in :mod:`wave`.
1317+
1318+
* Added :meth:`wave.Wave_read.getformat`, :meth:`wave.Wave_write.getformat`,
1319+
and :meth:`wave.Wave_write.setformat` for explicit frame format handling.
1320+
1321+
* :meth:`wave.Wave_write.setparams` accepts both 7-item tuples including
1322+
``format`` and 6-item tuples for backwards compatibility (defaulting to
1323+
``WAVE_FORMAT_PCM``).
1324+
1325+
* ``WAVE_FORMAT_IEEE_FLOAT`` output now includes a ``fact`` chunk,
1326+
as required for non-PCM WAVE formats.
1327+
1328+
(Contributed by Lionel Koenig and Michiel W. Beijen in :gh:`60729`.)
1329+
1330+
12971331
xml.parsers.expat
12981332
-----------------
12991333

@@ -1563,21 +1597,6 @@ typing
15631597
wave
15641598
----
15651599

1566-
* Added support for IEEE floating-point WAVE audio
1567-
(``WAVE_FORMAT_IEEE_FLOAT``) in :mod:`wave`.
1568-
1569-
* Added :meth:`wave.Wave_read.getformat`, :meth:`wave.Wave_write.getformat`,
1570-
and :meth:`wave.Wave_write.setformat` for explicit frame format handling.
1571-
1572-
* :meth:`wave.Wave_write.setparams` accepts both 7-item tuples including
1573-
``format`` and 6-item tuples for backwards compatibility (defaulting to
1574-
``WAVE_FORMAT_PCM``).
1575-
1576-
* ``WAVE_FORMAT_IEEE_FLOAT`` output now includes a ``fact`` chunk,
1577-
as required for non-PCM WAVE formats.
1578-
1579-
(Contributed by Lionel Koenig and Michiel W. Beijen in :gh:`60729`.)
1580-
15811600
* Removed the ``getmark()``, ``setmark()`` and ``getmarkers()`` methods
15821601
of the :class:`~wave.Wave_read` and :class:`~wave.Wave_write` classes,
15831602
which were deprecated since Python 3.13.

Include/internal/pycore_opcode_metadata.h

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_uop_ids.h

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_uop_metadata.h

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/_colorize.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,22 @@ class FancyCompleter(ThemeSection):
223223
str: str = ANSIColors.BOLD_GREEN
224224

225225

226+
@dataclass(frozen=True, kw_only=True)
227+
class HttpServer(ThemeSection):
228+
error: str = ANSIColors.YELLOW
229+
path: str = ANSIColors.CYAN
230+
serving: str = ANSIColors.GREEN
231+
size: str = ANSIColors.GREY
232+
status_informational: str = ANSIColors.RESET
233+
status_ok: str = ANSIColors.GREEN
234+
status_redirect: str = ANSIColors.INTENSE_CYAN
235+
status_client_error: str = ANSIColors.YELLOW
236+
status_server_error: str = ANSIColors.RED
237+
timestamp: str = ANSIColors.GREY
238+
url: str = ANSIColors.CYAN
239+
reset: str = ANSIColors.RESET
240+
241+
226242
@dataclass(frozen=True, kw_only=True)
227243
class LiveProfiler(ThemeSection):
228244
"""Theme section for the live profiling TUI (Tachyon profiler).
@@ -346,6 +362,18 @@ class Syntax(ThemeSection):
346362
reset: str = ANSIColors.RESET
347363

348364

365+
@dataclass(frozen=True, kw_only=True)
366+
class Timeit(ThemeSection):
367+
timing: str = ANSIColors.CYAN
368+
best: str = ANSIColors.BOLD_GREEN
369+
per_loop: str = ANSIColors.GREEN
370+
punctuation: str = ANSIColors.GREY
371+
warning: str = ANSIColors.YELLOW
372+
warning_worst: str = ANSIColors.MAGENTA
373+
warning_best: str = ANSIColors.GREEN
374+
reset: str = ANSIColors.RESET
375+
376+
349377
@dataclass(frozen=True, kw_only=True)
350378
class Traceback(ThemeSection):
351379
type: str = ANSIColors.BOLD_MAGENTA
@@ -378,8 +406,10 @@ class Theme:
378406
argparse: Argparse = field(default_factory=Argparse)
379407
difflib: Difflib = field(default_factory=Difflib)
380408
fancycompleter: FancyCompleter = field(default_factory=FancyCompleter)
409+
http_server: HttpServer = field(default_factory=HttpServer)
381410
live_profiler: LiveProfiler = field(default_factory=LiveProfiler)
382411
syntax: Syntax = field(default_factory=Syntax)
412+
timeit: Timeit = field(default_factory=Timeit)
383413
traceback: Traceback = field(default_factory=Traceback)
384414
unittest: Unittest = field(default_factory=Unittest)
385415

@@ -389,8 +419,10 @@ def copy_with(
389419
argparse: Argparse | None = None,
390420
difflib: Difflib | None = None,
391421
fancycompleter: FancyCompleter | None = None,
422+
http_server: HttpServer | None = None,
392423
live_profiler: LiveProfiler | None = None,
393424
syntax: Syntax | None = None,
425+
timeit: Timeit | None = None,
394426
traceback: Traceback | None = None,
395427
unittest: Unittest | None = None,
396428
) -> Self:
@@ -403,8 +435,10 @@ def copy_with(
403435
argparse=argparse or self.argparse,
404436
difflib=difflib or self.difflib,
405437
fancycompleter=fancycompleter or self.fancycompleter,
438+
http_server=http_server or self.http_server,
406439
live_profiler=live_profiler or self.live_profiler,
407440
syntax=syntax or self.syntax,
441+
timeit=timeit or self.timeit,
408442
traceback=traceback or self.traceback,
409443
unittest=unittest or self.unittest,
410444
)
@@ -421,8 +455,10 @@ def no_colors(cls) -> Self:
421455
argparse=Argparse.no_colors(),
422456
difflib=Difflib.no_colors(),
423457
fancycompleter=FancyCompleter.no_colors(),
458+
http_server=HttpServer.no_colors(),
424459
live_profiler=LiveProfiler.no_colors(),
425460
syntax=Syntax.no_colors(),
461+
timeit=Timeit.no_colors(),
426462
traceback=Traceback.no_colors(),
427463
unittest=Unittest.no_colors(),
428464
)

Lib/http/server.py

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@
8585

8686
from http import HTTPStatus
8787

88+
lazy import _colorize
89+
8890

8991
# Default error message template
9092
DEFAULT_ERROR_MESSAGE = """\
@@ -574,6 +576,31 @@ def flush_headers(self):
574576
self.wfile.write(b"".join(self._headers_buffer))
575577
self._headers_buffer = []
576578

579+
def _colorize_request(self, code, size, t):
580+
try:
581+
code_int = int(code)
582+
except (TypeError, ValueError):
583+
code_color = ""
584+
else:
585+
if code_int >= 500:
586+
code_color = t.status_server_error
587+
elif code_int >= 400:
588+
code_color = t.status_client_error
589+
elif code_int >= 300:
590+
code_color = t.status_redirect
591+
elif code_int >= 200:
592+
code_color = t.status_ok
593+
else:
594+
code_color = t.status_informational
595+
596+
request_line = self.requestline.translate(self._control_char_table)
597+
parts = request_line.split(None, 2)
598+
if len(parts) == 3:
599+
method, path, version = parts
600+
request_line = f"{method} {t.path}{path}{t.reset} {version}"
601+
602+
return f'"{request_line}" {code_color}{code} {t.size}{size}{t.reset}'
603+
577604
def log_request(self, code='-', size='-'):
578605
"""Log an accepted request.
579606
@@ -582,6 +609,7 @@ def log_request(self, code='-', size='-'):
582609
"""
583610
if isinstance(code, HTTPStatus):
584611
code = code.value
612+
self._log_request_info = (code, size)
585613
self.log_message('"%s" %s %s',
586614
self.requestline, str(code), str(size))
587615

@@ -596,7 +624,7 @@ def log_error(self, format, *args):
596624
XXX This should go to the separate error log.
597625
598626
"""
599-
627+
self._log_is_error = True
600628
self.log_message(format, *args)
601629

602630
# https://en.wikipedia.org/wiki/List_of_Unicode_characters#Control_codes
@@ -623,12 +651,22 @@ def log_message(self, format, *args):
623651
before writing the output to stderr.
624652
625653
"""
626-
627-
message = format % args
628-
sys.stderr.write("%s - - [%s] %s\n" %
629-
(self.address_string(),
630-
self.log_date_time_string(),
631-
message.translate(self._control_char_table)))
654+
message = (format % args).translate(self._control_char_table)
655+
t = _colorize.get_theme(tty_file=sys.stderr).http_server
656+
657+
info = getattr(self, "_log_request_info", None)
658+
if info is not None:
659+
self._log_request_info = None
660+
message = self._colorize_request(*info, t)
661+
elif getattr(self, "_log_is_error", False):
662+
self._log_is_error = False
663+
message = f"{t.error}{message}{t.reset}"
664+
665+
sys.stderr.write(
666+
f"{t.timestamp}{self.address_string()} - - "
667+
f"[{self.log_date_time_string()}]{t.reset} "
668+
f"{message}\n"
669+
)
632670

633671
def version_string(self):
634672
"""Return the server software version string."""
@@ -994,9 +1032,11 @@ def test(HandlerClass=BaseHTTPRequestHandler,
9941032
host, port = httpd.socket.getsockname()[:2]
9951033
url_host = f'[{host}]' if ':' in host else host
9961034
protocol = 'HTTPS' if tls_cert else 'HTTP'
1035+
t = _colorize.get_theme().http_server
1036+
url = f"{protocol.lower()}://{url_host}:{port}/"
9971037
print(
998-
f"Serving {protocol} on {host} port {port} "
999-
f"({protocol.lower()}://{url_host}:{port}/) ..."
1038+
f"{t.serving}Serving {protocol} on {host} port {port}{t.reset} "
1039+
f"({t.url}{url}{t.reset}) ..."
10001040
)
10011041
try:
10021042
httpd.serve_forever()

Lib/test/.ruff.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
extend = "../../.ruff.toml" # Inherit the project-wide settings
22

33
# Unlike Tools/, tests can use newer syntax than PYTHON_FOR_REGEN
4-
target-version = "py314"
4+
target-version = "py315"
55

66
extend-exclude = [
77
# Excluded (run with the other AC files in its own separate ruff job in pre-commit)

0 commit comments

Comments
 (0)