This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch v3-3-test
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/v3-3-test by this push:
     new 9ba8609b05a [v3-3-test] Pin the docs build to the default Python again 
(#72690)
9ba8609b05a is described below

commit 9ba8609b05aaeb085d5596d64eb131a92565c126
Author: Jarek Potiuk <[email protected]>
AuthorDate: Tue Sep 8 12:24:02 2026 +0200

    [v3-3-test] Pin the docs build to the default Python again (#72690)
    
    `breeze build-docs` gained a --python option, and because that option reads
    PYTHON_MAJOR_MINOR_VERSION, which every job of the docs publishing workflow
    sets, the docs quietly started building on whatever the workflow happened to
    export rather than on the Python they are meant for. That is how they ended 
up
    on 3.12, where Sphinx's mocking of third-party modules makes functools.wraps
    raise and providers fail to import.
    
    Which interpreter documents Airflow is not a per-invocation choice, so the
    option is gone and the build pins itself to the default again. The workflow
    reads the same constant instead of naming a version of its own, so the 
image it
    prepares cannot drift away from the one the docs build asks for.
    (cherry picked from commit 927ebd2905aaeccd81374e0a4c95e4588083a068)
---
 .github/workflows/publish-docs-to-s3.yml           | 17 ++++++++-
 dev/breeze/doc/images/output_build-docs.svg        | 44 +++++++++-------------
 dev/breeze/doc/images/output_build-docs.txt        |  2 +-
 .../airflow_breeze/commands/developer_commands.py  | 13 ++++---
 .../commands/developer_commands_config.py          |  1 -
 dev/breeze/tests/test_developer_commands.py        | 33 ++++++++++------
 6 files changed, 63 insertions(+), 47 deletions(-)

diff --git a/.github/workflows/publish-docs-to-s3.yml 
b/.github/workflows/publish-docs-to-s3.yml
index 3192aafbd4f..7f9d805ceaa 100644
--- a/.github/workflows/publish-docs-to-s3.yml
+++ b/.github/workflows/publish-docs-to-s3.yml
@@ -96,7 +96,7 @@ jobs:
       airflow-version: ${{ steps.parameters.outputs.airflow-version }}
       # yamllint disable rule:line-length
       skip-write-to-stable-folder: ${{ inputs.skip-write-to-stable-folder && 
'--skip-write-to-stable-folder' || '' }}
-      default-python-version: "3.10"
+      default-python-version: ${{ 
steps.default_python.outputs.default-python-version }}
       registry-providers: ${{ 
steps.derive_registry_inputs.outputs.registry-providers }}
       registry-full-build: ${{ 
steps.derive_registry_inputs.outputs.registry-full-build }}
     if: contains(fromJSON('[
@@ -160,6 +160,21 @@ jobs:
             exit 0
           fi
           python3 dev/registry/derive_wave_providers.py
+      - name: "Derive the default Python version"
+        id: default_python
+        shell: bash
+        # `breeze build-docs` always documents on breeze's default Python, so 
the image this
+        # workflow builds for it has to be that same one. Reading the constant 
keeps the two from
+        # drifting apart and silently making the docs job build an image 
nothing then uses.
+        run: |
+          DEFAULT_PYTHON=$(python3 -c "
+          import re, pathlib
+          text = 
pathlib.Path('dev/breeze/src/airflow_breeze/global_constants.py').read_text()
+          versions = 
re.search(r'^ALL_PYTHON_MAJOR_MINOR_VERSIONS\s*=\s*\[(.*?)\]', text, re.M | 
re.S)
+          print(re.findall(r'\"([0-9]+\.[0-9]+)\"', versions.group(1))[0])
+          ")
+          echo "Default Python version: '${DEFAULT_PYTHON}'"
+          echo "default-python-version=${DEFAULT_PYTHON}" >> "${GITHUB_OUTPUT}"
       - name: "Input parameters summary"
         shell: bash
         id: parameters
diff --git a/dev/breeze/doc/images/output_build-docs.svg 
b/dev/breeze/doc/images/output_build-docs.svg
index ba3d9295560..172f0f6576e 100644
--- a/dev/breeze/doc/images/output_build-docs.svg
+++ b/dev/breeze/doc/images/output_build-docs.svg
@@ -1,4 +1,4 @@
-<svg class="rich-terminal" viewBox="0 0 1482 1587.1999999999998" 
xmlns="http://www.w3.org/2000/svg";>
+<svg class="rich-terminal" viewBox="0 0 1482 1538.3999999999999" 
xmlns="http://www.w3.org/2000/svg";>
     <!-- Generated with Rich https://www.textualize.io -->
     <style>
 
@@ -43,7 +43,7 @@
 
     <defs>
     <clipPath id="breeze-build-docs-clip-terminal">
-      <rect x="0" y="0" width="1463.0" height="1536.1999999999998" />
+      <rect x="0" y="0" width="1463.0" height="1487.3999999999999" />
     </clipPath>
     <clipPath id="breeze-build-docs-line-0">
     <rect x="0" y="1.5" width="1464" height="24.65"/>
@@ -225,15 +225,9 @@
 <clipPath id="breeze-build-docs-line-59">
     <rect x="0" y="1441.1" width="1464" height="24.65"/>
             </clipPath>
-<clipPath id="breeze-build-docs-line-60">
-    <rect x="0" y="1465.5" width="1464" height="24.65"/>
-            </clipPath>
-<clipPath id="breeze-build-docs-line-61">
-    <rect x="0" y="1489.9" width="1464" height="24.65"/>
-            </clipPath>
     </defs>
 
-    <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" 
x="1" y="1" width="1480" height="1585.2" rx="8"/><text 
class="breeze-build-docs-title" fill="#c5c8c6" text-anchor="middle" x="740" 
y="27">Command:&#160;build-docs</text>
+    <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" 
x="1" y="1" width="1480" height="1536.4" rx="8"/><text 
class="breeze-build-docs-title" fill="#c5c8c6" text-anchor="middle" x="740" 
y="27">Command:&#160;build-docs</text>
             <g transform="translate(26,22)">
             <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
             <circle cx="22" cy="0" r="7" fill="#febc2e"/>
@@ -289,23 +283,21 @@
 </text><text class="breeze-build-docs-r5" x="0" y="1069.2" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-43)">│</text><text 
class="breeze-build-docs-r4" x="24.4" y="1069.2" textLength="353.8" 
clip-path="url(#breeze-build-docs-line-43)">--include-removed-providers&#160;&#160;</text><text
 class="breeze-build-docs-r1" x="402.6" y="1069.2" textLength="561.2" 
clip-path="url(#breeze-build-docs-line-43)">Whether&#160;to&#160;include&#160;providers&#160;that&#160;are&#160;removed.</te
 [...]
 </text><text class="breeze-build-docs-r5" x="0" y="1093.6" textLength="1464" 
clip-path="url(#breeze-build-docs-line-44)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-build-docs-r1" x="1464" y="1093.6" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-44)">
 </text><text class="breeze-build-docs-r5" x="0" y="1118" textLength="24.4" 
clip-path="url(#breeze-build-docs-line-45)">╭─</text><text 
class="breeze-build-docs-r5" x="24.4" y="1118" textLength="170.8" 
clip-path="url(#breeze-build-docs-line-45)">&#160;Misc&#160;options&#160;</text><text
 class="breeze-build-docs-r5" x="195.2" y="1118" textLength="1244.4" 
clip-path="url(#breeze-build-docs-line-45)">──────────────────────────────────────────────────────────────────────────────────────────────
 [...]
-</text><text class="breeze-build-docs-r5" x="0" y="1142.4" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-46)">│</text><text 
class="breeze-build-docs-r4" x="24.4" y="1142.4" textLength="244" 
clip-path="url(#breeze-build-docs-line-46)">--python&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-build-docs-r6" x="292.8" y="1142.4" textLength="24.4" 
clip-path="url(#breeze-build-docs-line-46)">-p</text><text 
class="breeze-build-docs-r1 [...]
-</text><text class="breeze-build-docs-r5" x="0" y="1166.8" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-47)">│</text><text 
class="breeze-build-docs-r7" x="341.6" y="1166.8" textLength="317.2" 
clip-path="url(#breeze-build-docs-line-47)">3.11&#160;|&#160;3.12&#160;|&#160;3.13&#160;|&#160;3.14)</text><text
 class="breeze-build-docs-r5" x="1451.8" y="1166.8" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-47)">│</text><text 
