Files

268 lines
7.7 KiB
Python

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Lance Namespace error types.
This module defines the exception hierarchy for Lance Namespace operations.
Each exception has an associated error code for programmatic handling.
Error codes are globally unique across all Lance Namespace implementations.
Examples
--------
Raise an error:
>>> raise TableNotFoundError("Table 'users' not found")
Chain with another exception:
>>> raise TableNotFoundError("Table 'users' not found") from original_error
Access the error code:
>>> try:
... namespace.describe_table(...)
... except LanceNamespaceError as e:
... print(e.code) # ErrorCode.TABLE_NOT_FOUND
... print(str(e)) # "Table 'users' not found"
"""
from enum import IntEnum
from typing import Type, Dict
class ErrorCode(IntEnum):
"""Lance Namespace error codes.
These codes are globally unique across all Lance Namespace implementations.
"""
UNSUPPORTED = 0
NAMESPACE_NOT_FOUND = 1
NAMESPACE_ALREADY_EXISTS = 2
NAMESPACE_NOT_EMPTY = 3
TABLE_NOT_FOUND = 4
TABLE_ALREADY_EXISTS = 5
TABLE_INDEX_NOT_FOUND = 6
TABLE_INDEX_ALREADY_EXISTS = 7
TABLE_TAG_NOT_FOUND = 8
TABLE_TAG_ALREADY_EXISTS = 9
TRANSACTION_NOT_FOUND = 10
TABLE_VERSION_NOT_FOUND = 11
TABLE_COLUMN_NOT_FOUND = 12
INVALID_INPUT = 13
CONCURRENT_MODIFICATION = 14
PERMISSION_DENIED = 15
UNAUTHENTICATED = 16
SERVICE_UNAVAILABLE = 17
INTERNAL = 18
INVALID_TABLE_STATE = 19
TABLE_SCHEMA_VALIDATION_ERROR = 20
class LanceNamespaceError(Exception):
"""Base exception for all Lance Namespace errors.
Attributes
----------
code : ErrorCode
The error code identifying the error type.
"""
code: ErrorCode = ErrorCode.INTERNAL
def __init__(self, message: str):
super().__init__(message)
class UnsupportedOperationError(LanceNamespaceError):
"""Raised when an operation is not supported by the backend."""
code = ErrorCode.UNSUPPORTED
class NamespaceNotFoundError(LanceNamespaceError):
"""Raised when the specified namespace does not exist."""
code = ErrorCode.NAMESPACE_NOT_FOUND
class NamespaceAlreadyExistsError(LanceNamespaceError):
"""Raised when a namespace with the specified name already exists."""
code = ErrorCode.NAMESPACE_ALREADY_EXISTS
class NamespaceNotEmptyError(LanceNamespaceError):
"""Raised when trying to drop a namespace that contains children."""
code = ErrorCode.NAMESPACE_NOT_EMPTY
class TableNotFoundError(LanceNamespaceError):
"""Raised when the specified table does not exist."""
code = ErrorCode.TABLE_NOT_FOUND
class TableAlreadyExistsError(LanceNamespaceError):
"""Raised when a table with the specified name already exists."""
code = ErrorCode.TABLE_ALREADY_EXISTS
class TableIndexNotFoundError(LanceNamespaceError):
"""Raised when the specified table index does not exist."""
code = ErrorCode.TABLE_INDEX_NOT_FOUND
class TableIndexAlreadyExistsError(LanceNamespaceError):
"""Raised when a table index with the specified name already exists."""
code = ErrorCode.TABLE_INDEX_ALREADY_EXISTS
class TableTagNotFoundError(LanceNamespaceError):
"""Raised when the specified table tag does not exist."""
code = ErrorCode.TABLE_TAG_NOT_FOUND
class TableTagAlreadyExistsError(LanceNamespaceError):
"""Raised when a table tag with the specified name already exists."""
code = ErrorCode.TABLE_TAG_ALREADY_EXISTS
class TransactionNotFoundError(LanceNamespaceError):
"""Raised when the specified transaction does not exist."""
code = ErrorCode.TRANSACTION_NOT_FOUND
class TableVersionNotFoundError(LanceNamespaceError):
"""Raised when the specified table version does not exist."""
code = ErrorCode.TABLE_VERSION_NOT_FOUND
class TableColumnNotFoundError(LanceNamespaceError):
"""Raised when the specified table column does not exist."""
code = ErrorCode.TABLE_COLUMN_NOT_FOUND
class InvalidInputError(LanceNamespaceError):
"""Raised when the request contains invalid parameters."""
code = ErrorCode.INVALID_INPUT
class ConcurrentModificationError(LanceNamespaceError):
"""Raised when an optimistic concurrency conflict occurs."""
code = ErrorCode.CONCURRENT_MODIFICATION
class PermissionDeniedError(LanceNamespaceError):
"""Raised when the user lacks permission for the operation."""
code = ErrorCode.PERMISSION_DENIED
class UnauthenticatedError(LanceNamespaceError):
"""Raised when authentication credentials are missing or invalid."""
code = ErrorCode.UNAUTHENTICATED
class ServiceUnavailableError(LanceNamespaceError):
"""Raised when the service is temporarily unavailable."""
code = ErrorCode.SERVICE_UNAVAILABLE
class InternalError(LanceNamespaceError):
"""Raised for unexpected internal errors."""
code = ErrorCode.INTERNAL
class InvalidTableStateError(LanceNamespaceError):
"""Raised when the table is in an invalid state for the operation."""
code = ErrorCode.INVALID_TABLE_STATE
class TableSchemaValidationError(LanceNamespaceError):
"""Raised when table schema validation fails."""
code = ErrorCode.TABLE_SCHEMA_VALIDATION_ERROR
# Mapping from error code to exception class
_ERROR_CODE_TO_EXCEPTION: Dict[ErrorCode, Type[LanceNamespaceError]] = {
ErrorCode.UNSUPPORTED: UnsupportedOperationError,
ErrorCode.NAMESPACE_NOT_FOUND: NamespaceNotFoundError,
ErrorCode.NAMESPACE_ALREADY_EXISTS: NamespaceAlreadyExistsError,
ErrorCode.NAMESPACE_NOT_EMPTY: NamespaceNotEmptyError,
ErrorCode.TABLE_NOT_FOUND: TableNotFoundError,
ErrorCode.TABLE_ALREADY_EXISTS: TableAlreadyExistsError,
ErrorCode.TABLE_INDEX_NOT_FOUND: TableIndexNotFoundError,
ErrorCode.TABLE_INDEX_ALREADY_EXISTS: TableIndexAlreadyExistsError,
ErrorCode.TABLE_TAG_NOT_FOUND: TableTagNotFoundError,
ErrorCode.TABLE_TAG_ALREADY_EXISTS: TableTagAlreadyExistsError,
ErrorCode.TRANSACTION_NOT_FOUND: TransactionNotFoundError,
ErrorCode.TABLE_VERSION_NOT_FOUND: TableVersionNotFoundError,
ErrorCode.TABLE_COLUMN_NOT_FOUND: TableColumnNotFoundError,
ErrorCode.INVALID_INPUT: InvalidInputError,
ErrorCode.CONCURRENT_MODIFICATION: ConcurrentModificationError,
ErrorCode.PERMISSION_DENIED: PermissionDeniedError,
ErrorCode.UNAUTHENTICATED: UnauthenticatedError,
ErrorCode.SERVICE_UNAVAILABLE: ServiceUnavailableError,
ErrorCode.INTERNAL: InternalError,
ErrorCode.INVALID_TABLE_STATE: InvalidTableStateError,
ErrorCode.TABLE_SCHEMA_VALIDATION_ERROR: TableSchemaValidationError,
}
def from_error_code(code: int, message: str) -> LanceNamespaceError:
"""Create an exception from an error code.
Parameters
----------
code : int
The numeric error code.
message : str
The error message.
Returns
-------
LanceNamespaceError
The appropriate exception type for the error code.
Examples
--------
>>> err = from_error_code(4, "Table not found")
>>> isinstance(err, TableNotFoundError)
True
>>> err.code
<ErrorCode.TABLE_NOT_FOUND: 4>
"""
try:
error_code = ErrorCode(code)
exc_class = _ERROR_CODE_TO_EXCEPTION.get(error_code, InternalError)
except ValueError:
exc_class = InternalError
return exc_class(message)