Skip to content
2 changes: 1 addition & 1 deletion cs3client/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from cs3.rpc.v1beta1.code_pb2 import CODE_OK

from .cs3client import CS3Client
from .exceptions.exceptions import AuthenticationException, SecretNotSetException
from .exceptions import AuthenticationException, SecretNotSetException
from .config import Config


Expand Down
74 changes: 74 additions & 0 deletions cs3client/exceptions/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""
exceptions

Custom exception classes for the CS3 client.
Where applicable, the default values correspond to the Linux standard error strings.

Authors: Rasmus Welander, Diogo Castro, Giuseppe Lo Presti.
Emails: [email protected], [email protected], [email protected]
Last updated: 01/08/2024
"""


class AuthenticationException(Exception):
"""
Standard error thrown when attempting an operation without the required access rights
"""

def __init__(self, message: str = "Operation not permitted"):
super().__init__(message)


class NotFoundException(IOError):
"""
Standard file missing message
"""

def __init__(self, message: str = "No such file or directory"):
super().__init__(message)


class SecretNotSetException(Exception):
"""
Standard file missing message
"""

def __init__(self, message: str = "Secret was not set, unable to authenticate"):
super().__init__(message)


class FileLockedException(IOError):
"""
Standard error thrown when attempting to overwrite a file/xattr with a mistmatched lock,
or when a lock operation cannot be performed because of failed preconditions
"""

def __init__(self, message: str = "Lock mismatch"):
super().__init__(message)


class UnknownException(Exception):
"""
Standard exception to be thrown when we get an error that is unknown, e.g. not defined in the cs3api
"""

def __init__(self, message: str = ""):
super().__init__(message)


class AlreadyExistsException(IOError):
"""
Standard error thrown when attempting to create a resource that already exists
"""

def __init__(self, message: str = "File exists"):
super().__init__(message)


class UnimplementedException(Exception):
"""
Standard error thrown when attempting to use a feature that is not implemented
"""

def __init__(self, message: str = "Not implemented"):
super().__init__(message)
73 changes: 0 additions & 73 deletions cs3client/exceptions/exceptions.py

This file was deleted.

15 changes: 8 additions & 7 deletions cs3client/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@


from .config import Config
from .exceptions.exceptions import AuthenticationException, FileLockedException
from .exceptions import AuthenticationException, FileLockedException
from .cs3resource import Resource
from .statuscodehandler import StatusCodeHandler

Expand Down Expand Up @@ -86,7 +86,7 @@ def set_xattr(self, auth_token: tuple, resource: Resource, key: str, value: str,
:raises: UnknownException (Unknown error)
"""
md = cs3spr.ArbitraryMetadata()
md.metadata.update({key: value}) # pylint: disable=no-member
md.metadata.update({key: str(value)}) # pylint: disable=no-member
req = cs3sp.SetArbitraryMetadataRequest(ref=resource.ref, arbitrary_metadata=md, lock_id=lock_id)
res = self._gateway.SetArbitraryMetadata(request=req, metadata=[auth_token])
# CS3 storages may refuse to set an xattr in case of lock mismatch: this is an overprotection,
Expand Down Expand Up @@ -170,8 +170,7 @@ def touch_file(self, auth_token: tuple, resource: Resource) -> None:
self._log.debug(f'msg="Invoked TouchFile" trace="{res.status.trace}"')

