diff --git a/src/jcloud_s3fuse/s3/backend.py b/src/jcloud_s3fuse/s3/backend.py index 33f4c86..b0a4ca1 100644 --- a/src/jcloud_s3fuse/s3/backend.py +++ b/src/jcloud_s3fuse/s3/backend.py @@ -13,6 +13,7 @@ # limitations under the License. import httpx +from .exceptions import S3InternalServerError, S3ObjectNotFoundError, S3ObjectPermissionError from typing import AsyncGenerator, Optional from urllib.parse import urljoin @@ -58,5 +59,12 @@ class S3Backend: urljoin(self.url, object_path), headers = headers ) as response: + if response.status_code == 404: + raise S3ObjectNotFoundError('Object not found', object_path = object_path) + if response.status_code == 403: + raise S3ObjectPermissionError('Object access forbidden', object_path = object_path) + if response.status_code // 100 == 5: + raise S3InternalServerError('Internal server error') + async for chunk in response.aiter_bytes(): yield chunk diff --git a/src/jcloud_s3fuse/s3/exceptions.py b/src/jcloud_s3fuse/s3/exceptions.py new file mode 100644 index 0000000..ef2dbca --- /dev/null +++ b/src/jcloud_s3fuse/s3/exceptions.py @@ -0,0 +1,56 @@ +# Copyright 2026 jCloud + +# 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. + +__all__ = [ + 'S3Error', + 'S3InternalServerError', + 'S3ObjectError', + 'S3ObjectNotFoundError', + 'S3ObjectPermissionError' +] + +class S3Error(Exception): + ''' + Base class for all S3 related errors. + ''' + +class S3InternalServerError(S3Error): + ''' + Internal S3 server error. + ''' + +class S3ObjectError(S3Error): + ''' + Base class for S3 object related errors. + ''' + + def __init__(self, *args: object, object_path: str = '') -> None: + super().__init__(*args) + self.object_path = object_path + + def __str__(self): + if self.args: + return f'{self.args[0]}{": " if self.object_path and self.args[0] else ""}{self.object_path if self.args[0] else ""}' + else: + return '' + +class S3ObjectNotFoundError(S3ObjectError): + ''' + S3 object was not found. + ''' + +class S3ObjectPermissionError(S3ObjectError): + ''' + Bad permissions to retrieve S3 object. + ''' \ No newline at end of file