diff --git a/.github/workflows/pre_commit_check.yml b/.github/workflows/pre_commit_check.yml index d1d51bedaa..d821efbb57 100644 --- a/.github/workflows/pre_commit_check.yml +++ b/.github/workflows/pre_commit_check.yml @@ -23,7 +23,7 @@ jobs: - name: Set up Python environment uses: actions/setup-python@master with: - python-version: v3.8 + python-version: 3.10 - name: Install python packages run: | pip install pre-commit diff --git a/.gitlab/ci/build.yml b/.gitlab/ci/build.yml index 778edf0464..fa4797caa0 100644 --- a/.gitlab/ci/build.yml +++ b/.gitlab/ci/build.yml @@ -228,7 +228,7 @@ pytest_build_system_macos: - macos parallel: 3 variables: - PYENV_VERSION: "3.9" + PYENV_VERSION: "3.10" # CCACHE_DIR: "/cache/idf_ccache". On macOS, you cannot write to this folder due to insufficient permissions. CCACHE_DIR: "" # ccache will use "$HOME/Library/Caches/ccache". # Workaround for a bug in Parallels executor where CI_PROJECT_DIR is not an absolute path, diff --git a/.gitlab/ci/common.yml b/.gitlab/ci/common.yml index dac12555a0..5962b31ba0 100644 --- a/.gitlab/ci/common.yml +++ b/.gitlab/ci/common.yml @@ -52,9 +52,9 @@ variables: CHECKOUT_REF_SCRIPT: "$CI_PROJECT_DIR/tools/ci/checkout_project_ref.py" # Docker images - ESP_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-env-v6.0:1" - ESP_IDF_DOC_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-idf-doc-env-v6.0:1-1" - TARGET_TEST_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/target-test-env-v6.0:1" + ESP_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-env-v6.0:2" + ESP_IDF_DOC_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-idf-doc-env-v6.0:2-1" + TARGET_TEST_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/target-test-env-v6.0:2" SONARQUBE_SCANNER_IMAGE: "${CI_DOCKER_REGISTRY}/sonarqube-scanner:5" # cache python dependencies diff --git a/.gitlab/ci/host-test.yml b/.gitlab/ci/host-test.yml index b5843f2763..95cfd71e7c 100644 --- a/.gitlab/ci/host-test.yml +++ b/.gitlab/ci/host-test.yml @@ -350,7 +350,7 @@ test_pytest_macos: reports: junit: XUNIT_RESULT.xml variables: - PYENV_VERSION: "3.9" + PYENV_VERSION: "3.10" # Workaround for a bug in Parallels executor where CI_PROJECT_DIR is not an absolute path, # but a relative path to the build directory (builds/espressif/esp-idf instead of ~/builds/espressif/esp-idf. # GitLab sets the project dir to this template `//` diff --git a/.mypy.ini b/.mypy.ini index e4f451ca26..fffc03b032 100644 --- a/.mypy.ini +++ b/.mypy.ini @@ -1,7 +1,7 @@ [mypy] # Specifies the Python version used to parse and check the target program -python_version = 3.9 +python_version = 3.10 # Disallows defining functions without type annotations or with incomplete type annotations # True => enforce type annotation in all function definitions diff --git a/docs/en/api-guides/build-system.rst b/docs/en/api-guides/build-system.rst index 3d17759bfd..c99871ff52 100644 --- a/docs/en/api-guides/build-system.rst +++ b/docs/en/api-guides/build-system.rst @@ -130,7 +130,7 @@ For more detailed information about integrating ESP-IDF with CMake into an IDE, Setting up the Python Interpreter --------------------------------- -ESP-IDF works well with Python version 3.9+. +ESP-IDF works well with Python version 3.10+. ``idf.py`` and other Python scripts will run with the default Python interpreter, i.e., ``python``. You can switch to a different one like ``python3 $IDF_PATH/tools/idf.py ...``, or you can set up a shell alias or another script to simplify the command. diff --git a/docs/en/api-guides/tools/idf-docker-image.rst b/docs/en/api-guides/tools/idf-docker-image.rst index 2633a04195..5ed4b5ed62 100644 --- a/docs/en/api-guides/tools/idf-docker-image.rst +++ b/docs/en/api-guides/tools/idf-docker-image.rst @@ -1,3 +1,5 @@ +.. _idf-docker-image: + **************** IDF Docker Image **************** @@ -14,7 +16,7 @@ IDF Docker image (``espressif/idf``) is intended for building applications and l The image contains: - Common utilities such as ``git``, ``wget``, ``curl``, and ``zip``. -- Python 3.9 or newer. +- Python 3.10 or newer. - A copy of a specific version of ESP-IDF. See below for information about versions. ``IDF_PATH`` environment variable is set and points to the ESP-IDF location in the container. - All the build tools required for the specific version of ESP-IDF: CMake, Ninja, cross-compiler toolchains, etc. - All Python packages required by ESP-IDF are installed in a virtual environment. diff --git a/docs/en/get-started/linux-macos-setup.rst b/docs/en/get-started/linux-macos-setup.rst index 643f873816..a440e5a37d 100644 --- a/docs/en/get-started/linux-macos-setup.rst +++ b/docs/en/get-started/linux-macos-setup.rst @@ -98,25 +98,23 @@ Then you need to install Apple Rosetta 2 by running Installing Python 3 ~~~~~~~~~~~~~~~~~~~ -Based on macOS `Catalina 10.15 release notes`_, use of Python 2.7 is not recommended and Python 2.7 is not included by default in future versions of macOS. Check what Python you currently have:: +Ensure that you have Python 3.10 or newer installed, as this is the minimum version supported by ESP-IDF. - python --version +Note that most of the recent versions of macOS include Python 3.9 (or older) by default, which is no longer supported. You will need to install Python 3.10 or later. -If the output is like ``Python 2.7.17``, your default interpreter is Python 2.7. If so, also check if Python 3 is not already installed on your computer:: +To install supported Python 3 on macOS: - python3 --version +- With HomeBrew_, run:: -If the above command returns an error, it means Python 3 is not installed. + brew install python3 -Below is an overview of the steps to install Python 3. +- With MacPorts_, run:: - - Installing with HomeBrew_ can be done as follows:: + sudo port install python313 - brew install python3 +.. note:: - - If you have MacPorts_, you can run:: - - sudo port install python38 + During installation, the install script will check for supported Python versions on your system and select the oldest version that meets the minimum requirement. .. _get-started-get-esp-idf: diff --git a/docs/en/get-started/start-project.rst b/docs/en/get-started/start-project.rst index 800ecfe3d2..3ee0868893 100644 --- a/docs/en/get-started/start-project.rst +++ b/docs/en/get-started/start-project.rst @@ -160,7 +160,7 @@ With some Linux distributions, you may get the error message similar to ``Could Python Compatibility ~~~~~~~~~~~~~~~~~~~~ -ESP-IDF supports Python 3.9 or newer. It is recommended to upgrade your operating system to a recent version satisfying this requirement. Other options include the installation of Python from `sources `_ or the use of a Python version management system such as `pyenv `_. +ESP-IDF supports Python 3.10 or newer. It is recommended to upgrade your operating system to a recent version satisfying this requirement. Other options include the installation of Python from `sources `_ or the use of a Python version management system such as `pyenv `_. .. only:: esp32 or esp32s2 or esp32s3 diff --git a/docs/en/migration-guides/release-6.x/6.0/tools.rst b/docs/en/migration-guides/release-6.x/6.0/tools.rst index 349b6c05b2..5e6a2e5767 100644 --- a/docs/en/migration-guides/release-6.x/6.0/tools.rst +++ b/docs/en/migration-guides/release-6.x/6.0/tools.rst @@ -30,3 +30,13 @@ We recommend to use ``idf.py gdb`` instead of ``idf.py gdbgui``, or debug in Ecl All commands with eFuse functionality now require a serial port to be specified. This was done to prevent accidental use of the wrong port, as these operations are irreversible. For all ``idf.py efuse*`` commands, you now need to specify the serial port with the ``--port`` argument (or ``ESPPORT`` environment variable). If the port is not specified, the command will fail with an error message. + + +Python 3.9 Deprecation +---------------------- + +Python 3.9 is no longer supported. The minimum required Python version is now 3.10. Please upgrade your Python installation to version 3.10 or later. Alternatively, you can use the provided Docker images. For more information, see :ref:`idf-docker-image`. + +Refer to the official `Python documentation `_ for instructions on upgrading Python for your operating system. + +For Linux users, it is recommended to upgrade to a newer version of your distribution that includes a supported Python version. diff --git a/docs/zh_CN/api-guides/build-system.rst b/docs/zh_CN/api-guides/build-system.rst index 680b831fe4..9ebd7c27b0 100644 --- a/docs/zh_CN/api-guides/build-system.rst +++ b/docs/zh_CN/api-guides/build-system.rst @@ -130,7 +130,7 @@ idf.py 设置 Python 解释器 ------------------ -ESP-IDF 适用于 Python 3.9 以上版本。 +ESP-IDF 适用于 Python 3.10 以上版本。 ``idf.py`` 和其他的 Python 脚本会使用默认的 Python 解释器运行,如 ``python``。你可以通过 ``python3 $IDF_PATH/tools/idf.py ...`` 命令切换到别的 Python 解释器,或者通过设置 shell 别名或其他脚本来简化该命令。 diff --git a/docs/zh_CN/api-guides/tools/idf-docker-image.rst b/docs/zh_CN/api-guides/tools/idf-docker-image.rst index 3641297621..7803c4c105 100644 --- a/docs/zh_CN/api-guides/tools/idf-docker-image.rst +++ b/docs/zh_CN/api-guides/tools/idf-docker-image.rst @@ -1,3 +1,5 @@ +.. _idf-docker-image: + ******************** IDF Docker 镜像 ******************** @@ -14,7 +16,7 @@ IDF Docker 镜像 (``espressif/idf``) 为使用特定版本的 ESP-IDF 自动化 该镜像包含以下内容: - 常见的实用工具,如 ``git``、``wget``、``curl`` 和 ``zip``。 -- Python 3.9 或更高版本。 +- Python 3.10 或更高版本。 - 特定版本 ESP-IDF 的副本。有关版本信息,请参阅下文。该副本中设置了 ``IDF_PATH`` 环境变量,并指向容器中 ESP-IDF 的位置。 - 构建特定版本 ESP-IDF 所需工具:CMake、Ninja、交叉编译器工具链等。 - ESP-IDF 需要的所有 Python 软件包。这些软件包均已安装在虚拟环境中。 diff --git a/docs/zh_CN/get-started/linux-macos-setup.rst b/docs/zh_CN/get-started/linux-macos-setup.rst index 4fb94c33a8..ad78ae64f7 100644 --- a/docs/zh_CN/get-started/linux-macos-setup.rst +++ b/docs/zh_CN/get-started/linux-macos-setup.rst @@ -96,27 +96,25 @@ Apple M1 用户 安装 Python 3 ---------------------------------------------- +~~~~~~~~~~~~~~ -`Catalina 10.15 发布说明`_ 中表示不推荐使用 Python 2.7 版本,在未来的 macOS 版本中也不会默认包含 Python 2.7。执行以下命令来检查当前使用的 Python 版本:: +请确保已安装 Python 3.10 或更高版本。Python 3.10 为 ESP-IDF 支持的最低版本。 - python --version +请注意,大多数新版 macOS 默认仅包含 Python 3.9(或更低版本),这些版本已不再受支持,请安装 Python 3.10 或更高版本。 -如果输出结果是 ``Python 2.7.17``,则代表默认解析器是 Python 2.7。这时需要运行以下命令检查电脑上是否已经安装过 Python 3:: +请根据以下步骤在 macOS 中安装受支持的 Python 3: - python3 --version +- 若使用 HomeBrew_,请运行:: -如果运行上述命令出现错误,则代表电脑上没有安装 Python 3。 + brew install python3 -请根据以下步骤安装 Python 3: +- 若使用 MacPorts_,请运行:: - - 使用 HomeBrew_ 进行安装的方法如下:: + sudo port install python313 - brew install python3 +.. note:: - - 使用 MacPorts_ 进行安装的方法如下:: - - sudo port install python38 + 安装过程中,安装脚本 (install.sh) 会检查系统中已安装的 Python 版本,并在所有符合最低要求的版本中,选择最早的版本使用。 .. _get-started-get-esp-idf: diff --git a/docs/zh_CN/get-started/start-project.rst b/docs/zh_CN/get-started/start-project.rst index d3c17d3034..bcc0ff1d8e 100644 --- a/docs/zh_CN/get-started/start-project.rst +++ b/docs/zh_CN/get-started/start-project.rst @@ -160,7 +160,7 @@ 兼容的 Python 版本 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -ESP-IDF 支持 Python 3.9 及以上版本,建议升级操作系统到最新版本从而更新 Python。也可选择从 `sources `_ 安装最新版 Python,或使用 Python 管理系统如 `pyenv `_ 对版本进行升级管理。 +ESP-IDF 支持 Python 3.10 及以上版本,建议升级操作系统到最新版本从而更新 Python。也可选择从 `源码 `_ 安装最新版 Python,或使用 Python 管理系统如 `pyenv `_ 对版本进行升级管理。 .. only:: esp32 or esp32s2 or esp32s3 diff --git a/ruff.toml b/ruff.toml index 4d795ecbf0..9e4b8ebda6 100644 --- a/ruff.toml +++ b/ruff.toml @@ -1,5 +1,5 @@ line-length = 120 -target-version = "py38" +target-version = "py310" [format] quote-style = "single" @@ -12,6 +12,7 @@ target-version = "py38" "F", # pyflakes "W", # pycodestyle "I", # reorder-imports + "UP", # pyupgrade ] ignore = [ "E203", # whitespace before ':' diff --git a/tools/check_python_dependencies.py b/tools/check_python_dependencies.py index 77bace591e..738ad0975a 100755 --- a/tools/check_python_dependencies.py +++ b/tools/check_python_dependencies.py @@ -6,7 +6,6 @@ import argparse import os import re import sys -from typing import Optional try: from packaging.requirements import Requirement @@ -20,22 +19,9 @@ except ImportError: ) sys.exit(1) -try: - from importlib.metadata import PackageNotFoundError - from importlib.metadata import requires as _requires - from importlib.metadata import version as _version -except ImportError: - # compatibility for python <=3.7 - from importlib_metadata import PackageNotFoundError # type: ignore - from importlib_metadata import requires as _requires # type: ignore - from importlib_metadata import version as _version # type: ignore - -try: - from typing import Set -except ImportError: - # This is a script run during the early phase of setting up the environment. So try to avoid failure caused by - # Python version incompatibility. The supported Python version is checked elsewhere. - pass +from importlib.metadata import PackageNotFoundError +from importlib.metadata import requires as _requires +from importlib.metadata import version as _version PYTHON_PACKAGE_RE = re.compile(r'[^<>=~]+') @@ -50,7 +36,7 @@ def validate_requirement_list(file_path: str) -> str: ) try: open(file_path, encoding='utf-8').close() - except IOError as e: + except OSError as e: raise argparse.ArgumentTypeError(f'Cannot read requirement file {file_path}: {e}') return file_path @@ -74,7 +60,7 @@ def get_version(name: str) -> str: return version -def get_requires(name: str) -> Optional[list]: +def get_requires(name: str) -> list | None: try: requires = _requires(name) except PackageNotFoundError: @@ -118,20 +104,20 @@ if __name__ == '__main__': elif con.startswith('-e') and '#egg=' in con: con_m = re.search(r'#egg=([^\s]+)', con) if not con_m: - print('Malformed input. Cannot find name in {}'.format(con)) + print(f'Malformed input. Cannot find name in {con}') sys.exit(1) con = con_m[1] name_m = PYTHON_PACKAGE_RE.search(con) if not name_m: - print('Malformed input. Cannot find name in {}'.format(con)) + print(f'Malformed input. Cannot find name in {con}') sys.exit(1) constr_dict[name_m[0]] = con.partition(' #')[0] # remove comments not_satisfied = [] # in string form which will be printed # already_checked set is used in order to avoid circular checks which would cause looping. - already_checked: Set[Requirement] = set() + already_checked: set[Requirement] = set() # required_set contains package names in string form without version constraints. If the package has a constraint # specification (package name + version requirement) then use that instead. new_req_list is used to store @@ -198,7 +184,7 @@ if __name__ == '__main__': # We are running inside a private virtual environment under IDF_TOOLS_PATH, # ask the user to run install.bat again. install_script = 'install.bat' if sys.platform == 'win32' else 'install.sh' - print('To install the missing packages, please run "{}"'.format(install_script)) + print(f'To install the missing packages, please run "{install_script}"') else: print( 'Please follow the instructions found in the "Set up the tools" section of ' @@ -208,7 +194,7 @@ if __name__ == '__main__': print('Diagnostic information:') idf_python_env_path = os.environ.get('IDF_PYTHON_ENV_PATH') print(' IDF_PYTHON_ENV_PATH: {}'.format(idf_python_env_path or '(not set)')) - print(' Python interpreter used: {}'.format(sys.executable)) + print(f' Python interpreter used: {sys.executable}') if not idf_python_env_path or idf_python_env_path not in sys.executable: print(' Warning: python interpreter not running from IDF_PYTHON_ENV_PATH') print(' PATH: {}'.format(os.getenv('PATH'))) diff --git a/tools/ci/check_type_comments.py b/tools/ci/check_type_comments.py index 38865b0842..c452f2fc25 100755 --- a/tools/ci/check_type_comments.py +++ b/tools/ci/check_type_comments.py @@ -1,39 +1,33 @@ #!/usr/bin/env python # -# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import argparse import subprocess -from sys import exit - -try: - from typing import List -except ImportError: - # Only used for type annotations - pass +import sys IGNORE_LIST_MYPY = 'tools/ci/mypy_ignore_list.txt' -def types_valid_global_rules(file_name, ignorelisted): # type: (str, bool) -> bool +def types_valid_global_rules(file_name: str, ignorelisted: bool) -> bool: """ Run Mypy check with global rules on the given file, return TRUE if Mypy check passes """ output = subprocess.DEVNULL if ignorelisted else None - mypy_exit_code = subprocess.call('mypy {}'.format(file_name), shell=True, stdout=output) + mypy_exit_code = subprocess.call(f'mypy {file_name}', shell=True, stdout=output) return not bool(mypy_exit_code) -def types_valid_ignored_rules(file_name): # type: (str) -> bool +def types_valid_ignored_rules(file_name: str) -> bool: """ Run Mypy check with rules for ignore list on the given file, return TRUE if Mypy check passes """ - mypy_exit_code = subprocess.call('mypy {} --python-version 3.8 --allow-untyped-defs'.format(file_name), shell=True) + mypy_exit_code = subprocess.call(f'mypy {file_name} --python-version 3.10 --allow-untyped-defs', shell=True) return not bool(mypy_exit_code) -def check_files(files): # type: (List[str]) -> List[str] +def check_files(files: list[str]) -> list[str]: """ Check files for type annotatins: - new python file -> run Mypy check with global rules @@ -45,7 +39,7 @@ def check_files(files): # type: (List[str]) -> List[str] """ type_issues = [] - with open(IGNORE_LIST_MYPY, 'r') as f: + with open(IGNORE_LIST_MYPY) as f: ignore_list = [item.strip() for item in f.readlines()] updated_ignore_list = ignore_list.copy() @@ -53,7 +47,7 @@ def check_files(files): # type: (List[str]) -> List[str] if file_name in ignore_list: if types_valid_global_rules(file_name, ignorelisted=True): updated_ignore_list.remove(file_name) - print('\33[93m\n File {} removed from ignore list - run commit again! \n\33[0m'.format(file_name)) + print(f'\33[93m\n File {file_name} removed from ignore list - run commit again! \n\33[0m') continue if types_valid_ignored_rules(file_name): @@ -68,12 +62,12 @@ def check_files(files): # type: (List[str]) -> List[str] if updated_ignore_list != ignore_list: with open(IGNORE_LIST_MYPY, 'w') as f: for item in updated_ignore_list: - f.write('{}\n'.format(item)) + f.write(f'{item}\n') return type_issues -def main(): # type: () -> None +def main() -> None: parser = argparse.ArgumentParser() parser.add_argument('filenames', nargs='*', help='Filenames to check.') args = parser.parse_args() @@ -84,7 +78,7 @@ def main(): # type: () -> None print('mypy check failed for:') for file_name in type_issues: print('\t', file_name) - exit(1) + sys.exit(1) if __name__ == '__main__': diff --git a/tools/detect_python.fish b/tools/detect_python.fish index 5b53fb9ab5..8e9947f3a8 100644 --- a/tools/detect_python.fish +++ b/tools/detect_python.fish @@ -3,11 +3,11 @@ # This is a port of detect_python.sh. More information are provided there. set OLDEST_PYTHON_SUPPORTED_MAJOR 3 -set OLDEST_PYTHON_SUPPORTED_MINOR 9 +set OLDEST_PYTHON_SUPPORTED_MINOR 10 set -x ESP_PYTHON python -for p_cmd in python3 python python3.9 python3.10 python3.11 python3.12 python3.13; +for p_cmd in python3 python python3.10 python3.11 python3.12 python3.13; $p_cmd --version >/dev/null 2>&1; or continue echo "Checking \"$p_cmd\" ..." diff --git a/tools/detect_python.sh b/tools/detect_python.sh index eb3b759f92..3f84a9b91e 100644 --- a/tools/detect_python.sh +++ b/tools/detect_python.sh @@ -8,11 +8,11 @@ # 3. If required version of python is not found, script will fail OLDEST_PYTHON_SUPPORTED_MAJOR=3 -OLDEST_PYTHON_SUPPORTED_MINOR=9 +OLDEST_PYTHON_SUPPORTED_MINOR=10 ESP_PYTHON=python -for p_cmd in python3 python python3.9 python3.10 python3.11 python3.12 python3.13; do +for p_cmd in python3 python python3.10 python3.11 python3.12 python3.13; do $p_cmd --version >/dev/null 2>&1 || continue echo "Checking \"$p_cmd\" ..." diff --git a/tools/python_version_checker.py b/tools/python_version_checker.py index aadaa29df4..3797637bb8 100755 --- a/tools/python_version_checker.py +++ b/tools/python_version_checker.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD # # SPDX-License-Identifier: Apache-2.0 # @@ -8,35 +8,27 @@ # # There are related tools/detect_python.{sh,fish} scripts which are called earlier when the paths are not properly # set-up and they only intend to prefer the use of Python 3 over Python 2. Why not more? All possible executables -# (python3.9, python3.10, ...) cannot be hardcoded there and at the end, the user is responsible to set-up a system +# (python3.10, python3.11, ...) cannot be hardcoded there and at the end, the user is responsible to set-up a system # where "python" or "python3" of compatible version is available. import sys +from collections.abc import Iterable -try: - # Python 2 is not supported anymore but still the old way of typing is used here in order to give a nice Python - # version failure and not a typing exception. - from typing import Iterable -except ImportError: - pass - -OLDEST_PYTHON_SUPPORTED = (3, 9) # keep it as tuple for comparison with sys.version_info +OLDEST_PYTHON_SUPPORTED = (3, 10) # keep it as tuple for comparison with sys.version_info -def _ver_to_str(it): # type: (Iterable) -> str +def _ver_to_str(it: Iterable) -> str: return '.'.join(str(x) for x in it) -def is_supported(): # type: () -> bool +def is_supported() -> bool: return sys.version_info[:2] >= OLDEST_PYTHON_SUPPORTED[:2] -def check(): # type: () -> None +def check() -> None: if not is_supported(): raise RuntimeError( - 'ESP-IDF supports Python {} or newer but you are using Python {}. Please upgrade your ' - 'installation as described in the documentation.'.format( - _ver_to_str(OLDEST_PYTHON_SUPPORTED), _ver_to_str(sys.version_info[:3]) - ) + f'ESP-IDF supports Python {_ver_to_str(OLDEST_PYTHON_SUPPORTED)} or newer but you are using Python ' + f'{_ver_to_str(sys.version_info[:3])}. Please upgrade your installation as described in the documentation.' ) diff --git a/tools/requirements/requirements.core.txt b/tools/requirements/requirements.core.txt index 13cbb8a1e6..a944b6abe6 100644 --- a/tools/requirements/requirements.core.txt +++ b/tools/requirements/requirements.core.txt @@ -6,8 +6,6 @@ setuptools packaging -# importlib_metadata: is part of python3.8 and newer as importlib.metadata -importlib_metadata; python_version < "3.8" click pyserial cryptography