""" Registry factory for creating registry clients. This module provides a factory for creating appropriate registry clients based on configuration or registry type. """ from typing import Dict, Type, Optional, Any from pathlib import Path from .base import RegistryInterface, RegistryConfig from .gitea.registry import GiteaRegistry from .gitea.config import GiteaConfig class RegistryFactory: """Factory for creating registry clients.""" _registry_types: Dict[str, Type[RegistryInterface]] = { 'gitea': GiteaRegistry, } @classmethod def create(cls, registry_type: str, config: Optional[Dict[str, Any]] = None) -> RegistryInterface: """Create a registry client of the specified type. Args: registry_type: Type of registry ('gitea', 'pypi', etc.) config: Optional configuration dictionary Returns: Registry client instance Raises: ValueError: If registry type is not supported """ if registry_type not in cls._registry_types: raise ValueError(f"Unsupported registry type: {registry_type}. " f"Supported types: {list(cls._registry_types.keys())}") registry_class = cls._registry_types[registry_type] # Handle Gitea-specific configuration if registry_type == 'gitea': if config: gitea_config = GiteaConfig( gitea_url=config.get('url', ''), repo_owner=config.get('owner', ''), repo_name=config.get('repo', ''), auth_token=config.get('auth_token') ) return registry_class(gitea_config) else: # Auto-detect from git repository return registry_class() # For other registry types, create with generic config if config: registry_config = RegistryConfig( name=config.get('name', registry_type), type=registry_type, url=config['url'], auth_token_env=config.get('auth_token_env') ) return registry_class(registry_config) else: raise ValueError(f"Configuration required for {registry_type} registry") @classmethod def create_from_pyproject_config(cls, pyproject_path: Optional[Path] = None, registry_name: str = 'gitea') -> RegistryInterface: """Create a registry client from pyproject.toml configuration. Args: pyproject_path: Path to pyproject.toml file. If None, looks in current directory. registry_name: Name of registry configuration to use Returns: Registry client instance Raises: ValueError: If configuration is invalid or registry not found """ if pyproject_path is None: pyproject_path = Path.cwd() / "pyproject.toml" if not pyproject_path.exists(): raise ValueError(f"pyproject.toml not found at {pyproject_path}") try: import tomllib except ImportError: try: import tomli as tomllib # Fallback for Python < 3.11 except ImportError: raise ImportError("tomllib or tomli required to read pyproject.toml") with open(pyproject_path, 'rb') as f: config = tomllib.load(f) # Look for release-management configuration release_config = config.get('tool', {}).get('release-management', {}) registries_config = release_config.get('registries', {}) if registry_name not in registries_config: raise ValueError(f"Registry '{registry_name}' not found in pyproject.toml configuration") registry_config = registries_config[registry_name] registry_type = registry_config.get('type', registry_name) # Add auth token from environment if specified auth_token_env = registry_config.get('auth_token_env') if auth_token_env: import os registry_config = registry_config.copy() registry_config['auth_token'] = os.getenv(auth_token_env) return cls.create(registry_type, registry_config) @classmethod def auto_detect(cls) -> RegistryInterface: """Auto-detect registry type from current environment. Currently only supports Gitea auto-detection from git repository. Returns: Registry client instance Raises: ValueError: If no registry can be auto-detected """ # Try Gitea auto-detection first try: return cls.create('gitea') except Exception: pass raise ValueError("Could not auto-detect registry type. " "Ensure you're in a git repository with Gitea remote, " "or provide explicit configuration.") @classmethod def register_registry_type(cls, registry_type: str, registry_class: Type[RegistryInterface]) -> None: """Register a new registry type. Args: registry_type: String identifier for the registry type registry_class: Registry class that implements RegistryInterface """ cls._registry_types[registry_type] = registry_class @classmethod def list_supported_types(cls) -> list[str]: """List all supported registry types. Returns: List of supported registry type strings """ return list(cls._registry_types.keys())