@@ -228,8 +228,14 @@ def update_runtime(
228228
229229 if dyn_type == "lower_bound" :
230230 all_pins .update ({pkg : f"=={ info ['lower_bound' ]} " for pkg , info in dynamic_packages .items ()})
231- else :
231+ elif dyn_type == "latest" :
232232 all_pins .update ({pkg : f"=={ int (info ['upper_bound' ].split ('.' )[0 ]) - 1 } .*" for pkg , info in dynamic_packages .items ()})
233+ else :
234+ # For "default", we still want to include the dynamic packages to get their hashes,
235+ # but we don't force a specific version if not already in base_pins.
236+ for pkg in dynamic_packages :
237+ if pkg not in all_pins :
238+ all_pins [pkg ] = ""
233239
234240 compiled : str = run_pip_compile (all_pins , python_version )
235241 base_blocks , dynamic_data = parse_compiled_requirements (compiled , set (dynamic_packages .keys ()))
@@ -260,7 +266,6 @@ def parse_requirements_template(template_path: Path) -> Dict[str, str]:
260266
261267 # Handle simple inclusions. This allows templates like requirements-3.11.in.j2
262268 # to pull in base requirements from _default_requirements.j2.
263- # Note: This is a shallow inclusion (non-recursive) suited for the current structure.
264269 includes = re .findall (r'{% include "testing/([^"]+)" %}' , content )
265270 for include in includes :
266271 pins .update (parse_requirements_template (TESTING_DIR / include ))
@@ -293,22 +298,24 @@ def main() -> None:
293298 # Dynamic packages are those whose versions are managed centrally in _pypi_packages.j2
294299 dynamic_packages : Dict [str , Dict [str , str ]] = parse_dynamic_packages ()
295300
296- # Extract base pins from the templates.
297- # Python 3.10 is typically our 'lower_bound' source.
298- # Python 3.13 is our 'latest' source for newer runtimes.
299- base_pins_lower : Dict [str , str ] = parse_requirements_template (TESTING_DIR / "requirements-3.10.in.j2" )
300- base_pins_latest : Dict [str , str ] = parse_requirements_template (TESTING_DIR / "requirements-3.13.in.j2" )
301-
302- # Define the runtime matrix: (output_template, display_label, base_pins, bounds_type, target_python)
303- runtimes : List [Tuple [str , str , Dict [str , str ], str , str ]] = [
304- ("requirements-3.10.txt.j2" , "Python 3.10" , base_pins_lower , "lower_bound" , "3.10" ),
305- ("requirements-3.11.txt.j2" , "Python 3.11" , base_pins_latest , "latest" , "3.11" ),
306- ("requirements-3.12.txt.j2" , "Python 3.12" , base_pins_latest , "latest" , "3.12" ),
307- ("requirements-3.13.txt.j2" , "Python 3.13" , base_pins_latest , "latest" , "3.13" ),
308- ("requirements-3.14.txt.j2" , "Python 3.14" , base_pins_latest , "latest" , "3.14" ),
309- ("requirements-3.15.txt.j2" , "Python 3.15" , base_pins_latest , "latest" , "3.15" ),
301+ # Define the runtime matrix: (output_template, display_label, in_template, bounds_type, target_python)
302+ # 3.10: minimum version
303+ # 3.11/3.12: default version
304+ # 3.13/3.14/3.15: latest major version
305+ runtime_configs = [
306+ ("requirements-3.10.txt.j2" , "Python 3.10" , "requirements-3.10.in.j2" , "lower_bound" , "3.10" ),
307+ ("requirements-3.11.txt.j2" , "Python 3.11" , "requirements-3.11.in.j2" , "default" , "3.11" ),
308+ ("requirements-3.12.txt.j2" , "Python 3.12" , "requirements-3.12.in.j2" , "default" , "3.12" ),
309+ ("requirements-3.13.txt.j2" , "Python 3.13" , "requirements-3.13.in.j2" , "latest" , "3.13" ),
310+ ("requirements-3.14.txt.j2" , "Python 3.14" , "requirements-3.14.in.j2" , "latest" , "3.14" ),
311+ ("requirements-3.15.txt.j2" , "Python 3.15" , "requirements-3.15.in.j2" , "latest" , "3.15" ),
310312 ]
311313
314+ runtimes = []
315+ for out_f , label , in_f , b_type , py_ver in runtime_configs :
316+ pins = parse_requirements_template (TESTING_DIR / in_f )
317+ runtimes .append ((out_f , label , pins , b_type , py_ver ))
318+
312319 # Run compilation in parallel to speed up the process.
313320 with concurrent .futures .ThreadPoolExecutor (max_workers = len (runtimes )) as executor :
314321 futures = [
0 commit comments