mirror of
https://github.com/apache/airflow.git
synced 2026-11-04 07:12:48 +00:00
* Skip provider tests when all test directories are excluded When running Providers[google] or Providers[amazon] on Python 3.14, generate_args_for_pytest removes the test folders for excluded providers, but the skip check in _run_test only triggered when the --ignore filter itself removed something. Since the folders were already removed upstream, the guard condition was never met, leaving pytest with only flags and no test directories — causing it to crash on unrecognized custom arguments. Remove the overly strict guard so the skip fires whenever no test directories remain in the args. * Fix PROD image docker tests for Python-version-excluded providers The docker tests expected all providers from prod_image_installed_providers.txt to be present, but providers like google and amazon declare excluded-python-versions in their provider.yaml. On Python 3.14, these providers are correctly excluded from the PROD image at build time, but the tests didn't account for this. Read provider.yaml exclusions and filter expected providers/imports based on the Docker image's Python version. * Skip Python-incompatible provider wheels during PROD image build get_distribution_specs.py now reads Requires-Python metadata from each wheel and skips wheels that are incompatible with the running interpreter. This prevents excluded providers (e.g. amazon on 3.14) from being passed to pip/uv and installed despite their exclusion. Also fix the requires-python specifier generation in packages.py: !=3.14 per PEP 440 only excludes 3.14.0, not 3.14.2. Use !=3.14.* wildcard to exclude the entire minor version.
73 lines
2.8 KiB
Python
Executable File
73 lines
2.8 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
# or more contributor license agreements. See the NOTICE file
|
|
# distributed with this work for additional information
|
|
# regarding copyright ownership. The ASF licenses this file
|
|
# to you under the Apache License, Version 2.0 (the
|
|
# "License"); you may not use this file except in compliance
|
|
# with the License. You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing,
|
|
# software distributed under the License is distributed on an
|
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
# KIND, either express or implied. See the License for the
|
|
# specific language governing permissions and limitations
|
|
# under the License.
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import sys
|
|
import zipfile
|
|
from email.parser import HeaderParser
|
|
from pathlib import Path
|
|
|
|
from packaging.specifiers import InvalidSpecifier, SpecifierSet
|
|
from packaging.utils import (
|
|
InvalidSdistFilename,
|
|
InvalidWheelFilename,
|
|
parse_sdist_filename,
|
|
parse_wheel_filename,
|
|
)
|
|
|
|
_CURRENT_PYTHON = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
|
|
|
|
|
|
def _compatible_with_current_python(wheel_path: str) -> bool:
|
|
"""Return False if the wheel's Requires-Python excludes the running interpreter."""
|
|
try:
|
|
with zipfile.ZipFile(wheel_path) as zf:
|
|
for name in zf.namelist():
|
|
if name.endswith(".dist-info/METADATA"):
|
|
requires = HeaderParser().parsestr(zf.read(name).decode("utf-8")).get("Requires-Python")
|
|
if requires:
|
|
return _CURRENT_PYTHON in SpecifierSet(requires)
|
|
return True
|
|
except (zipfile.BadZipFile, InvalidSpecifier, KeyError) as exc:
|
|
print(f"Warning: could not check Requires-Python for {wheel_path}: {exc}", file=sys.stderr)
|
|
return True
|
|
|
|
|
|
def print_package_specs(extras: str = "") -> None:
|
|
for package_path in sys.argv[1:]:
|
|
try:
|
|
package, _, _, _ = parse_wheel_filename(Path(package_path).name)
|
|
except InvalidWheelFilename:
|
|
try:
|
|
package, _ = parse_sdist_filename(Path(package_path).name)
|
|
except InvalidSdistFilename:
|
|
print(f"Could not parse package name from {package_path}", file=sys.stderr)
|
|
continue
|
|
if package_path.endswith(".whl") and not _compatible_with_current_python(package_path):
|
|
print(
|
|
f"Skipping {package} (Requires-Python not satisfied by {_CURRENT_PYTHON})",
|
|
file=sys.stderr,
|
|
)
|
|
continue
|
|
print(f"{package}{extras} @ file://{package_path}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print_package_specs(extras=os.environ.get("EXTRAS", ""))
|