""" CLI commands for issue management. This module provides Click commands for the unified issue management interface. """ import click from typing import Optional from .manager import IssuePluginManager from .exceptions import PluginNotFoundError, ConfigurationError from cli.presenters.views import IssueView @click.group() def issues(): """Issue management with multiple backend support.""" pass @issues.command() @click.option('--state', type=click.Choice(['open', 'closed', 'all']), default='all', help='Filter issues by state') @click.option('--backend', help='Override configured backend') def list(state: str, backend: Optional[str]): """List issues from configured backend.""" try: manager = IssuePluginManager() backend_instance = manager.get_backend(backend) issues_list = backend_instance.list_issues(state=state) if state == 'open': IssueView.show_open_issues(issues_list) else: IssueView.show_list(issues_list, f"Issues ({state})") except (PluginNotFoundError, ConfigurationError) as e: click.echo(f"Error: {e}", err=True) raise click.Abort() except Exception as e: click.echo(f"Unexpected error: {e}", err=True) raise click.Abort() @issues.command() @click.argument('issue_id') @click.option('--backend', help='Override configured backend') def show(issue_id: str, backend: Optional[str]): """Show details of a specific issue.""" try: manager = IssuePluginManager() backend_instance = manager.get_backend(backend) issue = backend_instance.get_issue(issue_id) # Convert issue to dict for display issue_data = { 'number': issue.number, 'title': issue.title, 'body': getattr(issue, '_body', ''), 'state': issue.state.value if hasattr(issue.state, 'value') else str(issue.state), 'created_at': issue.created_at, 'updated_at': getattr(issue, 'updated_at', issue.created_at), 'labels': [label.name if hasattr(label, 'name') else str(label) for label in issue.labels], 'assignees': getattr(issue, 'assignees', []) or [], 'assignee': getattr(issue, 'assignee', None), 'milestone': getattr(issue, 'milestone', None), 'html_url': getattr(issue, 'html_url', ''), 'state_label': getattr(issue, 'state_label', issue.state.value if hasattr(issue.state, 'value') else str(issue.state)), 'priority_label': getattr(issue, 'priority_label', 'Normal'), 'type_labels': getattr(issue, 'type_labels', []), 'other_labels': getattr(issue, 'other_labels', []), 'kanban_column': getattr(issue, 'kanban_column', 'To Do') } IssueView.show_issue_details(issue_data) except FileNotFoundError: click.echo(f"Error: Issue {issue_id} not found", err=True) raise click.Abort() except (PluginNotFoundError, ConfigurationError) as e: click.echo(f"Error: {e}", err=True) raise click.Abort() except Exception as e: click.echo(f"Unexpected error: {e}", err=True) raise click.Abort() @issues.command() @click.argument('title') @click.argument('body') @click.option('--backend', help='Override configured backend') def create(title: str, body: str, backend: Optional[str]): """Create a new issue.""" try: manager = IssuePluginManager() backend_instance = manager.get_backend(backend) issue = backend_instance.create_issue(title, body) # Convert issue to dict for display result = { 'number': issue.number, 'title': issue.title, 'state': issue.state.value if hasattr(issue.state, 'value') else str(issue.state) } IssueView.show_creation_success(result, "issue") click.echo(f"Issue #{issue.number} created successfully") except (PluginNotFoundError, ConfigurationError) as e: click.echo(f"Error: {e}", err=True) raise click.Abort() except Exception as e: click.echo(f"Unexpected error: {e}", err=True) raise click.Abort() @issues.command() @click.argument('issue_id') @click.argument('comment') @click.option('--backend', help='Override configured backend') def comment(issue_id: str, comment: str, backend: Optional[str]): """Add a comment to an issue.""" try: manager = IssuePluginManager() backend_instance = manager.get_backend(backend) result = backend_instance.add_comment(issue_id, comment) click.echo(f"Comment added to issue #{issue_id}") except ValueError as e: click.echo(f"Error: {e}", err=True) raise click.Abort() except (PluginNotFoundError, ConfigurationError) as e: click.echo(f"Error: {e}", err=True) raise click.Abort() except Exception as e: click.echo(f"Unexpected error: {e}", err=True) raise click.Abort() @issues.command() @click.argument('issue_id') @click.option('--backend', help='Override configured backend') def close(issue_id: str, backend: Optional[str]): """Close an issue.""" try: manager = IssuePluginManager() backend_instance = manager.get_backend(backend) issue = backend_instance.close_issue(issue_id) click.echo(f"Issue #{issue_id} closed successfully") except FileNotFoundError: click.echo(f"Error: Issue {issue_id} not found", err=True) raise click.Abort() except (PluginNotFoundError, ConfigurationError) as e: click.echo(f"Error: {e}", err=True) raise click.Abort() except Exception as e: click.echo(f"Unexpected error: {e}", err=True) raise click.Abort() # Make issues_group available for import issues_group = issues