class="breeze-build-docs-r1" x="1464" y="1166.8" [...]
-</text><text class="breeze-build-docs-r5" x="0" y="1191.2" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-48)">│</text><text 
class="breeze-build-docs-r4" x="24.4" y="1191.2" textLength="244" 
clip-path="url(#breeze-build-docs-line-48)">--include-commits&#160;&#160;&#160;</text><text
 class="breeze-build-docs-r1" x="341.6" y="1191.2" textLength="451.4" 
clip-path="url(#breeze-build-docs-line-48)">Include&#160;commits&#160;in&#160;the&#160;documentation.</text><text
 class="breeze-bu [...]
-</text><text class="breeze-build-docs-r5" x="0" y="1215.6" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-49)">│</text><text 
class="breeze-build-docs-r4" x="24.4" y="1215.6" textLength="244" 
clip-path="url(#breeze-build-docs-line-49)">--github-repository&#160;</text><text
 class="breeze-build-docs-r6" x="292.8" y="1215.6" textLength="24.4" 
clip-path="url(#breeze-build-docs-line-49)">-g</text><text 
class="breeze-build-docs-r1" x="341.6" y="1215.6" textLength="597.8" 
clip-path="ur [...]
-</text><text class="breeze-build-docs-r5" x="0" y="1240" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-50)">│</text><text 
class="breeze-build-docs-r4" x="24.4" y="1240" textLength="244" 
clip-path="url(#breeze-build-docs-line-50)">--builder&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-build-docs-r1" x="341.6" y="1240" textLength="768.6" 
clip-path="url(#breeze-build-docs-line-50)">Buildx&#160;builder&#160;used&#160;to&#160;perform&#
 [...]
