1919from packaging .version import InvalidVersion , Version
2020
2121from ._compat .typing import Self , assert_never
22+ from .errors import OCIEngineTooOldError
2223from .logger import log
2324from .typing import PathOrStr , PopenBytes
2425from .util import (
@@ -95,41 +96,30 @@ def options_summary(self) -> str | dict[str, str]:
9596DEFAULT_ENGINE = OCIContainerEngineConfig ("docker" )
9697
9798
98- def _check_engine_multiarch_support (engine : OCIContainerEngineConfig ) -> bool :
99+ def _check_engine_version (engine : OCIContainerEngineConfig ) -> None :
99100 try :
100101 version_string = call (engine .name , "version" , "-f" , "{{json .}}" , capture_stdout = True )
101102 version_info = json .loads (version_string .strip ())
102103 if engine .name == "docker" :
104+ # --platform support was introduced in 1.32 as experimental
105+ # docker cp, as used by cibuildwheel, has been fixed in v24 => API 1.43, https://github.com/moby/moby/issues/38995
103106 client_api_version = Version (version_info ["Client" ]["ApiVersion" ])
104107 engine_api_version = Version (version_info ["Server" ]["ApiVersion" ])
105- multiarch_supported = min (client_api_version , engine_api_version ) >= Version ("1.32" )
106- if multiarch_supported and int (version_info ["Client" ]["Version" ].split ("." )[0 ]) < 20 :
107- # check cli version because version < 20.x consider that experimental must be turned on
108- # for --platform to be allowed.
109- multiarch_supported = version_info ["Server" ].get ("Experimental" , False )
108+ version_supported = min (client_api_version , engine_api_version ) >= Version ("1.43" )
110109 elif engine .name == "podman" :
111110 client_api_version = Version (version_info ["Client" ]["APIVersion" ])
112111 if "Server" in version_info :
113112 engine_api_version = Version (version_info ["Server" ]["APIVersion" ])
114113 else :
115114 engine_api_version = client_api_version
116- multiarch_supported = min (client_api_version , engine_api_version ) >= Version ("3" )
115+ # --platform support was introduced in v3
116+ version_supported = min (client_api_version , engine_api_version ) >= Version ("3" )
117117 else :
118118 assert_never (engine .name )
119- except subprocess .CalledProcessError :
120- log .warning (
121- f"{ engine .name } version information could not be retrieved. Assuming no multiarch support."
122- )
123- multiarch_supported = False
124- except KeyError :
125- log .warning (f"{ engine .name } version information incomplete. Assuming no multiarch support." )
126- multiarch_supported = False
127- except InvalidVersion :
128- log .warning (
129- f"{ engine .name } version information could not be parsed. Assuming no multiarch support."
130- )
131- multiarch_supported = False
132- return multiarch_supported
119+ if not version_supported :
120+ raise OCIEngineTooOldError () from None
121+ except (subprocess .CalledProcessError , KeyError , InvalidVersion ) as e :
122+ raise OCIEngineTooOldError () from e
133123
134124
135125class OCIContainer :
@@ -182,6 +172,8 @@ def __init__(
182172 def __enter__ (self ) -> Self :
183173 self .name = f"cibuildwheel-{ uuid .uuid4 ()} "
184174
175+ _check_engine_version (self .engine )
176+
185177 # work-around for Travis-CI PPC64le Docker runs since 2021:
186178 # this avoids network splits
187179 # https://github.com/pypa/cibuildwheel/issues/904
@@ -190,13 +182,9 @@ def __enter__(self) -> Self:
190182 if detect_ci_provider () == CIProvider .travis_ci and platform .machine () == "ppc64le" :
191183 network_args = ["--network=host" ]
192184
193- if _check_engine_multiarch_support (self .engine ):
194- # we need '--pull=always' otherwise some images with the wrong platform get re-used (e.g. 386 image for amd64)
195- # c.f. https://github.com/moby/moby/issues/48197#issuecomment-2282802313
196- platform_args = [f"--platform={ self .oci_platform .value } " , "--pull=always" ]
197- else :
198- platform_args = []
199- log .warning (f"{ self .engine .name } does not support multiarch images." )
185+ # we need '--pull=always' otherwise some images with the wrong platform get re-used (e.g. 386 image for amd64)
186+ # c.f. https://github.com/moby/moby/issues/48197#issuecomment-2282802313
187+ platform_args = [f"--platform={ self .oci_platform .value } " , "--pull=always" ]
200188
201189 simulate_32_bit = False
202190 if self .oci_platform == OCIPlatform .i386 :
@@ -210,8 +198,6 @@ def __enter__(self) -> Self:
210198 * run_cmd , * platform_args , self .image , * ctr_cmd , capture_stdout = True
211199 ).strip ()
212200 except subprocess .CalledProcessError :
213- if not platform_args :
214- raise
215201 # The image might have been built with amd64 architecture
216202 # Let's try that
217203 platform_args = ["--platform=linux/amd64" , * platform_args [1 :]]
0 commit comments