Skip to content

Commit 0e60215

Browse files
authored
Merge branch '3.14' into backport-f04bea4-3.14
2 parents 52edaa7 + 4d7fab9 commit 0e60215

File tree

85 files changed

+1020
-462
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+1020
-462
lines changed

.github/workflows/build.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,29 @@ jobs:
386386
- name: Build and test
387387
run: ./Android/android.py ci --fast-ci ${{ matrix.arch }}-linux-android
388388

389+
build-ios:
390+
name: iOS
391+
needs: build-context
392+
if: needs.build-context.outputs.run-tests == 'true'
393+
timeout-minutes: 60
394+
runs-on: macos-15
395+
steps:
396+
- uses: actions/checkout@v4
397+
with:
398+
persist-credentials: false
399+
400+
# GitHub recommends explicitly selecting the desired Xcode version:
401+
# https://github.com/actions/runner-images/issues/12541#issuecomment-3083850140
402+
# This became a necessity as a result of
403+
# https://github.com/actions/runner-images/issues/12541 and
404+
# https://github.com/actions/runner-images/issues/12751.
405+
- name: Select Xcode version
406+
run: |
407+
sudo xcode-select --switch /Applications/Xcode_16.4.app
408+
409+
- name: Build and test
410+
run: python3 Apple ci iOS --fast-ci --simulator 'iPhone 16e,OS=18.5'
411+
389412
build-wasi:
390413
name: 'WASI'
391414
needs: build-context
@@ -694,6 +717,7 @@ jobs:
694717
- build-ubuntu
695718
- build-ubuntu-ssltests
696719
- build-android
720+
- build-ios
697721
- build-wasi
698722
- test-hypothesis
699723
- build-asan
@@ -728,6 +752,7 @@ jobs:
728752
build-ubuntu,
729753
build-ubuntu-ssltests,
730754
build-android,
755+
build-ios,
731756
build-wasi,
732757
test-hypothesis,
733758
build-asan,

Apple/__main__.py

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,7 @@ def test(context: argparse.Namespace, host: str | None = None) -> None:
823823
+ [
824824
"--",
825825
"test",
826-
"--slow-ci" if context.slow else "--fast-ci",
826+
f"--{context.ci_mode}-ci",
827827
"--single-process",
828828
"--no-randomize",
829829
# Timeout handling requires subprocesses; explicitly setting
@@ -836,11 +836,39 @@ def test(context: argparse.Namespace, host: str | None = None) -> None:
836836
)
837837

838838

839+
def apple_sim_host(platform_name: str) -> str:
840+
"""Determine the native simulator target for this platform."""
841+
for _, slice_parts in HOSTS[platform_name].items():
842+
for host_triple in slice_parts:
843+
parts = host_triple.split('-')
844+
if parts[0] == platform.machine() and parts[-1] == "simulator":
845+
return host_triple
846+
847+
raise KeyError(platform_name)
848+
849+
839850
def ci(context: argparse.Namespace) -> None:
840-
"""The implementation of the "ci" command."""
851+
"""The implementation of the "ci" command.
852+
853+
In "Fast" mode, this compiles the build python, and the simulator for the
854+
build machine's architecture; and runs the test suite with `--fast-ci`
855+
configuration.
856+
857+
In "Slow" mode, it compiles the build python, plus all candidate
858+
architectures (both device and simulator); then runs the test suite with
859+
`--slow-ci` configuration.
860+
"""
841861
clean(context, "all")
842-
build(context, host="all")
843-
test(context, host="all")
862+
if context.ci_mode == "slow":
863+
# In slow mode, build and test the full XCframework
864+
build(context, host="all")
865+
test(context, host="all")
866+
else:
867+
# In fast mode, just build the simulator platform.
868+
sim_host = apple_sim_host(context.platform)
869+
build(context, host="build")
870+
build(context, host=sim_host)
871+
test(context, host=sim_host)
844872

845873

