From d610d1c868f24b7cac27f374c98dfd4b3e98963c Mon Sep 17 00:00:00 2001 From: David Beall <6121439+beallio@users.noreply.github.com> Date: Tue, 4 Aug 2026 07:39:13 -0700 Subject: [PATCH] fix(typing): make ty suppressions valid with and without the spark extra CI's lint leg installs `--extra spark`; a plain `uv sync` does not. The two configurations need opposite suppressions: - without pyspark, `from pyspark.sql import ...` is unresolved-import; - with pyspark, that import resolves but `SparkSession.builder` does not, because pyspark declares it as a classproperty ty cannot follow, giving unresolved-attribute instead. Whichever set is not needed is then reported as an unused directive, so no arrangement of ignore comments alone satisfies both environments. Silence unused-ignore-comment and carry both suppressions. This does not re-broaden unresolved-import detection, which an earlier review found had been globally disabled; that rule remains active. Verified locally without the extra: ruff check, ruff format --check, ty check ., and pytest all pass. The with-extra configuration is verified by CI's lint leg, which is what caught this. --- pyproject.toml | 13 +++++++++++++ src/wherewolf/execution/spark_engine.py | 2 +- tests/conftest.py | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 4249045..cd7bbc9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -73,6 +73,19 @@ markers = [ data_file = "/tmp/wherewolf/.coverage" timid = true +[tool.ty.rules] +# pyspark is an optional extra, so ty sees two different worlds. Without the extra +# installed, `from pyspark.sql import ...` is an unresolved-import; with it, that +# import resolves but `SparkSession.builder` does not (pyspark declares it as a +# classproperty ty cannot follow), producing unresolved-attribute instead. The two +# configurations therefore need opposite `ty: ignore` comments, and whichever set is +# not needed is reported as an unused directive. CI's lint leg installs +# `--extra spark`; a plain `uv sync` does not. Silencing unused-directive reports is +# what lets both suppressions coexist. Do not remove the `ty: ignore` comments in +# src/wherewolf/execution/spark_engine.py or tests/conftest.py because they look +# unused locally — they are load-bearing in the other configuration. +unused-ignore-comment = "ignore" + [dependency-groups] dev = [ "hatch>=1.17.0", diff --git a/src/wherewolf/execution/spark_engine.py b/src/wherewolf/execution/spark_engine.py index 8d01a47..e4dcbad 100644 --- a/src/wherewolf/execution/spark_engine.py +++ b/src/wherewolf/execution/spark_engine.py @@ -32,7 +32,7 @@ def _get_session(self) -> Any: spark_session = import_module("pyspark.sql").SparkSession root_session = ( # pyspark exposes `builder` dynamically, which ty cannot resolve. - spark_session.builder.appName("Wherewolf") + spark_session.builder.appName("Wherewolf") # ty: ignore[unresolved-attribute] .master("local[1]") .config("spark.driver.memory", "512m") .config("spark.ui.enabled", "false") diff --git a/tests/conftest.py b/tests/conftest.py index fcb0107..c048dd9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -29,7 +29,7 @@ def spark_session() -> Iterator[Any]: ) session = ( - SparkSession.builder.appName("wherewolf-tests") + SparkSession.builder.appName("wherewolf-tests") # ty: ignore[unresolved-attribute] .master("local[1]") .config("spark.driver.memory", "512m") .config("spark.ui.enabled", "false")