Implement comprehensive type annotations and mypy configuration as part of code quality initiative. Achieve 100% type annotation coverage for main CLI entry points and resolve Optional type inconsistencies. ## Key Improvements ### CLI Layer (100% Type Coverage) - tddai_cli.py: Complete type annotations for all 21 functions - cli/core.py: Full type coverage for CLI framework (20 functions) - cli/commands/issues.py: Fixed Optional[List[str]] parameter types - cli/commands/workspace.py: Improved type checker logic for Optional handling ### Service Layer Type Safety - services/issue_service.py: Fixed Optional parameter type signatures - services/project_service.py: Updated Optional type annotations - tddai/issue_creator.py: Proper Optional[List[str]] usage - tddai/project_manager.py: Fixed Optional parameter handling ### Mypy Configuration - pyproject.toml: Added comprehensive mypy configuration - Gradual adoption strategy with module-specific strictness - Python 3.12 compatibility for proper type checking - Incremental typing approach for legacy modules ## Technical Details - Proper Optional vs Union type usage throughout - Generic type annotations for collections - Return type annotations for all public functions - Fixed implicit Optional violations (PEP 484) - Type checker logic improvements for better safety ## Benefits - Improved IDE autocomplete and error detection - Compile-time type checking for CLI commands - Better maintainability and debugging capabilities - Foundation for expanding type safety to remaining modules Resolves #27 - Type safety improvements 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
100 lines
4.0 KiB
Python
100 lines
4.0 KiB
Python
"""
|
|
Workspace CLI commands.
|
|
"""
|
|
|
|
from tddai import TddaiError
|
|
from services import WorkspaceService
|
|
from cli.presenters import OutputFormatter, WorkspaceView
|
|
|
|
|
|
class WorkspaceCommands:
|
|
"""Commands for workspace operations."""
|
|
|
|
def __init__(self):
|
|
self.service = WorkspaceService()
|
|
|
|
def status(self) -> None:
|
|
"""Show current workspace status."""
|
|
try:
|
|
summary = self.service.get_workspace_summary()
|
|
WorkspaceView.show_status(summary)
|
|
except TddaiError as e:
|
|
OutputFormatter.exit_with_error(str(e))
|
|
|
|
def start_issue(self, issue_number: int) -> None:
|
|
"""Start working on an issue."""
|
|
try:
|
|
OutputFormatter.info(f"Starting work on issue #{issue_number}...")
|
|
OutputFormatter.info(f"Fetching issue #{issue_number} details...")
|
|
|
|
workspace_info = self.service.start_issue_workspace(issue_number)
|
|
summary = self.service.get_workspace_summary()
|
|
WorkspaceView.show_start_success(summary)
|
|
|
|
except TddaiError as e:
|
|
if "Already working on" in str(e):
|
|
OutputFormatter.warning(str(e))
|
|
print(" Run 'make tdd-finish' first or 'make tdd-status' to see details")
|
|
OutputFormatter.exit_with_error("Cannot start new workspace", 1)
|
|
else:
|
|
OutputFormatter.exit_with_error(str(e))
|
|
|
|
def finish_issue(self) -> None:
|
|
"""Finish current issue workspace."""
|
|
try:
|
|
issue_number = self.service.finish_current_workspace()
|
|
if issue_number is None:
|
|
OutputFormatter.error("No active issue workspace")
|
|
print(" Nothing to finish")
|
|
OutputFormatter.exit_with_error("", 1)
|
|
return # Explicit return for type checker
|
|
|
|
# Get test count before finishing
|
|
summary = self.service.get_workspace_summary()
|
|
test_count = summary.get('test_count', 0)
|
|
|
|
WorkspaceView.show_finish_success(issue_number, test_count)
|
|
|
|
except TddaiError as e:
|
|
OutputFormatter.exit_with_error(str(e))
|
|
|
|
def add_test_guidance(self) -> None:
|
|
"""Show guidance for adding tests."""
|
|
try:
|
|
summary = self.service.get_workspace_summary()
|
|
if not summary['active']:
|
|
OutputFormatter.error("No active issue workspace")
|
|
print(" Run 'make tdd-start NUM=X' first")
|
|
OutputFormatter.exit_with_error("", 1)
|
|
|
|
issue_num = summary['issue_number']
|
|
issue_title = summary['issue_title']
|
|
workspace_dir = summary['workspace_dir']
|
|
|
|
print(f"🧪 Adding test to issue #{issue_num} workspace")
|
|
OutputFormatter.empty_line()
|
|
OutputFormatter.key_value("Issue", f"#{issue_num}: {issue_title}")
|
|
OutputFormatter.key_value("Workspace", f"{workspace_dir}/issue_{issue_num}/")
|
|
OutputFormatter.empty_line()
|
|
|
|
print("🤖 Please ask Claude Code to generate a test:")
|
|
OutputFormatter.empty_line()
|
|
print(" Command: 'Generate a test for the current workspace issue'")
|
|
OutputFormatter.empty_line()
|
|
|
|
print("📝 Test Requirements:")
|
|
print(f" - Save test in: {workspace_dir}/issue_{issue_num}/tests/")
|
|
print(f" - Name format: test_issue_{issue_num}_<scenario>.py")
|
|
print(f" - Include docstring referencing issue #{issue_num}")
|
|
print(" - Follow TDD principles (test should fail initially)")
|
|
print(" - Review requirements.md and test_plan.md for context")
|
|
OutputFormatter.empty_line()
|
|
|
|
print("📋 Issue Details:")
|
|
OutputFormatter.key_value("Title", issue_title)
|
|
# Note: Could fetch full issue details if needed
|
|
OutputFormatter.empty_line()
|
|
print("💡 After generation: Use 'make tdd-status' to see all tests")
|
|
|
|
except TddaiError as e:
|
|
OutputFormatter.exit_with_error(str(e)) |