2424import json
2525import subprocess
2626import sys
27+ import shutil
2728import os
2829import pkg_resources
2930
5859
5960# Required until Arduino switches to v5
6061IDF5 = platform .get_package_version ("framework-espidf" ).split ("." )[1 ].startswith ("5" )
62+ IDF_ENV_VERSION = "1.0.0"
6163FRAMEWORK_DIR = platform .get_package_dir ("framework-espidf" )
6264TOOLCHAIN_DIR = platform .get_package_dir (
6365 "toolchain-%s" % ("riscv32-esp" if mcu == "esp32c3" else ("xtensa-%s" % mcu ))
@@ -1097,17 +1099,13 @@ def _get_installed_pip_packages(python_exe_path):
10971099 # https://github.com/platformio/platformio-core/issues/4614
10981100 "urllib3" : "<2" ,
10991101 # https://github.com/platformio/platform-espressif32/issues/635
1100- "cryptography" : ">=2.1.4,<35.0.0" ,
1101- "future" : ">=0.15.2 " ,
1102- "pyparsing" : ">=2.0.3,<2.4.0" ,
1103- "kconfiglib" : "= =13.7.1" ,
1104- "idf-component-manager" : "~=1.0" ,
1102+ "cryptography" : "~=41.0.1" if IDF5 else " >=2.1.4,<35.0.0" ,
1103+ "future" : ">=0.18.3 " ,
1104+ "pyparsing" : "~=3.0.9" if IDF5 else " >=2.0.3,<2.4.0" ,
1105+ "kconfiglib" : "~=14.1.0" if IDF5 else "~ =13.7.1" ,
1106+ "idf-component-manager" : "~=1.2.3" if IDF5 else "~=1. 0" ,
11051107 }
11061108
1107- if IDF5 :
1108- # Remove specific versions for IDF5 as not required
1109- deps = {dep : "" for dep in deps }
1110-
11111109 python_exe_path = get_python_exe ()
11121110 installed_packages = _get_installed_pip_packages (python_exe_path )
11131111 packages_to_install = []
@@ -1151,40 +1149,71 @@ def _get_installed_pip_packages(python_exe_path):
11511149 )
11521150 )
11531151
1152+ def get_idf_venv_dir ():
1153+ # The name of the IDF venv contains the IDF version to avoid possible conflicts and
1154+ # unnecessary reinstallation of Python dependencies in cases when Arduino
1155+ # as an IDF component requires a different version of the IDF package and
1156+ # hence a different set of Python deps or their versions
1157+ idf_version = get_original_version (platform .get_package_version ("framework-espidf" ))
1158+ return os .path .join (
1159+ env .subst ("$PROJECT_CORE_DIR" ), "penv" , ".espidf-" + idf_version
1160+ )
1161+
1162+ def ensure_python_venv_available ():
1163+
1164+ def _is_venv_outdated (venv_data_file ):
1165+ try :
1166+ with open (venv_data_file , "r" , encoding = "utf8" ) as fp :
1167+ venv_data = json .load (fp )
1168+ if venv_data .get ("version" , "" ) != IDF_ENV_VERSION :
1169+ return True
1170+ return False
1171+ except :
1172+ return True
11541173
1155- def get_python_exe ():
11561174 def _create_venv (venv_dir ):
11571175 pip_path = os .path .join (
11581176 venv_dir ,
11591177 "Scripts" if IS_WINDOWS else "bin" ,
11601178 "pip" + (".exe" if IS_WINDOWS else "" ),
11611179 )
1162- if not os .path .isfile (pip_path ):
1163- # Use the built-in PlatformIO Python to create a standalone IDF virtual env
1164- env .Execute (
1165- env .VerboseAction (
1166- '"$PYTHONEXE" -m venv --clear "%s"' % venv_dir ,
1167- "Creating a virtual environment for IDF Python dependencies" ,
1180+
1181+ if os .path .isdir (venv_dir ):
1182+ try :
1183+ print ("Removing an oudated IDF virtual environment" )
1184+ shutil .rmtree (venv_dir )
1185+ except OSError :
1186+ print (
1187+ "Error: Cannot remove an outdated IDF virtual environment. " \
1188+ "Please remove the `%s` folder manually!" % venv_dir
11681189 )
1190+ env .Exit (1 )
1191+
1192+ # Use the built-in PlatformIO Python to create a standalone IDF virtual env
1193+ env .Execute (
1194+ env .VerboseAction (
1195+ '"$PYTHONEXE" -m venv --clear "%s"' % venv_dir ,
1196+ "Creating a new virtual environment for IDF Python dependencies" ,
11691197 )
1198+ )
11701199
11711200 assert os .path .isfile (
11721201 pip_path
1173- ), "Error: Failed to create a proper virtual environment. Missing the pip binary!"
1202+ ), "Error: Failed to create a proper virtual environment. Missing the ` pip` binary!"
11741203
1175- # The name of the IDF venv contains the IDF version to avoid possible conflicts and
1176- # unnecessary reinstallation of Python dependencies in cases when Arduino
1177- # as an IDF component requires a different version of the IDF package and
1178- # hence a different set of Python deps or their versions
1179- idf_version = get_original_version (platform .get_package_version ("framework-espidf" ))
1180- venv_dir = os .path .join (
1181- env .subst ("$PROJECT_CORE_DIR" ), "penv" , ".espidf-" + idf_version )
11821204
1183- if not os .path .isdir (venv_dir ):
1205+ venv_dir = get_idf_venv_dir ()
1206+ venv_data_file = os .path .join (venv_dir , "pio-idf-venv.json" )
1207+ if not os .path .isfile (venv_data_file ) or _is_venv_outdated (venv_data_file ):
11841208 _create_venv (venv_dir )
1209+ with open (venv_data_file , "w" , encoding = "utf8" ) as fp :
1210+ venv_info = {"version" : IDF_ENV_VERSION }
1211+ json .dump (venv_info , fp , indent = 2 )
1212+
11851213
1214+ def get_python_exe ():
11861215 python_exe_path = os .path .join (
1187- venv_dir ,
1216+ get_idf_venv_dir () ,
11881217 "Scripts" if IS_WINDOWS else "bin" ,
11891218 "python" + (".exe" if IS_WINDOWS else "" ),
11901219 )
@@ -1200,6 +1229,7 @@ def _create_venv(venv_dir):
12001229# ESP-IDF requires Python packages with specific versions in a virtual environment
12011230#
12021231
1232+ ensure_python_venv_available ()
12031233install_python_deps ()
12041234
12051235# ESP-IDF package doesn't contain .git folder, instead package version is specified
0 commit comments