diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 52d2e07..88303a2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,86 +1,86 @@ name: main on: - push: - pull_request: + push: + pull_request: concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 - - name: Setup Python - uses: actions/setup-python@v4 - with: - python-version: '3.12' + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: "3.12" - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: '20' - - - name: Build - run: | - python -m pip install build - python -m build . + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" - - name: Store the distribution packages - uses: actions/upload-artifact@v3 - with: - name: python-package-distributions - path: dist/ - - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 + - name: Build + run: | + python -m pip install build + python -m build . - - name: Setup Python - uses: actions/setup-python@v4 - with: - python-version: '3.12' + - name: Store the distribution packages + uses: actions/upload-artifact@v3 + with: + name: python-package-distributions + path: dist/ - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: '20' - - - name: Test - run: | - python -m pip install --upgrade pip - pip install ".[test]" + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 - pytest -v \ - --junitxml=test-results/junit.xml \ - --cov=pyodide-build \ - pyodide_build + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: "3.12" - - uses: codecov/codecov-action@v4 - with: - fail_ci_if_error: false + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" - publish: - name: >- - Publish Python 🐍 distribution 📦 to PyPI - needs: - - build - runs-on: ubuntu-latest - if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') - environment: - name: pypi - url: https://pypi.org/p/pyodide-build - permissions: - id-token: write # IMPORTANT: mandatory for trusted publishing - steps: - - name: Download all the dists - uses: actions/download-artifact@v3 - with: - name: python-package-distributions - path: dist/ - - name: Publish distribution 📦 to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 \ No newline at end of file + - name: Test + run: | + python -m pip install --upgrade pip + pip install ".[test]" + + pytest -v \ + --junitxml=test-results/junit.xml \ + --cov=pyodide-build \ + pyodide_build + + - uses: codecov/codecov-action@v4 + with: + fail_ci_if_error: false + + publish: + name: >- + Publish to PyPI + needs: + - build + runs-on: ubuntu-latest + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') + environment: + name: pypi + url: https://pypi.org/p/pyodide-build + permissions: + id-token: write # IMPORTANT: mandatory for trusted publishing + steps: + - name: Download all the dists + uses: actions/download-artifact@v3 + with: + name: python-package-distributions + path: dist/ + - name: Publish distribution 📦 to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.gitignore b/.gitignore index cacd460..c6d0f13 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,6 @@ emsdk/emsdk geckodriver.log node_modules dist/ -pyodide-build/**/build.log +pyodide_build/**/build.log xbuildenv/ -.pyodide-xbuildenv* \ No newline at end of file +.pyodide-xbuildenv* diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 18ede84..d1fdf27 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -74,9 +74,9 @@ repos: additional_dependencies: *mypy-deps - repo: https://github.com/pre-commit/mirrors-prettier - rev: "v4.0.0-alpha.8" + rev: "v3.1.0" hooks: - id: prettier ci: - autoupdate_schedule: "quarterly" \ No newline at end of file + autoupdate_schedule: "quarterly" diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fa3076..b123379 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ # Changelog + All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), @@ -6,4 +7,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased -- pyodide-build is now developed under https://github.com/pyodide/pyodide-build. \ No newline at end of file +- pyodide-build is now developed under https://github.com/pyodide/pyodide-build. diff --git a/pyodide_build/tests/fixture.py b/pyodide_build/tests/conftest.py similarity index 100% rename from pyodide_build/tests/fixture.py rename to pyodide_build/tests/conftest.py diff --git a/pyodide_build/tests/test_build_env.py b/pyodide_build/tests/test_build_env.py index 726671e..ce7ce9d 100644 --- a/pyodide_build/tests/test_build_env.py +++ b/pyodide_build/tests/test_build_env.py @@ -1,51 +1,13 @@ -# flake8: noqa -# This file contains tests that ensure build environment is properly initialized in -# both in-tree and out-of-tree builds. - import os import pytest -from conftest import ROOT_PATH from pyodide_build import build_env, common -from pyodide_build.xbuildenv import CrossBuildEnvManager from pyodide_build.config import BUILD_KEY_TO_VAR - -from .fixture import reset_cache, reset_env_vars, dummy_xbuildenv, dummy_xbuildenv_url +from pyodide_build.xbuildenv import CrossBuildEnvManager class TestInTree: - def test_init_environment(self, reset_env_vars, reset_cache): - assert "PYODIDE_ROOT" not in os.environ - - build_env.init_environment() - - assert "PYODIDE_ROOT" in os.environ - assert os.environ["PYODIDE_ROOT"] == str(ROOT_PATH) - - def test_init_environment_pyodide_root_already_set( - self, reset_env_vars, reset_cache - ): - assert "PYODIDE_ROOT" not in os.environ - os.environ["PYODIDE_ROOT"] = "/set_by_user" - - build_env.init_environment() - - assert os.environ["PYODIDE_ROOT"] == "/set_by_user" - - def test_get_pyodide_root(self, reset_env_vars, reset_cache): - assert "PYODIDE_ROOT" not in os.environ - - assert build_env.get_pyodide_root() == ROOT_PATH - - def test_get_pyodide_root_pyodide_root_already_set( - self, reset_env_vars, reset_cache - ): - assert "PYODIDE_ROOT" not in os.environ - os.environ["PYODIDE_ROOT"] = "/set_by_user" - - assert str(build_env.get_pyodide_root()) == "/set_by_user" - def test_search_pyodide_root(self, tmp_path, reset_env_vars, reset_cache): pyproject_file = tmp_path / "pyproject.toml" pyproject_file.write_text("[tool._pyodide]") @@ -56,66 +18,6 @@ def test_search_pyodide_root(self, tmp_path, reset_env_vars, reset_cache): pyproject_file.unlink() assert build_env.search_pyodide_root(tmp_path) is None - def test_in_xbuildenv(self, reset_env_vars, reset_cache): - assert not build_env.in_xbuildenv() - - def test_get_build_environment_vars(self, reset_env_vars, reset_cache): - build_vars = build_env.get_build_environment_vars(ROOT_PATH) - - # extra variables that does not come from config files. - extra_vars = set(["PYODIDE", "PYODIDE_PACKAGE_ABI", "PYTHONPATH"]) - all_keys = set(BUILD_KEY_TO_VAR.values()) | extra_vars - for var in build_vars: - assert var in all_keys, f"Unknown {var}" - - # Additionally we set these variables - for var in extra_vars: - assert var in build_vars, f"Missing {var}" - - def test_get_build_flag(self, reset_env_vars, reset_cache): - for key, val in build_env.get_build_environment_vars( - pyodide_root=ROOT_PATH - ).items(): - assert build_env.get_build_flag(key) == val - - with pytest.raises(ValueError): - build_env.get_build_flag("UNKNOWN_VAR") - - def test_get_build_environment_vars_host_env( - self, monkeypatch, reset_env_vars, reset_cache - ): - # host environment variables should have precedence over - # variables defined in Makefile.envs - - import os - - e = build_env.get_build_environment_vars(ROOT_PATH) - assert e["PYODIDE"] == "1" - - monkeypatch.setenv("HOME", "/home/user") - monkeypatch.setenv("PATH", "/usr/bin:/bin") - # We now inject PKG_CONFIG_LIBDIR inside buildpkg.py - # monkeypatch.setenv("PKG_CONFIG_LIBDIR", "/x/y/z:/c/d/e") - - build_env.get_build_environment_vars.cache_clear() - - e_host = build_env.get_build_environment_vars(ROOT_PATH) - assert e_host.get("HOME") == os.environ.get("HOME") - assert e_host.get("PATH") == os.environ.get("PATH") - - assert e_host.get("HOME") != e.get("HOME") - assert e_host.get("PATH") != e.get("PATH") - - build_env.get_build_environment_vars.cache_clear() - - monkeypatch.delenv("HOME") - monkeypatch.setenv("RANDOM_ENV", "1234") - - build_env.get_build_environment_vars.cache_clear() - e = build_env.get_build_environment_vars(ROOT_PATH) - assert "HOME" not in e - assert "RANDOM_ENV" not in e - class TestOutOfTree(TestInTree): # Note: other tests are inherited from TestInTree @@ -129,6 +31,16 @@ def test_init_environment(self, dummy_xbuildenv, reset_env_vars, reset_cache): assert "PYODIDE_ROOT" in os.environ assert os.environ["PYODIDE_ROOT"] == str(manager.pyodide_root) + def test_init_environment_pyodide_root_already_set( + self, reset_env_vars, reset_cache + ): + assert "PYODIDE_ROOT" not in os.environ + os.environ["PYODIDE_ROOT"] = "/set_by_user" + + build_env.init_environment() + + assert os.environ["PYODIDE_ROOT"] == "/set_by_user" + def test_get_pyodide_root(self, dummy_xbuildenv, reset_env_vars, reset_cache): assert "PYODIDE_ROOT" not in os.environ @@ -136,6 +48,14 @@ def test_get_pyodide_root(self, dummy_xbuildenv, reset_env_vars, reset_cache): manager = CrossBuildEnvManager(dummy_xbuildenv / common.xbuildenv_dirname()) assert pyodide_root == manager.pyodide_root + def test_get_pyodide_root_pyodide_root_already_set( + self, reset_env_vars, reset_cache + ): + assert "PYODIDE_ROOT" not in os.environ + os.environ["PYODIDE_ROOT"] = "/set_by_user" + + assert str(build_env.get_pyodide_root()) == "/set_by_user" + def test_in_xbuildenv(self, dummy_xbuildenv, reset_env_vars, reset_cache): assert build_env.in_xbuildenv() diff --git a/pyodide_build/tests/test_cli.py b/pyodide_build/tests/test_cli.py index 6aa4cd1..5f3b57d 100644 --- a/pyodide_build/tests/test_cli.py +++ b/pyodide_build/tests/test_cli.py @@ -1,33 +1,21 @@ -# flake8: noqa - import shutil +import zipfile from pathlib import Path +from typing import Any import pytest -import zipfile import typer from typer.testing import CliRunner -from typing import Any + import pyodide_build -from pyodide_build import common, build_env, cli +from pyodide_build import build_env, cli, common from pyodide_build.cli import ( build, build_recipes, config, create_zipfile, - skeleton, - xbuildenv, py_compile, -) - -from .fixture import ( - temp_python_lib, - temp_python_lib2, - dummy_xbuildenv, - mock_emscripten, - dummy_xbuildenv_url, - reset_env_vars, - reset_cache, + skeleton, ) only_node = pytest.mark.xfail_browsers( @@ -419,7 +407,7 @@ def my_get_config_vars(*args): outdir = tmp_path / "out" app = typer.Typer() app.command(**build.main.typer_kwargs)(build.main) # type:ignore[attr-defined] - result = runner.invoke(app, [str(srcdir), "--outdir", str(outdir)]) + runner.invoke(app, [str(srcdir), "--outdir", str(outdir)]) wheel_file = next(outdir.glob("*.whl")) print(zipfile.ZipFile(wheel_file).namelist()) so_file = next( diff --git a/pyodide_build/tests/test_cli_xbuildenv.py b/pyodide_build/tests/test_cli_xbuildenv.py index c0b6e6c..4da912f 100644 --- a/pyodide_build/tests/test_cli_xbuildenv.py +++ b/pyodide_build/tests/test_cli_xbuildenv.py @@ -1,5 +1,3 @@ -# flake8: noqa - import os import shutil from pathlib import Path @@ -14,12 +12,6 @@ from pyodide_build.common import chdir from pyodide_build.xbuildenv_releases import CROSS_BUILD_ENV_METADATA_URL_ENV_VAR -from .fixture import ( - dummy_xbuildenv_url, - fake_xbuildenv_releases_compatible, - fake_xbuildenv_releases_incompatible, -) - def mock_pyodide_lock() -> PyodideLockSpec: return PyodideLockSpec( diff --git a/pyodide_build/tests/test_config.py b/pyodide_build/tests/test_config.py index 6bbbdb9..88bedb8 100644 --- a/pyodide_build/tests/test_config.py +++ b/pyodide_build/tests/test_config.py @@ -1,7 +1,3 @@ -# flake8: noqa -# flake8 is not happy with fixture imports - -from conftest import ROOT_PATH from pyodide_build import common from pyodide_build.config import ( BUILD_KEY_TO_VAR, @@ -11,18 +7,22 @@ ) from pyodide_build.xbuildenv import CrossBuildEnvManager -from .fixture import reset_cache, reset_env_vars, dummy_xbuildenv, dummy_xbuildenv_url - -class TestConfigManager_InTree: - def test_default_config(self): - config_manager = ConfigManager(pyodide_root=ROOT_PATH) +class TestConfigManager_OutOfTree: + def test_default_config(self, dummy_xbuildenv, reset_env_vars, reset_cache): + xbuildenv_manager = CrossBuildEnvManager( + dummy_xbuildenv / common.xbuildenv_dirname() + ) + config_manager = ConfigManager(pyodide_root=xbuildenv_manager.pyodide_root) default_config = config_manager._load_default_config() assert default_config.keys() == DEFAULT_CONFIG.keys() - def test_makefile_envs(self): - config_manager = ConfigManager(pyodide_root=ROOT_PATH) + def test_makefile_envs(self, dummy_xbuildenv, reset_env_vars, reset_cache): + xbuildenv_manager = CrossBuildEnvManager( + dummy_xbuildenv / common.xbuildenv_dirname() + ) + config_manager = ConfigManager(pyodide_root=xbuildenv_manager.pyodide_root) makefile_vars = config_manager._load_makefile_envs() @@ -35,13 +35,21 @@ def test_makefile_envs(self): for key in default_config: assert key not in makefile_vars - def test_get_make_environment_vars(self, reset_env_vars, reset_cache): - config_manager = ConfigManager(pyodide_root=ROOT_PATH) + def test_get_make_environment_vars( + self, dummy_xbuildenv, reset_env_vars, reset_cache + ): + xbuildenv_manager = CrossBuildEnvManager( + dummy_xbuildenv / common.xbuildenv_dirname() + ) + config_manager = ConfigManager(pyodide_root=xbuildenv_manager.pyodide_root) make_vars = config_manager._get_make_environment_vars() - assert make_vars["PYODIDE_ROOT"] == str(ROOT_PATH) + assert make_vars["PYODIDE_ROOT"] == str(xbuildenv_manager.pyodide_root) - def test_computed_vars(self): - config_manager = ConfigManager(pyodide_root=ROOT_PATH) + def test_computed_vars(self, dummy_xbuildenv, reset_env_vars, reset_cache): + xbuildenv_manager = CrossBuildEnvManager( + dummy_xbuildenv / common.xbuildenv_dirname() + ) + config_manager = ConfigManager(pyodide_root=xbuildenv_manager.pyodide_root) makefile_vars = config_manager._load_makefile_envs() @@ -50,8 +58,11 @@ def test_computed_vars(self): assert makefile_vars[k] != v # The template should have been substituted assert "$(" not in makefile_vars[k] - def test_load_config_from_env(self): - config_manager = ConfigManager(pyodide_root=ROOT_PATH) + def test_load_config_from_env(self, dummy_xbuildenv, reset_env_vars, reset_cache): + xbuildenv_manager = CrossBuildEnvManager( + dummy_xbuildenv / common.xbuildenv_dirname() + ) + config_manager = ConfigManager(pyodide_root=xbuildenv_manager.pyodide_root) env = { "CMAKE_TOOLCHAIN_FILE": "/path/to/toolchain", @@ -62,7 +73,9 @@ def test_load_config_from_env(self): assert config["cmake_toolchain_file"] == "/path/to/toolchain" assert config["meson_cross_file"] == "/path/to/crossfile" - def test_load_config_from_file(self, tmp_path, reset_env_vars, reset_cache): + def test_load_config_from_file( + self, tmp_path, dummy_xbuildenv, reset_env_vars, reset_cache + ): pyproject_file = tmp_path / "pyproject.toml" env = { @@ -78,7 +91,10 @@ def test_load_config_from_file(self, tmp_path, reset_env_vars, reset_cache): meson_cross_file = "$(MESON_CROSS_FILE)" """) - config_manager = ConfigManager(pyodide_root=ROOT_PATH) + xbuildenv_manager = CrossBuildEnvManager( + dummy_xbuildenv / common.xbuildenv_dirname() + ) + config_manager = ConfigManager(pyodide_root=xbuildenv_manager.pyodide_root) config = config_manager._load_config_file(pyproject_file, env) @@ -88,46 +104,21 @@ def test_load_config_from_file(self, tmp_path, reset_env_vars, reset_cache): assert config["rust_toolchain"] == "nightly" assert config["meson_cross_file"] == "/path/to/crossfile" - def test_config_all(self): - config_manager = ConfigManager(pyodide_root=ROOT_PATH) - config = config_manager.config - - for key in BUILD_KEY_TO_VAR.keys(): - assert key in config - - def test_to_env(self): - config_manager = ConfigManager(pyodide_root=ROOT_PATH) - env = config_manager.to_env() - for env_var in BUILD_KEY_TO_VAR.values(): - assert env_var in env - - -class TestConfigManager_OutOfTree: - # Note: other tests are inherited from TestInTree - - def test_makefile_envs(self, dummy_xbuildenv, reset_env_vars, reset_cache): + def test_config_all(self, dummy_xbuildenv, reset_env_vars, reset_cache): xbuildenv_manager = CrossBuildEnvManager( dummy_xbuildenv / common.xbuildenv_dirname() ) config_manager = ConfigManager(pyodide_root=xbuildenv_manager.pyodide_root) + config = config_manager.config - makefile_vars = config_manager._load_makefile_envs() - - # It should contain information about the cpython and emscripten versions - assert "pyversion" in makefile_vars - assert "pyodide_emscripten_version" in makefile_vars - assert "pythoninclude" in makefile_vars - - default_config = config_manager._load_default_config() - for key in default_config: - assert key not in makefile_vars + for key in BUILD_KEY_TO_VAR.keys(): + assert key in config - def test_get_make_environment_vars( - self, dummy_xbuildenv, reset_env_vars, reset_cache - ): + def test_to_env(self, dummy_xbuildenv, reset_env_vars, reset_cache): xbuildenv_manager = CrossBuildEnvManager( dummy_xbuildenv / common.xbuildenv_dirname() ) config_manager = ConfigManager(pyodide_root=xbuildenv_manager.pyodide_root) - make_vars = config_manager._get_make_environment_vars() - assert make_vars["PYODIDE_ROOT"] == str(xbuildenv_manager.pyodide_root) + env = config_manager.to_env() + for env_var in BUILD_KEY_TO_VAR.values(): + assert env_var in env diff --git a/pyodide_build/tests/test_oot_build.py b/pyodide_build/tests/test_oot_build.py index c80ebc0..3c6a760 100644 --- a/pyodide_build/tests/test_oot_build.py +++ b/pyodide_build/tests/test_oot_build.py @@ -2,16 +2,6 @@ from pyodide_build.out_of_tree import build -# flake8: noqa -from .fixture import ( - dummy_xbuildenv, - dummy_xbuildenv_url, - reset_env_vars, - reset_cache, -) - -# selenium fixture b/c we can't run this test until after building Python. - def test_non_platformed_build(dummy_xbuildenv, tmp_path): """Check that we don't accidentally attach Pyodide platform to non diff --git a/pyodide_build/tests/test_pypi.py b/pyodide_build/tests/test_pypi.py index 9ccb7db..49c760c 100644 --- a/pyodide_build/tests/test_pypi.py +++ b/pyodide_build/tests/test_pypi.py @@ -1,5 +1,3 @@ -# flake8: noqa - import re import subprocess import sys @@ -15,13 +13,6 @@ from typer.testing import CliRunner from pyodide_build.cli import build -from .fixture import ( - reset_cache, - reset_env_vars, - dummy_xbuildenv, - dummy_xbuildenv_url, - mock_emscripten, -) runner = CliRunner() diff --git a/pyodide_build/tests/test_pyzip.py b/pyodide_build/tests/test_pyzip.py index bf0f6e3..c6ce363 100644 --- a/pyodide_build/tests/test_pyzip.py +++ b/pyodide_build/tests/test_pyzip.py @@ -1,9 +1,5 @@ -# flake8: noqa - from pyodide_build.pyzip import create_zipfile, default_filterfunc -from .fixture import temp_python_lib, temp_python_lib2 - def test_defaultfilterfunc(temp_python_lib): ignored = ["test", "turtle.py"] diff --git a/pyodide_build/tests/test_xbuildenv.py b/pyodide_build/tests/test_xbuildenv.py index ed37c18..40933d6 100644 --- a/pyodide_build/tests/test_xbuildenv.py +++ b/pyodide_build/tests/test_xbuildenv.py @@ -1,15 +1,7 @@ -# flake8: noqa - import pytest from pyodide_build.xbuildenv import CrossBuildEnvManager, _url_to_version -from .fixture import ( - dummy_xbuildenv_url, - fake_xbuildenv_releases_compatible, - fake_xbuildenv_releases_incompatible, -) - @pytest.fixture() def monkeypatch_subprocess_run_pip(monkeypatch): diff --git a/pyproject.toml b/pyproject.toml index 70687b4..5b6009e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -73,3 +73,105 @@ version.path = "pyodide_build/__init__.py" exclude = [ "/pyodide_build/tests", ] + +[tool.mypy] +python_version = "3.12" +mypy_path = ["src/py", "pyodide-build"] +show_error_codes = true +warn_unreachable = true +enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"] +plugins = ["pydantic.mypy"] + +# Strict checks +warn_unused_configs = true +check_untyped_defs = true +disallow_any_generics = true +disallow_subclassing_any = false +disallow_untyped_calls = false +disallow_untyped_defs = false +disallow_incomplete_defs = true +disallow_untyped_decorators = true +no_implicit_optional = true +warn_redundant_casts = true +warn_unused_ignores = true +warn_return_any = false +no_implicit_reexport = true +strict_equality = true + +[[tool.mypy.overrides]] +module = [ + "_pyodide_core", + "docutils.parsers.rst", + "js", + "loky", + "matplotlib.*", + "PIL.*", + "pyodide_js", + "pyodide_js._api", + "pytest_pyodide", + "pytest_pyodide.runner", + "pytest_pyodide.utils", + "ruamel.yaml", + "termcolor", + "test", + "tomli", + "tomllib", + "typer", + "virtualenv", + "auditwheel_emscripten.*" +] +ignore_missing_imports = true + + +[tool.ruff] +lint.select = [ + "B0", # bugbear (all B0* checks enabled by default) + "B904", # bugbear (Within an except clause, raise exceptions with raise ... from err) + "B905", # bugbear (zip() without an explicit strict= parameter set.) + "C9", # mccabe complexity + "E", # pycodestyles + "W", # pycodestyles + "F", # pyflakes + "I", # isort + "PGH", # pygrep-hooks + "PLC", # pylint conventions + "PLE", # pylint errors + "UP", # pyupgrade +] +lint.ignore = ["E402", "E501", "E731", "E741", "UP038"] +# line-length = 219 # E501: Recommended goal is 88 to match black +target-version = "py311" + +[tool.ruff.lint.per-file-ignores] +"src/py/_pyodide/_base.py" = [ + "PGH001", # No builtin `eval()` allowed +] +"src/tests/test_jsproxy.py" = [ + "PGH001", # No builtin `eval()` allowed +] +"src/tests/test_typeconversions.py" = [ + "PGH001", # No builtin `eval()` allowed +] +"tools/*" = [ + "B008", # Do not perform function call `typer.Optional` in argument defaults +] + +[tool.ruff.lint.flake8-bugbear] +extend-immutable-calls = ["typer.Argument", "typer.Option"] + +[tool.ruff.lint.isort] +known-first-party = [ + "pyodide", + "pyodide_js", + "micropip", + "pyodide_build", + "_pyodide", + "js", +] +known-third-party = [ + "build", + "pyodide_lock", +] + +[tool.ruff.lint.mccabe] +max-complexity = 31 # C901: Recommended goal is 10