-</text><text class="breeze-build-docs-r5" x="0" y="1264.4" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-51)">│</text><text 
class="breeze-build-docs-r7" x="341.6" y="1264.4" textLength="73.2" 
clip-path="url(#breeze-build-docs-line-51)">(TEXT)</text><text 
class="breeze-build-docs-r5" x="1451.8" y="1264.4" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-51)">│</text><text 
class="breeze-build-docs-r1" x="1464" y="1264.4" textLength="12.2" 
clip-path="url(#breeze-build-doc [...]
-</text><text class="breeze-build-docs-r5" x="0" y="1288.8" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-52)">│</text><text 
class="breeze-build-docs-r4" x="24.4" y="1288.8" textLength="244" 
clip-path="url(#breeze-build-docs-line-52)">--distributions-list</text><text 
class="breeze-build-docs-r1" x="341.6" y="1288.8" textLength="1098" 
clip-path="url(#breeze-build-docs-line-52)">Optional,&#160;contains&#160;space&#160;separated&#160;list&#160;of&#160;package&#160;ids&#160;that&#1
 [...]
-</text><text class="breeze-build-docs-r5" x="0" y="1313.2" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-53)">│</text><text 
class="breeze-build-docs-r1" x="341.6" y="1313.2" textLength="1098" 
clip-path="url(#breeze-build-docs-line-53)">documentation&#160;building,&#160;and&#160;document&#160;publishing.&#160;It&#160;is&#160;an&#160;easier&#160;alternative&#160;to&#160;adding&#160;&#160;&#160;&#160;</text><text
 class="breeze-build-docs-r5" x="1451.8" y="1313.2" textLength="12.2 [...]
