Skip to content

Commit 1004680

Browse files
Add guarded behavior-preserving ruff repairs
1 parent 1c60125 commit 1004680

1 file changed

Lines changed: 230 additions & 0 deletions

File tree

Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
name: Apply guarded ruff repairs
2+
3+
on:
4+
push:
5+
branches:
6+
- claude/inference-comparison-4vlt4q
7+
paths:
8+
- .github/workflows/apply-ruff-repairs.yml
9+
10+
permissions:
11+
contents: write
12+
13+
jobs:
14+
repair:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Check out branch
18+
uses: actions/checkout@v4
19+
with:
20+
ref: claude/inference-comparison-4vlt4q
21+
fetch-depth: 0
22+
23+
- name: Apply exact guarded replacements
24+
run: |
25+
python - <<'PY'
26+
from pathlib import Path
27+
28+
def replace_once(path: str, old: str, new: str) -> None:
29+
p = Path(path)
30+
text = p.read_text()
31+
count = text.count(old)
32+
if count != 1:
33+
raise RuntimeError(f"{path}: expected exactly one match, found {count}: {old!r}")
34+
p.write_text(text.replace(old, new, 1))
35+
36+
replace_once(
37+
"src/nns/_reg_engine.py",
38+
"import math\nimport re\n",
39+
"import math\nimport re\nfrom itertools import pairwise\n",
40+
)
41+
replace_once(
42+
"src/nns/_reg_engine.py",
43+
"ord_value = max(1, int(math.floor(dep * 10 + 0.5)))",
44+
"ord_value = max(1, math.floor(dep * 10 + 0.5))",
45+
)
46+
replace_once(
47+
"src/nns/_reg_engine.py",
48+
"ord_value = max(1, int(math.floor(ord_value / 2)))",
49+
"ord_value = max(1, math.floor(ord_value / 2))",
50+
)
51+
replace_once(
52+
"src/nns/_reg_engine.py",
53+
"for a, b in zip(unique_knots[:-1], unique_knots[1:]):",
54+
"for a, b in pairwise(unique_knots):",
55+
)
56+
replace_once(
57+
"src/nns/_reg_engine.py",
58+
'"Variable": names + ["DENOMINATOR"],',
59+
'"Variable": [*names, "DENOMINATOR"],',
60+
)
61+
replace_once(
62+
"src/nns/_reg_engine.py",
63+
"k = max(1, int(math.floor((1.0 - dep) * math.sqrt(x.shape[0]))))",
64+
"k = max(1, math.floor((1.0 - dep) * math.sqrt(x.shape[0])))",
65+
)
66+
67+
replace_once(
68+
"src/nns/_rrng.py",
69+
"v1 = int(math.floor(self.unif_rand() * 65536))",
70+
"v1 = math.floor(self.unif_rand() * 65536)",
71+
)
72+
replace_once(
73+
"src/nns/_rrng.py",
74+
"bits = int(math.ceil(math.log2(dn)))",
75+
"bits = math.ceil(math.log2(dn))",
76+
)
77+
replace_once(
78+
"src/nns/_rrng.py",
79+
" def sample_int(self, n: int, size: int | None = None, replace: bool = False) -> NDArray[np.int64]:\n",
80+
" def sample_int(\n self, n: int, size: int | None = None, replace: bool = False\n ) -> NDArray[np.int64]:\n",
81+
)
82+
83+
replace_once(
84+
"src/nns/boost.py",
85+
"size = max(1, min(n_obs - 1, int(round(cv_fraction * n_obs))))",
86+
"size = max(1, min(n_obs - 1, round(cv_fraction * n_obs)))",
87+
)
88+
replace_once(
89+
"src/nns/boost.py",
90+
"k_small = max(1, int(math.floor(math.sqrt(minimum_train_size))))",
91+
"k_small = max(1, math.floor(math.sqrt(minimum_train_size)))",
92+
)
93+
replace_once(
94+
"src/nns/boost.py",
95+
"k_candidates = list(dict.fromkeys(list(range(1, k_small + 1)) + [minimum_train_size]))",
96+
"k_candidates = list(dict.fromkeys([*range(1, k_small + 1), minimum_train_size]))",
97+
)
98+
99+
replace_once(
100+
"src/nns/stack.py",
101+
"def _scalar_integer(value: Any, name: str, minimum: int = 0, allow_null: bool = False) -> int | None:\n",
102+
"def _scalar_integer(\n value: Any, name: str, minimum: int = 0, allow_null: bool = False\n) -> int | None:\n",
103+
)
104+
replace_once(
105+
"src/nns/stack.py",
106+
" [class_values.index(v) + 1 for v in (dv.tolist() if response_categorical else dv.astype(np.float64).tolist())],\n",
107+
" [\n class_values.index(v) + 1\n for v in (\n dv.tolist()\n if response_categorical\n else dv.astype(np.float64).tolist()\n )\n ],\n",
108+
)
109+
replace_once(
110+
"src/nns/stack.py",
111+
' "Method 2 was removed because dimension reduction requires more than one original predictor.",\n',
112+
' "Method 2 was removed because dimension reduction requires more than "\n "one original predictor.",\n',
113+
)
114+
replace_once(
115+
"src/nns/stack.py",
116+
" return np.clip(np.asarray(code, dtype=np.float64), 1, n_classes).astype(np.int64).astype(np.float64)\n",
117+
" return (\n np.clip(np.asarray(code, dtype=np.float64), 1, n_classes)\n .astype(np.int64)\n .astype(np.float64)\n )\n",
118+
)
119+
replace_once(
120+
"src/nns/stack.py",
121+
"size = min(g.size - 1, max(1, int(round(holdout_size * g.size))))",
122+
"size = min(g.size - 1, max(1, round(holdout_size * g.size)))",
123+
)
124+
replace_once(
125+
"src/nns/stack.py",
126+
"size = max(1, min(n_obs - 1, int(round(holdout_size * n_obs))))",
127+
"size = max(1, min(n_obs - 1, round(holdout_size * n_obs)))",
128+
)
129+
replace_once(
130+
"src/nns/stack.py",
131+
" def coefficient_vector(design: NDArray[np.float64], response: NDArray[np.float64]) -> NDArray[np.float64]:\n",
132+
" def coefficient_vector(\n design: NDArray[np.float64], response: NDArray[np.float64]\n ) -> NDArray[np.float64]:\n",
133+
)
134+
replace_once(
135+
"src/nns/stack.py",
136+
"l_small = max(1, int(math.floor(math.sqrt(n_obs))))",
137+
"l_small = max(1, math.floor(math.sqrt(n_obs)))",
138+
)
139+
140+
replace_once(
141+
"src/nns/var.py",
142+
" _METHOD1_GUARD_MESSAGE = (\n",
143+
" method1_guard_message = (\n",
144+
)
145+
replace_once(
146+
"src/nns/var.py",
147+
''' def run_var_stack(stack_obj_fn: Any, stack_objective: str) -> dict[str, Any]:
148+
return nns_stack(
149+
lagged_iv,
150+
lagged_dv,
151+
ivs_test=ivs_test,
152+
obj_fn=cast(Any, stack_obj_fn),
153+
objective=cast(Any, stack_objective),
154+
folds=1,
155+
method=(1, 2),
156+
order=None,
157+
stack=True,
158+
dim_red_method=cast(Any, dim_red_threshold_method),
159+
ts_test=ts_test,
160+
)
161+
162+
try:
163+
result = run_var_stack(var_obj_fn, objective_value)
164+
except ValueError as error:
165+
if not (use_default_objective and str(error) == _METHOD1_GUARD_MESSAGE):
166+
raise
167+
result = run_var_stack(mse_obj_fn, "min")
168+
''',
169+
''' def run_var_stack(
170+
stack_obj_fn: Any,
171+
stack_objective: str,
172+
stack_iv: np.ndarray,
173+
stack_dv: np.ndarray,
174+
stack_test: np.ndarray,
175+
stack_ts_test: int,
176+
) -> dict[str, Any]:
177+
return nns_stack(
178+
stack_iv,
179+
stack_dv,
180+
ivs_test=stack_test,
181+
obj_fn=cast(Any, stack_obj_fn),
182+
objective=cast(Any, stack_objective),
183+
folds=1,
184+
method=(1, 2),
185+
order=None,
186+
stack=True,
187+
dim_red_method=cast(Any, dim_red_threshold_method),
188+
ts_test=stack_ts_test,
189+
)
190+
191+
try:
192+
result = run_var_stack(
193+
var_obj_fn,
194+
objective_value,
195+
lagged_iv,
196+
lagged_dv,
197+
ivs_test,
198+
ts_test,
199+
)
200+
except ValueError as error:
201+
if not (use_default_objective and str(error) == method1_guard_message):
202+
raise
203+
result = run_var_stack(
204+
mse_obj_fn,
205+
"min",
206+
lagged_iv,
207+
lagged_dv,
208+
ivs_test,
209+
ts_test,
210+
)
211+
''',
212+
)
213+
214+
replace_once(
215+
"tests/parity/test_regression.py",
216+
'with pytest.raises(ValueError, match="noise.reduction"):',
217+
'with pytest.raises(ValueError, match=r"noise\\.reduction"):',
218+
)
219+
PY
220+
221+
- name: Verify ruff and commit
222+
run: |
223+
python -m pip install -q ruff
224+
ruff check .
225+
git config user.name "github-actions[bot]"
226+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
227+
git rm .github/workflows/apply-ruff-repairs.yml
228+
git add src tests
229+
git commit -m "Resolve remaining ruff findings without behavior changes"
230+
git push origin HEAD:claude/inference-comparison-4vlt4q

0 commit comments

Comments
 (0)