Skip to content

Commit b82ee36

Browse files
committed
Merge branch 'master' into use-native-endianness-in-ctypes/112014
2 parents feb9f5a + 6d2b551 commit b82ee36

55 files changed

Lines changed: 780 additions & 211 deletions

Some content is hidden

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

.github/workflows/build.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,12 @@ jobs:
245245
os: ${{ matrix.os }}
246246
test-opts: ${{ matrix.test-opts || '' }}
247247

248+
build-ubuntu-installed:
249+
name: 'Ubuntu (installed)'
250+
needs: build-context
251+
if: needs.build-context.outputs.run-ubuntu == 'true'
252+
uses: ./.github/workflows/reusable-install.yml
253+
248254
build-ubuntu-ssltests:
249255
name: 'Ubuntu SSL tests'
250256
runs-on: ${{ matrix.os }}
@@ -636,6 +642,7 @@ jobs:
636642
- build-windows
637643
- build-macos
638644
- build-ubuntu
645+
- build-ubuntu-installed
639646
- build-ubuntu-ssltests
640647
- build-ios
641648
- build-emscripten
@@ -685,6 +692,7 @@ jobs:
685692
!fromJSON(needs.build-context.outputs.run-ubuntu)
686693
&& '
687694
build-ubuntu,
695+
build-ubuntu-installed,
688696
build-ubuntu-ssltests,
689697
test-hypothesis,
690698
build-asan,

.github/workflows/reusable-check-html-ids.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ jobs:
2020
with:
2121
persist-credentials: false
2222
ref: ${{ github.event.pull_request.head.sha }}
23+
- name: 'Downgrade Git'
24+
# Temporarily downgrade to 2.43 until 2.55 is in the runner image,
25+
# to avoid "fatal: shallow file has changed since we read it" bug.
26+
# See https://github.com/python/cpython/issues/151365.
27+
run: |
28+
sudo apt-get install -y --allow-downgrades 'git=1:2.43.*' 'git-man=1:2.43.*'
29+
git --version
2330
- name: 'Find merge base'
2431
id: merge-base
2532
run: |

.github/workflows/reusable-context.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,15 @@ jobs:
9090
|| ''
9191
}}
9292
93+
- name: 'Downgrade Git'
94+
# Temporarily downgrade to 2.43 until 2.55 is in the runner image,
95+
# to avoid "fatal: shallow file has changed since we read it" bug.
96+
# See https://github.com/python/cpython/issues/151365.
97+
if: github.event_name == 'pull_request'
98+
run: |
99+
sudo apt-get install -y --allow-downgrades 'git=1:2.43.*' 'git-man=1:2.43.*'
100+
git --version
101+
93102
# Adapted from https://github.com/actions/checkout/issues/520#issuecomment-1167205721
94103
- name: Fetch commits to get branch diff
95104
if: github.event_name == 'pull_request'

.github/workflows/reusable-docs.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ jobs:
4747
&& github.event.pull_request.head.sha
4848
|| ''
4949
}}
50+
- name: 'Downgrade Git'
51+
# Temporarily downgrade to 2.43 until 2.55 is in the runner image,
52+
# to avoid "fatal: shallow file has changed since we read it" bug.
53+
# See https://github.com/python/cpython/issues/151365.
54+
if: github.event_name == 'pull_request'
55+
run: |
56+
sudo apt-get install -y --allow-downgrades 'git=1:2.43.*' 'git-man=1:2.43.*'
57+
git --version
5058
# Adapted from https://github.com/actions/checkout/issues/520#issuecomment-1167205721
5159
- name: 'Fetch commits to get branch diff'
5260
if: github.event_name == 'pull_request'
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: Reusable Ubuntu (installed)
2+
3+
on:
4+
workflow_call:
5+
6+
permissions:
7+
contents: read
8+
9+
env:
10+
FORCE_COLOR: 1
11+
12+
jobs:
13+
build-install-test:
14+
name: build, install and test
15+
runs-on: ubuntu-26.04-arm
16+
timeout-minutes: 60
17+
env:
18+
PYTHONSTRICTEXTENSIONBUILD: 1
19+
steps:
20+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
21+
with:
22+
persist-credentials: false
23+
- name: Register gcc problem matcher
24+
run: echo "::add-matcher::.github/problem-matchers/gcc.json"
25+
- name: Set install dir
26+
run:
27+
echo "INSTALL_DIR=$(realpath "${GITHUB_WORKSPACE}/../installed-python")" >> "$GITHUB_ENV"
28+
- name: Install dependencies
29+
run: sudo ./.github/workflows/posix-deps-apt.sh
30+
- name: Configure CPython
31+
run: ./configure --config-cache --prefix="$INSTALL_DIR"
32+
- name: Build CPython
33+
run: make -j
34+
- name: Install CPython
35+
run: make install
36+
- name: Set installed interpreter
37+
run: |
38+
ldversion=$(./python -c 'import sysconfig; print(sysconfig.get_config_var("LDVERSION"))')
39+
echo "INSTALLED_PYTHON=${INSTALL_DIR}/bin/python${ldversion}" >> "$GITHUB_ENV"
40+
- name: Display build info
41+
run: |
42+
"$INSTALLED_PYTHON" -m test.pythoninfo
43+
- name: Test the installed Python
44+
run: xvfb-run "$INSTALLED_PYTHON" -m test --fast-ci --timeout=900

