Skip to content

Commit 8fa8a55

Browse files
Really Himclaude
andcommitted
fix: resolve mypy type annotation errors in test files and CLI
- Add -> None return type annotations to all test functions - Fix positional-only parameter issue in deprecated_wrapper function - Add Path type annotation for temp_project_dir parameter in test_stats.py All mypy checks now pass successfully. 🤖 Generated with Claude Code Co-Authored-By: Claude <[email protected]>
1 parent 2aa16ae commit 8fa8a55

10 files changed

Lines changed: 132 additions & 52 deletions

fix_remaining_annotations.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import re
2+
from pathlib import Path
3+
4+
# Remaining test files with mypy errors
5+
test_files = [
6+
"tests/unit/cli/test_config_view.py",
7+
]
8+
9+
for file_path in test_files:
10+
path = Path(file_path)
11+
if not path.exists():
12+
print(f"Skipping {file_path} (not found)")
13+
continue
14+
15+
content = path.read_text()
16+
17+
# Pattern to match test functions without return type annotation
18+
pattern = r'(\s+def test_[^(]+\(self[^)]*\))(\s*:)'
19+
20+
def replacer(match):
21+
# Add -> None before the colon
22+
return match.group(1) + ' -> None' + match.group(2)
23+
24+
# Apply the replacement
25+
new_content = re.sub(pattern, replacer, content)
26+
27+
if new_content != content:
28+
path.write_text(new_content)
29+
print(f"Fixed {file_path}")
30+
else:
31+
print(f"No changes needed for {file_path}")
32+
33+
# Now fix the specific issue in test_stats.py - missing type annotation for temp_project_dir parameter
34+
stats_file = Path("tests/unit/cli/test_stats.py")
35+
if stats_file.exists():
36+
content = stats_file.read_text()
37+
# Fix the specific line with missing parameter type annotation
38+
content = content.replace(
39+
"def test_negative_depth(self, temp_project_dir) -> None:",
40+
"def test_negative_depth(self, temp_project_dir: Path) -> None:"
41+
)
42+
stats_file.write_text(content)
43+
print(f"Fixed parameter annotation in tests/unit/cli/test_stats.py")

fix_test_annotations.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import re
2+
from pathlib import Path
3+
4+
# List of test files with mypy errors
5+
test_files = [
6+
"tests/unit/cli/test_validate_config.py",
7+
"tests/unit/cli/test_ignore_patterns.py",
8+
"tests/unit/cli/test_generate_config.py",
9+
"tests/unit/cli/test_metrics.py",
10+
"tests/unit/cli/test_config.py",
11+
"tests/unit/cli/test_stats.py",
12+
]
13+
14+
for file_path in test_files:
15+
path = Path(file_path)
16+
if not path.exists():
17+
print(f"Skipping {file_path} (not found)")
18+
continue
19+
20+
content = path.read_text()
21+
22+
# Pattern to match test functions without return type annotation
23+
# Matches: def test_name(self): or def test_name(self, ...):
24+
pattern = r'(\s+def test_[^(]+\(self[^)]*\))(\s*:)'
25+
26+
def replacer(match):
27+
# Add -> None before the colon
28+
return match.group(1) + ' -> None' + match.group(2)
29+
30+
# Apply the replacement
31+
new_content = re.sub(pattern, replacer, content)
32+
33+
if new_content != content:
34+
path.write_text(new_content)
35+
print(f"Fixed {file_path}")
36+
else:
37+
print(f"No changes needed for {file_path}")

src/antipasta/cli/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def create_deprecated_command(new_cmd_path: str, old_function: click.Command) ->
3434

