From 19345a7607224c9b1c3612dfd106b1aca69cb560 Mon Sep 17 00:00:00 2001 From: Christian Clauss Date: Mon, 9 Dec 2024 17:42:26 +0100 Subject: [PATCH] Python lint: Use ruff instead of flake8. NFC (#23085) https://docs.astral.sh/ruff is an extremely fast Python linter and code formatter, written in Rust. With over 800 linting rules, ruff can be used to replace [Flake8](https://pypi.org/project/flake8/) (plus dozens of plugins), [Black](https://github.com/psf/black), [isort](https://pypi.org/project/isort/), [pydocstyle](https://pypi.org/project/pydocstyle/), [pyupgrade](https://pypi.org/project/pyupgrade/), [autoflake](https://pypi.org/project/autoflake/), and more, all while executing tens or hundreds of times faster than any individual tool. --- .circleci/config.yml | 6 +-- .flake8 | 19 ---------- docs/process.md | 6 +-- em-config.py | 2 +- emcc.py | 12 +++++- emrun.py | 10 ++++- emsymbolizer.py | 4 +- pyproject.toml | 67 +++++++++++++++++++++++++++++++++ requirements-dev.txt | 6 +-- test/benchmark/benchmark_sse.py | 4 +- test/runner.py | 6 +-- tools/file_packager.py | 10 ++++- tools/link.py | 10 ++++- tools/webidl_binder.py | 10 ++++- 14 files changed, 127 insertions(+), 45 deletions(-) delete mode 100644 .flake8 diff --git a/.circleci/config.yml b/.circleci/config.yml index c0536063facaa..5c5844c7e8c63 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -419,12 +419,12 @@ jobs: - run: make -C site text - run: tools/maint/check_emcc_help_text.py - run: make -C site html - flake8: + ruff: executor: bionic steps: - checkout - pip-install - - run: python3 -m flake8 --show-source --statistics + - run: ruff check mypy: executor: bionic steps: @@ -970,7 +970,7 @@ jobs: workflows: build-test: jobs: - - flake8 + - ruff - mypy - eslint - build-docs diff --git a/.flake8 b/.flake8 deleted file mode 100644 index 865ca1e004956..0000000000000 --- a/.flake8 +++ /dev/null @@ -1,19 +0,0 @@ -[flake8] -ignore = E111,E114,E501,E261,E266,E121,E402,E241,W504,E741,B011,B023,U101 -exclude = - ./node_modules/, # third-party code - ./third_party/, # third-party code - ./tools/filelock.py, # third-party code - ./tools/scons/, # third-party code - ./test/third_party/, # third-party code - ./site/source/conf.py, - ./site/source/_themes/, - ./system/lib/, # system libraries - ./cache/, # download/built content - .git -# The ports plugins have a lot of unused imports because -# they need to implement the specific plugin APIs -per-file-ignores = - ./tools/ports/*.py: U100 - ./test/*.py: U100 - ./tools/toolchain_profiler.py: U100 diff --git a/docs/process.md b/docs/process.md index 0c3b23b1062d7..f1bf04a714a11 100644 --- a/docs/process.md +++ b/docs/process.md @@ -55,8 +55,8 @@ pre-processor. See [`.clang-format`][clang-format] for more details. ### Python Code We generally follow the pep8 standard with the major exception that we use 2 -spaces for indentation. `flake8` is run on all PRs to ensure that python code -conforms to this style. See [`.flake8`][flake8] for more details. +spaces for indentation. `ruff` is run on all PRs to ensure that Python code +conforms to this style. See [`pyproject.toml`][pyproject.toml] for more details. #### Static Type Checking @@ -304,7 +304,7 @@ To update our libraries to a newer musl release: [emsdk_tags]: https://github.com/emscripten-core/emsdk/tags [emscripten_tags]: https://github.com/emscripten-core/emscripten/tags [clang-format]: https://github.com/emscripten-core/emscripten/blob/main/.clang-format -[flake8]: https://github.com/emscripten-core/emscripten/blob/main/.flake8 +[pyproject.toml]: https://github.com/emscripten-core/emscripten/blob/main/pyproject.toml [mypy]: https://github.com/emscripten-core/emscripten/blob/main/.mypy [update_docs]: https://github.com/emscripten-core/emscripten/blob/main/tools/maint/update_docs.py [llvm_repo]: https://github.com/llvm/llvm-project diff --git a/em-config.py b/em-config.py index 2708d18ca6dd2..bcbd9abe1cf8d 100755 --- a/em-config.py +++ b/em-config.py @@ -24,7 +24,7 @@ def main(): not re.match(r"^[\w\W_][\w\W_\d]*$", sys.argv[1]) or \ not hasattr(config, sys.argv[1]): print('Usage: em-config VAR_NAME', file=sys.stderr) - exit(1) + sys.exit(1) print(getattr(config, sys.argv[1])) return 0 diff --git a/emcc.py b/emcc.py index dfe088e7b75c0..7f30d13cdc058 100644 --- a/emcc.py +++ b/emcc.py @@ -1023,7 +1023,7 @@ def get_clang_command_asm(): if state.mode == Mode.PCH: inputs = [i[1] for i in input_files] for header in inputs: - if not shared.suffix(header) in HEADER_ENDINGS: + if shared.suffix(header) not in HEADER_ENDINGS: exit_with_error(f'cannot mix precompiled headers with non-header inputs: {inputs} : {header}') cmd = get_clang_command() + inputs if options.output_file: @@ -1127,7 +1127,15 @@ def version_string(): return f'emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) {utils.EMSCRIPTEN_VERSION}{revision_suffix}' -def parse_args(newargs): +def parse_args(newargs): # noqa: C901, PLR0912, PLR0915 + """Future modifications should consider refactoring to reduce complexity. + + * The McCabe cyclomatiic complexity is currently 117 vs 10 recommended. + * There are currently 115 branches vs 12 recommended. + * There are currently 302 statements vs 50 recommended. + + To revalidate these numbers, run `ruff check --select=C901,PLR091`. + """ options = EmccOptions() settings_changes = [] user_js_defines = [] diff --git a/emrun.py b/emrun.py index 90812813b4d48..0d33218c2d747 100644 --- a/emrun.py +++ b/emrun.py @@ -1583,7 +1583,15 @@ def parse_args(args): return parser.parse_args(args) -def run(args): +def run(args): # noqa: C901, PLR0912, PLR0915 + """Future modifications should consider refactoring to reduce complexity. + + * The McCabe cyclomatiic complexity is currently 74 vs 10 recommended. + * There are currently 86 branches vs 12 recommended. + * There are currently 202 statements vs 50 recommended. + + To revalidate these numbers, run `ruff check --select=C901,PLR091`. + """ global browser_process, browser_exe, processname_killed_atexit, emrun_options, emrun_not_enabled_nag_printed options = emrun_options = parse_args(args) diff --git a/emsymbolizer.py b/emsymbolizer.py index 1a9cf27f25d56..7ba3b951c852b 100755 --- a/emsymbolizer.py +++ b/emsymbolizer.py @@ -121,10 +121,8 @@ def parse(self, filename): self.version = source_map_json['version'] self.sources = source_map_json['sources'] - vlq_map = {} chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' - for i, c in enumerate(chars): - vlq_map[c] = i + vlq_map = {c: i for i, c in enumerate(chars)} def decodeVLQ(string): result = [] diff --git a/pyproject.toml b/pyproject.toml index 38bf2a5e67beb..f4c62aacb8f16 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,70 @@ +[tool.ruff] +exclude = [ + "./cache/", + "./node_modules/", + "./site/source/_themes/", + "./site/source/conf.py", + "./system/lib/", + "./test/third_party/", + "./third_party/", + "./tools/filelock.py", + "./tools/scons/", + ".git", +] + +lint.select = [ + "ARG", + "ASYNC", + "B", + "C90", + "E", + "F", + "PERF", + "PL", + "W", + "YTT", +] + +lint.ignore = [ + "ARG001", + "ARG002", + "ARG005", + "B006", + "B011", + "B018", + "B023", + "B026", + "B904", + "E402", + "E501", + "E721", + "E741", + "PERF203", + "PERF401", + "PLR1704", + "PLR1714", + "PLR5501", + "PLW0602", + "PLW0603", + "PLW1510", + "PLW2901", +] + +lint.per-file-ignores."emrun.py" = [ "PLE0704" ] + +lint.mccabe.max-complexity = 48 # Recommended: 10 + +lint.pylint.allow-magic-value-types = [ + "bytes", + "float", + "int", + "str", +] +lint.pylint.max-args = 15 # Recommended: 5 +lint.pylint.max-branches = 49 # Recommended: 12 +lint.pylint.max-returns = 16 # Recommended: 6 +lint.pylint.max-statements = 142 # Recommended: 50 + [tool.coverage.run] source = [ "." ] omit = [ diff --git a/requirements-dev.txt b/requirements-dev.txt index c67851c37317d..6fea74921d9df 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,14 +1,12 @@ # TODO(sbc): switch to using Pipenv since it seems like that way to go # these day managing python deps. -# These requirements are only needed for developers who want to run flake8 on +# These requirements are only needed for developers who want to run ruff on # the codebase and generate docs using Sphinx, not for users of emscripten. # Install with `pip3 install -r requirements-dev.txt` -flake8==5.0.4 -flake8-bugbear==22.9.23 -flake8-unused-arguments==0.0.11 coverage[toml]==5.5 mypy==0.971 +ruff==0.8.2 types-requests==2.27.14 unittest-xml-reporting==3.1.0 diff --git a/test/benchmark/benchmark_sse.py b/test/benchmark/benchmark_sse.py index 28b75dbbd8200..65f296c1dafce 100644 --- a/test/benchmark/benchmark_sse.py +++ b/test/benchmark/benchmark_sse.py @@ -134,14 +134,14 @@ def format_comparison(a, b): total_time_html_scalar = 0 total_time_html_simd = 0 - for chart_name in charts_native.keys(): + for chart_name, chart_native_results in charts_native.items(): # Extract data for each chart. categories = [] nativeScalarResults = [] nativeSimdResults = [] htmlScalarResults = [] htmlSimdResults = [] - native_results = charts_native[chart_name] + native_results = chart_native_results wasm_results = charts_html[chart_name] textual_results_native = '

' textual_results_html = '

' diff --git a/test/runner.py b/test/runner.py index 9808181e224be..5896fe4f15b9e 100755 --- a/test/runner.py +++ b/test/runner.py @@ -106,7 +106,7 @@ def check_js_engines(): working_engines = [e for e in config.JS_ENGINES if jsrun.check_engine(e)] if len(working_engines) < len(config.JS_ENGINES): print('Not all the JS engines in JS_ENGINES appears to work.') - exit(1) + sys.exit(1) if common.EMTEST_ALL_ENGINES: print('(using ALL js engines)') @@ -311,11 +311,9 @@ def load_test_suites(args, modules, start_at, repeat): def flattened_tests(loaded_tests): tests = [] for subsuite in loaded_tests: - for test in subsuite: - tests.append(test) + tests.extend(subsuite) return tests - def suite_for_module(module, tests): suite_supported = module.__name__ in ('test_core', 'test_other', 'test_posixtest') if not common.EMTEST_SAVE_DIR and not shared.DEBUG: diff --git a/tools/file_packager.py b/tools/file_packager.py index 123462418bd44..f2e2c7729fd01 100755 --- a/tools/file_packager.py +++ b/tools/file_packager.py @@ -354,7 +354,15 @@ def generate_object_file(data_files): shared.check_call(cmd) -def main(): +def main(): # noqa: C901, PLR0912, PLR0915 + """Future modifications should consider refactoring to reduce complexity. + + * The McCabe cyclomatiic complexity is currently 60 vs 10 recommended. + * There are currently 63 branches vs 12 recommended. + * There are currently 151 statements vs 50 recommended. + + To revalidate these numbers, run `ruff check --select=C901,PLR091`. + """ if len(sys.argv) == 1: err('''Usage: file_packager TARGET [--preload A [B..]] [--embed C [D..]] [--exclude E [F..]]] [--js-output=OUTPUT.js] [--no-force] [--use-preload-cache] [--indexedDB-name=EM_PRELOAD_CACHE] [--separate-metadata] [--lz4] [--use-preload-plugins] [--no-node] See the source for more details.''') diff --git a/tools/link.py b/tools/link.py index 88f16036f7b92..cc90247085fb6 100644 --- a/tools/link.py +++ b/tools/link.py @@ -631,7 +631,15 @@ def check_browser_versions(): @ToolchainProfiler.profile_block('linker_setup') -def phase_linker_setup(options, state, newargs): +def phase_linker_setup(options, state, newargs): # noqa: C901, PLR0912, PLR0915 + """Future modifications should consider refactoring to reduce complexity. + + * The McCabe cyclomatiic complexity is currently 251 vs 10 recommended. + * There are currently 262 branches vs 12 recommended. + * There are currently 578 statements vs 50 recommended. + + To revalidate these numbers, run `ruff check --select=C901,PLR091`. + """ system_libpath = '-L' + str(cache.get_lib_dir(absolute=True)) state.append_link_flag(system_libpath) diff --git a/tools/webidl_binder.py b/tools/webidl_binder.py index b8a152608a324..2e54f792d58f8 100644 --- a/tools/webidl_binder.py +++ b/tools/webidl_binder.py @@ -386,10 +386,18 @@ def type_to_cdec(raw): return ret + '*' -def render_function(class_name, func_name, sigs, return_type, non_pointer, +def render_function(class_name, func_name, sigs, return_type, non_pointer, # noqa: C901, PLR0912, PLR0915 copy, operator, constructor, is_static, func_scope, call_content=None, const=False, array_attribute=False, bind_to=None): + """Future modifications should consider refactoring to reduce complexity. + + * The McCabe cyclomatiic complexity is currently 67 vs 10 recommended. + * There are currently 79 branches vs 12 recommended. + * There are currently 195 statements vs 50 recommended. + + To revalidate these numbers, run `ruff check --select=C901,PLR091`. + """ legacy_mode = CHECKS not in ['ALL', 'FAST'] all_checks = CHECKS == 'ALL'