def write_file(
self, auth_token: tuple, resource: Resource, content: Union[str, bytes], size: int,
lock_md: tuple = ('', '')
self, auth_token: tuple, resource: Resource, content: Union[str, bytes], size: int, lock_md: tuple = None
) -> None:
"""
Write a file using the given userid as access token. The entire content is written
Expand All @@ -183,14 +182,16 @@ def write_file(
:param resource: Resource to write content to
:param content: content to write
:param size: size of content (optional)
:param lock_md: tuple (<app_name>, <lock_id>)
:param lock_md: tuple (<app_name>, <lock_id>) (optional)
:return: None (Success)
:raises: FileLockedException (File is locked),
:raises: AuthenticationException (Authentication failed)
:raises: UnknownException (Unknown error)

"""
app_name, lock_id = lock_md
app_name = lock_id = ''
if lock_md:
app_name, lock_id = lock_md
tstart = time.time()
# prepare endpoint
if size == -1:
Expand Down Expand Up @@ -228,7 +229,7 @@ def write_file(
"X-Reva-Transfer": protocol.token,
**dict([auth_token]),
"X-Lock-Id": lock_id,
"X-Lock_Holder": app_name,
"X-Lock-Holder": app_name,
}
putres = requests.put(
url=protocol.upload_endpoint,
Expand Down
22 changes: 7 additions & 15 deletions cs3client/statuscodehandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import cs3.rpc.v1beta1.code_pb2 as cs3code
import cs3.rpc.v1beta1.status_pb2 as cs3status

from .exceptions.exceptions import AuthenticationException, NotFoundException, \
from .exceptions import AuthenticationException, NotFoundException, \
UnknownException, AlreadyExistsException, FileLockedException, UnimplementedException
from .config import Config

Expand Down Expand Up @@ -75,31 +75,23 @@ def handle_errors(self, status: cs3status.Status, operation: str, msg: str = Non

if status.code == cs3code.CODE_FAILED_PRECONDITION or status.code == cs3code.CODE_ABORTED:
self._log_precondition_info(status, operation, status_message, msg)
raise FileLockedException(f'Failed precondition: operation="{operation}" '
f'status_code="{status.code}" message="{status.message}"')
raise FileLockedException
if status.code == cs3code.CODE_ALREADY_EXISTS:
self._log_already_exists(status, operation, status_message, msg)
raise AlreadyExistsException(f'Resource already exists: operation="{operation}" '
f'status_code="{status.code}" message="{status.message}"')
raise AlreadyExistsException
if status.code == cs3code.CODE_UNIMPLEMENTED:
self._log.info(f'msg="Invoked {operation} on unimplemented feature" ')
raise UnimplementedException(f'Unimplemented feature: operation="{operation}" '
f'status_code="{status.code}" message="{status.message}"')
raise UnimplementedException
if status.code == cs3code.CODE_NOT_FOUND:
self._log_not_found_info(status, operation, status_message, msg)
raise NotFoundException(f'Not found: operation="{operation}" '
f'status_code="{status.code}" message="{status.message}"')
raise NotFoundException
if status.code == cs3code.CODE_UNAUTHENTICATED:
self._log_authentication_error(status, operation, status_message, msg)
raise AuthenticationException(f'Operation not permitted: operation="{operation}" '
f'status_code="{status.code}" message="{status.message}"')
raise AuthenticationException
if status.code != cs3code.CODE_OK:
if "path not found" in str(status.message).lower():
self._log.info(f'msg="Invoked {operation} on missing file" ')
raise NotFoundException(
message=f'No such file or directory: operation="{operation}" '
f'status_code="{status.code}" message="{status.message}"'
)
raise NotFoundException
self._log_unknown_error(status, operation, status_message, msg)
raise UnknownException(f'Unknown Error: operation="{operation}" status_code="{status.code}" '
f'message="{status.message}"')
2 changes: 1 addition & 1 deletion docs/source/exceptions.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
exceptions Module
=================

.. automodule:: exceptions.exceptions
.. automodule:: exceptions
:members:
:undoc-members:
:show-inheritance:
2 changes: 1 addition & 1 deletion tests/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from unittest.mock import Mock, patch
import pytest

from cs3client.exceptions.exceptions import (
from cs3client.exceptions import (
AuthenticationException,
NotFoundException,
UnknownException,
Expand Down
2 changes: 1 addition & 1 deletion tests/test_checkpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import pytest
import cs3.rpc.v1beta1.code_pb2 as cs3code

from cs3client.exceptions.exceptions import (
from cs3client.exceptions import (
AuthenticationException,
NotFoundException,
UnknownException,
Expand Down
2 changes: 1 addition & 1 deletion tests/test_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import cs3.rpc.v1beta1.code_pb2 as cs3code

from cs3client.cs3resource import Resource
from cs3client.exceptions.exceptions import (
from cs3client.exceptions import (
AuthenticationException,
NotFoundException,
FileLockedException,
Expand Down
2 changes: 1 addition & 1 deletion tests/test_share.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import cs3.storage.provider.v1beta1.resources_pb2 as cs3spr
import cs3.rpc.v1beta1.code_pb2 as cs3code

from cs3client.exceptions.exceptions import (
from cs3client.exceptions import (
AuthenticationException,
NotFoundException,
UnknownException,
Expand Down
2 changes: 1 addition & 1 deletion tests/test_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from unittest.mock import Mock, patch
import cs3.rpc.v1beta1.code_pb2 as cs3code

from cs3client.exceptions.exceptions import (
from cs3client.exceptions import (
AuthenticationException,
NotFoundException,
UnknownException,
Expand Down
Loading