Doc/c-api/capsule.rst

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -108,25 +108,20 @@ Refer to :ref:`using-capsules` for more information on using these objects.
108108
109109
Import a pointer to a C object from a capsule attribute in a module. The
110110
*name* parameter should specify the full name to the attribute, as in
111-
``module.attribute``. The *name* stored in the capsule must match this
112-
string exactly.
113-
114-
This function splits *name* on the ``.`` character, and imports the first
115-
element. It then processes further elements using attribute lookups.
111+
``package.module.attribute``.
112+
Modules are imported if needed,
113+
other components are looked up as attributes.
114+
The *name* stored in the capsule must match this string exactly.
116115
117116
Return the capsule's internal *pointer* on success. On failure, set an
118117
exception and return ``NULL``.
119118
120-
.. note::
121-
122-
If *name* points to an attribute of some submodule or subpackage, this
123-
submodule or subpackage must be previously imported using other means
124-
(for example, by using :c:func:`PyImport_ImportModule`) for the
125-
attribute lookups to succeed.
126-
127119
.. versionchanged:: 3.3
128120
*no_block* has no effect anymore.
129121
122+
.. versionchanged:: next
123+
Submodules are now imported if needed.
124+
130125
131126
.. c:function:: int PyCapsule_IsValid(PyObject *capsule, const char *name)
132127

Doc/library/asyncio-task.rst

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -668,12 +668,12 @@ Eager task factory
668668
Shielding from cancellation
669669
===========================
670670

671-
.. awaitablefunction:: shield(aw)
671+
.. awaitablefunction:: shield(arg)
672672

673673
Protect an :ref:`awaitable object <asyncio-awaitables>`
674674
from being :meth:`cancelled <Task.cancel>`.
675675

676-
If *aw* is a coroutine it is automatically scheduled as a Task.
676+
If *arg* is a coroutine it is automatically scheduled as a Task.
677677

678678
The statement::
679679

@@ -714,7 +714,7 @@ Shielding from cancellation
714714
Removed the *loop* parameter.
715715

716716
.. deprecated:: 3.10
717-
Deprecation warning is emitted if *aw* is not Future-like object
717+
Deprecation warning is emitted if *arg* is not Future-like object
718718
and there is no running event loop.
719719

720720

@@ -837,13 +837,13 @@ Timeouts
837837

838838
.. versionadded:: 3.11
839839

840-
.. function:: wait_for(aw, timeout)
840+
.. function:: wait_for(fut, timeout)
841841
:async:
842842

843-
Wait for the *aw* :ref:`awaitable <asyncio-awaitables>`
843+
Wait for the *fut* :ref:`awaitable <asyncio-awaitables>`
844844
to complete with a timeout.
845845

846-
If *aw* is a coroutine it is automatically scheduled as a Task.
846+
If *fut* is a coroutine it is automatically scheduled as a Task.
847847

848848
*timeout* can either be ``None`` or a float or int number of seconds
849849
to wait for. If *timeout* is ``None``, block until the future
@@ -859,7 +859,7 @@ Timeouts
859859
so the total wait time may exceed the *timeout*. If an exception
860860
happens during cancellation, it is propagated.
861861

862-
If the wait is cancelled, the future *aw* is also cancelled.
862+
If the wait is cancelled, the future *fut* is also cancelled.
863863

864864
.. _asyncio_example_waitfor:
865865

@@ -884,8 +884,8 @@ Timeouts
884884
# timeout!
885885

886886
.. versionchanged:: 3.7
887-
When *aw* is cancelled due to a timeout, ``wait_for`` waits
888-
for *aw* to be cancelled. Previously, it raised
887+
When *fut* is cancelled due to a timeout, ``wait_for`` waits
888+
for *fut* to be cancelled. Previously, it raised
889889
:exc:`TimeoutError` immediately.
890890