846874
def parse_args() -> argparse.Namespace:
@@ -947,11 +975,13 @@ def parse_args() -> argparse.Namespace:
947975
"an ARM64 iPhone 16 Pro simulator running iOS 26.0."
948976
),
949977
)
950-
cmd.add_argument(
951-
"--slow",
952-
action="store_true",
953-
help="Run tests with --slow-ci options.",
954-
)
978+
group = cmd.add_mutually_exclusive_group()
979+
group.add_argument(
980+
"--fast-ci", action="store_const", dest="ci_mode", const="fast",
981+
help="Add test arguments for GitHub Actions")
982+
group.add_argument(
983+
"--slow-ci", action="store_const", dest="ci_mode", const="slow",
984+
help="Add test arguments for buildbots")
955985

956986
for subcommand in [configure_build, configure_host, build, ci]:
957987
subcommand.add_argument(
@@ -1012,4 +1042,10 @@ def signal_handler(*args):
10121042

10131043

10141044
if __name__ == "__main__":
1045+
# Under the buildbot, stdout is not a TTY, but we must still flush after
1046+
# every line to make sure our output appears in the correct order relative
1047+
# to the output of our subprocesses.
1048+
for stream in [sys.stdout, sys.stderr]:
1049+
stream.reconfigure(line_buffering=True)
1050+
10151051
main()

Apple/iOS/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,17 @@ Once you have a built an XCframework, you can test that framework by running:
224224

225225
$ python Apple test iOS
226226

227+
This test will attempt to find an "SE-class" simulator (i.e., an iPhone SE, or
228+
iPhone 16e, or similar), and run the test suite on the most recent version of
229+
iOS that is available. You can specify a simulator using the `--simulator`
230+
command line argument, providing the name of the simulator (e.g., `--simulator
231+
'iPhone 16 Pro'`). You can also use this argument to control the OS version used
232+
for testing; `--simulator 'iPhone 16 Pro,OS=18.2'` would attempt to run the
233+
tests on an iPhone 16 Pro running iOS 18.2.
234+
235+
If the test runner is executed on GitHub Actions, the `GITHUB_ACTIONS`
236+
environment variable will be exposed to the iOS process at runtime.
237+
227238
### Testing a single-architecture framework
228239

229240
The `Apple/testbed` folder that contains an Xcode project that is able to run

Apple/testbed/TestbedTests/TestbedTests.m

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ - (void)testPython {
3535
setenv("NO_COLOR", "1", true);
3636
setenv("PYTHON_COLORS", "0", true);
3737

38+
if (getenv("GITHUB_ACTIONS")) {
39+
NSLog(@"Running in a GitHub Actions environment");
40+
}
3841
// Arguments to pass into the test suite runner.
3942
// argv[0] must identify the process; any subsequent arg
4043
// will be handled as if it were an argument to `python -m test`

Apple/testbed/__main__.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import argparse
22
import json
3+
import os
34
import re
45
import shutil
56
import subprocess
@@ -78,13 +79,21 @@ def xcode_test(location: Path, platform: str, simulator: str, verbose: bool):
7879
check=True,
7980
)
8081

82+
# Any environment variable prefixed with TEST_RUNNER_ is exposed into the
83+
# test runner environment. There are some variables (like those identifying
84+
# CI platforms) that can be useful to have access to.
85+
test_env = os.environ.copy()
86+
if "GITHUB_ACTIONS" in os.environ:
87+
test_env["TEST_RUNNER_GITHUB_ACTIONS"] = os.environ["GITHUB_ACTIONS"]
88+
8189
print("Running test project...")
8290
# Test execution *can't* be run -quiet; verbose mode
8391
# is how we see the output of the test output.
8492
process = subprocess.Popen(
8593
["xcodebuild", "test-without-building"] + args,
8694
stdout=subprocess.PIPE,
8795
stderr=subprocess.STDOUT,
96+
env=test_env,
8897
)
8998
while line := (process.stdout.readline()).decode(*DECODE_ARGS):
9099
# Strip the timestamp/process prefix from each log line
@@ -412,4 +421,9 @@ def main():
412421

413422

414423
if __name__ == "__main__":
424+
# Under the buildbot, stdout is not a TTY, but we must still flush after
425+
# every line to make sure our output appears in the correct order relative
426+
# to the output of our subprocesses.
427+
for stream in [sys.stdout, sys.stderr]:
428+
stream.reconfigure(line_buffering=True)
415429
main()

Doc/c-api/codec.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Codec registry and support functions
3939
*object* is passed through the decoder function found for the given
4040
*encoding* using the error handling method defined by *errors*. *errors* may
4141
be ``NULL`` to use the default method defined for the codec. Raises a
42-
:exc:`LookupError` if no encoder can be found.
42+
:exc:`LookupError` if no decoder can be found.
4343
4444
4545
Codec lookup API

Doc/c-api/dict.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ Dictionary Objects
5050
5151
.. c:function:: int PyDict_Contains(PyObject *p, PyObject *key)
5252
53-
Determine if dictionary *p* contains *key*. If an item in *p* is matches
53+
Determine if dictionary *p* contains *key*. If an item in *p* matches
5454
*key*, return ``1``, otherwise return ``0``. On error, return ``-1``.
5555
This is equivalent to the Python expression ``key in p``.
5656
@@ -198,7 +198,7 @@ Dictionary Objects
198198
.. c:function:: int PyDict_Pop(PyObject *p, PyObject *key, PyObject **result)
199199
200200
Remove *key* from dictionary *p* and optionally return the removed value.
201-
Do not raise :exc:`KeyError` if the key missing.
201+
Do not raise :exc:`KeyError` if the key is missing.
202202
203203
- If the key is present, set *\*result* to a new reference to the removed
204204
value if *result* is not ``NULL``, and return ``1``.
@@ -207,7 +207,7 @@ Dictionary Objects
207207
- On error, raise an exception and return ``-1``.
208208
209209
Similar to :meth:`dict.pop`, but without the default value and
210-
not raising :exc:`KeyError` if the key missing.
210+
not raising :exc:`KeyError` if the key is missing.
211211
212212
.. versionadded:: 3.13
213213

Doc/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,7 @@
359359
'papersize': 'a4paper',
360360
# The font size ('10pt', '11pt' or '12pt').
361361
'pointsize': '10pt',
362+
'maxlistdepth': '8', # See https://github.com/python/cpython/issues/139588
362363
}
363364

