More usage of python3 features (#1636)

Mostly f-strings, but a few others too.
This commit is contained in:
Sam Clegg
2025-12-01 17:11:00 -08:00
committed by GitHub
parent a040059ae2
commit 6e4471361a
2 changed files with 86 additions and 111 deletions

196
emsdk.py
View File

@@ -26,10 +26,9 @@ if os.name == 'nt':
from urllib.parse import urljoin from urllib.parse import urljoin
from urllib.request import urlopen from urllib.request import urlopen
import functools
if sys.version_info < (3, 0): if sys.version_info < (3, 2):
print(f'error: emsdk requires python 3.0 or above ({sys.executable} {sys.version})', file=sys.stderr) print(f'error: emsdk requires python 3.2 or above ({sys.executable} {sys.version})', file=sys.stderr)
sys.exit(1) sys.exit(1)
emsdk_packages_url = 'https://storage.googleapis.com/webassembly/emscripten-releases-builds/deps/' emsdk_packages_url = 'https://storage.googleapis.com/webassembly/emscripten-releases-builds/deps/'
@@ -203,17 +202,17 @@ def parse_github_url_and_refspec(url):
return ('', '', None) return ('', '', None)
if url.endswith(('/tree/', '/tree', '/commit/', '/commit')): if url.endswith(('/tree/', '/tree', '/commit/', '/commit')):
raise Exception('Malformed git URL and refspec ' + url + '!') raise Exception(f'Malformed git URL and refspec {url}!')
if '/tree/' in url: if '/tree/' in url:
if url.endswith('/'): if url.endswith('/'):
raise Exception('Malformed git URL and refspec ' + url + '!') raise Exception(f'Malformed git URL and refspec {url}!')
url, refspec = url.split('/tree/') url, refspec = url.split('/tree/')
remote_name = url.split('/')[-2] remote_name = url.split('/')[-2]
return (url, refspec, remote_name) return (url, refspec, remote_name)
elif '/commit/' in url: elif '/commit/' in url:
if url.endswith('/'): if url.endswith('/'):
raise Exception('Malformed git URL and refspec ' + url + '!') raise Exception(f'Malformed git URL and refspec {url}!')
url, refspec = url.split('/commit/') url, refspec = url.split('/commit/')
remote_name = url.split('/')[-2] remote_name = url.split('/')[-2]
return (url, refspec, remote_name) return (url, refspec, remote_name)
@@ -340,13 +339,13 @@ def win_set_environment_variable_direct(key, value, system=True):
# Register locally from CURRENT USER section. # Register locally from CURRENT USER section.
folder = winreg.OpenKeyEx(winreg.HKEY_CURRENT_USER, 'Environment', 0, winreg.KEY_ALL_ACCESS) folder = winreg.OpenKeyEx(winreg.HKEY_CURRENT_USER, 'Environment', 0, winreg.KEY_ALL_ACCESS)
winreg.SetValueEx(folder, key, 0, winreg.REG_EXPAND_SZ, value) winreg.SetValueEx(folder, key, 0, winreg.REG_EXPAND_SZ, value)
debug_print('Set key=' + key + ' with value ' + value + ' in registry.') debug_print(f'Set key={key} with value {value} in registry.')
return True return True
except Exception as e: except Exception as e:
# 'Access is denied.' # 'Access is denied.'
if e.args[3] == 5: if e.args[3] == 5:
exit_with_error('failed to set the environment variable \'' + key + '\'! Setting environment variables permanently requires administrator access. Please rerun this command with administrative privileges. This can be done for example by holding down the Ctrl and Shift keys while opening a command prompt in start menu.') exit_with_error(f'failed to set the environment variable \'{key}\'! Setting environment variables permanently requires administrator access. Please rerun this command with administrative privileges. This can be done for example by holding down the Ctrl and Shift keys while opening a command prompt in start menu.')
errlog('Failed to write environment variable ' + key + ':') errlog(f'Failed to write environment variable {key}:')
errlog(str(e)) errlog(str(e))
return False return False
finally: finally:
@@ -384,7 +383,7 @@ def win_get_environment_variable(key, system=True, user=True, fallback=True):
# this catch is if both the registry key threw an exception and the key is not in os.environ # this catch is if both the registry key threw an exception and the key is not in os.environ
if e.args[0] != 2: if e.args[0] != 2:
# 'The system cannot find the file specified.' # 'The system cannot find the file specified.'
errlog('Failed to read environment variable ' + key + ':') errlog(f'Failed to read environment variable {key}:')
errlog(str(e)) errlog(str(e))
return None return None
return value return value
@@ -416,16 +415,16 @@ def win_set_environment_variable(key, value, system, user):
# Escape % signs so that we don't expand references to environment variables. # Escape % signs so that we don't expand references to environment variables.
value = value.replace('%', '^%') value = value.replace('%', '^%')
if len(value) >= 1024: if len(value) >= 1024:
exit_with_error('the new environment variable ' + key + ' is more than 1024 characters long! A value this long cannot be set via command line: please add the environment variable specified above to system environment manually via Control Panel.') exit_with_error(f'the new environment variable {key} is more than 1024 characters long! A value this long cannot be set via command line: please add the environment variable specified above to system environment manually via Control Panel.')
cmd = ['SETX', key, value] cmd = ['SETX', key, value]
debug_print(str(cmd)) debug_print(str(cmd))
retcode = subprocess.call(cmd, stdout=subprocess.PIPE) retcode = subprocess.call(cmd, stdout=subprocess.PIPE)
if retcode != 0: if retcode != 0:
errlog('ERROR! Failed to set environment variable ' + key + '=' + value + '. You may need to set it manually.') errlog(f'ERROR! Failed to set environment variable {key}={value}. You may need to set it manually.')
else: else:
return True return True
except Exception as e: except Exception as e:
errlog('ERROR! Failed to set environment variable ' + key + '=' + value + ':') errlog(f'ERROR! Failed to set environment variable {key}={value}:')
errlog(str(e)) errlog(str(e))
errlog('You may need to set it manually.') errlog('You may need to set it manually.')
@@ -467,7 +466,7 @@ def win_set_environment_variables(env_vars_to_add, system, user):
def win_delete_environment_variable(key, system=True, user=True): def win_delete_environment_variable(key, system=True, user=True):
debug_print('win_delete_environment_variable(key=' + key + ', system=' + str(system) + ')') debug_print(f'win_delete_environment_variable(key={key}, system={system})')
return win_set_environment_variable(key, None, system, user) return win_set_environment_variable(key, None, system, user)
@@ -481,19 +480,14 @@ def sdk_path(path):
# Removes a single file, suppressing exceptions on failure. # Removes a single file, suppressing exceptions on failure.
def rmfile(filename): def rmfile(filename):
debug_print('rmfile(' + filename + ')') debug_print(f'rmfile({filename})')
if os.path.lexists(filename): if os.path.lexists(filename):
os.remove(filename) os.remove(filename)
# http://stackoverflow.com/questions/600268/mkdir-p-functionality-in-python
def mkdir_p(path): def mkdir_p(path):
debug_print('mkdir_p(' + path + ')') debug_print(f'mkdir_p({path})')
try: os.makedirs(path, exist_ok=True)
os.makedirs(path)
except OSError as exc: # Python >2.5
if exc.errno != errno.EEXIST or not os.path.isdir(path):
raise
def is_nonempty_directory(path): def is_nonempty_directory(path):
@@ -513,7 +507,7 @@ def run(cmd, cwd=None, quiet=False):
# http://pythonicprose.blogspot.fi/2009/10/python-extract-targz-archive.html # http://pythonicprose.blogspot.fi/2009/10/python-extract-targz-archive.html
def untargz(source_filename, dest_dir): def untargz(source_filename, dest_dir):
print("Unpacking '" + source_filename + "' to '" + dest_dir + "'") print(f"Unpacking '{source_filename}' to '{dest_dir}'")
mkdir_p(dest_dir) mkdir_p(dest_dir)
returncode = run(['tar', '-xvf' if VERBOSE else '-xf', sdk_path(source_filename), '--strip', '1'], cwd=dest_dir) returncode = run(['tar', '-xvf' if VERBOSE else '-xf', sdk_path(source_filename), '--strip', '1'], cwd=dest_dir)
# tfile = tarfile.open(source_filename, 'r:gz') # tfile = tarfile.open(source_filename, 'r:gz')
@@ -531,7 +525,7 @@ def fix_potentially_long_windows_pathname(pathname):
# Test if emsdk calls fix_potentially_long_windows_pathname() with long # Test if emsdk calls fix_potentially_long_windows_pathname() with long
# relative paths (which is problematic) # relative paths (which is problematic)
if not os.path.isabs(pathname) and len(pathname) > 200: if not os.path.isabs(pathname) and len(pathname) > 200:
errlog('Warning: Seeing a relative path "' + pathname + '" which is dangerously long for being referenced as a short Windows path name. Refactor emsdk to be able to handle this!') errlog(f'Warning: Seeing a relative path "{pathname}" which is dangerously long for being referenced as a short Windows path name. Refactor emsdk to be able to handle this!')
if pathname.startswith('\\\\?\\'): if pathname.startswith('\\\\?\\'):
return pathname return pathname
pathname = os.path.normpath(pathname.replace('/', '\\')) pathname = os.path.normpath(pathname.replace('/', '\\'))
@@ -554,7 +548,7 @@ def move_with_overwrite(src, dest):
# http://stackoverflow.com/questions/12886768/simple-way-to-unzip-file-in-python-on-all-oses # http://stackoverflow.com/questions/12886768/simple-way-to-unzip-file-in-python-on-all-oses
def unzip(source_filename, dest_dir): def unzip(source_filename, dest_dir):
print("Unpacking '" + source_filename + "' to '" + dest_dir + "'") print(f"Unpacking '{source_filename}' to '{dest_dir}'")
mkdir_p(dest_dir) mkdir_p(dest_dir)
common_subdir = None common_subdir = None
try: try:
@@ -609,11 +603,11 @@ def unzip(source_filename, dest_dir):
if common_subdir: if common_subdir:
remove_tree(unzip_to_dir) remove_tree(unzip_to_dir)
except zipfile.BadZipfile as e: except zipfile.BadZipfile as e:
errlog("Unzipping file '" + source_filename + "' failed due to reason: " + str(e) + "! Removing the corrupted zip file.") errlog(f"Unzipping file '{source_filename}' failed due to reason: {e}! Removing the corrupted zip file.")
rmfile(source_filename) rmfile(source_filename)
return False return False
except Exception as e: except Exception as e:
errlog("Unzipping file '" + source_filename + "' failed due to reason: " + str(e)) errlog(f"Unzipping file '{source_filename}' failed due to reason: {e}")
return False return False
return True return True
@@ -725,11 +719,11 @@ def download_with_urllib(url, file_name):
# On failure, returns None. # On failure, returns None.
def download_file(url, dstpath, download_even_if_exists=False, def download_file(url, dstpath, download_even_if_exists=False,
filename_prefix='', silent=False): filename_prefix='', silent=False):
debug_print('download_file(url=' + url + ', dstpath=' + dstpath + ')') debug_print(f'download_file(url={url}, dstpath={dstpath})')
file_name = get_download_target(url, dstpath, filename_prefix) file_name = get_download_target(url, dstpath, filename_prefix)
if os.path.exists(file_name) and not download_even_if_exists: if os.path.exists(file_name) and not download_even_if_exists:
print("File '" + file_name + "' already downloaded, skipping.") print(f"File '{file_name}' already downloaded, skipping.")
return file_name return file_name
mkdir_p(os.path.dirname(file_name)) mkdir_p(os.path.dirname(file_name))
@@ -744,7 +738,7 @@ def download_file(url, dstpath, download_even_if_exists=False,
else: else:
download_with_urllib(url, file_name) download_with_urllib(url, file_name)
except Exception as e: except Exception as e:
errlog("Error: Downloading URL '" + url + "': " + str(e)) errlog(f"Error: Downloading URL '{url}': {e}")
return None return None
except KeyboardInterrupt: except KeyboardInterrupt:
rmfile(file_name) rmfile(file_name)
@@ -754,7 +748,7 @@ def download_file(url, dstpath, download_even_if_exists=False,
def run_get_output(cmd, cwd=None): def run_get_output(cmd, cwd=None):
debug_print('run_get_output(cmd=' + str(cmd) + ', cwd=' + str(cwd) + ')') debug_print(f'run_get_output(cmd={cmd}, cwd={cwd})')
process = subprocess.Popen(cmd, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, env=os.environ.copy(), universal_newlines=True) process = subprocess.Popen(cmd, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, env=os.environ.copy(), universal_newlines=True)
stdout, stderr = process.communicate() stdout, stderr = process.communicate()
return (process.returncode, stdout, stderr) return (process.returncode, stdout, stderr)
@@ -822,31 +816,31 @@ def get_git_remotes(repo_path):
def git_clone(url, dstpath, branch, remote_name='origin'): def git_clone(url, dstpath, branch, remote_name='origin'):
debug_print('git_clone(url=' + url + ', dstpath=' + dstpath + ')') debug_print(f'git_clone(url={url}, dstpath={dstpath})')
if os.path.isdir(os.path.join(dstpath, '.git')): if os.path.isdir(os.path.join(dstpath, '.git')):
remotes = get_git_remotes(dstpath) remotes = get_git_remotes(dstpath)
if remote_name in remotes: if remote_name in remotes:
debug_print('Repository ' + url + ' with remote "' + remote_name + '" already cloned to directory ' + dstpath + ', skipping.') debug_print(f'Repository {url} with remote "{remote_name}" already cloned to directory {dstpath}, skipping.')
return True return True
else: else:
debug_print('Repository ' + url + ' with remote "' + remote_name + '" already cloned to directory ' + dstpath + ', but remote has not yet been added. Creating.') debug_print(f'Repository {url} with remote "{remote_name}" already cloned to directory {dstpath}, but remote has not yet been added. Creating.')
return run([GIT(), 'remote', 'add', remote_name, url], cwd=dstpath) == 0 return run([GIT(), 'remote', 'add', remote_name, url], cwd=dstpath) == 0
mkdir_p(dstpath) mkdir_p(dstpath)
git_clone_args = ['--recurse-submodules', '--branch', branch] # Do not check out a branch (installer will issue a checkout command right after) git_clone_args = ['--recurse-submodules', '--branch', branch] # Do not check out a branch (installer will issue a checkout command right after)
if GIT_CLONE_SHALLOW: if GIT_CLONE_SHALLOW:
git_clone_args += ['--depth', '1'] git_clone_args += ['--depth', '1']
print('Cloning from ' + url + '...') print(f'Cloning from {url}...')
return run([GIT(), 'clone', '-o', remote_name] + git_clone_args + [url, dstpath]) == 0 return run([GIT(), 'clone', '-o', remote_name] + git_clone_args + [url, dstpath]) == 0
def git_pull(repo_path, branch_or_tag, remote_name='origin'): def git_pull(repo_path, branch_or_tag, remote_name='origin'):
debug_print('git_pull(repo_path=' + repo_path + ', branch/tag=' + branch_or_tag + ', remote_name=' + remote_name + ')') debug_print(f'git_pull(repo_path={repo_path}, branch/tag={branch_or_tag}, remote_name={remote_name})')
ret = run([GIT(), 'fetch', '--quiet', remote_name], repo_path) ret = run([GIT(), 'fetch', '--quiet', remote_name], repo_path)
if ret != 0: if ret != 0:
return False return False
try: try:
print("Fetching latest changes to the branch/tag '" + branch_or_tag + "' for '" + repo_path + "'...") print(f"Fetching latest changes to the branch/tag '{branch_or_tag}' for '{repo_path}'...")
ret = run([GIT(), 'fetch', '--quiet', remote_name], repo_path) ret = run([GIT(), 'fetch', '--quiet', remote_name], repo_path)
if ret != 0: if ret != 0:
return False return False
@@ -871,13 +865,13 @@ def git_pull(repo_path, branch_or_tag, remote_name='origin'):
except Exception: except Exception:
errlog('git operation failed!') errlog('git operation failed!')
return False return False
print("Successfully updated and checked out branch/tag '" + branch_or_tag + "' on repository '" + repo_path + "'") print(f"Successfully updated and checked out branch/tag '{branch_or_tag}' on repository '{repo_path}'")
print("Current repository version: " + git_repo_version(repo_path)) print("Current repository version: " + git_repo_version(repo_path))
return True return True
def git_clone_checkout_and_pull(url, dstpath, branch, override_remote_name='origin'): def git_clone_checkout_and_pull(url, dstpath, branch, override_remote_name='origin'):
debug_print('git_clone_checkout_and_pull(url=' + url + ', dstpath=' + dstpath + ', branch=' + branch + ', override_remote_name=' + override_remote_name + ')') debug_print(f'git_clone_checkout_and_pull(url={url}, dstpath={dstpath}, branch={branch}, override_remote_name={override_remote_name})')
# Make sure the repository is cloned first # Make sure the repository is cloned first
success = git_clone(url, dstpath, branch, override_remote_name) success = git_clone(url, dstpath, branch, override_remote_name)
@@ -970,13 +964,13 @@ def find_cmake():
if tool.id == 'cmake' and tool.is_active(): if tool.id == 'cmake' and tool.is_active():
cmake_exe = locate_cmake_from_tool(tool) cmake_exe = locate_cmake_from_tool(tool)
if cmake_exe: if cmake_exe:
info('Found installed+activated CMake tool at "' + cmake_exe + '"') info(f'Found installed+activated CMake tool at "{cmake_exe}"')
return cmake_exe return cmake_exe
# 2. If cmake already exists in PATH, then use that cmake to configure the build. # 2. If cmake already exists in PATH, then use that cmake to configure the build.
cmake_exe = which('cmake') cmake_exe = which('cmake')
if cmake_exe: if cmake_exe:
info('Found CMake from PATH at "' + cmake_exe + '"') info(f'Found CMake from PATH at "{cmake_exe}"')
return cmake_exe return cmake_exe
# 3. Finally, if user has installed a cmake tool, but has not activated that, then use # 3. Finally, if user has installed a cmake tool, but has not activated that, then use
@@ -987,14 +981,14 @@ def find_cmake():
if tool.id == 'cmake' and tool.is_installed(): if tool.id == 'cmake' and tool.is_installed():
cmake_exe = locate_cmake_from_tool(tool) cmake_exe = locate_cmake_from_tool(tool)
if cmake_exe: if cmake_exe:
info('Found installed CMake tool at "' + cmake_exe + '"') info(f'Found installed CMake tool at "{cmake_exe}"')
return cmake_exe return cmake_exe
exit_with_error('Unable to find "cmake" in PATH, or as installed/activated tool! Please install CMake first') exit_with_error('Unable to find "cmake" in PATH, or as installed/activated tool! Please install CMake first')
def make_build(build_root, build_type): def make_build(build_root, build_type):
debug_print('make_build(build_root=' + build_root + ', build_type=' + build_type + ')') debug_print(f'make_build(build_root={build_root}, build_type={build_type})')
if CPU_CORES > 1: if CPU_CORES > 1:
print('Performing a parallel build with ' + str(CPU_CORES) + ' cores.') print('Performing a parallel build with ' + str(CPU_CORES) + ' cores.')
else: else:
@@ -1018,7 +1012,7 @@ def make_build(build_root, build_type):
print('Running build: ' + str(make)) print('Running build: ' + str(make))
ret = subprocess.check_call(make, cwd=build_root, env=build_env(CMAKE_GENERATOR)) ret = subprocess.check_call(make, cwd=build_root, env=build_env(CMAKE_GENERATOR))
if ret != 0: if ret != 0:
errlog('Build failed with exit code ' + ret + '!') errlog('Build failed with exit code {ret}!')
errlog('Working directory: ' + build_root) errlog('Working directory: ' + build_root)
return False return False
except Exception as e: except Exception as e:
@@ -1065,7 +1059,7 @@ def cmake_configure(generator, build_root, src_root, build_type, extra_cmake_arg
open(os.path.join(build_root, 'recmake.' + ('bat' if WINDOWS else 'sh')), 'w').write(' '.join(map(quote_parens, cmdline))) open(os.path.join(build_root, 'recmake.' + ('bat' if WINDOWS else 'sh')), 'w').write(' '.join(map(quote_parens, cmdline)))
ret = subprocess.check_call(cmdline, cwd=build_root, env=build_env(CMAKE_GENERATOR)) ret = subprocess.check_call(cmdline, cwd=build_root, env=build_env(CMAKE_GENERATOR))
if ret != 0: if ret != 0:
errlog('CMake invocation failed with exit code ' + ret + '!') errlog('CMake invocation failed with exit code {ret}!')
errlog('Working directory: ' + build_root) errlog('Working directory: ' + build_root)
return False return False
except OSError as e: except OSError as e:
@@ -1387,13 +1381,13 @@ def download_firefox(tool):
# Abort if detaching was not successful # Abort if detaching was not successful
if os.path.exists(mount_point): if os.path.exists(mount_point):
raise Exception('Previous mount of Firefox already exists at "' + mount_point + '", unable to proceed.') raise Exception(f'Previous mount of Firefox already exists at "{mount_point}", unable to proceed.')
# Mount the archive # Mount the archive
run(['hdiutil', 'attach', filename]) run(['hdiutil', 'attach', filename])
firefox_dir = os.path.join(mount_point, app_name) firefox_dir = os.path.join(mount_point, app_name)
if not os.path.isdir(firefox_dir): if not os.path.isdir(firefox_dir):
raise Exception('Unable to find Firefox directory "' + firefox_dir + '" inside app image.') raise Exception(f'Unable to find Firefox directory "{firefox_dir}" inside app image.')
# And install by copying the files from the archive # And install by copying the files from the archive
shutil.copytree(firefox_dir, root) shutil.copytree(firefox_dir, root)
@@ -1522,7 +1516,7 @@ def binaryen_build_root(tool):
def uninstall_binaryen(tool): def uninstall_binaryen(tool):
debug_print('uninstall_binaryen(' + str(tool) + ')') debug_print('uninstall_binaryen(' + str(tool) + ')')
build_root = binaryen_build_root(tool) build_root = binaryen_build_root(tool)
print("Deleting path '" + build_root + "'") print(f"Deleting path '{build_root}'")
remove_tree(build_root) remove_tree(build_root)
@@ -1563,7 +1557,7 @@ def build_binaryen_tool(tool):
def download_and_extract(archive, dest_dir, filename_prefix='', clobber=True): def download_and_extract(archive, dest_dir, filename_prefix='', clobber=True):
debug_print('download_and_extract(archive=' + archive + ', dest_dir=' + dest_dir + ')') debug_print('download_and_extract(archive={archive}, dest_dir={dest_dir})')
url = urljoin(emsdk_packages_url, archive) url = urljoin(emsdk_packages_url, archive)
@@ -1723,7 +1717,7 @@ def extract_newest_node_nightly_version(versions):
def download_node_nightly(tool): def download_node_nightly(tool):
nightly_versions = fetch_nightly_node_versions() nightly_versions = fetch_nightly_node_versions()
latest_nightly = extract_newest_node_nightly_version(nightly_versions) latest_nightly = extract_newest_node_nightly_version(nightly_versions)
print('Latest Node.js Nightly download available is "' + latest_nightly + '"') print('Latest Node.js Nightly download available is "{latest_nightly}"')
output_dir = os.path.abspath('node/nightly-' + latest_nightly) output_dir = os.path.abspath('node/nightly-' + latest_nightly)
# Node.js zip structure quirk: Linux and macOS archives have a /bin, # Node.js zip structure quirk: Linux and macOS archives have a /bin,
@@ -1794,9 +1788,9 @@ def generate_em_config(active_tools, permanently_activate, system):
for name, value in activated_config.items(): for name, value in activated_config.items():
if value.startswith('['): if value.startswith('['):
cfg += name + " = " + value + "\n" cfg += f'{name} = {value}\n'
else: else:
cfg += name + " = '" + value + "'\n" cfg += f"{name} = '{value}'\n"
emroot = find_emscripten_root(active_tools) emroot = find_emscripten_root(active_tools)
if emroot: if emroot:
@@ -1856,14 +1850,11 @@ def find_msbuild_dir():
return '' return ''
class Tool(object): class Tool:
def __init__(self, data): def __init__(self, data):
# Convert the dictionary representation of the tool in 'data' to members of # Convert the dictionary representation of the tool in 'data' to members of
# this class for convenience. # this class for convenience.
for key, value in data.items(): for key, value in data.items():
# Python2 compat, convert unicode to str
if sys.version_info < (3,) and isinstance(value, unicode): # noqa
value = value.encode('Latin-1')
setattr(self, key, value) setattr(self, key, value)
# Cache the name ID of this Tool (these are read very often) # Cache the name ID of this Tool (these are read very often)
@@ -1916,7 +1907,7 @@ class Tool(object):
for tool_name in self.uses: for tool_name in self.uses:
tool = find_tool(tool_name) tool = find_tool(tool_name)
if not tool: if not tool:
debug_print('Tool ' + str(self) + ' depends on ' + tool_name + ' which does not exist!') debug_print(f'Tool {self} depends on {tool_name} which does not exist!')
continue continue
if tool.needs_compilation(): if tool.needs_compilation():
return True return True
@@ -2024,7 +2015,7 @@ class Tool(object):
for tool_name in self.uses: for tool_name in self.uses:
tool = find_tool(tool_name) tool = find_tool(tool_name)
if tool is None: if tool is None:
errlog("Manifest error: No tool by name '" + tool_name + "' found! This may indicate an internal SDK error!") errlog(f"Manifest error: No tool by name '{tool_name}' found! This may indicate an internal SDK error!")
return False return False
if not tool.is_installed(): if not tool.is_installed():
return False return False
@@ -2072,7 +2063,7 @@ class Tool(object):
for key, value in activated_cfg.items(): for key, value in activated_cfg.items():
if key not in EM_CONFIG_DICT: if key not in EM_CONFIG_DICT:
debug_print(str(self) + ' is not active, because key="' + key + '" does not exist in .emscripten') debug_print(f'{self} is not active, because key="{key}" does not exist in .emscripten')
return False return False
# all paths are stored dynamically relative to the emsdk root, so # all paths are stored dynamically relative to the emsdk root, so
@@ -2080,7 +2071,7 @@ class Tool(object):
config_value = EM_CONFIG_DICT[key].replace("emsdk_path + '", "'" + EMSDK_PATH) config_value = EM_CONFIG_DICT[key].replace("emsdk_path + '", "'" + EMSDK_PATH)
config_value = config_value.strip("'") config_value = config_value.strip("'")
if config_value != value: if config_value != value:
debug_print(str(self) + ' is not active, because key="' + key + '" has value "' + config_value + '" but should have value "' + value + '"') debug_print(f'{self} is not active, because key="{key}" has value "{config_value}" but should have value "{value}"')
return False return False
return True return True
@@ -2090,7 +2081,7 @@ class Tool(object):
for env in envs: for env in envs:
key, value = parse_key_value(env) key, value = parse_key_value(env)
if key not in os.environ or to_unix_path(os.environ[key]) != to_unix_path(value): if key not in os.environ or to_unix_path(os.environ[key]) != to_unix_path(value):
debug_print(str(self) + ' is not active, because environment variable key="' + key + '" has value "' + str(os.getenv(key)) + '" but should have value "' + value + '"') debug_print(f'{self} is not active, because environment variable key="{key}" has value "{os.getenv(key)}" but should have value "{value}"')
return False return False
if hasattr(self, 'activated_path'): if hasattr(self, 'activated_path'):
@@ -2098,7 +2089,7 @@ class Tool(object):
for p in path: for p in path:
path_items = os.environ['PATH'].replace('\\', '/').split(ENVPATH_SEPARATOR) path_items = os.environ['PATH'].replace('\\', '/').split(ENVPATH_SEPARATOR)
if not normalized_contains(path_items, p): if not normalized_contains(path_items, p):
debug_print(str(self) + ' is not active, because environment variable PATH item "' + p + '" is not present (PATH=' + os.environ['PATH'] + ')') debug_print(f'{self} is not active, because environment variable PATH item "{p}" is not present (PATH={os.environ["PATH"]})')
return False return False
return True return True
@@ -2130,7 +2121,7 @@ class Tool(object):
already being installed. already being installed.
""" """
if self.can_be_installed() is not True: if self.can_be_installed() is not True:
exit_with_error("The tool '" + str(self) + "' is not available due to the reason: " + self.can_be_installed()) exit_with_error(f"The tool '{self}' is not available due to the reason: {self.can_be_installed()}")
if self.id == 'sdk': if self.id == 'sdk':
return self.install_sdk() return self.install_sdk()
@@ -2141,17 +2132,17 @@ class Tool(object):
"""Returns True if any SDK component was installed of False all componented """Returns True if any SDK component was installed of False all componented
were already installed. were already installed.
""" """
print("Installing SDK '" + str(self) + "'..") print(f"Installing SDK '{self}'..")
installed = False installed = False
for tool_name in self.uses: for tool_name in self.uses:
tool = find_tool(tool_name) tool = find_tool(tool_name)
if tool is None: if tool is None:
exit_with_error("manifest error: No tool by name '" + tool_name + "' found! This may indicate an internal SDK error!") exit_with_error(f"manifest error: No tool by name '{tool_name}' found! This may indicate an internal SDK error!")
installed |= tool.install() installed |= tool.install()
if not installed: if not installed:
print("All SDK components already installed: '" + str(self) + "'.") print(f"All SDK components already installed: '{self}'.")
return False return False
if getattr(self, 'custom_install_script', None) == 'emscripten_npm_install': if getattr(self, 'custom_install_script', None) == 'emscripten_npm_install':
@@ -2164,7 +2155,7 @@ class Tool(object):
if not emscripten_npm_install(self, emscripten_dir): if not emscripten_npm_install(self, emscripten_dir):
exit_with_error('post-install step failed: emscripten_npm_install') exit_with_error('post-install step failed: emscripten_npm_install')
print("Done installing SDK '" + str(self) + "'.") print(f"Done installing SDK '{self}'.")
return True return True
def install_tool(self): def install_tool(self):
@@ -2176,10 +2167,10 @@ class Tool(object):
# installed every time when requested, since the install step is then used to git # installed every time when requested, since the install step is then used to git
# pull the tool to a newer version. # pull the tool to a newer version.
if self.is_installed() and not hasattr(self, 'git_branch'): if self.is_installed() and not hasattr(self, 'git_branch'):
print("Skipped installing " + self.name + ", already installed.") print(f"Skipped installing {self.name}, already installed.")
return False return False
print("Installing tool '" + str(self) + "'..") print(f"Installing tool '{self}'..")
url = self.download_url() url = self.download_url()
custom_install_scripts = { custom_install_scripts = {
@@ -2227,12 +2218,12 @@ class Tool(object):
with open(emscripten_version_file_path, 'w') as f: with open(emscripten_version_file_path, 'w') as f:
f.write('"%s"\n' % version) f.write('"%s"\n' % version)
print("Done installing tool '" + str(self) + "'.") print(f"Done installing tool '{self}'.")
# Sanity check that the installation succeeded, and if so, remove unneeded # Sanity check that the installation succeeded, and if so, remove unneeded
# leftover installation files. # leftover installation files.
if not self.is_installed(skip_version_check=True): if not self.is_installed(skip_version_check=True):
exit_with_error("installation of '" + str(self) + "' failed, but no error was detected. Either something went wrong with the installation, or this may indicate an internal emsdk error.") exit_with_error(f"installation of '{self}' failed, but no error was detected. Either something went wrong with the installation, or this may indicate an internal emsdk error.")
self.cleanup_temp_install_files() self.cleanup_temp_install_files()
self.update_installed_version() self.update_installed_version()
@@ -2244,22 +2235,22 @@ class Tool(object):
url = self.download_url() url = self.download_url()
if url.endswith(ARCHIVE_SUFFIXES): if url.endswith(ARCHIVE_SUFFIXES):
download_target = get_download_target(url, download_dir, getattr(self, 'download_prefix', '')) download_target = get_download_target(url, download_dir, getattr(self, 'download_prefix', ''))
debug_print("Deleting temporary download: " + download_target) debug_print(f"Deleting temporary download: {download_target}")
rmfile(download_target) rmfile(download_target)
def uninstall(self): def uninstall(self):
if not self.is_installed(): if not self.is_installed():
print("Tool '" + str(self) + "' was not installed. No need to uninstall.") print(f"Tool '{self}' was not installed. No need to uninstall.")
return return
print("Uninstalling tool '" + str(self) + "'..") print(f"Uninstalling tool '{self}'..")
if hasattr(self, 'custom_uninstall_script'): if hasattr(self, 'custom_uninstall_script'):
if self.custom_uninstall_script == 'uninstall_binaryen': if self.custom_uninstall_script == 'uninstall_binaryen':
uninstall_binaryen(self) uninstall_binaryen(self)
else: else:
raise Exception('Unknown custom_uninstall_script directive "' + self.custom_uninstall_script + '"!') raise Exception(f'Unknown custom_uninstall_script directive "{self.custom_uninstall_script}"!')
print("Deleting path '" + self.installation_path() + "'") print(f"Deleting path '{self.installation_path()}'")
remove_tree(self.installation_path()) remove_tree(self.installation_path())
print("Done uninstalling '" + str(self) + "'.") print(f"Done uninstalling '{self}'.")
def dependencies(self): def dependencies(self):
if not hasattr(self, 'uses'): if not hasattr(self, 'uses'):
@@ -2412,22 +2403,13 @@ def get_emscripten_releases_tot():
def get_release_hash(arg, releases_info): def get_release_hash(arg, releases_info):
return releases_info.get(arg, None) or releases_info.get('sdk-' + arg + '-64bit') return releases_info.get(arg, None) or releases_info.get(f'sdk-{arg}-64bit')
def version_key(ver): def version_key(ver):
return tuple(map(int, re.split('[._-]', ver)[:3])) return tuple(map(int, re.split('[._-]', ver)[:3]))
# A sort function that is compatible with both Python 2 and Python 3 using a
# custom comparison function.
def python_2_3_sorted(arr, cmp):
if sys.version_info >= (3,):
return sorted(arr, key=functools.cmp_to_key(cmp))
else:
return sorted(arr, cmp=cmp)
def is_emsdk_sourced_from_github(): def is_emsdk_sourced_from_github():
return os.path.exists(os.path.join(EMSDK_PATH, '.git')) return os.path.exists(os.path.join(EMSDK_PATH, '.git'))
@@ -2524,12 +2506,6 @@ def load_releases_versions():
return versions return versions
def is_string(s):
if sys.version_info[0] >= 3:
return isinstance(s, str)
return isinstance(s, basestring) # noqa
def load_sdk_manifest(): def load_sdk_manifest():
try: try:
manifest = json.loads(open(sdk_path("emsdk_manifest.json"), "r").read()) manifest = json.loads(open(sdk_path("emsdk_manifest.json"), "r").read())
@@ -2566,7 +2542,7 @@ def load_sdk_manifest():
return version_key(ver) == version_key(reference) return version_key(ver) == version_key(reference)
if cmp_operand == '!=': if cmp_operand == '!=':
return version_key(ver) != version_key(reference) return version_key(ver) != version_key(reference)
raise Exception('Invalid cmp_operand "' + cmp_operand + '"!') raise Exception(f'Invalid cmp_operand "{cmp_operand}"!')
def passes_filters(param, ver, filters): def passes_filters(param, ver, filters):
for v in filters: for v in filters:
@@ -2583,7 +2559,7 @@ def load_sdk_manifest():
t2 = copy.copy(t) t2 = copy.copy(t)
found_param = False found_param = False
for p, v in vars(t2).items(): for p, v in vars(t2).items():
if is_string(v) and param in v: if isinstance(v, str) and param in v:
t2.__dict__[p] = v.replace(param, ver) t2.__dict__[p] = v.replace(param, ver)
found_param = True found_param = True
if not found_param: if not found_param:
@@ -2889,15 +2865,15 @@ def construct_env_with_vars(env_vars_to_add):
continue continue
info(key + ' = ' + value) info(key + ' = ' + value)
if POWERSHELL: if POWERSHELL:
env_string += '$env:' + key + '="' + value + '"\n' env_string += f'$env:{key}="{value}"\n'
elif CMD: elif CMD:
env_string += 'SET ' + key + '=' + value + '\n' env_string += f'SET {key}={value}\n'
elif CSH: elif CSH:
env_string += 'setenv ' + key + ' "' + value + '";\n' env_string += f'setenv {key} "{value}";\n'
elif FISH: elif FISH:
env_string += 'set -gx ' + key + ' "' + value + '";\n' env_string += f'set -gx {key} "{value}";\n'
elif BASH: elif BASH:
env_string += 'export ' + key + '="' + value + '";\n' env_string += f'export {key}="{value}";\n'
else: else:
assert False assert False
@@ -3162,11 +3138,11 @@ def main(args):
tool_name, url_and_refspec = forked_url.split('@') tool_name, url_and_refspec = forked_url.split('@')
t = find_tool(tool_name) t = find_tool(tool_name)
if not t: if not t:
errlog('Failed to find tool ' + tool_name + '!') errlog('Failed to find tool {tool_name}!')
return False return False
else: else:
t.url, t.git_branch, t.remote_name = parse_github_url_and_refspec(url_and_refspec) t.url, t.git_branch, t.remote_name = parse_github_url_and_refspec(url_and_refspec)
debug_print('Reading git repository URL "' + t.url + '" and git branch "' + t.git_branch + '" for Tool "' + tool_name + '".') debug_print(f'Reading git repository URL "{t.url}" and git branch "{t.git_branch}" for Tool "{tool_name}".')
forked_url = extract_string_arg('--override-repository') forked_url = extract_string_arg('--override-repository')
@@ -3179,7 +3155,7 @@ def main(args):
CMAKE_GENERATOR = build_generator.group(1) CMAKE_GENERATOR = build_generator.group(1)
args[i] = '' args[i] = ''
else: else:
errlog("Cannot parse CMake generator string: " + args[i] + ". Try wrapping generator string with quotes") errlog(f"Cannot parse CMake generator string: {args[i]}. Try wrapping generator string with quotes")
return 1 return 1
elif args[i].startswith('--build='): elif args[i].startswith('--build='):
build_type = re.match(r'^--build=(.+)$', args[i]) build_type = re.match(r'^--build=(.+)$', args[i])
@@ -3192,10 +3168,10 @@ def main(args):
CMAKE_BUILD_TYPE_OVERRIDE = build_types[build_type_index] CMAKE_BUILD_TYPE_OVERRIDE = build_types[build_type_index]
args[i] = '' args[i] = ''
except Exception: except Exception:
errlog('Unknown CMake build type "' + build_type + '" specified! Please specify one of ' + str(build_types)) errlog(f'Unknown CMake build type "{build_type}" specified! Please specify one of {build_types}')
return 1 return 1
else: else:
errlog("Invalid command line parameter " + args[i] + ' specified!') errlog(f'Invalid command line parameter {args[i]} specified!')
return 1 return 1
args = [x for x in args if x] args = [x for x in args if x]
@@ -3301,7 +3277,7 @@ def main(args):
print('Items marked with * are activated for the current user.') print('Items marked with * are activated for the current user.')
if has_partially_active_tools[0]: if has_partially_active_tools[0]:
env_cmd = 'emsdk_env.bat' if WINDOWS else 'source ./emsdk_env.sh' env_cmd = 'emsdk_env.bat' if WINDOWS else 'source ./emsdk_env.sh'
print('Items marked with (*) are selected for use, but your current shell environment is not configured to use them. Type "' + env_cmd + '" to set up your current shell to use them' + (', or call "emsdk activate --permanent <name_of_sdk>" to permanently activate them.' if WINDOWS else '.')) print(f'Items marked with (*) are selected for use, but your current shell environment is not configured to use them. Type "{env_cmd}" to set up your current shell to use them' + (', or call "emsdk activate --permanent <name_of_sdk>" to permanently activate them.' if WINDOWS else '.'))
if not arg_old: if not arg_old:
print('') print('')
print("To access the historical archived versions, type 'emsdk list --old'") print("To access the historical archived versions, type 'emsdk list --old'")
@@ -3353,7 +3329,7 @@ def main(args):
print('Deactivating tool ' + str(tool) + '.') print('Deactivating tool ' + str(tool) + '.')
tools_to_activate.remove(tool) tools_to_activate.remove(tool)
else: else:
print('Tool "' + arg + '" was not active, no need to deactivate.') print(f'Tool "{arg}" was not active, no need to deactivate.')
if not tools_to_activate: if not tools_to_activate:
errlog('No tools/SDKs specified to activate! Usage:\n emsdk activate tool/sdk1 [tool/sdk2] [...]') errlog('No tools/SDKs specified to activate! Usage:\n emsdk activate tool/sdk1 [tool/sdk2] [...]')
return 1 return 1
@@ -3375,7 +3351,7 @@ def main(args):
CPU_CORES = int(multicore.group(1)) CPU_CORES = int(multicore.group(1))
args[i] = '' args[i] = ''
else: else:
errlog("Invalid command line parameter " + args[i] + ' specified!') errlog(f'Invalid command line parameter {args[i]} specified!')
return 1 return 1
elif args[i] == '--shallow': elif args[i] == '--shallow':
GIT_CLONE_SHALLOW = True GIT_CLONE_SHALLOW = True
@@ -3412,12 +3388,12 @@ def main(args):
return 1 return 1
tool = find_tool(args[0]) tool = find_tool(args[0])
if tool is None: if tool is None:
errlog("Error: Tool by name '" + args[0] + "' was not found.") errlog(f"Error: Tool by name '{args[0]}' was not found.")
return 1 return 1
tool.uninstall() tool.uninstall()
return 0 return 0
errlog("Unknown command '" + cmd + "' given! Type 'emsdk help' to get a list of commands.") errlog(f"Unknown command '{cmd}' given! Type 'emsdk help' to get a list of commands.")
return 1 return 1

View File

@@ -28,7 +28,6 @@ import os
import platform import platform
import urllib.request import urllib.request
import shutil import shutil
import subprocess
import sys import sys
from subprocess import check_call from subprocess import check_call
from zip import unzip_cmd, zip_cmd from zip import unzip_cmd, zip_cmd