-</text><text class="breeze-build-docs-r5" x="0" y="1337.6" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-54)">│</text><text 
class="breeze-build-docs-r1" x="341.6" y="1337.6" textLength="1098" 
clip-path="url(#breeze-build-docs-line-54)">individual&#160;packages&#160;as&#160;arguments&#160;to&#160;every&#160;command.&#160;This&#160;overrides&#160;the&#160;packages&#160;passed&#160;as&#160;&#160;</text><text
 class="breeze-build-docs-r5" x="1451.8" y="1337.6" textLength="12.2" cli [...]
-</text><text class="breeze-build-docs-r5" x="0" y="1362" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-55)">│</text><text 
class="breeze-build-docs-r1" x="341.6" y="1362" textLength="134.2" 
clip-path="url(#breeze-build-docs-line-55)">arguments.&#160;</text><text 
class="breeze-build-docs-r7" x="475.8" y="1362" textLength="73.2" 
clip-path="url(#breeze-build-docs-line-55)">(TEXT)</text><text 
class="breeze-build-docs-r5" x="1451.8" y="1362" textLength="12.2" 
clip-path="url(#breeze- [...]
-</text><text class="breeze-build-docs-r5" x="0" y="1386.4" textLength="1464" 
clip-path="url(#breeze-build-docs-line-56)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-build-docs-r1" x="1464" y="1386.4" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-56)">
-</text><text class="breeze-build-docs-r5" x="0" y="1410.8" textLength="24.4" 
clip-path="url(#breeze-build-docs-line-57)">╭─</text><text 
class="breeze-build-docs-r5" x="24.4" y="1410.8" textLength="195.2" 
clip-path="url(#breeze-build-docs-line-57)">&#160;Common&#160;options&#160;</text><text
 class="breeze-build-docs-r5" x="219.6" y="1410.8" textLength="1220" 
clip-path="url(#breeze-build-docs-line-57)">────────────────────────────────────────────────────────────────────────────────────────
 [...]
-</text><text class="breeze-build-docs-r5" x="0" y="1435.2" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-58)">│</text><text 
class="breeze-build-docs-r4" x="24.4" y="1435.2" textLength="109.8" 
clip-path="url(#breeze-build-docs-line-58)">--dry-run</text><text 
class="breeze-build-docs-r6" x="158.6" y="1435.2" textLength="24.4" 
clip-path="url(#breeze-build-docs-line-58)">-D</text><text 
class="breeze-build-docs-r1" x="207.4" y="1435.2" textLength="719.8" 
clip-path="url(#breeze-buil [...]
-</text><text class="breeze-build-docs-r5" x="0" y="1459.6" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-59)">│</text><text 
class="breeze-build-docs-r4" x="24.4" y="1459.6" textLength="109.8" 
clip-path="url(#breeze-build-docs-line-59)">--verbose</text><text 
class="breeze-build-docs-r6" x="158.6" y="1459.6" textLength="24.4" 
clip-path="url(#breeze-build-docs-line-59)">-v</text><text 
class="breeze-build-docs-r1" x="207.4" y="1459.6" textLength="585.6" 
clip-path="url(#breeze-buil [...]
-</text><text class="breeze-build-docs-r5" x="0" y="1484" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-60)">│</text><text 
class="breeze-build-docs-r4" x="24.4" y="1484" textLength="109.8" 
clip-path="url(#breeze-build-docs-line-60)">--answer&#160;</text><text 
class="breeze-build-docs-r6" x="158.6" y="1484" textLength="24.4" 
clip-path="url(#breeze-build-docs-line-60)">-a</text><text 
class="breeze-build-docs-r1" x="207.4" y="1484" textLength="329.4" 
clip-path="url(#breeze-build-d [...]
-</text><text class="breeze-build-docs-r5" x="0" y="1508.4" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-61)">│</text><text 
class="breeze-build-docs-r4" x="24.4" y="1508.4" textLength="109.8" 
clip-path="url(#breeze-build-docs-line-61)">--help&#160;&#160;&#160;</text><text
 class="breeze-build-docs-r6" x="158.6" y="1508.4" textLength="24.4" 