364365
# Grouping the document tree into LaTeX files. List of tuples

Doc/library/html.parser.rst

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,18 @@
1515
This module defines a class :class:`HTMLParser` which serves as the basis for
1616
parsing text files formatted in HTML (HyperText Mark-up Language) and XHTML.
1717

18-
.. class:: HTMLParser(*, convert_charrefs=True)
18+
.. class:: HTMLParser(*, convert_charrefs=True, scripting=False)
1919

2020
Create a parser instance able to parse invalid markup.
2121

22-
If *convert_charrefs* is ``True`` (the default), all character
23-
references (except the ones in ``script``/``style`` elements) are
22+
If *convert_charrefs* is true (the default), all character
23+
references (except the ones in elements like ``script`` and ``style``) are
2424
automatically converted to the corresponding Unicode characters.
2525

26+
If *scripting* is false (the default), the content of the ``noscript``
27+
element is parsed normally; if it's true, it's returned as is without
28+
being parsed.
29+
2630
An :class:`.HTMLParser` instance is fed HTML data and calls handler methods
2731
when start tags, end tags, text, comments, and other markup elements are
2832
encountered. The user should subclass :class:`.HTMLParser` and override its
@@ -37,6 +41,9 @@ parsing text files formatted in HTML (HyperText Mark-up Language) and XHTML.
3741
.. versionchanged:: 3.5
3842
The default value for argument *convert_charrefs* is now ``True``.
3943

44+
.. versionchanged:: 3.14.1
45+
Added the *scripting* parameter.
46+
4047

4148
Example HTML Parser Application
4249
-------------------------------
@@ -161,24 +168,24 @@ implementations do nothing (except for :meth:`~HTMLParser.handle_startendtag`):
161168
.. method:: HTMLParser.handle_data(data)
162169

163170
This method is called to process arbitrary data (e.g. text nodes and the
164-
content of ``<script>...</script>`` and ``<style>...</style>``).
171+
content of elements like ``script`` and ``style``).
165172

166173

167174
.. method:: HTMLParser.handle_entityref(name)
168175

