diff --git a/emcc.py b/emcc.py index 2653a23f273b6..d0cff5ad6dfdd 100755 --- a/emcc.py +++ b/emcc.py @@ -42,6 +42,7 @@ from tools import colored_logger, diagnostics, building from tools.shared import unsuffixed, unsuffixed_basename, WINDOWS, safe_copy from tools.shared import run_process, read_and_preprocess, exit_with_error, DEBUG +from tools.shared import read_file, write_file, read_binary from tools.shared import do_replace, strip_prefix from tools.response_file import substitute_response_files from tools.minimal_runtime_shell import generate_minimal_runtime_html @@ -357,7 +358,7 @@ def standardize_setting_change(key, value): filename = strip_prefix(value, '@') if not os.path.exists(filename): exit_with_error('%s: file not found parsing argument: %s=%s' % (filename, key, value)) - value = open(filename).read().strip() + value = read_file(filename).strip() else: value = value.replace('\\', '\\\\') @@ -589,7 +590,7 @@ def check_human_readable_list(items): def make_js_executable(script): - src = open(script).read() + src = read_file(script) cmd = shared.shlex_join(config.JS_ENGINE) if not os.path.isabs(config.JS_ENGINE[0]): # TODO: use whereis etc. And how about non-*NIX? @@ -1350,19 +1351,19 @@ def phase_linker_setup(options, state, newargs, settings_map): add_link_flag(state, sys.maxsize, f) if options.emrun: - options.pre_js += open(shared.path_from_root('src', 'emrun_prejs.js')).read() + '\n' - options.post_js += open(shared.path_from_root('src', 'emrun_postjs.js')).read() + '\n' + options.pre_js += read_file(shared.path_from_root('src', 'emrun_prejs.js')) + '\n' + options.post_js += read_file(shared.path_from_root('src', 'emrun_postjs.js')) + '\n' # emrun mode waits on program exit settings.EXIT_RUNTIME = 1 if options.cpu_profiler: - options.post_js += open(shared.path_from_root('src', 'cpuprofiler.js')).read() + '\n' + options.post_js += read_file(shared.path_from_root('src', 'cpuprofiler.js')) + '\n' if options.memory_profiler: settings.MEMORYPROFILER = 1 if options.thread_profiler: - options.post_js += open(shared.path_from_root('src', 'threadprofiler.js')).read() + '\n' + options.post_js += read_file(shared.path_from_root('src', 'threadprofiler.js')) + '\n' if options.memory_init_file is None: options.memory_init_file = settings.OPT_LEVEL >= 2 @@ -2527,7 +2528,7 @@ def phase_source_transforms(options, target): # Apply pre and postjs files if final_js and (options.pre_js or options.post_js): logger.debug('applying pre/postjses') - src = open(final_js).read() + src = read_file(final_js) final_js += '.pp.js' with open(final_js, 'w') as f: # pre-js code goes right after the Module integration code (so it @@ -2553,9 +2554,9 @@ def phase_memory_initializer(memfile): # is set the memory initializer url. global final_js - src = open(final_js).read() + src = read_file(final_js) src = do_replace(src, '// {{MEM_INITIALIZER}}', 'var memoryInitializer = "%s";' % os.path.basename(memfile)) - open(final_js + '.mem.js', 'w').write(src) + write_file(final_js + '.mem.js', src) final_js += '.mem.js' @@ -2565,9 +2566,9 @@ def phase_final_emitting(options, state, target, wasm_target, memfile): # Remove some trivial whitespace # TODO: do not run when compress has already been done on all parts of the code - # src = open(final_js).read() + # src = read_file(final_js) # src = re.sub(r'\n+[ \n]*\n+', '\n', src) - # open(final_js, 'w').write(src) + # write_file(final_js, src) if settings.USE_PTHREADS: target_dir = os.path.dirname(os.path.abspath(target)) @@ -2578,7 +2579,7 @@ def phase_final_emitting(options, state, target, wasm_target, memfile): # Minify the worker.js file in optimized builds if (settings.OPT_LEVEL >= 1 or settings.SHRINK_LEVEL >= 1) and not settings.DEBUG_LEVEL: minified_worker = building.acorn_optimizer(worker_output, ['minifyWhitespace'], return_output=True) - open(worker_output, 'w').write(minified_worker) + write_file(worker_output, minified_worker) # track files that will need native eols generated_text_files_with_native_eols = [] @@ -2599,16 +2600,15 @@ def phase_final_emitting(options, state, target, wasm_target, memfile): # Unmangle previously mangled `import.meta` references in both main code and libraries. # See also: `preprocess` in parseTools.js. if settings.EXPORT_ES6 and settings.USE_ES6_IMPORT_META: - src = open(final_js).read() + src = read_file(final_js) final_js += '.esmeta.js' - with open(final_js, 'w') as f: - f.write(src.replace('EMSCRIPTEN$IMPORT$META', 'import.meta')) + write_file(final_js, src.replace('EMSCRIPTEN$IMPORT$META', 'import.meta')) save_intermediate('es6-import-meta') # Apply pre and postjs files if options.extern_pre_js or options.extern_post_js: logger.debug('applying extern pre/postjses') - src = open(final_js).read() + src = read_file(final_js) final_js += '.epp.js' with open(final_js, 'w') as f: f.write(fix_windows_newlines(options.extern_pre_js)) @@ -2753,13 +2753,13 @@ def consume_arg_file(): elif check_arg('--js-transform'): options.js_transform = consume_arg() elif check_arg('--pre-js'): - options.pre_js += open(consume_arg_file()).read() + '\n' + options.pre_js += read_file(consume_arg_file()) + '\n' elif check_arg('--post-js'): - options.post_js += open(consume_arg_file()).read() + '\n' + options.post_js += read_file(consume_arg_file()) + '\n' elif check_arg('--extern-pre-js'): - options.extern_pre_js += open(consume_arg_file()).read() + '\n' + options.extern_pre_js += read_file(consume_arg_file()) + '\n' elif check_arg('--extern-post-js'): - options.extern_post_js += open(consume_arg_file()).read() + '\n' + options.extern_post_js += read_file(consume_arg_file()) + '\n' elif check_arg('--compiler-wrapper'): config.COMPILER_WRAPPER = consume_arg() elif check_flag('--post-link'): @@ -3177,10 +3177,10 @@ def run_closure_compiler(): # replace placeholder strings with correct subresource locations if final_js and settings.SINGLE_FILE and not settings.WASM2JS: - js = open(final_js).read() + js = read_file(final_js) if settings.MINIMAL_RUNTIME: - js = do_replace(js, '<<< WASM_BINARY_DATA >>>', base64_encode(open(wasm_target, 'rb').read())) + js = do_replace(js, '<<< WASM_BINARY_DATA >>>', base64_encode(read_binary(wasm_target))) else: js = do_replace(js, '<<< WASM_BINARY_FILE >>>', shared.JS.get_subresource_location(wasm_target)) shared.try_delete(wasm_target) @@ -3191,7 +3191,7 @@ def run_closure_compiler(): def modularize(): global final_js logger.debug('Modularizing, assigning to var ' + settings.EXPORT_NAME) - src = open(final_js).read() + src = read_file(final_js) return_value = settings.EXPORT_NAME if settings.WASM_ASYNC_COMPILATION: @@ -3386,7 +3386,7 @@ def generate_traditional_runtime_html(target, options, js_target, target_basenam if settings.SINGLE_FILE: js_contents = script.inline or '' if script.src: - js_contents += open(js_target).read() + js_contents += read_file(js_target) shared.try_delete(js_target) script.src = None script.inline = js_contents @@ -3479,13 +3479,13 @@ def generate_worker_js(target, js_target, target_basename): proxy_worker_filename = (settings.PROXY_TO_WORKER_FILENAME or worker_target_basename) + '.js' target_contents = worker_js_script(proxy_worker_filename) - open(target, 'w').write(target_contents) + write_file(target, target_contents) def worker_js_script(proxy_worker_filename): - web_gl_client_src = open(shared.path_from_root('src', 'webGLClient.js')).read() - idb_store_src = open(shared.path_from_root('src', 'IDBStore.js')).read() - proxy_client_src = open(shared.path_from_root('src', 'proxyClient.js')).read() + web_gl_client_src = read_file(shared.path_from_root('src', 'webGLClient.js')) + idb_store_src = read_file(shared.path_from_root('src', 'IDBStore.js')) + proxy_client_src = read_file(shared.path_from_root('src', 'proxyClient.js')) proxy_client_src = do_replace(proxy_client_src, '{{{ filename }}}', proxy_worker_filename) proxy_client_src = do_replace(proxy_client_src, '{{{ IDBStore.js }}}', idb_store_src) return web_gl_client_src + '\n' + proxy_client_src diff --git a/emrun.py b/emrun.py index 34e9eb5088985..b4c05cf24cf43 100755 --- a/emrun.py +++ b/emrun.py @@ -691,7 +691,8 @@ def do_POST(self): except OSError: pass filename = os.path.join(dump_out_directory, os.path.normpath(filename)) - open(filename, 'wb').write(data) + with open(filename, 'wb') as fh: + fh.write(data) logi('Wrote ' + str(len(data)) + ' bytes to file "' + filename + '".') have_received_messages = True elif path == '/system_info': @@ -1060,7 +1061,8 @@ def get_computer_model(): model = check_output(cmd) model = re.search('(.*)', model) model = model.group(1).strip() - open(os.path.join(os.getenv("HOME"), '.emrun.hwmodel.cached'), 'w').write(model) # Cache the hardware model to disk + with open(os.path.join(os.getenv("HOME"), '.emrun.hwmodel.cached'), 'w') as fh: + fh.write(model) # Cache the hardware model to disk return model except Exception: hwmodel = check_output(['sysctl', 'hw.model']) @@ -1385,7 +1387,8 @@ def get_system_info(format_json): return info.strip() else: try: - unique_system_id = open(os.path.expanduser('~/.emrun.generated.guid'), 'r').read().strip() + with open(os.path.expanduser('~/.emrun.generated.guid')) as fh: + unique_system_id = fh.read().strip() except Exception: import uuid unique_system_id = str(uuid.uuid4()) diff --git a/site/source/conf.py b/site/source/conf.py index 7b572b5ee1a36..7ed7e0576e992 100644 --- a/site/source/conf.py +++ b/site/source/conf.py @@ -18,6 +18,7 @@ import sys import os +from pathlib import Path # At the top. #HamishW https://pypi.python.org/pypi/sphinx-bootstrap-theme/ ... @@ -93,8 +94,7 @@ # |version| and |release|, also used in various other places throughout the # built documents. # - -emscripten_version = open(os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'emscripten-version.txt'))).read().strip().replace('"', '') +emscripten_version = Path(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'emscripten-version.txt').resolve().read_text().strip().replace('"', '') # The short X.Y version. version = emscripten_version[:emscripten_version.rindex('.')] diff --git a/site/source/get_wiki.py b/site/source/get_wiki.py index 5987954c7c63d..6464ff976f1cc 100755 --- a/site/source/get_wiki.py +++ b/site/source/get_wiki.py @@ -22,6 +22,7 @@ import stat import sys import time +from pathlib import Path import api_items @@ -91,7 +92,7 @@ def ConvertFilesToRst(): continue inputfilename = wiki_checkout + file - markdown = open(inputfilename).read() + markdown = Path(inputfilename).read_text() if 'This article has moved from the wiki to the new site' in markdown: continue if 'This page has been migrated to the main site' in markdown: diff --git a/tools/clean_webconsole.py b/tools/clean_webconsole.py index f1cc8545720ac..630d2ab495ae6 100644 --- a/tools/clean_webconsole.py +++ b/tools/clean_webconsole.py @@ -9,6 +9,7 @@ import os import re import sys +from pathlib import Path __rootpath__ = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -21,8 +22,11 @@ def nice(x): return '0x' + ('0' * (len(x) - 6)) + x[2:].upper() -repdata = open(path_from_root('system', 'include', 'GL', 'gl.h')).readlines() + ['\n'] + \ - open(path_from_root('system', 'include', 'GL', 'glext.h')).readlines() +repdata = ( + Path(path_from_root('system', 'include', 'GL', 'gl.h')).read_text().splitline(keepends=True) + + ['\n'] + + Path(path_from_root('system', 'include', 'GL', 'glext.h')).read_text().splitlines(keepends=True) +) reps = {} for rep in repdata: rep = rep.replace('\t', ' ').replace('\n', '') diff --git a/tools/config.py b/tools/config.py index 2acd58306207b..732f26a98e981 100644 --- a/tools/config.py +++ b/tools/config.py @@ -106,7 +106,8 @@ def parse_config_file(): Also check EM_ environment variables to override specific config keys. """ config = {} - config_text = open(EM_CONFIG, 'r').read() + with open(EM_CONFIG) as fh: + config_text = fh.read() try: exec(config_text, config) except Exception as e: @@ -171,7 +172,9 @@ def parse_config_file(): def generate_config(path, first_time=False): # Note: repr is used to ensure the paths are escaped correctly on Windows. # The full string is replaced so that the template stays valid Python. - config_data = open(path_from_root('tools', 'settings_template.py')).read().splitlines() + + with open(path_from_root('tools', 'settings_template.py')) as fh: + config_data = fh.read().splitlines() config_data = config_data[3:] # remove the initial comment config_data = '\n'.join(config_data) # autodetect some default paths diff --git a/tools/ctor_evaller.py b/tools/ctor_evaller.py index 336d9013508f4..f780183cb5ff5 100755 --- a/tools/ctor_evaller.py +++ b/tools/ctor_evaller.py @@ -93,7 +93,7 @@ def eval_ctors(js, wasm_file, num): # main def main(): - js = open(js_file).read() + js = shared.read_file(js_file) ctors_start, ctors_end = find_ctors(js) if ctors_start < 0: logger.debug('ctor_evaller: no ctors') @@ -114,7 +114,7 @@ def main(): logger.debug('ctor_evaller: not successful') sys.exit(0) logger.debug('ctor_evaller: we managed to remove %d ctors' % num_successful) - open(js_file, 'w').write(new_js) + shared.write_file(js_file, new_js) if __name__ == '__main__': diff --git a/tools/debug/autodediffer.py b/tools/debug/autodediffer.py index ad2d46375bb34..be9385ef9dab7 100644 --- a/tools/debug/autodediffer.py +++ b/tools/debug/autodediffer.py @@ -12,6 +12,8 @@ from __future__ import print_function import os, sys +from pathlib import Path + def process_line(line): #AD:2041,0.900000 @@ -20,8 +22,8 @@ def process_line(line): num, val = line.split(',') return [int(num), float(val)] -a = open(sys.argv[1], 'r').readlines() -b = open(sys.argv[2], 'r').readlines() +a = Path(sys.argv[1]).read_text().splitlines(keepends=True) +b = Path(sys.argv[2]).read_text().splitlines(keepends=True) MIN = 0.0001 if len(sys.argv) < 4 else sys.argv[3] ai = 0 diff --git a/tools/debug/bisect_pair.py b/tools/debug/bisect_pair.py index ccaa623eaef74..678ff024579f4 100644 --- a/tools/debug/bisect_pair.py +++ b/tools/debug/bisect_pair.py @@ -11,23 +11,20 @@ from __future__ import print_function import os, sys, shutil +from pathlib import Path from subprocess import Popen, PIPE, STDOUT __rootpath__ = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) + + def path_from_root(*pathelems): return os.path.join(__rootpath__, *pathelems) -exec(open(path_from_root('tools', 'shared.py'), 'r').read()) - -file1 = open(sys.argv[1]).read() -file2 = open(sys.argv[2]).read() + +exec(Path(path_from_root('tools', 'shared.py').read_text())) -leftf = open('left', 'w') -leftf.write(file1) -leftf.close() +shutil.copyfile(sys.argv[1], 'left') +shutil.copyfile(sys.argv[2], 'right') -rightf = open('right', 'w') -rightf.write(file2) -rightf.close() def run_code(name): ret = run_js(name, stderr=PIPE, full_output=True, assert_returncode=None, engine=SPIDERMONKEY_ENGINE) diff --git a/tools/debug/bisect_pair_lines.py b/tools/debug/bisect_pair_lines.py index 4ad06d7d5555b..38a53ca23017c 100644 --- a/tools/debug/bisect_pair_lines.py +++ b/tools/debug/bisect_pair_lines.py @@ -13,23 +13,18 @@ from __future__ import print_function import os, sys, shutil +from pathlib import Path from subprocess import Popen, PIPE, STDOUT __rootpath__ = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) def path_from_root(*pathelems): return os.path.join(__rootpath__, *pathelems) -exec(open(path_from_root('tools', 'shared.py'), 'r').read()) + +exec(Path(path_from_root('tools', 'shared.py').read()) -file1 = open(sys.argv[1]).read() -file2 = open(sys.argv[2]).read() +shutil.copyfile(sys.argv[1], 'left') +shutil.copyfile(sys.argv[2], 'right') -leftf = open('left', 'w') -leftf.write(file1) -leftf.close() - -rightf = open('right', 'w') -rightf.write(file2) -rightf.close() def run_code(name): ret = run_js(name, stderr=PIPE, full_output=True) @@ -53,7 +48,7 @@ def run_code(name): while True: mid = int((low + high)/2) print(low, high, ' current: %d' % mid, end=' ') - open('middle', 'w').write('\n'.join(left_lines[:mid] + right_lines[mid:])) + Path('middle').write_text('\n'.join(left_lines[:mid] + right_lines[mid:])) shutil.copyfile('middle', 'middle' + str(mid)) result = run_code('middle') print(result == left_result, result == right_result)#, 'XXX', left_result, 'YYY', result, 'ZZZ', right_result diff --git a/tools/debug/bisect_pair_wast.py b/tools/debug/bisect_pair_wast.py index 36e78664cb080..68786c872700b 100644 --- a/tools/debug/bisect_pair_wast.py +++ b/tools/debug/bisect_pair_wast.py @@ -11,23 +11,18 @@ from __future__ import print_function import os, sys, shutil +from pathlib import Path from subprocess import Popen, PIPE, STDOUT __rootpath__ = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) + def path_from_root(*pathelems): return os.path.join(__rootpath__, *pathelems) -exec(open(path_from_root('tools', 'shared.py'), 'r').read()) - -file1 = open(sys.argv[1]).read() -file2 = open(sys.argv[2]).read() -leftf = open('left', 'w') -leftf.write(file1) -leftf.close() +exec(Path(path_from_root('tools', 'shared.py')).read_text()) -rightf = open('right', 'w') -rightf.write(file2) -rightf.close() +shutil.copyfile(sys.argv[1], 'left') +shutil.copyfile(sys.argv[2], 'right') def run_code(name): shutil.copyfile(name, 'src.cpp.o.wat') diff --git a/tools/debug/diff_autodebugger.py b/tools/debug/diff_autodebugger.py index 36d8d28422cec..6c50be0fd04bd 100644 --- a/tools/debug/diff_autodebugger.py +++ b/tools/debug/diff_autodebugger.py @@ -9,9 +9,11 @@ ''' from __future__ import print_function import os, sys +from pathlib import Path -f1 = open(sys.argv[1], 'r').readlines() -f2 = open(sys.argv[2], 'r').readlines() + +f1 = Path(sys.argv[1]).read_text().splitlines(keepends=True) +f2 = Path(sys.argv[2]).read_text().splitlines(keepends=True) for i in range(len(f1)): if f1[i] == f2[i]: continue diff --git a/tools/debug/find_bigis.py b/tools/debug/find_bigis.py index 9d02c677aefbc..e7b72950c2979 100644 --- a/tools/debug/find_bigis.py +++ b/tools/debug/find_bigis.py @@ -9,9 +9,10 @@ from __future__ import print_function import os, sys, re +from pathlib import Path filename = sys.argv[1] -data = open(filename).read() +data = Path(filename).read_text() iss = re.findall(r' i\d+ [^=]', data) set_iss = set(iss) bigs = [] diff --git a/tools/debug/stubify_ll.py b/tools/debug/stubify_ll.py index 9c1f29ca30b79..890a6768eac01 100644 --- a/tools/debug/stubify_ll.py +++ b/tools/debug/stubify_ll.py @@ -9,11 +9,13 @@ from __future__ import print_function import os, sys +from pathlib import Path + kill = False valids = sys.argv[2].split(',') -for line in open(sys.argv[1]).readlines(): +for line in Path(sys.argv[1]).read_text().splitlines(keepends=True): line = line.replace('\n', '') if line.startswith('define ') and line.endswith('{'): ok = False diff --git a/tools/determinism_checker.py b/tools/determinism_checker.py index a129ab27941de..952cdd9f8a625 100644 --- a/tools/determinism_checker.py +++ b/tools/determinism_checker.py @@ -10,13 +10,14 @@ import random import subprocess import time +from pathlib import Path def run(): subprocess.check_call(['emcc', 'src.cpp', '-O2']) ret = {} for relevant_file in os.listdir('.'): - ret[relevant_file] = open(relevant_file).read() + ret[relevant_file] = Path(relevant_file).read_text() return ret @@ -24,12 +25,12 @@ def write(data, subdir): if not os.path.exists(subdir): os.mkdir(subdir) for relevant_file in data.keys(): - open(os.path.join(subdir, relevant_file), 'w').write(data[relevant_file]) + Path(os.path.join(subdir, relevant_file)).write_text(data[relevant_file]) os.chdir('/tmp/emscripten_temp') assert len(os.listdir('.')) == 0, 'temp dir should start out empty, after that, everything there looks important to us' -open('src.cpp', 'w').write(''' +Path('src.cpp').write_text(''' #include int main() diff --git a/tools/emdump.py b/tools/emdump.py index 0ec6910e80959..33949cf37ff64 100755 --- a/tools/emdump.py +++ b/tools/emdump.py @@ -14,6 +14,8 @@ import re import subprocess import sys +from pathlib import Path + # If true, we are printing delta information between two data sets. If false, we are just printing symbol info for a single data set diffing_two_data_sets = False @@ -372,13 +374,13 @@ def analyze_javascript_file_contents(filename, file_contents, total_source_set_s def analyze_javascript_file(filename, total_source_set_size, symbol_map=None): - file_contents = open(filename).read() + file_contents = Path(filename).read_text() print('Analyzing JS file ' + filename + ', ' + str(len(file_contents)) + ' bytes...') return analyze_javascript_file_contents(filename, file_contents, total_source_set_size, symbol_map) def analyze_html_file(filename, total_source_set_size, symbol_map=None): - file_contents = open(filename).read() + file_contents = Path(filename).read_text() print('Analyzing HTML file ' + filename + ', ' + str(len(file_contents)) + ' bytes...') data = {} parse_pos = 0 diff --git a/tools/emprofile.py b/tools/emprofile.py index 43206f8c41add..8163776e61c78 100755 --- a/tools/emprofile.py +++ b/tools/emprofile.py @@ -10,6 +10,8 @@ import sys import tempfile import time +from pathlib import Path + profiler_logs_path = os.path.join(tempfile.gettempdir(), 'emscripten_toolchain_profiler_logs') @@ -53,7 +55,7 @@ def create_profiling_graph(): print('Processing ' + str(len(log_files)) + ' profile log files in "' + profiler_logs_path + '"...') for f in log_files: try: - json_data = open(f, 'r').read() + json_data = Path(f).read_text() if len(json_data.strip()) == 0: continue lines = json_data.split('\n') @@ -75,8 +77,8 @@ def create_profiling_graph(): emprofile_json_data = json.dumps(all_results, indent=2) html_file = OUTFILE + '.html' - html_contents = open(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'toolchain_profiler.results_template.html'), 'r').read().replace('{{{ emprofile_json_data }}}', emprofile_json_data) - open(html_file, 'w').write(html_contents) + html_contents = Path(os.path.dirname(os.path.realpath(__file__)), 'toolchain_profiler.results_template.html').read_text().replace('{{{ emprofile_json_data }}}', emprofile_json_data) + Path(html_file).write_text(html_contents) print('Wrote "' + html_file + '"') diff --git a/tools/experimental/reproduceriter.py b/tools/experimental/reproduceriter.py index d2f4768daf168..9f36f23f85f07 100644 --- a/tools/experimental/reproduceriter.py +++ b/tools/experimental/reproduceriter.py @@ -113,6 +113,7 @@ import re import sys import shutil +from pathlib import Path assert len(sys.argv) >= 4, 'Usage: reproduceriter.py IN_DIR OUT_DIR FIRST_JS [WINDOW_LOCATION]' @@ -147,21 +148,23 @@ if filename.endswith('.js'): fullname = os.path.join(parent, filename) print(' ', fullname) - js = open(fullname).read() + with open(fullname) as fh: + js = fh.read() js = re.sub(r'document\.on(\w+) ?= ?([\w.$]+)', lambda m: 'Recorder.onEvent("' + m.group(1) + '", ' + m.group(2) + ')', js) js = re.sub(r'''([\w.'"\[\]]+)\.addEventListener\(([\w,. $]+)\)''', lambda m: 'Recorder.addListener(' + m.group(1) + ', ' + m.group(2) + ')', js) - open(fullname, 'w').write(js) + Path(fullname).write_text(js) # Add our boilerplate print('add boilerplate...') -open(os.path.join(out_dir, first_js), 'w').write( - (open(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'src', 'headless.js')).read() % ( - window_location, window_location.split('?')[-1], on_idle or 'null', dirs_to_drop - ) if shell else '') + - open(os.path.join(os.path.dirname(__file__), 'reproduceriter.js')).read() + - open(os.path.join(in_dir, first_js)).read() + ('\nwindow.runEventLoop();\n' if shell else '') -) +with open(os.path.join(out_dir, first_js), 'w') as fh1: + fh1.write( + (Path(os.path.dirname(os.path.dirname(__file__)), 'src', 'headless.js').read_text() % ( + window_location, window_location.split('?')[-1], on_idle or 'null', dirs_to_drop + ) if shell else '') + + Path(os.path.dirname(__file__), 'reproduceriter.js').read_text() + + Path(in_dir, first_js).read_text() + ('\nwindow.runEventLoop();\n' if shell else '') + ) print('done!') diff --git a/tools/file_packager.py b/tools/file_packager.py index 50500ef14d5d0..40e4b7eb2120b 100755 --- a/tools/file_packager.py +++ b/tools/file_packager.py @@ -458,7 +458,7 @@ def was_seen(name): basename = os.path.basename(filename) if file_['mode'] == 'embed': # Embed - data = list(bytearray(open(file_['srcpath'], 'rb').read())) + data = list(bytearray(shared.read_binary(file_['srcpath']))) code += '''var fileData%d = [];\n''' % counter if data: parts = [] diff --git a/tools/hacky_postprocess_around_closure_limitations.py b/tools/hacky_postprocess_around_closure_limitations.py index 99b0ab4540869..dfed1cabb4535 100644 --- a/tools/hacky_postprocess_around_closure_limitations.py +++ b/tools/hacky_postprocess_around_closure_limitations.py @@ -6,8 +6,9 @@ sys.path.insert(1, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from tools import building +from tools.shared import read_file, write_file -f = open(sys.argv[1], 'r').read() +f = read_file(sys.argv[1]) orig_size = len(f) f = f.strip() @@ -51,10 +52,10 @@ f = re.sub(r'([;{}=,\*/\(\)\[\]])[\s]', r'\1', f) # Finally, rerun minifier because the above changes may have left redundant whitespaces -open(sys.argv[1], 'w').write(f) +write_file(sys.argv[1], f) minified = building.acorn_optimizer(sys.argv[1], ['minifyWhitespace'], return_output=True) -open(sys.argv[1], 'w').write(minified) +write_file(sys.argv[1], minified) # optimized_size = len(f) # print('Further optimized ' + str(optimized_size - orig_size) + ' bytes (' + str(orig_size) + ' -> ' + str(optimized_size) + ' bytes, {0:.2f}'.format((optimized_size-orig_size)*100.0/orig_size) + '%)') -open(sys.argv[1], 'w').write(f) +write_file(sys.argv[1], f) diff --git a/tools/js_optimizer.py b/tools/js_optimizer.py index 54e4abc40a0c9..ef9bbcb0e0312 100755 --- a/tools/js_optimizer.py +++ b/tools/js_optimizer.py @@ -151,7 +151,7 @@ def run_on_js(filename, passes, extra_info=None, just_split=False, just_concat=F if not isinstance(passes, list): passes = [passes] - js = open(filename).read() + js = shared.read_file(filename) if os.linesep != '\n': js = js.replace(os.linesep, '\n') # we assume \n in the splitting code @@ -333,7 +333,7 @@ def write_chunk(chunk, i): acorn_passes.append('minifyWhitespace') cld = building.acorn_optimizer(cld, acorn_passes) temp_files.note(cld) - coutput = open(cld).read() + coutput = shared.read_file(cld) coutput = coutput.replace('wakaUnknownBefore();', start_asm) after = 'wakaUnknownAfter' @@ -364,7 +364,7 @@ def write_chunk(chunk, i): # sort functions by size, to make diffing easier and to improve aot times funcses = [] for out_file in filenames: - funcses.append(split_funcs(open(out_file).read(), False)) + funcses.append(split_funcs(shared.read_file(out_file), False)) funcs = [item for sublist in funcses for item in sublist] funcses = None if not os.environ.get('EMCC_NO_OPT_SORT'): @@ -381,7 +381,7 @@ def write_chunk(chunk, i): else: # just concat the outputs for out_file in filenames: - f.write(open(out_file).read()) + f.write(shared.read_file(out_file)) with ToolchainProfiler.profile_block('write_post'): f.write('\n') diff --git a/tools/minimal_runtime_shell.py b/tools/minimal_runtime_shell.py index 741781d41a9c4..32df6d6a4f7d2 100644 --- a/tools/minimal_runtime_shell.py +++ b/tools/minimal_runtime_shell.py @@ -157,7 +157,7 @@ def generate_minimal_runtime_load_statement(target_basename): def generate_minimal_runtime_html(target, options, js_target, target_basename): logger.debug('generating HTML for minimal runtime') - shell = open(options.shell_path, 'r').read() + shell = shared.read_file(options.shell_path) if settings.SINGLE_FILE: # No extra files needed to download in a SINGLE_FILE build. shell = shell.replace('{{{ DOWNLOAD_JS_AND_WASM_FILES }}}', '') @@ -166,7 +166,7 @@ def generate_minimal_runtime_html(target, options, js_target, target_basename): temp_files = shared.configuration.get_temp_files() with temp_files.get_file(suffix='.js') as shell_temp: - open(shell_temp, 'w').write(shell) + shared.write_file(shell_temp, shell) shell = shared.read_and_preprocess(shell_temp) if re.search(r'{{{\s*SCRIPT\s*}}}', shell): @@ -178,7 +178,7 @@ def generate_minimal_runtime_html(target, options, js_target, target_basename): # In SINGLE_FILE build, embed the main .js file into the .html output if settings.SINGLE_FILE: - js_contents = open(js_target).read() + js_contents = shared.read_file(js_target) shared.try_delete(js_target) else: js_contents = '' diff --git a/tools/ports/freetype.py b/tools/ports/freetype.py index c028626c3b1ab..74f0b741c1d7f 100644 --- a/tools/ports/freetype.py +++ b/tools/ports/freetype.py @@ -5,6 +5,7 @@ import os import shutil +from pathlib import Path TAG = 'version_1' HASH = '0d0b1280ba0501ad0a23cf1daa1f86821c722218b59432734d3087a89acd22aabd5c3e5e1269700dcd41e87073046e906060f167c032eb91a3ac8c5808a02783' @@ -26,7 +27,7 @@ def create(final): os.makedirs(dest_path) shutil.rmtree(dest_path, ignore_errors=True) shutil.copytree(source_path, dest_path) - open(os.path.join(dest_path, 'include/ftconfig.h'), 'w').write(ftconf_h) + Path(dest_path, 'include/ftconfig.h').write_text(ftconf_h) # build srcs = ['src/autofit/autofit.c', diff --git a/tools/ports/libjpeg.py b/tools/ports/libjpeg.py index 2413775a40f91..796114cc66de9 100644 --- a/tools/ports/libjpeg.py +++ b/tools/ports/libjpeg.py @@ -6,6 +6,7 @@ import os import shutil import logging +from pathlib import Path VERSION = '9c' HASH = 'b2affe9a1688bd49fc033f4682c4a242d4ee612f1affaef532f5adcb4602efc4433c4a52a4b3d69e7440ff1f6413b1b041b419bc90efd6d697999961a9a6afb7' @@ -30,7 +31,7 @@ def create(final): shutil.rmtree(dest_path, ignore_errors=True) shutil.copytree(source_path, dest_path) - open(os.path.join(dest_path, 'jconfig.h'), 'w').write(jconfig_h) + Path(dest_path, 'jconfig.h').write_text(jconfig_h) ports.install_headers(dest_path) ports.build_port( diff --git a/tools/ports/libmodplug.py b/tools/ports/libmodplug.py index b934c2e7a2390..307c9d022ab90 100644 --- a/tools/ports/libmodplug.py +++ b/tools/ports/libmodplug.py @@ -6,6 +6,7 @@ import os import shutil import logging +from pathlib import Path TAG = '11022021' HASH = 'f770031ad6c2152cbed8c8eab8edf2be1d27f9e74bc255a9930c17019944ee5fdda5308ea992c66a78af9fe1d8dca090f6c956910ce323f8728247c10e44036b' @@ -30,7 +31,7 @@ def create(output_path): shutil.rmtree(dest_path, ignore_errors=True) shutil.copytree(source_path, dest_path) - open(os.path.join(sauce_path, 'config.h'), 'w').write(config_h) + Path(sauce_path, 'config.h').write_text(config_h) flags = [ '-DOPT_GENERIC', diff --git a/tools/ports/libpng.py b/tools/ports/libpng.py index 8e17609a0be09..a79c4ab73956c 100644 --- a/tools/ports/libpng.py +++ b/tools/ports/libpng.py @@ -6,6 +6,7 @@ import os import shutil import logging +from pathlib import Path TAG = '1.6.37' HASH = '2ce2b855af307ca92a6e053f521f5d262c36eb836b4810cb53c809aa3ea2dcc08f834aee0ffd66137768a54397e28e92804534a74abb6fc9f6f3127f14c9c338' @@ -30,7 +31,7 @@ def create(final): shutil.rmtree(dest_path, ignore_errors=True) shutil.copytree(source_path, dest_path) - open(os.path.join(dest_path, 'pnglibconf.h'), 'w').write(pnglibconf_h) + Path(dest_path, 'pnglibconf.h').write_text(pnglibconf_h) ports.install_headers(dest_path) ports.build_port(dest_path, final, flags=['-s', 'USE_ZLIB=1'], exclude_files=['pngtest'], exclude_dirs=['scripts', 'contrib']) diff --git a/tools/ports/mpg123.py b/tools/ports/mpg123.py index 8160fb1480b6c..bc2f92c3f1f85 100644 --- a/tools/ports/mpg123.py +++ b/tools/ports/mpg123.py @@ -6,6 +6,7 @@ import os import shutil import logging +from pathlib import Path TAG = '1.26.2' HASH = 'aa63fcb08b243a1e09f7701b3d84a19d7412a87253d54d49f014fdb9e75bbc81d152a41ed750fccde901453929b2a001585a7645351b41845ad205c17a73dcc9' @@ -30,8 +31,8 @@ def create(output_path): shutil.rmtree(dest_path, ignore_errors=True) shutil.copytree(source_path, dest_path) - open(os.path.join(sauce_path, 'config.h'), 'w').write(config_h) - open(os.path.join(libmpg123_path, 'mpg123.h'), 'w').write(mpg123_h) + Path(sauce_path, 'config.h').write_text(config_h) + Path(libmpg123_path, 'mpg123.h').write_text(mpg123_h) flags = [ '-DOPT_GENERIC', diff --git a/tools/ports/ogg.py b/tools/ports/ogg.py index 95c86a17c83e7..29ed89662ecf2 100644 --- a/tools/ports/ogg.py +++ b/tools/ports/ogg.py @@ -6,6 +6,7 @@ import logging import os import shutil +from pathlib import Path TAG = 'version_1' HASH = '929e8d6003c06ae09593021b83323c8f1f54532b67b8ba189f4aedce52c25dc182bac474de5392c46ad5b0dea5a24928e4ede1492d52f4dd5cd58eea9be4dba7' @@ -28,7 +29,7 @@ def create(final): shutil.rmtree(dest_path, ignore_errors=True) shutil.copytree(source_path, dest_path) - open(os.path.join(dest_path, 'include', 'ogg', 'config_types.h'), 'w').write(config_types_h) + Path(dest_path, 'include', 'ogg', 'config_types.h').write_text(config_types_h) header_dir = os.path.join(ports.get_include_dir(), 'ogg') shutil.rmtree(header_dir, ignore_errors=True) diff --git a/tools/ports/zlib.py b/tools/ports/zlib.py index 0542063cecee4..bcde7fb90ab69 100644 --- a/tools/ports/zlib.py +++ b/tools/ports/zlib.py @@ -5,6 +5,7 @@ import os import shutil +from pathlib import Path TAG = '1.2.11' HASH = 'a42b8359e76cf7b3ae70bf31f0f8a8caa407ac80e8fe08b838076cd5e45ac2e685dae45eb59db2d25543fb3b5bd13b843a02bb8373cda704d7238be50d5e9c68' @@ -26,7 +27,7 @@ def create(final): os.makedirs(dest_path) shutil.rmtree(dest_path, ignore_errors=True) shutil.copytree(source_path, dest_path) - open(os.path.join(dest_path, 'zconf.h'), 'w').write(zconf_h) + Path(dest_path, 'zconf.h').write_text(zconf_h) ports.install_headers(dest_path) # build diff --git a/tools/settings.py b/tools/settings.py index 7d2bfc71b24a9..9d1c1ed76a2bb 100644 --- a/tools/settings.py +++ b/tools/settings.py @@ -96,13 +96,15 @@ def __init__(self): self.allowed_settings.clear() # Load the JS defaults into python. - settings = open(path_from_root('src', 'settings.js')).read().replace('//', '#') + with open(path_from_root('src', 'settings.js')) as fh: + settings = fh.read().replace('//', '#') settings = re.sub(r'var ([\w\d]+)', r'attrs["\1"]', settings) # Variable TARGET_NOT_SUPPORTED is referenced by value settings.js (also beyond declaring it), # so must pass it there explicitly. exec(settings, {'attrs': self.attrs}) - settings = open(path_from_root('src', 'settings_internal.js')).read().replace('//', '#') + with open(path_from_root('src', 'settings_internal.js')) as fh: + settings = fh.read().replace('//', '#') settings = re.sub(r'var ([\w\d]+)', r'attrs["\1"]', settings) internal_attrs = {} exec(settings, {'attrs': internal_attrs}) diff --git a/tools/shared.py b/tools/shared.py index 86cb8ba50bcfb..2f62fe7dfe6f9 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -339,7 +339,7 @@ def set_version_globals(): def generate_sanity(): sanity_file_content = EMSCRIPTEN_VERSION + '|' + config.LLVM_ROOT + '|' + get_clang_version() - config_data = open(config.EM_CONFIG).read() + config_data = read_file(config.EM_CONFIG) checksum = binascii.crc32(config_data.encode()) sanity_file_content += '|%#x\n' % checksum return sanity_file_content @@ -407,7 +407,7 @@ def check_sanity(force=False): sanity_file = Cache.get_path('sanity.txt') with Cache.lock(): if os.path.exists(sanity_file): - sanity_data = open(sanity_file).read() + sanity_data = read_file(sanity_file) if sanity_data != expected: logger.debug('old sanity: %s' % sanity_data) logger.debug('new sanity: %s' % expected) @@ -788,7 +788,7 @@ def read_and_preprocess(filename, expand_macros=False): args += ['--expandMacros'] run_js_tool(path_from_root('tools/preprocessor.js'), args, True, stdout=open(stdout, 'w'), cwd=dirname) - out = open(stdout, 'r').read() + out = read_file(stdout) return out @@ -799,6 +799,24 @@ def do_replace(input_, pattern, replacement): return input_.replace(pattern, replacement) +def read_file(file_path): + """Read from a file opened in text mode""" + with open(file_path) as fh: + return fh.read() + + +def read_binary(file_path): + """Read from a file opened in binary mode""" + with open(file_path, 'rb') as fh: + return fh.read() + + +def write_file(file_path, text): + """Write to a file opened in text mode""" + with open(file_path, 'w') as fh: + fh.write(text) + + # ============================================================================ # End declarations. # ============================================================================ diff --git a/tools/update_js.py b/tools/update_js.py index 7570bb9c52e45..3b134cc839060 100644 --- a/tools/update_js.py +++ b/tools/update_js.py @@ -8,6 +8,7 @@ ''' import os +from pathlib import Path def all_children(subdir): @@ -20,7 +21,7 @@ def all_children(subdir): if not (x.endswith('.py') or x.endswith('.c') or x.endswith('.cpp') or x.endswith('.h') or x.endswith('.js') or x.endswith('.ll')): continue print(x) - orig = open(x).read() + orig = Path(x).read_text() fixed = orig.copy() fixed = fixed.replace('Module["print"](', 'out(') fixed = fixed.replace('Module[\'print\'](', 'out(') @@ -45,4 +46,4 @@ def all_children(subdir): fixed = fixed.replace('Module.printErr = ', 'err = ') if fixed != orig: - open(x, 'w').write(fixed) + Path(x).write_text(fixed) diff --git a/tools/wasm-sourcemap.py b/tools/wasm-sourcemap.py index a18b1e64d7877..ca1571d17056b 100755 --- a/tools/wasm-sourcemap.py +++ b/tools/wasm-sourcemap.py @@ -18,10 +18,12 @@ import os import re from subprocess import Popen, PIPE +from pathlib import Path import sys sys.path.insert(1, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + logger = logging.getLogger('wasm-sourcemap') @@ -176,7 +178,7 @@ def remove_dead_entries(entries): def read_dwarf_entries(wasm, options): if options.dwarfdump_output: - output = open(options.dwarfdump_output, 'rb').read() + output = Path(options.dwarfdump_output).read_bytes() elif options.dwarfdump: logger.debug('Reading DWARF information from %s' % wasm) if not os.path.exists(options.dwarfdump): diff --git a/tools/webassembly.py b/tools/webassembly.py index 9081e94af15bb..d34330797169a 100644 --- a/tools/webassembly.py +++ b/tools/webassembly.py @@ -97,7 +97,7 @@ def add_emscripten_metadata(wasm_file): # the EMSCRIPTEN_METADATA_MINOR ) - orig = open(wasm_file, 'rb').read() + orig = shared.read_binary(wasm_file) with open(wasm_file, 'wb') as f: f.write(orig[0:8]) # copy magic number and version # write the special section diff --git a/tools/webidl_binder.py b/tools/webidl_binder.py index 4f625e9a52825..201b18da6c8de 100644 --- a/tools/webidl_binder.py +++ b/tools/webidl_binder.py @@ -55,7 +55,7 @@ def getExtendedAttribute(self, name): # noqa: U100 p.parse(r''' interface VoidPtr { }; -''' + open(input_file).read()) +''' + shared.read_file(input_file)) data = p.finish() interfaces = {}