3535
@click.command(hidden=True) # Hidden from help text
3636
@click.pass_context
37-
def deprecated_wrapper(ctx: click.Context, **kwargs: Any) -> None:
37+
def deprecated_wrapper(ctx: click.Context, /, **kwargs: Any) -> None:
3838
click.echo(
3939
f"⚠️ Warning: This command is deprecated. "
4040
f"Please use 'antipasta {new_cmd_path}' instead.",

tests/unit/cli/test_config.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
class TestConfigCommandGroup:
1212
"""Test the config command group and subcommands."""
1313

14-
def test_config_help(self):
14+
def test_config_help(self) -> None:
1515
"""Test config command help."""
1616
runner = CliRunner()
1717
result = runner.invoke(cli, ["config", "--help"])
@@ -23,7 +23,7 @@ def test_config_help(self):
2323
assert "validate" in result.output
2424
assert "view" in result.output
2525

26-
def test_config_generate_subcommand(self):
26+
def test_config_generate_subcommand(self) -> None:
2727
"""Test config generate subcommand works."""
2828
runner = CliRunner()
2929
with tempfile.TemporaryDirectory() as tmpdir:
@@ -38,7 +38,7 @@ def test_config_generate_subcommand(self):
3838
assert output_file.exists()
3939
assert "✅ Configuration saved to" in result.output
4040

41-
def test_config_validate_subcommand(self):
41+
def test_config_validate_subcommand(self) -> None:
4242
"""Test config validate subcommand works."""
4343
runner = CliRunner()
4444
with tempfile.TemporaryDirectory() as tmpdir:
@@ -68,7 +68,7 @@ def test_config_validate_subcommand(self):
6868
assert result.exit_code == 0
6969
assert "✅ Configuration file is valid" in result.output
7070

71-
def test_config_view_subcommand(self):
71+
def test_config_view_subcommand(self) -> None:
7272
"""Test config view subcommand works."""
7373
runner = CliRunner()
7474
with tempfile.TemporaryDirectory() as tmpdir:
@@ -98,7 +98,7 @@ def test_config_view_subcommand(self):
9898
assert f"Configuration: {config_file}" in result.output
9999
assert "Status: ✅ Valid" in result.output
100100

101-
def test_backward_compatibility_generate_config(self):
101+
def test_backward_compatibility_generate_config(self) -> None:
102102
"""Test backward compatibility for generate-config command."""
103103
runner = CliRunner()
104104
with tempfile.TemporaryDirectory() as tmpdir:
@@ -115,7 +115,7 @@ def test_backward_compatibility_generate_config(self):
115115
assert "Please use 'antipasta config generate'" in result.output
116116
assert output_file.exists()
117117

118-
def test_backward_compatibility_validate_config(self):
118+
def test_backward_compatibility_validate_config(self) -> None:
119119
"""Test backward compatibility for validate-config command."""
120120
runner = CliRunner()
121121
with tempfile.TemporaryDirectory() as tmpdir:
@@ -147,7 +147,7 @@ def test_backward_compatibility_validate_config(self):
147147
assert "Please use 'antipasta config validate'" in result.output
148148
assert "✅ Configuration file is valid" in result.output
149149

150-
def test_deprecated_commands_hidden_from_help(self):
150+
def test_deprecated_commands_hidden_from_help(self) -> None:
151151
"""Test that deprecated commands are hidden from main help."""
152152
runner = CliRunner()
153153
result = runner.invoke(cli, ["--help"])

tests/unit/cli/test_config_view.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
class TestConfigViewCommand:
1414
"""Test the config view command."""
1515

16-
def test_view_valid_config_summary(self):
16+
def test_view_valid_config_summary(self) -> None:
1717
"""Test viewing a valid configuration in summary format."""
1818
runner = CliRunner()
1919
with tempfile.TemporaryDirectory() as tmpdir:
@@ -55,7 +55,7 @@ def test_view_valid_config_summary(self):
5555
assert "IGNORE PATTERNS (2)" in result.output
5656
assert "Using .gitignore: Yes" in result.output
5757

58-
def test_view_nonexistent_config(self):
58+
def test_view_nonexistent_config(self) -> None:
5959
"""Test viewing a nonexistent configuration file."""
6060
runner = CliRunner()
6161
with tempfile.TemporaryDirectory() as tmpdir:
@@ -67,7 +67,7 @@ def test_view_nonexistent_config(self):
6767
assert "Configuration file not found" in result.output
6868
assert "Run 'antipasta config generate'" in result.output
6969

70-
def test_view_invalid_config_with_validation(self):
70+
def test_view_invalid_config_with_validation(self) -> None:
7171
"""Test viewing an invalid configuration with validation enabled."""
7272
runner = CliRunner()
7373
with tempfile.TemporaryDirectory() as tmpdir:
@@ -91,7 +91,7 @@ def test_view_invalid_config_with_validation(self):
9191
assert "Status: ❌ Invalid" in result.output
9292
assert "Configuration has validation errors" in result.output
9393

94-
def test_view_raw_format(self):
94+
def test_view_raw_format(self) -> None:
9595
"""Test viewing configuration in raw format."""
9696
runner = CliRunner()
9797
with tempfile.TemporaryDirectory() as tmpdir:
@@ -107,7 +107,7 @@ def test_view_raw_format(self):
107107
assert result.exit_code == 0
108108
assert result.output.strip() == content.strip()
109109

110-
def test_view_json_format(self):
110+
def test_view_json_format(self) -> None:
111111
"""Test viewing configuration in JSON format."""
112112
runner = CliRunner()
113113
with tempfile.TemporaryDirectory() as tmpdir:
@@ -142,7 +142,7 @@ def test_view_json_format(self):
142142
assert data["languages"][0]["name"] == "python"
143143
assert data["use_gitignore"] is False
144144

145-
def test_view_yaml_format(self):
145+
def test_view_yaml_format(self) -> None:
146146
"""Test viewing configuration in YAML format."""
147147
runner = CliRunner()
148148
with tempfile.TemporaryDirectory() as tmpdir:
@@ -174,7 +174,7 @@ def test_view_yaml_format(self):
174174
assert data["defaults"]["max_cyclomatic_complexity"] == 10
175175
assert data["languages"][0]["name"] == "python"
176176

177-
def test_view_table_format(self):
177+
def test_view_table_format(self) -> None:
178178
"""Test viewing configuration in table format."""
179179
runner = CliRunner()
180180
with tempfile.TemporaryDirectory() as tmpdir:
@@ -222,7 +222,7 @@ def test_view_table_format(self):
222222
assert "║" in result.output
223223
assert "╚" in result.output
224224

225-
def test_view_no_languages_config(self):
225+
def test_view_no_languages_config(self) -> None:
226226
"""Test viewing configuration with no languages configured."""
227227
runner = CliRunner()
228228
with tempfile.TemporaryDirectory() as tmpdir:
@@ -244,7 +244,7 @@ def test_view_no_languages_config(self):
244244
assert "No languages configured" in result.output
245245
assert "Using .gitignore: No" in result.output
246246

247-
def test_view_many_ignore_patterns(self):
247+
def test_view_many_ignore_patterns(self) -> None:
248248
"""Test viewing configuration with many ignore patterns."""
249249
runner = CliRunner()
250250
with tempfile.TemporaryDirectory() as tmpdir:
@@ -276,7 +276,7 @@ def test_view_many_ignore_patterns(self):
276276
assert "pattern_0" in result.output
277277
assert "... and 5 more" in result.output
278278

279-
def test_view_no_validate_flag(self):
279+
def test_view_no_validate_flag(self) -> None:
280280
"""Test viewing configuration with --no-validate flag."""
281281
runner = CliRunner()
282282
with tempfile.TemporaryDirectory() as tmpdir:
@@ -297,7 +297,7 @@ def test_view_no_validate_flag(self):
297297
# But no validation errors shown with --no-validate
298298
assert "Configuration has validation errors" not in result.output
299299

300-
def test_view_default_config_file(self):
300+
def test_view_default_config_file(self) -> None:
301301
"""Test that view defaults to .antipasta.yaml."""
302302
runner = CliRunner()
303303
with runner.isolated_filesystem():

tests/unit/cli/test_generate_config.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
class TestGenerateConfigCommand:
1414
"""Test the generate-config command."""
1515

16-
def test_non_interactive_generates_default_config(self):
16+
def test_non_interactive_generates_default_config(self) -> None:
1717
"""Test that non-interactive mode generates a valid default config."""
1818
runner = CliRunner()
1919
with tempfile.TemporaryDirectory() as tmpdir:
@@ -33,7 +33,7 @@ def test_non_interactive_generates_default_config(self):
3333
assert len(config.languages) == 1
3434
assert config.languages[0].name == "python"
3535

36-
def test_non_interactive_overwrites_existing_file(self):
36+
def test_non_interactive_overwrites_existing_file(self) -> None:
3737
"""Test that non-interactive mode overwrites existing files without prompting."""
3838
runner = CliRunner()
3939
with tempfile.TemporaryDirectory() as tmpdir:
@@ -50,7 +50,7 @@ def test_non_interactive_overwrites_existing_file(self):
5050
assert "existing content" not in content
5151
assert "# antipasta configuration file" in content
5252

53-
def test_interactive_mode_with_defaults(self):
53+
def test_interactive_mode_with_defaults(self) -> None:
5454
"""Test interactive mode accepting all defaults."""
5555
runner = CliRunner()
5656
with tempfile.TemporaryDirectory() as tmpdir:
@@ -81,7 +81,7 @@ def test_interactive_mode_with_defaults(self):
8181
assert config.defaults.max_cyclomatic_complexity == 10
8282
assert config.defaults.max_cognitive_complexity == 15
8383

84-
def test_interactive_mode_with_custom_values(self):
84+
def test_interactive_mode_with_custom_values(self) -> None:
8585
"""Test interactive mode with custom threshold values."""
8686
runner = CliRunner()
8787
with tempfile.TemporaryDirectory() as tmpdir:
@@ -124,7 +124,7 @@ def test_interactive_mode_with_custom_values(self):
124124
assert "*.pyc" in config.ignore_patterns
125125
assert "__pycache__" in config.ignore_patterns
126126

127-
def test_interactive_mode_file_exists_abort(self):
127+
def test_interactive_mode_file_exists_abort(self) -> None:
128128
"""Test that interactive mode aborts when user declines to overwrite."""
129129
runner = CliRunner()
130130
with tempfile.TemporaryDirectory() as tmpdir:
@@ -156,7 +156,7 @@ def test_interactive_mode_file_exists_abort(self):
156156
content = output_file.read_text()
157157
assert content == "existing content\n"
158158

159-
def test_interactive_mode_file_exists_overwrite(self):
159+
def test_interactive_mode_file_exists_overwrite(self) -> None:
160160
"""Test that interactive mode overwrites when user confirms."""
161161
runner = CliRunner()
162162
with tempfile.TemporaryDirectory() as tmpdir:
@@ -188,7 +188,7 @@ def test_interactive_mode_file_exists_overwrite(self):
188188
assert "old content" not in content
189189
assert "# antipasta configuration file" in content
190190

191-
def test_default_output_path(self):
191+
def test_default_output_path(self) -> None:
192192
"""Test that default output path is .antipasta.yaml."""
193193
runner = CliRunner()
194194
with runner.isolated_filesystem():
@@ -198,7 +198,7 @@ def test_default_output_path(self):
198198
assert Path(".antipasta.yaml").exists()
199199
assert "✅ Configuration saved to .antipasta.yaml" in result.output
200200

201-
def test_generated_config_has_helpful_comments(self):
201+
def test_generated_config_has_helpful_comments(self) -> None:
202202
"""Test that generated config includes helpful comments."""
203203
runner = CliRunner()
204204
with tempfile.TemporaryDirectory() as tmpdir:
@@ -217,7 +217,7 @@ def test_generated_config_has_helpful_comments(self):
217217
assert "# Files and patterns to ignore during analysis" in content
218218
assert "# Whether to use .gitignore file for excluding files" in content
219219

220-
def test_javascript_coming_soon_message(self):
220+
def test_javascript_coming_soon_message(self) -> None:
221221
"""Test that JavaScript/TypeScript shows 'coming soon' message."""
222222
runner = CliRunner()
223223
with tempfile.TemporaryDirectory() as tmpdir:
@@ -248,7 +248,7 @@ def test_javascript_coming_soon_message(self):
248248
assert len(config.languages) == 1
249249
assert config.languages[0].name == "python"
250250

251-
def test_permission_error_handling(self):
251+
def test_permission_error_handling(self) -> None:
252252
"""Test that permission errors are handled gracefully."""
253253
runner = CliRunner()
254254
with patch("builtins.open", side_effect=PermissionError("Permission denied")):
@@ -259,7 +259,7 @@ def test_permission_error_handling(self):
259259
assert result.exit_code == 1
260260
assert "❌ Error saving configuration: Permission denied" in result.output
261261

262-
def test_interactive_mode_invalid_values_reprompt(self):
262+
def test_interactive_mode_invalid_values_reprompt(self) -> None:
263263
"""Test that invalid values trigger re-prompt."""
264264
runner = CliRunner()
265265
with tempfile.TemporaryDirectory() as tmpdir:
@@ -289,7 +289,7 @@ def test_interactive_mode_invalid_values_reprompt(self):
289289
assert result.exit_code == 0
290290
assert output_file.exists()
291291

292-
def test_shows_metric_ranges_in_prompts(self):
292+
def test_shows_metric_ranges_in_prompts(self) -> None:
293293
"""Test that metric prompts show valid ranges."""
294294
runner = CliRunner()
295295
with tempfile.TemporaryDirectory() as tmpdir:
@@ -317,7 +317,7 @@ def test_shows_metric_ranges_in_prompts(self):
317317
assert "Range: 1-100" in result.output # Cognitive
318318
assert "Range: 0-100" in result.output # Maintainability
319319

320-
def test_advanced_metrics_validation(self):
320+
def test_advanced_metrics_validation(self) -> None:
321321
"""Test validation of advanced Halstead metrics."""
322322
runner = CliRunner()
323323
with tempfile.TemporaryDirectory() as tmpdir:

0 commit comments

Comments
 (0)