169176
This method is called to process a named character reference of the form
170177
``&name;`` (e.g. ``&gt;``), where *name* is a general entity reference
171-
(e.g. ``'gt'``). This method is never called if *convert_charrefs* is
172-
``True``.
178+
(e.g. ``'gt'``).
179+
This method is only called if *convert_charrefs* is false.
173180

174181

175182
.. method:: HTMLParser.handle_charref(name)
176183

177184
This method is called to process decimal and hexadecimal numeric character
178185
references of the form :samp:`&#{NNN};` and :samp:`&#x{NNN};`. For example, the decimal
179186
equivalent for ``&gt;`` is ``&#62;``, whereas the hexadecimal is ``&#x3E;``;
180-
in this case the method will receive ``'62'`` or ``'x3E'``. This method
181-
is never called if *convert_charrefs* is ``True``.
187+
in this case the method will receive ``'62'`` or ``'x3E'``.
188+
This method is only called if *convert_charrefs* is false.
182189

183190

184191
.. method:: HTMLParser.handle_comment(data)
@@ -292,8 +299,8 @@ Parsing an element with a few attributes and a title:
292299
Data : Python
293300
End tag : h1
294301

295-
The content of ``script`` and ``style`` elements is returned as is, without
296-
further parsing:
302+
The content of elements like ``script`` and ``style`` is returned as is,
303+
without further parsing:
297304

298305
.. doctest::
299306

@@ -304,10 +311,10 @@ further parsing:
304311
End tag : style
305312

306313
>>> parser.feed('<script type="text/javascript">'
307-
... 'alert("<strong>hello!</strong>");</script>')
314+
... 'alert("<strong>hello! &#9786;</strong>");</script>')
308315
Start tag: script
309316
attr: ('type', 'text/javascript')
310-
Data : alert("<strong>hello!</strong>");
317+
Data : alert("<strong>hello! &#9786;</strong>");
311318
End tag : script
312319

313320
Parsing comments:
@@ -336,7 +343,7 @@ correct char (note: these 3 references are all equivalent to ``'>'``):
336343

337344
Feeding incomplete chunks to :meth:`~HTMLParser.feed` works, but
338345
:meth:`~HTMLParser.handle_data` might be called more than once
339-
(unless *convert_charrefs* is set to ``True``):
346+
if *convert_charrefs* is false:
340347

341348
.. doctest::
342349

Doc/library/logging.rst

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,12 +1082,13 @@ LoggerAdapter Objects
10821082
information into logging calls. For a usage example, see the section on
10831083
:ref:`adding contextual information to your logging output <context-info>`.
10841084

1085-
.. class:: LoggerAdapter(logger, extra, merge_extra=False)
1085+
.. class:: LoggerAdapter(logger, extra=None, merge_extra=False)
10861086

10871087
Returns an instance of :class:`LoggerAdapter` initialized with an
1088-
underlying :class:`Logger` instance, a dict-like object (*extra*), and a
1089-
boolean (*merge_extra*) indicating whether or not the *extra* argument of
1090-
individual log calls should be merged with the :class:`LoggerAdapter` extra.
1088+
underlying :class:`Logger` instance, an optional dict-like object (*extra*),
1089+
and an optional boolean (*merge_extra*) indicating whether or not
1090+
the *extra* argument of individual log calls should be merged with
1091+
the :class:`LoggerAdapter` extra.
10911092
The default behavior is to ignore the *extra* argument of individual log
10921093
calls and only use the one of the :class:`LoggerAdapter` instance
10931094

@@ -1127,9 +1128,13 @@ information into logging calls. For a usage example, see the section on
11271128
Attribute :attr:`!manager` and method :meth:`!_log` were added, which
11281129
delegate to the underlying logger and allow adapters to be nested.
11291130

1131+
.. versionchanged:: 3.10
1132+
1133+
The *extra* argument is now optional.
1134+
11301135
.. versionchanged:: 3.13
11311136

1132-
The *merge_extra* argument was added.
1137+
The *merge_extra* parameter was added.
11331138

11341139

11351140
Thread Safety

0 commit comments

Comments
 (0)