891891
.. versionchanged:: 3.10
@@ -898,20 +898,20 @@ Timeouts
898898
Waiting primitives
899899
==================
900900

901-
.. function:: wait(aws, *, timeout=None, return_when=ALL_COMPLETED)
901+
.. function:: wait(fs, *, timeout=None, return_when=ALL_COMPLETED)
902902
:async:
903903

904-
Run :class:`~asyncio.Future` and :class:`~asyncio.Task` instances in the *aws*
904+
Run :class:`~asyncio.Future` and :class:`~asyncio.Task` instances in the *fs*
905905
iterable concurrently and block until the condition specified
906906
by *return_when*.
907907

908-
The *aws* iterable must not be empty.
908+
The *fs* iterable must not be empty.
909909

910910
Returns two sets of Tasks/Futures: ``(done, pending)``.
911911

912912
Usage::
913913

914-
done, pending = await asyncio.wait(aws)
914+
done, pending = await asyncio.wait(fs)
915915

916916
*timeout* (a float or int), if specified, can be used to control
917917
the maximum number of seconds to wait before returning.
@@ -943,7 +943,7 @@ Waiting primitives
943943
Unlike :func:`~asyncio.wait_for`, ``wait()`` does not cancel the
944944
futures when a timeout occurs.
945945

946-
If ``wait()`` is cancelled, the futures in *aws* are not cancelled
946+
If ``wait()`` is cancelled, the futures in *fs* are not cancelled
947947
and continue to run.
948948

949949
.. versionchanged:: 3.10
@@ -956,9 +956,9 @@ Waiting primitives
956956
Added support for generators yielding tasks.
957957

958958

959-
.. function:: as_completed(aws, *, timeout=None)
959+
.. function:: as_completed(fs, *, timeout=None)
960960

961-
Run :ref:`awaitable objects <asyncio-awaitables>` in the *aws* iterable
961+
Run :ref:`awaitable objects <asyncio-awaitables>` in the *fs* iterable
962962
concurrently. The returned object can be iterated to obtain the results
963963
of the awaitables as they finish.
964964

@@ -1011,7 +1011,7 @@ Waiting primitives
10111011
Removed the *loop* parameter.
10121012

10131013
.. deprecated:: 3.10
1014-
Deprecation warning is emitted if not all awaitable objects in the *aws*
1014+
Deprecation warning is emitted if not all awaitable objects in the *fs*
10151015
iterable are Future-like objects and there is no running event loop.
10161016

10171017
.. versionchanged:: 3.12

Doc/library/os.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ process and user.
452452
process. For most purposes, it is more useful to use
453453
:func:`getpass.getuser` since the latter checks the environment variables
454454
:envvar:`LOGNAME` or :envvar:`USERNAME` to find out who the user is, and
455-
falls back to ``pwd.getpwuid(os.getuid())[0]`` to get the login name of the
455+
falls back to ``pwd.getpwuid(os.getuid()).pw_name`` to get the login name of the
456456
current real user id.
457457

458458
.. availability:: Unix, Windows, not WASI.

Lib/contextlib.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -199,22 +199,20 @@ def __enter__(self):
199199
# do not keep args and kwds alive unnecessarily
200200
# they are only needed for recreation, which is not possible anymore
201201
del self.args, self.kwds, self.func
202-
try:
203-
return next(self.gen)
204-
except StopIteration:
205-
raise RuntimeError("generator didn't yield") from None
202+
# Slightly faster way to return next(self.gen):
203+
for once in self.gen:
204+
return once
205+
raise RuntimeError("generator didn't yield")
206206

207207
def __exit__(self, typ, value, traceback):
208208
if typ is None:
209-
try:
210-
next(self.gen)
211-
except StopIteration:
212-
return False
213-
else:
209+
# Faster way to run next(self.gen) and check for StopIteration:
210+
for _ in self.gen:
214211
try:
215212
raise RuntimeError("generator didn't stop")
216213
finally:
217214
self.gen.close()
215+
return False
218216
else:
219217
if value is None:
220218
# Need to force instantiation so we can reliably

Lib/getpass.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ def getuser():
428428

429429
try:
430430
import pwd
431-
return pwd.getpwuid(os.getuid())[0]
431+
return pwd.getpwuid(os.getuid()).pw_name
432432
except (ImportError, KeyError) as e:
433433
raise OSError('No username set in the environment') from e
434434

0 commit comments

Comments
 (0)