24
24
import json
25
25
import subprocess
26
26
import sys
27
+ import shutil
27
28
import os
28
29
import pkg_resources
29
30
58
59
59
60
# Required until Arduino switches to v5
60
61
IDF5 = platform .get_package_version ("framework-espidf" ).split ("." )[1 ].startswith ("5" )
62
+ IDF_ENV_VERSION = "1.0.0"
61
63
FRAMEWORK_DIR = platform .get_package_dir ("framework-espidf" )
62
64
TOOLCHAIN_DIR = platform .get_package_dir (
63
65
"toolchain-%s" % ("riscv32-esp" if mcu == "esp32c3" else ("xtensa-%s" % mcu ))
@@ -1097,17 +1099,13 @@ def _get_installed_pip_packages(python_exe_path):
1097
1099
# https://github.com/platformio/platformio-core/issues/4614
1098
1100
"urllib3" : "<2" ,
1099
1101
# 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" ,
1105
1107
}
1106
1108
1107
- if IDF5 :
1108
- # Remove specific versions for IDF5 as not required
1109
- deps = {dep : "" for dep in deps }
1110
-
1111
1109
python_exe_path = get_python_exe ()
1112
1110
installed_packages = _get_installed_pip_packages (python_exe_path )
1113
1111
packages_to_install = []
@@ -1151,40 +1149,71 @@ def _get_installed_pip_packages(python_exe_path):
1151
1149
)
1152
1150
)
1153
1151
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
1154
1173
1155
- def get_python_exe ():
1156
1174
def _create_venv (venv_dir ):
1157
1175
pip_path = os .path .join (
1158
1176
venv_dir ,
1159
1177
"Scripts" if IS_WINDOWS else "bin" ,
1160
1178
"pip" + (".exe" if IS_WINDOWS else "" ),
1161
1179
)
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
1168
1189
)
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" ,
1169
1197
)
1198
+ )
1170
1199
1171
1200
assert os .path .isfile (
1172
1201
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!"
1174
1203
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 )
1182
1204
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 ):
1184
1208
_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
+
1185
1213
1214
+ def get_python_exe ():
1186
1215
python_exe_path = os .path .join (
1187
- venv_dir ,
1216
+ get_idf_venv_dir () ,
1188
1217
"Scripts" if IS_WINDOWS else "bin" ,
1189
1218
"python" + (".exe" if IS_WINDOWS else "" ),
1190
1219
)
@@ -1200,6 +1229,7 @@ def _create_venv(venv_dir):
1200
1229
# ESP-IDF requires Python packages with specific versions in a virtual environment
1201
1230
#
1202
1231
1232
+ ensure_python_venv_available ()
1203
1233
install_python_deps ()
1204
1234
1205
1235
# ESP-IDF package doesn't contain .git folder, instead package version is specified
0 commit comments