from __future__ import annotations import sqlite3 import uuid from typing import Any from cracklab.server.repositories.methods import MethodsRepository from cracklab.server.services.method_definition import ( MethodDefinitionError, validate_method_definition, ) class MethodServiceError(ValueError): pass class MethodService: def __init__(self, conn: sqlite3.Connection) -> None: self._methods = MethodsRepository(conn) def create_method( self, name: str, description: str | None = None, method_id: str | None = None, ) -> str: if not name or not name.strip(): raise MethodServiceError("Method name must not be empty") if method_id is None: method_id = f"MTH-{uuid.uuid4().hex}" if not method_id: raise MethodServiceError("Method ID must not be empty") self._methods.create_method( method_id=method_id, name=name.strip(), description=description.strip() if description else None, ) return method_id def create_method_version( self, method_id: str, version: int, definition: dict[str, Any], ) -> None: if version <= 0: raise MethodServiceError( "Method version must be greater than zero" ) try: validate_method_definition(definition) except MethodDefinitionError as exc: raise MethodServiceError(str(exc)) from exc self._methods.create_method_version( method_id=method_id, version=version, definition=definition, ) def create_next_method_version( self, method_id: str, definition: dict[str, Any], ) -> int: try: validate_method_definition(definition) except MethodDefinitionError as exc: raise MethodServiceError(str(exc)) from exc version = self._methods.get_next_method_version(method_id) self._methods.create_method_version( method_id=method_id, version=version, definition=definition, ) return version def get_method(self, method_id: str) -> sqlite3.Row | None: return self._methods.get_method(method_id) def list_methods(self) -> list[sqlite3.Row]: return self._methods.list_methods() def get_method_version( self, method_id: str, version: int, ) -> sqlite3.Row | None: return self._methods.get_method_version( method_id, version, ) def list_method_versions( self, method_id: str, ) -> list[sqlite3.Row]: return self._methods.list_method_versions(method_id) def get_latest_method_version( self, method_id: str, ) -> sqlite3.Row | None: versions = self._methods.list_method_versions(method_id) if not versions: return None return versions[-1]