Source code for src.integrations.kanban_factory

"""Factory for creating kanban provider instances.

Simplifies the process of creating the right kanban provider
based on configuration.
"""

import os
from typing import Any, Dict, Optional

from src.config.marcus_config import get_config
from src.integrations.kanban_interface import KanbanInterface, KanbanProvider
from src.integrations.providers import (
    GitHubKanban,
    LinearKanban,
    Planka,
    SQLiteKanban,
)


[docs] class KanbanFactory: """Factory for creating kanban provider instances."""
[docs] @staticmethod def create( provider: str, config: Optional[Dict[str, Any]] = None ) -> KanbanInterface: """ Create a kanban provider instance. Parameters ---------- provider : str Provider name ('planka', 'linear', 'github') config : Optional[Dict[str, Any]] Optional configuration override Returns ------- KanbanInterface KanbanInterface implementation Raises ------ ValueError If provider is not supported """ # Get centralized configuration marcus_config = get_config() provider_lower = provider.lower() if provider_lower == KanbanProvider.PLANKA.value: if not config: config = { "project_name": os.getenv( "PLANKA_PROJECT_NAME", "Task Master Test" ), } # Use KanbanClient-based implementation return Planka(config) elif provider_lower == KanbanProvider.LINEAR.value: if not config: config = { "api_key": marcus_config.kanban.linear_api_key or os.getenv("LINEAR_API_KEY"), "team_id": marcus_config.kanban.linear_team_id or os.getenv("LINEAR_TEAM_ID"), "project_id": os.getenv("LINEAR_PROJECT_ID"), } return LinearKanban(config) elif provider_lower == KanbanProvider.GITHUB.value: if not config: config = { "token": marcus_config.kanban.github_token or os.getenv("GITHUB_TOKEN"), "owner": marcus_config.kanban.github_owner or os.getenv("GITHUB_OWNER"), "repo": marcus_config.kanban.github_repo or os.getenv("GITHUB_REPO"), "project_number": int(os.getenv("GITHUB_PROJECT_NUMBER", "1")), } return GitHubKanban(config) # type: ignore[abstract] elif provider_lower == KanbanProvider.SQLITE.value: if not config: config = { "db_path": ( marcus_config.kanban.sqlite_db_path or os.getenv( "SQLITE_KANBAN_DB_PATH", "./data/kanban.db", ) ), "project_name": ( marcus_config.kanban.board_name or os.getenv( "MARCUS_PROJECT_NAME", "Marcus Project", ) ), "attachments_dir": ( marcus_config.kanban.sqlite_attachments_dir or os.getenv( "SQLITE_KANBAN_ATTACHMENTS_DIR", "./data/attachments", ) ), } return SQLiteKanban(config) else: raise ValueError(f"Unsupported kanban provider: {provider}")
[docs] @staticmethod def get_default_provider() -> str: """Get the default provider from configuration.""" config = get_config() return config.kanban.provider or os.getenv("KANBAN_PROVIDER", "sqlite")
[docs] @staticmethod def create_default(config: Optional[Dict[str, Any]] = None) -> KanbanInterface: """Create the default kanban provider.""" provider = KanbanFactory.get_default_provider() return KanbanFactory.create(provider, config)