Source code for cadrumo.adapters.persistence.storage.bucket.errors
"""Canonical typed exception hierarchy for the per-bucket directory model.Each class carries a structured payload (active bucket id, holding PID,conflicting bucket id, recovery context) so callers can render typeddiagnostics without re-parsing the message string. Every class inheritsfrom :class:`core.errors.hierarchy.CadrumoError`; the project error registry's``__init_subclass__`` hook binds each subclass to its declared:class:`core.errors.error_codes.ErrorCode` row at import time."""from__future__importannotationsfromcollections.abcimportMappingfrom..errorsimportSecureStorageError
[docs]classBucketError(SecureStorageError):"""Base class for every per-bucket lifecycle error."""
[docs]classBucketValidationError(BucketError):"""Raised when a bucket parameter fails validation."""def__init__(self,message:str|None=None,*,context:Mapping[str,object]|None=None,)->None:"""Build a bucket validation failure with structured context."""super().__init__(message,context=context,translated_message="errors.integrity.integrity_storage_bucket_validation",)
[docs]classBucketBusyError(BucketError):"""Raised when a second process attempts to unlock a held bucket. Carries the holding PID so the caller can render the diagnostic without re-parsing the lockfile. """def__init__(self,*,bucket_id:str,holding_pid:int)->None:"""Build a busy-bucket failure naming the lock holder."""super().__init__(context={"bucket_id":bucket_id,"holding_pid":holding_pid},translated_message="errors.locked.locked_storage_bucket_busy",)self.bucket_id=bucket_idself.holding_pid=holding_pid
[docs]classBucketAlreadyPresentError(BucketError):"""Raised when provisioning would collide with an existing bucket id. Carries the conflicting bucket id. """def__init__(self,*,bucket_id:str)->None:"""Build an existing-bucket collision failure."""super().__init__(context={"bucket_id":bucket_id},translated_message="errors.refused.refused_storage_bucket_already_present",)self.bucket_id=bucket_id
[docs]classBucketPathTooLongError(BucketError):"""Raised when provisioning a bucket directory exceeds the Windows ``MAX_PATH`` ceiling. Classified via :func:`core.paths.is_windows_long_path_error` from a caught ``WinError 3`` / ``WinError 206`` on legacy (non long-path-aware) Windows workstations. Distinct from :class:`BucketValidationError` so the CLI names the actual cause (the resolved bucket directory tree is too deep for ``MAX_PATH``) instead of a generic validation failure. """def__init__(self,*,bucket_id:str,path:str)->None:"""Build a path-length failure with the resolved path."""super().__init__(context={"bucket_id":bucket_id,"path":path},translated_message="errors.error.error_storage_bucket_path_too_long",)self.bucket_id=bucket_idself.path=path
[docs]classBucketLockedError(BucketError):"""Raised when an operation requires an unlocked :class:`BucketSession`. Carries the storage identity and the failed unlocked-state observation. Recovery policy belongs to the boundary because a bucket id is not a verified public profile-action argument. """def__init__(self,*,bucket_id:str)->None:"""Build a locked-bucket failure."""super().__init__(context={"bucket_id":bucket_id,"bucket_session_unlocked":False},translated_message="errors.locked.locked_storage_bucket_session",)self.bucket_id=bucket_id