Skip to content

Commit 1d768a7

Browse files
Merge branch 'main' into error-warning-argparse
2 parents 71f9d76 + b85e10f commit 1d768a7

40 files changed

+358
-119
lines changed

.github/workflows/build.yml

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

417+
build-ios:
418+
name: iOS
419+
needs: build-context
420+
if: needs.build-context.outputs.run-tests == 'true'
421+
timeout-minutes: 60
422+
runs-on: macos-15
423+
steps:
424+
- uses: actions/checkout@v4
425+
with:
426+
persist-credentials: false
427+
428+
# GitHub recommends explicitly selecting the desired Xcode version:
429+
# https://github.com/actions/runner-images/issues/12541#issuecomment-3083850140
430+
# This became a necessity as a result of
431+
# https://github.com/actions/runner-images/issues/12541 and
432+
# https://github.com/actions/runner-images/issues/12751.
433+
- name: Select Xcode version
434+
run: |
435+
sudo xcode-select --switch /Applications/Xcode_16.4.app
436+
437+
- name: Build and test
438+
run: python3 Apple ci iOS --fast-ci --simulator 'iPhone 16e,OS=18.5'
439+
417440
build-wasi:
418441
name: 'WASI'
419442
needs: build-context
@@ -723,6 +746,7 @@ jobs:
723746
- build-ubuntu-ssltests-awslc
724747
- build-ubuntu-ssltests-openssl
725748
- build-android
749+
- build-ios
726750
- build-wasi
727751
- test-hypothesis
728752
- build-asan
@@ -759,6 +783,7 @@ jobs:
759783
build-ubuntu-ssltests-awslc,
760784
build-ubuntu-ssltests-openssl,
761785
build-android,
786+
build-ios,
762787
build-wasi,
763788
test-hypothesis,
764789
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/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

Include/pyport.h

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -509,23 +509,18 @@ extern "C" {
509509
#endif
510510

511511
#ifdef WITH_THREAD
512-
# ifdef Py_BUILD_CORE
513-
# ifdef HAVE_THREAD_LOCAL
514-
# error "HAVE_THREAD_LOCAL is already defined"
515-
# endif
516-
# define HAVE_THREAD_LOCAL 1
517-
# ifdef thread_local
518-
# define _Py_thread_local thread_local
519-
# elif __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__)
520-
# define _Py_thread_local _Thread_local
521-
# elif defined(_MSC_VER) /* AKA NT_THREADS */
522-
# define _Py_thread_local __declspec(thread)
523-
# elif defined(__GNUC__) /* includes clang */
524-
# define _Py_thread_local __thread
525-
# else
526-
// fall back to the PyThread_tss_*() API, or ignore.
527-
# undef HAVE_THREAD_LOCAL
528-
# endif
512+
// HAVE_THREAD_LOCAL is just defined here for compatibility's sake
513+
# define HAVE_THREAD_LOCAL 1
514+
# ifdef thread_local
515+
# define _Py_thread_local thread_local
516+
# elif __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__)
517+
# define _Py_thread_local _Thread_local
518+
# elif defined(_MSC_VER) /* AKA NT_THREADS */
519+
# define _Py_thread_local __declspec(thread)
520+
# elif defined(__GNUC__) /* includes clang */
521+
# define _Py_thread_local __thread
522+
# else
523+
# error "no supported thread-local variable storage classifier"
529524
# endif
530525
#endif
531526

Lib/linecache.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,12 @@ def updatecache(filename, module_globals=None):
123123
if _source_unavailable(filename):
124124
return []
125125

126-
if filename.startswith('<frozen ') and module_globals is not None:
126+
if filename.startswith('<frozen '):
127127
# This is a frozen module, so we need to use the filename
128128
# from the module globals.
129+
if module_globals is None:
130+
return []
131+
129132
fullname = module_globals.get('__file__')
130133
if fullname is None:
131134
return []

Lib/os.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,7 @@ def reload_environ():
832832
env_data.clear()
833833
env_data.update(data)
834834

835+
__all__.append("reload_environ")
835836

836837
def getenv(key, default=None):
837838
"""Get an environment variable, return None if it doesn't exist.

Lib/pdb.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3577,7 +3577,13 @@ def main():
35773577
parser.error("argument -m: not allowed with argument --pid")
35783578
try:
35793579
attach(opts.pid, opts.commands)
3580-
except PermissionError as e:
3580+
except RuntimeError:
3581+
print(
3582+
f"Cannot attach to pid {opts.pid}, please make sure that the process exists "
3583+
"and is using the same Python version."
3584+
)
3585+
sys.exit(1)
3586+
except PermissionError:
35813587
exit_with_permission_help_text()
35823588
return
35833589
elif opts.module:

0 commit comments

Comments
 (0)