"""Error handling contracts for services. Defines the three allowed error handling patterns so callers know what to expect from any service method. Pattern Selection ================ - ABORT_ON_ERROR: Operations where failure must propagate (auth, writes, config changes) - RETURN_DEFAULT: Informational reads where partial data is acceptable - PARTIAL_RESULT: Operations on collections where some items may fail independently Switching patterns is a breaking change — document in changelog. """ from __future__ import annotations ABORT_ON_ERROR = "abort_on_error" """Raise an exception. Router converts to HTTP. Use for auth, writes, state changes.""" RETURN_DEFAULT = "return_default" """Return empty result and log warning. Never raises. Use for informational reads.""" PARTIAL_RESULT = "partial_result" """Return (result, errors) tuple. Use for batch operations on collections.""" class ServiceErrorContract: """Documents the error handling pattern for a service or method. Callers use this to understand how errors affect the return value: ABORT_ON_ERROR Raise an exception. Router handles it, converts to HTTP response. Used for: authentication, authorization, write operations, state changes, and any operation where partial success is meaningless. RETURN_DEFAULT Return empty/None result and log a warning. Caller gets a valid result with no items, not an error. Used for: informational reads (list, get) where infrastructure unavailability should not block the UI. PARTIAL_RESULT Return a result that contains both successful items and a list of errors. Caller decides what to do with each. Used for: batch operations, multi-item fetches where one item failing does not invalidate the rest. """ ABORT_ON_ERROR = ABORT_ON_ERROR RETURN_DEFAULT = RETURN_DEFAULT PARTIAL_RESULT = PARTIAL_RESULT @classmethod def doc(cls, pattern: str, *, since: str | None = None) -> str: """Return a docstring fragment describing the error pattern.""" desc = { ABORT_ON_ERROR: "Raises exceptions on error. Router handles conversion to HTTP.", RETURN_DEFAULT: "Returns empty result and logs warning on error. Never raises.", PARTIAL_RESULT: "Returns (result, errors) tuple. Errors collected, not raised.", }[pattern] if since: return f"{desc} (Since: {since})" return desc