From fefb72a1271ed17f36da28f48b373f34551ae433 Mon Sep 17 00:00:00 2001 From: Evert Lammerts Date: Sat, 4 Oct 2025 23:02:29 +0200 Subject: [PATCH 1/2] mypy pre-commit hook --- .github/workflows/code_quality.yml | 2 +- .pre-commit-config.yaml | 5 +++++ tests/stubs/mypy.ini | 14 -------------- tests/stubs/test_stubs.py | 25 ------------------------- 4 files changed, 6 insertions(+), 40 deletions(-) delete mode 100644 tests/stubs/mypy.ini delete mode 100644 tests/stubs/test_stubs.py diff --git a/.github/workflows/code_quality.yml b/.github/workflows/code_quality.yml index 00848933..719e54ca 100644 --- a/.github/workflows/code_quality.yml +++ b/.github/workflows/code_quality.yml @@ -19,7 +19,7 @@ defaults: jobs: run_checks: - name: Run linting and formatting + name: Run linting, formatting and static type checker runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5b78d185..393ff1c0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,6 +19,11 @@ repos: hooks: - id: cmake-format + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.17.1 + hooks: + - id: mypy + - repo: local hooks: - id: post-checkout-submodules diff --git a/tests/stubs/mypy.ini b/tests/stubs/mypy.ini deleted file mode 100644 index ff840b82..00000000 --- a/tests/stubs/mypy.ini +++ /dev/null @@ -1,14 +0,0 @@ -[mypy] -mypy_path = duckdb -[mypy-fsspec] -ignore_missing_imports = True -[mypy-pandas] -ignore_missing_imports = True -[mypy-polars] -ignore_missing_imports = True -[mypy-pyarrow] -ignore_missing_imports = True -[mypy-pyarrow.lib] -ignore_missing_imports = True -[mypy-torch] -ignore_missing_imports = True \ No newline at end of file diff --git a/tests/stubs/test_stubs.py b/tests/stubs/test_stubs.py deleted file mode 100644 index 96efed5d..00000000 --- a/tests/stubs/test_stubs.py +++ /dev/null @@ -1,25 +0,0 @@ -from pathlib import Path - -from mypy import stubtest - -MYPY_INI_PATH = Path(__file__).parent / "mypy.ini" - - -def test_generated_stubs(): - skip_stubs_errors = ["pybind11", "git_revision", "is inconsistent, metaclass differs"] - - options = stubtest.parse_options(["duckdb", "--mypy-config-file", MYPY_INI_PATH]) - stubtest.test_stubs(options) - - broken_stubs = [ - error.get_description() - for error in stubtest.test_module("duckdb") - if not any(skip in error.get_description() for skip in skip_stubs_errors) - ] - - if not broken_stubs: - return - print("Stubs must be updated, either add them to skip_stubs_errors or update __init__.pyi accordingly") - print(broken_stubs) - - assert not broken_stubs From e633cb2c1a477cae2abd153921eee66d221ec88f Mon Sep 17 00:00:00 2001 From: Evert Lammerts Date: Mon, 6 Oct 2025 11:27:44 +0200 Subject: [PATCH 2/2] mypy file selection in pre-commit --- .pre-commit-config.yaml | 6 ++++++ duckdb/polars_io.py | 4 ++-- pyproject.toml | 6 ++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 393ff1c0..4fd64e4d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -23,6 +23,12 @@ repos: rev: v1.17.1 hooks: - id: mypy + # Match all files under duckdb/ or _duckdb-stubs/, + # but not under duckdb/experimental/ or duckdb/query_graph/ + files: ^(duckdb/(?!experimental/|query_graph/)|_duckdb-stubs/) + args: ["--config-file", "pyproject.toml"] + language: system + entry: uv run mypy - repo: local hooks: diff --git a/duckdb/polars_io.py b/duckdb/polars_io.py index 61ead5bc..2c075baf 100644 --- a/duckdb/polars_io.py +++ b/duckdb/polars_io.py @@ -277,8 +277,8 @@ def source_generator( for record_batch in iter(results.read_next_batch, None): if predicate is not None and duck_predicate is None: # We have a predicate, but did not manage to push it down, we fallback here - yield pl.from_arrow(record_batch).filter(predicate) # type: ignore[arg-type,misc] + yield pl.from_arrow(record_batch).filter(predicate) # type: ignore[arg-type,misc,unused-ignore] else: - yield pl.from_arrow(record_batch) # type: ignore[misc] + yield pl.from_arrow(record_batch) # type: ignore[misc,unused-ignore] return register_io_source(source_generator, schema=schema) diff --git a/pyproject.toml b/pyproject.toml index 52b63edc..2faea5e0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -316,6 +316,7 @@ filterwarnings = [ [tool.mypy] packages = ["duckdb", "_duckdb"] +mypy_path = ["_duckdb-stubs"] strict = true warn_unreachable = true pretty = true @@ -323,13 +324,18 @@ python_version = "3.9" exclude = [ "duckdb/experimental/", # not checking the pyspark API "duckdb/query_graph/", # old and unmaintained (should probably remove) + "tests", + "scripts", + "sqlogic", ] [[tool.mypy.overrides]] module = [ "fsspec.*", + "numpy", "pandas", "polars", + "polars.io.plugins", "pyarrow.*", "torch", "tensorflow",