clip-path="url(#breeze-build-docs-line-61)">-h</text><text 
class="breeze-build-docs-r1" x="207.4" y="1508.4" textLength="329.4" 
clip-path="u [...]
-</text><text class="breeze-build-docs-r5" x="0" y="1532.8" textLength="1464" 
clip-path="url(#breeze-build-docs-line-62)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-build-docs-r1" x="1464" y="1532.8" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-62)">
+</text><text class="breeze-build-docs-r5" x="0" y="1142.4" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-46)">│</text><text 
class="breeze-build-docs-r4" x="24.4" y="1142.4" textLength="244" 
clip-path="url(#breeze-build-docs-line-46)">--include-commits&#160;&#160;&#160;</text><text
 class="breeze-build-docs-r1" x="341.6" y="1142.4" textLength="451.4" 
clip-path="url(#breeze-build-docs-line-46)">Include&#160;commits&#160;in&#160;the&#160;documentation.</text><text
 class="breeze-bu [...]
+</text><text class="breeze-build-docs-r5" x="0" y="1166.8" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-47)">│</text><text 
class="breeze-build-docs-r4" x="24.4" y="1166.8" textLength="244" 
clip-path="url(#breeze-build-docs-line-47)">--github-repository&#160;</text><text
 class="breeze-build-docs-r6" x="292.8" y="1166.8" textLength="24.4" 
clip-path="url(#breeze-build-docs-line-47)">-g</text><text 
class="breeze-build-docs-r1" x="341.6" y="1166.8" textLength="597.8" 
clip-path="ur [...]
+</text><text class="breeze-build-docs-r5" x="0" y="1191.2" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-48)">│</text><text 
class="breeze-build-docs-r4" x="24.4" y="1191.2" textLength="244" 
clip-path="url(#breeze-build-docs-line-48)">--builder&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</text><text
 class="breeze-build-docs-r1" x="341.6" y="1191.2" textLength="768.6" 
clip-path="url(#breeze-build-docs-line-48)">Buildx&#160;builder&#160;used&#160;to&#160;per
 [...]
+</text><text class="breeze-build-docs-r5" x="0" y="1215.6" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-49)">│</text><text 
class="breeze-build-docs-r7" x="341.6" y="1215.6" textLength="73.2" 
clip-path="url(#breeze-build-docs-line-49)">(TEXT)</text><text 
class="breeze-build-docs-r5" x="1451.8" y="1215.6" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-49)">│</text><text 
class="breeze-build-docs-r1" x="1464" y="1215.6" textLength="12.2" 
clip-path="url(#breeze-build-doc [...]
+</text><text class="breeze-build-docs-r5" x="0" y="1240" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-50)">│</text><text 
class="breeze-build-docs-r4" x="24.4" y="1240" textLength="244" 
clip-path="url(#breeze-build-docs-line-50)">--distributions-list</text><text 
class="breeze-build-docs-r1" x="341.6" y="1240" textLength="1098" 
clip-path="url(#breeze-build-docs-line-50)">Optional,&#160;contains&#160;space&#160;separated&#160;list&#160;of&#160;package&#160;ids&#160;that&#160;are
 [...]
+</text><text class="breeze-build-docs-r5" x="0" y="1264.4" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-51)">│</text><text 
class="breeze-build-docs-r1" x="341.6" y="1264.4" textLength="1098" 
clip-path="url(#breeze-build-docs-line-51)">documentation&#160;building,&#160;and&#160;document&#160;publishing.&#160;It&#160;is&#160;an&#160;easier&#160;alternative&#160;to&#160;adding&#160;&#160;&#160;&#160;</text><text
 class="breeze-build-docs-r5" x="1451.8" y="1264.4" textLength="12.2 [...]
