a548266461
- Add backend/ai/utils.py — parse_classification, parse_suggestions, strip_code_fences shared by all AI providers; removes duplicated private functions from anthropic_provider.py and openai_provider.py - Add backend/deps/utils.py — get_client_ip, parse_uuid request-parsing helpers; removes local _ip() variants from admin.py, auth.py, shares.py, folders.py - Add backend/storage/exceptions.py — canonical CloudConnectionError definition; all routers and backends import from here instead of redefining - Move validate_password_strength to backend/services/auth.py; removes duplicated _validate_password_strength from admin.py and auth.py Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
20 lines
828 B
Python
20 lines
828 B
Python
"""Storage exception types — import from here, never redefine elsewhere."""
|
|
from __future__ import annotations
|
|
|
|
|
|
class CloudConnectionError(Exception):
|
|
"""Raised when a cloud provider signals a non-retryable connection problem.
|
|
|
|
Attributes:
|
|
reason: "token_expired" — access token expired; API layer can refresh and retry.
|
|
"invalid_grant" — refresh token revoked; user must reconnect.
|
|
|
|
The backend never updates the DB. The API layer (_call_cloud_op in cloud.py)
|
|
catches this exception, performs the DB state transition, and decides whether
|
|
to retry or surface a 503 to the client (B2 design, D-05/D-06).
|
|
"""
|
|
|
|
def __init__(self, msg: str = "", *, reason: str = "") -> None:
|
|
super().__init__(msg)
|
|
self.reason = reason # "token_expired" | "invalid_grant"
|