Source code for artifacts.errors

"""Exception hierarchy for the Artifacts wrapper."""

from __future__ import annotations

from typing import Any, Optional


[docs] class ArtifactsError(Exception): """Base exception for all artifacts wrapper errors."""
[docs] class ArtifactsAPIError(ArtifactsError): """The API returned an error response.""" def __init__( self, code: int, message: str, data: Optional[dict[str, Any]] = None, ): self.code = code self.message = message self.data = data super().__init__(f"[{code}] {message}")
[docs] class CharacterNotFoundError(ArtifactsAPIError): """Character not found (498)."""
[docs] class CooldownActiveError(ArtifactsAPIError): """Character is in cooldown (499)."""
[docs] class ActionInProgressError(ArtifactsAPIError): """An action is already in progress (486)."""
[docs] class NotFoundError(ArtifactsAPIError): """Resource not found (404)."""
[docs] class InventoryFullError(ArtifactsAPIError): """Character inventory is full (497)."""
[docs] class InsufficientGoldError(ArtifactsAPIError): """Not enough gold (492)."""
[docs] class AlreadyAtDestinationError(ArtifactsAPIError): """Already at destination (490)."""
[docs] class SkillLevelTooLowError(ArtifactsAPIError): """Skill level too low (493)."""
[docs] class EquipmentSlotError(ArtifactsAPIError): """Equipment slot error (491)."""
[docs] class MemberRequiredError(ArtifactsAPIError): """Member / founder required (451)."""
[docs] class MapBlockedError(ArtifactsAPIError): """Map is blocked (596)."""
[docs] class NoPathError(ArtifactsAPIError): """No path to destination (595)."""
[docs] class ContentNotOnMapError(ArtifactsAPIError): """Content not found on map (598)."""
[docs] class TaskError(ArtifactsAPIError): """Task-related error (474-489)."""
[docs] class GrandExchangeError(ArtifactsAPIError): """Grand Exchange error (433-438)."""
[docs] class ValidationError(ArtifactsAPIError): """Request validation error (422)."""
[docs] class ConditionsNotMetError(ArtifactsAPIError): """Conditions not met (496)."""
[docs] class RetryExhaustedError(ArtifactsError): """All retry attempts have been exhausted.""" def __init__( self, message: str, last_exception: Exception | None = None, ): self.last_exception = last_exception super().__init__(message)
# Map API error codes to exception classes ERROR_MAP: dict[int, type[ArtifactsAPIError]] = { 404: NotFoundError, 422: ValidationError, 433: GrandExchangeError, 434: GrandExchangeError, 435: GrandExchangeError, 436: GrandExchangeError, 437: GrandExchangeError, 438: GrandExchangeError, 451: MemberRequiredError, 474: TaskError, 475: TaskError, 486: ActionInProgressError, 487: TaskError, 488: TaskError, 489: TaskError, 490: AlreadyAtDestinationError, 491: EquipmentSlotError, 492: InsufficientGoldError, 493: SkillLevelTooLowError, 496: ConditionsNotMetError, 497: InventoryFullError, 498: CharacterNotFoundError, 499: CooldownActiveError, 595: NoPathError, 596: MapBlockedError, 598: ContentNotOnMapError, }
[docs] def raise_for_error(status: int, body: dict[str, Any]) -> None: """Parse an error response body and raise the appropriate exception.""" error_data = body.get("error", {}) code = error_data.get("code", status) message = error_data.get("message", "Unknown error") data = error_data.get("data") exc_class = ERROR_MAP.get(code, ArtifactsAPIError) raise exc_class(code=code, message=message, data=data)