+</text><text class="breeze-build-docs-r5" x="0" y="1288.8" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-52)">│</text><text 
class="breeze-build-docs-r1" x="341.6" y="1288.8" textLength="1098" 
clip-path="url(#breeze-build-docs-line-52)">individual&#160;packages&#160;as&#160;arguments&#160;to&#160;every&#160;command.&#160;This&#160;overrides&#160;the&#160;packages&#160;passed&#160;as&#160;&#160;</text><text
 class="breeze-build-docs-r5" x="1451.8" y="1288.8" textLength="12.2" cli [...]
+</text><text class="breeze-build-docs-r5" x="0" y="1313.2" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-53)">│</text><text 
class="breeze-build-docs-r1" x="341.6" y="1313.2" textLength="134.2" 
clip-path="url(#breeze-build-docs-line-53)">arguments.&#160;</text><text 
class="breeze-build-docs-r7" x="475.8" y="1313.2" textLength="73.2" 
clip-path="url(#breeze-build-docs-line-53)">(TEXT)</text><text 
class="breeze-build-docs-r5" x="1451.8" y="1313.2" textLength="12.2" 
clip-path="url( [...]
+</text><text class="breeze-build-docs-r5" x="0" y="1337.6" textLength="1464" 
clip-path="url(#breeze-build-docs-line-54)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-build-docs-r1" x="1464" y="1337.6" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-54)">
+</text><text class="breeze-build-docs-r5" x="0" y="1362" textLength="24.4" 
clip-path="url(#breeze-build-docs-line-55)">╭─</text><text 
class="breeze-build-docs-r5" x="24.4" y="1362" textLength="195.2" 
clip-path="url(#breeze-build-docs-line-55)">&#160;Common&#160;options&#160;</text><text
 class="breeze-build-docs-r5" x="219.6" y="1362" textLength="1220" 
clip-path="url(#breeze-build-docs-line-55)">──────────────────────────────────────────────────────────────────────────────────────────────
 [...]
+</text><text class="breeze-build-docs-r5" x="0" y="1386.4" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-56)">│</text><text 
class="breeze-build-docs-r4" x="24.4" y="1386.4" textLength="109.8" 
clip-path="url(#breeze-build-docs-line-56)">--dry-run</text><text 
class="breeze-build-docs-r6" x="158.6" y="1386.4" textLength="24.4" 
clip-path="url(#breeze-build-docs-line-56)">-D</text><text 
class="breeze-build-docs-r1" x="207.4" y="1386.4" textLength="719.8" 
clip-path="url(#breeze-buil [...]
+</text><text class="breeze-build-docs-r5" x="0" y="1410.8" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-57)">│</text><text 
class="breeze-build-docs-r4" x="24.4" y="1410.8" textLength="109.8" 
clip-path="url(#breeze-build-docs-line-57)">--verbose</text><text 
class="breeze-build-docs-r6" x="158.6" y="1410.8" textLength="24.4" 
clip-path="url(#breeze-build-docs-line-57)">-v</text><text 
class="breeze-build-docs-r1" x="207.4" y="1410.8" textLength="585.6" 
clip-path="url(#breeze-buil [...]
+</text><text class="breeze-build-docs-r5" x="0" y="1435.2" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-58)">│</text><text 
class="breeze-build-docs-r4" x="24.4" y="1435.2" textLength="109.8" 
clip-path="url(#breeze-build-docs-line-58)">--answer&#160;</text><text 
class="breeze-build-docs-r6" x="158.6" y="1435.2" textLength="24.4" 
clip-path="url(#breeze-build-docs-line-58)">-a</text><text 
class="breeze-build-docs-r1" x="207.4" y="1435.2" textLength="329.4" 
clip-path="url(#breeze [...]
+</text><text class="breeze-build-docs-r5" x="0" y="1459.6" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-59)">│</text><text 
class="breeze-build-docs-r4" x="24.4" y="1459.6" textLength="109.8" 
clip-path="url(#breeze-build-docs-line-59)">--help&#160;&#160;&#160;</text><text
 class="breeze-build-docs-r6" x="158.6" y="1459.6" textLength="24.4" 
