From b4ce22d74e89fdd0ccb26b838e62a9e216601c0a Mon Sep 17 00:00:00 2001 From: clintonsteiner Date: Sun, 22 Feb 2026 01:25:26 -0600 Subject: [PATCH 1/7] gh-145098: Run Apple Silicon macOS CI on macos-26 (Tahoe) --- .github/workflows/build.yml | 8 ++++---- .github/workflows/jit.yml | 2 +- .github/workflows/tail-call.yml | 2 +- .../Build/2026-02-22-12-00-00.gh-issue-145098.macos26.rst | 3 +++ 4 files changed, 9 insertions(+), 6 deletions(-) create mode 100644 Misc/NEWS.d/next/Build/2026-02-22-12-00-00.gh-issue-145098.macos26.rst diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d777f35ac208fd..75d74f56924a66 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -200,10 +200,10 @@ jobs: strategy: fail-fast: false matrix: - # macos-14 is M1, macos-15-intel is Intel. + # macos-26 is Apple Silicon, macos-15-intel is Intel. # macos-15-intel only runs tests against the GIL-enabled CPython. os: - - macos-14 + - macos-26 - macos-15-intel free-threading: - false @@ -387,7 +387,7 @@ jobs: matrix: include: - arch: aarch64 - runs-on: macos-14 + runs-on: macos-26 - arch: x86_64 runs-on: ubuntu-24.04 @@ -404,7 +404,7 @@ jobs: needs: build-context if: needs.build-context.outputs.run-ios == 'true' timeout-minutes: 60 - runs-on: macos-14 + runs-on: macos-26 steps: - uses: actions/checkout@v6 with: diff --git a/.github/workflows/jit.yml b/.github/workflows/jit.yml index 9188839b26ee71..acf1df60817d58 100644 --- a/.github/workflows/jit.yml +++ b/.github/workflows/jit.yml @@ -86,7 +86,7 @@ jobs: runner: macos-15-intel - target: aarch64-apple-darwin/clang architecture: aarch64 - runner: macos-14 + runner: macos-26 - target: x86_64-unknown-linux-gnu/gcc architecture: x86_64 runner: ubuntu-24.04 diff --git a/.github/workflows/tail-call.yml b/.github/workflows/tail-call.yml index 32c6aa75e479f8..63ec5497b2c994 100644 --- a/.github/workflows/tail-call.yml +++ b/.github/workflows/tail-call.yml @@ -69,7 +69,7 @@ jobs: - target: x86_64-apple-darwin/clang runner: macos-15-intel - target: aarch64-apple-darwin/clang - runner: macos-14 + runner: macos-26 steps: - uses: actions/checkout@v6 with: diff --git a/Misc/NEWS.d/next/Build/2026-02-22-12-00-00.gh-issue-145098.macos26.rst b/Misc/NEWS.d/next/Build/2026-02-22-12-00-00.gh-issue-145098.macos26.rst new file mode 100644 index 00000000000000..3def9ed3768f07 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-02-22-12-00-00.gh-issue-145098.macos26.rst @@ -0,0 +1,3 @@ +CI now runs Apple Silicon macOS jobs on GitHub Actions ``macos-26`` (Tahoe) +instead of ``macos-14`` in the build, JIT, and tail-call workflows. +Intel-specific jobs remain on ``macos-15-intel``. From 19824ffa76f30188a38bdf9090653d731e98c7a2 Mon Sep 17 00:00:00 2001 From: clintonsteiner Date: Sun, 22 Feb 2026 01:28:42 -0600 Subject: [PATCH 2/7] ci: ios, use default xcode install --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 75d74f56924a66..54942f4b83ddaa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -417,10 +417,10 @@ jobs: # https://github.com/actions/runner-images/issues/12751. - name: Select Xcode version run: | - sudo xcode-select --switch /Applications/Xcode_15.4.app + sudo xcode-select --switch /Applications/Xcode.app - name: Build and test - run: python3 Apple ci iOS --fast-ci --simulator 'iPhone SE (3rd generation),OS=17.5' + run: python3 Apple ci iOS --fast-ci --simulator 'iPhone 17,OS=latest' build-wasi: name: 'WASI' From 8cfb4ca870b64ed2b5eaeedab95805eed8e1b656 Mon Sep 17 00:00:00 2001 From: clintonsteiner Date: Sun, 22 Feb 2026 01:37:34 -0600 Subject: [PATCH 3/7] ios: retry curl with http1.1, attempt to fix curl failure --- Apple/__main__.py | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/Apple/__main__.py b/Apple/__main__.py index 253bdfaab5520c..0c4fedd17a0f14 100644 --- a/Apple/__main__.py +++ b/Apple/__main__.py @@ -345,16 +345,36 @@ def download(url: str, target_dir: Path) -> Path: out_path = target_path / basename(url) if not Path(out_path).is_file(): - run([ - "curl", - "-Lf", - "--retry", - "5", - "--retry-all-errors", - "-o", - out_path, - url, - ]) + curl_attempts = [ + [], + # Retry over HTTP/1.1 if the initial transfer fails with a curl + # transport error (commonly seen with some runner/proxy setups). + ["--http1.1"], + ] + for i, extra_args in enumerate(curl_attempts, 1): + try: + run([ + "curl", + "-Lf", + "--retry", + "5", + "--retry-all-errors", + *extra_args, + "-o", + out_path, + url, + ]) + except CalledProcessError as exc: + if i < len(curl_attempts) and exc.returncode in {16, 56, 92}: + out_path.unlink(missing_ok=True) + print( + f"curl exited {exc.returncode}; " + "retrying download with --http1.1" + ) + continue + raise + else: + break else: print(f"Using cached version of {basename(url)}") return out_path From 9c291a4be0488f7a305ac27c5b052dec07ead71a Mon Sep 17 00:00:00 2001 From: clintonsteiner Date: Sun, 22 Feb 2026 01:44:16 -0600 Subject: [PATCH 4/7] rename news entry --- ...macos26.rst => 2026-02-22-12-00-00.gh-issue-145098.n7Qk2m.rst} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Misc/NEWS.d/next/Build/{2026-02-22-12-00-00.gh-issue-145098.macos26.rst => 2026-02-22-12-00-00.gh-issue-145098.n7Qk2m.rst} (100%) diff --git a/Misc/NEWS.d/next/Build/2026-02-22-12-00-00.gh-issue-145098.macos26.rst b/Misc/NEWS.d/next/Build/2026-02-22-12-00-00.gh-issue-145098.n7Qk2m.rst similarity index 100% rename from Misc/NEWS.d/next/Build/2026-02-22-12-00-00.gh-issue-145098.macos26.rst rename to Misc/NEWS.d/next/Build/2026-02-22-12-00-00.gh-issue-145098.n7Qk2m.rst From 90dd9aed4ddc6c5892bd49e5caa4e4267df96af8 Mon Sep 17 00:00:00 2001 From: clintonsteiner Date: Sun, 22 Feb 2026 03:12:04 -0600 Subject: [PATCH 5/7] remove news listing --- .../next/Build/2026-02-22-12-00-00.gh-issue-145098.n7Qk2m.rst | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 Misc/NEWS.d/next/Build/2026-02-22-12-00-00.gh-issue-145098.n7Qk2m.rst diff --git a/Misc/NEWS.d/next/Build/2026-02-22-12-00-00.gh-issue-145098.n7Qk2m.rst b/Misc/NEWS.d/next/Build/2026-02-22-12-00-00.gh-issue-145098.n7Qk2m.rst deleted file mode 100644 index 3def9ed3768f07..00000000000000 --- a/Misc/NEWS.d/next/Build/2026-02-22-12-00-00.gh-issue-145098.n7Qk2m.rst +++ /dev/null @@ -1,3 +0,0 @@ -CI now runs Apple Silicon macOS jobs on GitHub Actions ``macos-26`` (Tahoe) -instead of ``macos-14`` in the build, JIT, and tail-call workflows. -Intel-specific jobs remain on ``macos-15-intel``. From 27b3fa0bee3647d1b453397fea13cf24a2379adc Mon Sep 17 00:00:00 2001 From: clintonsteiner Date: Sun, 22 Feb 2026 06:58:55 -0600 Subject: [PATCH 6/7] update layout comment per pr suggestion --- Include/internal/pycore_dict.h | 7 +++++-- Objects/dictobject.c | 9 +++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Include/internal/pycore_dict.h b/Include/internal/pycore_dict.h index 59e88be6aeec12..474da75a0baa16 100644 --- a/Include/internal/pycore_dict.h +++ b/Include/internal/pycore_dict.h @@ -171,7 +171,9 @@ typedef enum { DICT_KEYS_SPLIT = 2 } DictKeysKind; -/* See dictobject.c for actual layout of DictKeysObject */ +/* See dictobject.c for the full DictKeysObject memory layout. + * A PyDictKeysObject* points to the fixed-size header below. + */ struct _dictkeysobject { Py_ssize_t dk_refcnt; @@ -211,7 +213,8 @@ struct _dictkeysobject { - 4 bytes if dk_size <= 0xffffffff (int32_t*) - 8 bytes otherwise (int64_t*) - Dynamically sized, SIZEOF_VOID_P is minimum. */ + Dynamically sized. This is the start of the variable-sized tail that + immediately follows the fixed-size header. */ char dk_indices[]; /* char is required to avoid strict aliasing. */ /* "PyDictKeyEntry or PyDictUnicodeEntry dk_entries[USABLE_FRACTION(DK_SIZE(dk))];" array follows: diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 6c802ca569d48c..e53c6deeb62e7b 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -17,6 +17,7 @@ As of Python 3.6, this is compact and ordered. Basic idea is described here: layout: +---------------------+ +| struct _dictkeysobj | | dk_refcnt | | dk_log2_size | | dk_log2_index_bytes | @@ -25,13 +26,17 @@ As of Python 3.6, this is compact and ordered. Basic idea is described here: | dk_usable | | dk_nentries | +---------------------+ -| dk_indices[] | +| dk_indices[] | <-- starts at &dk->dk_indices[0] | | +---------------------+ -| dk_entries[] | +| dk_entries[] | <-- starts at DK_ENTRIES(dk) | | +---------------------+ +A PyDictKeysObject* points to the start of the fixed-size header. +The variable-sized part begins at dk_indices and is followed immediately by +the entry array. + dk_indices is actual hashtable. It holds index in entries, or DKIX_EMPTY(-1) or DKIX_DUMMY(-2). Size of indices is dk_size. Type of each index in indices varies with dk_size: From 1bf01371d61ea68c94e2916b1f2049339dbf7a7a Mon Sep 17 00:00:00 2001 From: clintonsteiner Date: Sun, 22 Feb 2026 16:57:04 -0600 Subject: [PATCH 7/7] Revert "ios: retry curl with http1.1, attempt to fix curl failure" This reverts commit 8cfb4ca870b64ed2b5eaeedab95805eed8e1b656. ... pr comments flagged, this failure in ci could have been due to flaky issues --- Apple/__main__.py | 40 ++++++++++------------------------------ 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/Apple/__main__.py b/Apple/__main__.py index 0c4fedd17a0f14..253bdfaab5520c 100644 --- a/Apple/__main__.py +++ b/Apple/__main__.py @@ -345,36 +345,16 @@ def download(url: str, target_dir: Path) -> Path: out_path = target_path / basename(url) if not Path(out_path).is_file(): - curl_attempts = [ - [], - # Retry over HTTP/1.1 if the initial transfer fails with a curl - # transport error (commonly seen with some runner/proxy setups). - ["--http1.1"], - ] - for i, extra_args in enumerate(curl_attempts, 1): - try: - run([ - "curl", - "-Lf", - "--retry", - "5", - "--retry-all-errors", - *extra_args, - "-o", - out_path, - url, - ]) - except CalledProcessError as exc: - if i < len(curl_attempts) and exc.returncode in {16, 56, 92}: - out_path.unlink(missing_ok=True) - print( - f"curl exited {exc.returncode}; " - "retrying download with --http1.1" - ) - continue - raise - else: - break + run([ + "curl", + "-Lf", + "--retry", + "5", + "--retry-all-errors", + "-o", + out_path, + url, + ]) else: print(f"Using cached version of {basename(url)}") return out_path