Skip to content

Commit 8fa0517

Browse files
committed
fix: clear the stale type: ignore comments and gate warn_unused_ignores
33 line-level ignores across 10 modules no longer suppress anything, per mypy --warn-unused-ignores in both the CausalPy and CausalPy-pymc6 envs (identical unused set in both). Deleted them; narrowed the one partially unused case in instrumental_variable.py to the code still needed (call-arg, not union-attr). warn_unused_ignores is now on in [tool.mypy] so a future fix that drops the underlying error also has to drop its now-stale ignore.
1 parent 3338e2a commit 8fa0517

10 files changed

Lines changed: 34 additions & 37 deletions

causalpy/checks/mccrary.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ def run(
9191
rd = experiment
9292
threshold = rd.treatment_threshold # type: ignore[attr-defined]
9393
running_var = rd.running_variable_name # type: ignore[attr-defined]
94-
data = rd.data # type: ignore[attr-defined]
94+
data = rd.data
9595

9696
x = data[running_var].values
9797
below = x[x < threshold]

causalpy/checks/placebo_in_time.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -528,7 +528,7 @@ def _compute_intervention_length(self, experiment: BaseExperiment) -> Any:
528528
return self.intervention_length
529529

530530
treatment_time = experiment.treatment_time # type: ignore[attr-defined]
531-
data = experiment.data # type: ignore[attr-defined]
531+
data = experiment.data
532532

533533
treatment_end = getattr(experiment, "treatment_end_time", None)
534534
if treatment_end is not None:
@@ -1042,13 +1042,9 @@ def _draw_expected_effect_samples(
10421042
raise ValueError("expected_effect_prior is not set.")
10431043
if hasattr(prior, "rvs"):
10441044
if self.random_seed is None:
1045-
return np.asarray(prior.rvs(n)) # type: ignore[union-attr]
1045+
return np.asarray(prior.rvs(n))
10461046
if self._rvs_accepts_random_state(prior):
1047-
return np.asarray(
1048-
prior.rvs( # type: ignore[union-attr]
1049-
n, random_state=self._rng_for_stage(0)
1050-
)
1051-
)
1047+
return np.asarray(prior.rvs(n, random_state=self._rng_for_stage(0)))
10521048

10531049
prior_type = f"{type(prior).__module__}.{type(prior).__qualname__}"
10541050
if unseeded_custom_priors is not None:
@@ -1065,7 +1061,7 @@ def _draw_expected_effect_samples(
10651061
"marks its type as unseeded.",
10661062
stacklevel=2,
10671063
)
1068-
return np.asarray(prior.rvs(n)) # type: ignore[union-attr]
1064+
return np.asarray(prior.rvs(n))
10691065
raise TypeError(
10701066
f"expected_effect_prior must have an .rvs(n) method, got "
10711067
f"{type(prior).__name__}."
@@ -1147,7 +1143,7 @@ def run(
11471143
unseeded_custom_priors: list[dict[str, str]] = []
11481144
factory = self._get_factory(context)
11491145
treatment_time = experiment.treatment_time # type: ignore[attr-defined]
1150-
data = experiment.data # type: ignore[attr-defined]
1146+
data = experiment.data
11511147
intervention_length = self._compute_intervention_length(experiment)
11521148
required_pre_period_rows = self._get_intervention_window_observation_count(
11531149
data, treatment_time, intervention_length

causalpy/experiments/interrupted_time_series.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,13 +274,13 @@ def input_validation(
274274
# Validate treatment_end_time > treatment_time
275275
# Type check: we've already validated both match the index type, so they're compatible
276276
# NOTE: Both treatment_time and treatment_end_time are INCLUSIVE (>=) in their respective periods
277-
if treatment_end_time <= treatment_time: # type: ignore[operator]
277+
if treatment_end_time <= treatment_time:
278278
raise ValueError(
279279
f"treatment_end_time ({treatment_end_time}) must be greater than treatment_time ({treatment_time})"
280280
)
281281
# Validate treatment_end_time is within data range
282282
# NOTE: treatment_end_time is INCLUSIVE, so it can equal data.index.max()
283-
if treatment_end_time > data.index.max(): # type: ignore[operator]
283+
if treatment_end_time > data.index.max():
284284
raise ValueError(
285285
f"treatment_end_time ({treatment_end_time}) is beyond the data range (max: {data.index.max()})"
286286
)

causalpy/experiments/inverse_propensity_weighting.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -448,9 +448,9 @@ def _compute_ate_overlap(
448448
weighted_outcome_trt,
449449
n_ntrt,
450450
n_trt,
451-
) = self.make_overlap_adjustments(ps) # type: ignore[assignment]
452-
ntrt = np.sum(weighted_outcome_ntrt) / np.sum(n_ntrt) # type: ignore[arg-type]
453-
trt = np.sum(weighted_outcome_trt) / np.sum(n_trt) # type: ignore[arg-type]
451+
) = self.make_overlap_adjustments(ps)
452+
ntrt = np.sum(weighted_outcome_ntrt) / np.sum(n_ntrt)
453+
trt = np.sum(weighted_outcome_trt) / np.sum(n_trt)
454454
ate = trt - ntrt
455455
return ate, trt, ntrt
456456

@@ -478,7 +478,7 @@ def _compute_ate_doubly_robust(
478478
weighted_outcome_trt,
479479
_n_ntrt,
480480
_n_trt,
481-
) = self.make_doubly_robust_adjustment(ps) # type: ignore[assignment]
481+
) = self.make_doubly_robust_adjustment(ps)
482482
trt = np.mean(weighted_outcome_trt)
483483
ntrt = np.mean(weighted_outcome_ntrt)
484484
ate = trt - ntrt

causalpy/experiments/panel_regression.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -854,11 +854,11 @@ def plot_trajectories(
854854
if units is not None:
855855
selected_units = units
856856
elif self.n_units <= n_sample:
857-
selected_units = all_units # type: ignore[assignment]
857+
selected_units = all_units
858858
else:
859859
if select == "random":
860860
rng = np.random.default_rng(42)
861-
selected_units = rng.choice(all_units, size=n_sample, replace=False) # type: ignore[assignment]
861+
selected_units = rng.choice(all_units, size=n_sample, replace=False)
862862
elif select == "extreme":
863863
# Select units with the largest and smallest mean outcomes
864864
unit_means = self.data.groupby(self.unit_fe_variable, observed=True)[
@@ -953,7 +953,7 @@ def plot_trajectories(
953953
# OLS: get fitted values for this unit
954954
y_fitted = np.squeeze(self.model.predict(self.design["X"]))[
955955
sorted_obs_indices
956-
] # type: ignore[union-attr]
956+
]
957957
ax.plot(
958958
sorted_time_vals,
959959
y_fitted,

causalpy/experiments/staggered_did.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -589,8 +589,8 @@ def _aggregate_effects_bayesian(
589589
).groups
590590
att_gt_rows: list[dict] = []
591591
for key, idx in gt_groups.items():
592-
g_val = key[0] # type: ignore[index]
593-
t_val = key[1] # type: ignore[index]
592+
g_val = key[0]
593+
t_val = key[1]
594594
# Find positions in treated_indices
595595
positions = [np.where(treated_indices == i)[0][0] for i in idx]
596596
tau_gt = tau_draws_treated[:, :, positions].mean(axis=2)
@@ -1196,8 +1196,8 @@ def _get_group_time_placebo_data_bayesian(self) -> pd.DataFrame:
11961196
["G", self.time_variable_name], observed=True
11971197
).groups
11981198
for key, idx in gt_groups.items():
1199-
g_val = key[0] # type: ignore[index]
1200-
t_val = key[1] # type: ignore[index]
1199+
g_val = key[0]
1200+
t_val = key[1]
12011201
positions = [np.where(self.data.index == i)[0][0] for i in idx]
12021202
tau_gt = tau_draws_all[:, :, positions].mean(axis=2)
12031203
att_gt_rows.append(

causalpy/formula_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ def _normalize_patsy_data(data: pd.DataFrame) -> pd.DataFrame:
9696
# ``isetitem`` accepts a Series at runtime; pandas-stubs omits it.
9797
normalized_data.isetitem(
9898
position,
99-
pd.Series(values, index=data.index, dtype=object), # type: ignore[arg-type]
99+
pd.Series(values, index=data.index, dtype=object),
100100
)
101101
return normalized_data
102102

causalpy/pymc_models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2119,7 +2119,7 @@ def build_model(
21192119

21202120
# Add coeffs coordinate if we have exogenous variables
21212121
if self._exog_var_names:
2122-
model_coords["coeffs"] = self._exog_var_names # type: ignore[assignment]
2122+
model_coords["coeffs"] = self._exog_var_names
21232123

21242124
with self:
21252125
self.add_coords(model_coords)

causalpy/transforms.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -102,12 +102,12 @@ def memorize_chunk(
102102
if self._is_datetime_like(x):
103103
self._is_datetime = True
104104
x_dt = pd.to_datetime(x)
105-
x_min: pd.Timestamp = pd.Timestamp(x_dt.min()) # type: ignore[assignment]
105+
x_min: pd.Timestamp = pd.Timestamp(x_dt.min())
106106
if self._origin is None:
107107
self._origin = x_min
108108
else:
109109
# Handle chunked data - keep the overall minimum
110-
self._origin = min(self._origin, x_min) # type: ignore[assignment]
110+
self._origin = min(self._origin, x_min)
111111

112112
def memorize_finish(self) -> None:
113113
"""Called after all chunks processed - finalize state."""
@@ -149,7 +149,7 @@ def transform(
149149
t_numeric = (threshold_dt - self._origin).total_seconds() / (24 * 3600)
150150
else:
151151
x_numeric = np.asarray(x, dtype=float)
152-
t_numeric = float(threshold) # type: ignore[arg-type]
152+
t_numeric = float(threshold)
153153

154154
return (x_numeric >= t_numeric).astype(float)
155155

@@ -161,7 +161,7 @@ def _parse_threshold(
161161
return threshold
162162
else:
163163
# Assume it's something pandas can convert (str or numeric)
164-
return pd.Timestamp(threshold) # type: ignore[arg-type, return-value]
164+
return pd.Timestamp(threshold)
165165

166166

167167
class RampTransform:
@@ -222,11 +222,11 @@ def memorize_chunk(
222222
if self._is_datetime_like(x):
223223
self._is_datetime = True
224224
x_dt = pd.to_datetime(x)
225-
x_min: pd.Timestamp = pd.Timestamp(x_dt.min()) # type: ignore[assignment]
225+
x_min: pd.Timestamp = pd.Timestamp(x_dt.min())
226226
if self._origin is None:
227227
self._origin = x_min
228228
else:
229-
self._origin = min(self._origin, x_min) # type: ignore[assignment]
229+
self._origin = min(self._origin, x_min)
230230

231231
def memorize_finish(self) -> None:
232232
"""Called after all chunks processed."""
@@ -269,7 +269,7 @@ def transform(
269269
t_numeric = (threshold_dt - self._origin).total_seconds() / (24 * 3600)
270270
else:
271271
x_numeric = np.asarray(x, dtype=float)
272-
t_numeric = float(threshold) # type: ignore[arg-type]
272+
t_numeric = float(threshold)
273273

274274
return np.maximum(0.0, x_numeric - t_numeric)
275275

@@ -281,7 +281,7 @@ def _parse_threshold(
281281
return threshold
282282
else:
283283
# Assume it's something pandas can convert (str or numeric)
284-
return pd.Timestamp(threshold) # type: ignore[arg-type, return-value]
284+
return pd.Timestamp(threshold)
285285

286286

287287
class ElapsedDaysTransform:
@@ -326,9 +326,9 @@ def transform(self, x: Any) -> np.ndarray:
326326

327327

328328
# Create callable stateful transforms for use in formulas
329-
step = patsy.stateful_transform(StepTransform) # type: ignore[attr-defined]
330-
ramp = patsy.stateful_transform(RampTransform) # type: ignore[attr-defined]
331-
elapsed = patsy.stateful_transform(ElapsedDaysTransform) # type: ignore[attr-defined]
329+
step = patsy.stateful_transform(StepTransform)
330+
ramp = patsy.stateful_transform(RampTransform)
331+
elapsed = patsy.stateful_transform(ElapsedDaysTransform)
332332

333333
__all__ = [
334334
"step",

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,8 @@ ignore_missing_imports = true
235235
warn_unused_configs = true
236236
# The allowlist is empty: the package type-checks clean. What could not be expressed in the type system is a handful of line-level ``type: ignore`` comments, each with the reasoning next to it.
237237
#
238-
# ``warn_unused_ignores`` would make those comments self-cleaning, and is worth turning on, but it currently reports 33 pre-existing unused ignores across 10 modules. Clearing those is its own change, not a rider on this one.
238+
# ``warn_unused_ignores`` keeps those comments self-cleaning: a fix that removes the underlying error now fails the check unless the now-unneeded ignore is deleted with it.
239+
warn_unused_ignores = true
239240

240241
[tool.marimo.runtime]
241242
watcher_on_save = "autorun"

0 commit comments

Comments
 (0)