clip-path="url(#breeze-build-docs-line-59)">-h</text><text 
class="breeze-build-docs-r1" x="207.4" y="1459.6" textLength="329.4" 
clip-path="u [...]
+</text><text class="breeze-build-docs-r5" x="0" y="1484" textLength="1464" 
clip-path="url(#breeze-build-docs-line-60)">╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯</text><text
 class="breeze-build-docs-r1" x="1464" y="1484" textLength="12.2" 
clip-path="url(#breeze-build-docs-line-60)">
 </text>
     </g>
     </g>
diff --git a/dev/breeze/doc/images/output_build-docs.txt 
b/dev/breeze/doc/images/output_build-docs.txt
index b5fd49b382b..16f4bb39a00 100644
--- a/dev/breeze/doc/images/output_build-docs.txt
+++ b/dev/breeze/doc/images/output_build-docs.txt
@@ -1 +1 @@
-f78851cc65cd841293f0487b803d51a8
+7cefd2a8c0346a060a6f76fa60f9ed3a
diff --git a/dev/breeze/src/airflow_breeze/commands/developer_commands.py 
b/dev/breeze/src/airflow_breeze/commands/developer_commands.py
index a879e1066bf..15f0f980a3b 100644
--- a/dev/breeze/src/airflow_breeze/commands/developer_commands.py
+++ b/dev/breeze/src/airflow_breeze/commands/developer_commands.py
@@ -822,7 +822,6 @@ def _build_python_docs(
     *,
     generated_path: Path,
     builder: str,
-    python: str,
     clean_build: bool,
     clean_inventory_cache: bool,
     refresh_airflow_inventories: bool,
@@ -838,9 +837,14 @@ def _build_python_docs(
     spellcheck_only: bool,
     doc_packages: tuple[str, ...],
 ):
+    # Docs are always built on the default Python. The Sphinx configuration 
mocks third-party
+    # modules, and what that mocking does depends on the interpreter - on 3.12 
functools copies
+    # __type_params__, for which a mock returns another mock rather than a 
tuple, so providers
+    # decorating methods with functools.wraps over a mocked callable fail to 
import. Letting a
+    # caller pick the interpreter here silently changes what the docs build 
can document.
     build_params = BuildCiParams(
         github_repository=github_repository,
-        python=python,
+        python=DEFAULT_PYTHON_MAJOR_MINOR_VERSION,
         builder=builder,
     )
     rebuild_or_pull_ci_image_if_needed(command_params=build_params)
@@ -895,7 +899,7 @@ def _build_python_docs(
     )
     shell_params = ShellParams(
         github_repository=github_repository,
-        python=python,
+        python=DEFAULT_PYTHON_MAJOR_MINOR_VERSION,
         mount_sources=MOUNT_ALL,
     )
     result = execute_command_in_shell(shell_params, 
project_name="breeze-docs", command=cmd)
@@ -942,7 +946,6 @@ def _build_python_docs(
 @option_github_repository
 @option_include_not_ready_providers
 @option_include_removed_providers
-@option_python
 @click.option(
     "--one-pass-only",
     help="Builds documentation in one pass only. This is useful for debugging 
sphinx errors.",
@@ -987,7 +990,6 @@ def build_docs(
     include_commits: bool,
     one_pass_only: bool,
     package_filter: tuple[str, ...],
-    python: str,
     distributions_list: str,
     spellcheck_only: bool,
     sdk: tuple[str, ...],
@@ -1018,7 +1020,6 @@ def build_docs(
             include_commits=include_commits,
             one_pass_only=one_pass_only,
             package_filter=package_filter,
-            python=python,
             distributions_list=distributions_list,
             spellcheck_only=spellcheck_only,
             doc_packages=doc_packages,
diff --git 
a/dev/breeze/src/airflow_breeze/commands/developer_commands_config.py 
b/dev/breeze/src/airflow_breeze/commands/developer_commands_config.py
index f3816139abe..17d32146110 100644
--- a/dev/breeze/src/airflow_breeze/commands/developer_commands_config.py
+++ b/dev/breeze/src/airflow_breeze/commands/developer_commands_config.py
@@ -385,7 +385,6 @@ DEVELOPER_PARAMETERS: dict[str, list[dict[str, str | 
list[str]]]] = {
         {
             "name": "Misc options",
             "options": [
-                "--python",
                 "--include-commits",
                 "--github-repository",
                 "--builder",
diff --git a/dev/breeze/tests/test_developer_commands.py 
b/dev/breeze/tests/test_developer_commands.py
index d5b0ca1a070..2336b0585ba 100644
--- a/dev/breeze/tests/test_developer_commands.py
+++ b/dev/breeze/tests/test_developer_commands.py
@@ -23,6 +23,7 @@ import pytest
 from click.testing import CliRunner
 
 from airflow_breeze.commands.developer_commands import build_docs
+from airflow_breeze.global_constants import DEFAULT_PYTHON_MAJOR_MINOR_VERSION
 
 
 @pytest.fixture
@@ -31,7 +32,12 @@ def runner():
 
 
 class TestBuildDocsPythonVersion:
-    """`breeze build-docs` must document with the Python version it was asked 
for."""
+    """`breeze build-docs` always documents on the default Python.
+
+    The Sphinx config mocks third-party modules and what that mocking does 
depends on the
+    interpreter, so the docs build must not follow whatever Python the caller 
happens to have
+    selected - see the comment in ``_build_python_docs``.
+    """
 
     @pytest.fixture(autouse=True)
     def _no_docker(self, monkeypatch):
@@ -54,15 +60,18 @@ class TestBuildDocsPythonVersion:
             runner.invoke(build_docs, args, env=env, catch_exceptions=False)
         return mock_rebuild, mock_shell
 
-    @pytest.mark.parametrize(
-        ("args", "env"),
-        [
-            pytest.param(["--python", "3.12"], None, id="python-option"),
-            pytest.param([], {"PYTHON_MAJOR_MINOR_VERSION": "3.12"}, 
id="python-env-var"),
-        ],
-    )
-    def test_selected_python_is_used_for_image_and_shell(self, runner, args, 
env):
-        mock_rebuild, mock_shell = self._invoke(runner, [*args, 
"--docs-only"], env=env)
+    def test_environment_python_does_not_change_the_docs_build(self, runner):
+        # PYTHON_MAJOR_MINOR_VERSION is set on every job of the docs 
publishing workflow, so an
+        # option reading it silently decided what the docs were built with.
+        mock_rebuild, mock_shell = self._invoke(
+            runner, ["--docs-only"], env={"PYTHON_MAJOR_MINOR_VERSION": "3.12"}
+        )
+
+        assert mock_rebuild.call_args.kwargs["command_params"].python == 
DEFAULT_PYTHON_MAJOR_MINOR_VERSION
+        assert mock_shell.call_args.args[0].python == 
DEFAULT_PYTHON_MAJOR_MINOR_VERSION
+
+    def test_python_option_is_rejected(self, runner):
+        result = runner.invoke(build_docs, ["--python", "3.12", "--docs-only"])
 
-        assert mock_rebuild.call_args.kwargs["command_params"].python == "3.12"
-        assert mock_shell.call_args.args[0].python == "3.12"
+        assert result.exit_code != 0
+        assert "no such option" in result.output.lower()

Reply via email to