Merge branch 'fix/check_python_dependencies_v5.3' into 'release/v5.3'

fix(tools): handle packages with dots in their names during dependency checks (v5.3)

See merge request espressif/esp-idf!38063
This commit is contained in:
Roland Dobai
2025-04-21 15:49:39 +08:00

View File

@ -1,11 +1,12 @@
#!/usr/bin/env python
#
# SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
import argparse
import os
import re
import sys
from typing import Optional
try:
from packaging.requirements import Requirement
@ -17,12 +18,14 @@ except ImportError:
sys.exit(1)
try:
from importlib.metadata import requires
from importlib.metadata import version as get_version
from importlib.metadata import requires as _requires
from importlib.metadata import version as _version
from importlib.metadata import PackageNotFoundError
except ImportError:
# compatibility for python <=3.7
from importlib_metadata import requires # type: ignore
from importlib_metadata import version as get_version # type: ignore
from importlib_metadata import requires as _requires # type: ignore
from importlib_metadata import version as _version # type: ignore
from importlib_metadata import PackageNotFoundError # type: ignore
try:
from typing import Set
@ -33,6 +36,34 @@ except ImportError:
PYTHON_PACKAGE_RE = re.compile(r'[^<>=~]+')
# The version and requires function from importlib.metadata in python prior
# 3.10 does perform distribution name normalization before searching for
# package distribution. This might cause problems for package with dot in its
# name as the wheel build backend(e.g. setuptools >= 75.8.1), may perform
# distribution name normalization. If the package name is not found, try again
# with normalized name.
# https://packaging.python.org/en/latest/specifications/binary-distribution-format/#escaping-and-unicode
def normalize_name(name: str) -> str:
return re.sub(r'[-_.]+', '-', name).lower().replace('-', '_')
def get_version(name: str) -> str:
try:
version = _version(name)
except PackageNotFoundError:
version = _version(normalize_name(name))
return version
def get_requires(name: str) -> Optional[list]:
try:
requires = _requires(name)
except PackageNotFoundError:
requires = _requires(normalize_name(name))
return requires
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='ESP-IDF Python package dependency checker')
parser.add_argument('--requirements', '-r',
@ -108,7 +139,7 @@ if __name__ == '__main__':
dependency_requirements = set()
extras = list(requirement.extras) or ['']
# `requires` returns all sub-requirements including all extras - we need to filter out just required ones
for name in requires(requirement.name) or []:
for name in get_requires(requirement.name) or []:
sub_req = Requirement(name)
# check extras e.g. esptool[hsm]
for extra in extras: