"""Module defining custom package exceptions."""
from __future__ import annotations
import functools
import warnings
from typing import Any, Callable
import requests
[docs]class BaseSentinelHubException(Exception):
"""A base package exception"""
[docs]class DownloadFailedException(BaseSentinelHubException):
"""General exception which is raised whenever download fails"""
def __init__(self, msg: str, *, request_exception: requests.RequestException | None = None) -> None:
super().__init__(msg)
self.request_exception = request_exception
[docs]class OutOfRequestsException(DownloadFailedException):
"""An exception raised whenever download cannot be done because user has run out of requests or processing units"""
[docs]class AwsDownloadFailedException(DownloadFailedException):
"""This exception is raised when download fails because of a missing file in AWS"""
[docs]class ImageDecodingError(BaseSentinelHubException):
"""This exception is raised when downloaded image is not properly decoded"""
[docs]class MissingDataInRequestException(BaseSentinelHubException):
"""This exception is raised when an iteration is performed on a request without data."""
[docs]class HashedNameCollisionException(BaseSentinelHubException):
"""This exception is raised when two different requests are assigned the same hashed name."""
[docs]class SHDeprecationWarning(DeprecationWarning):
"""A custom deprecation warning for sentinelhub-py package"""
[docs]class SHUserWarning(UserWarning):
"""A custom user warning for sentinelhub-py package"""
[docs]class SHRuntimeWarning(RuntimeWarning):
"""A custom runtime warning for sentinelhub-py package"""
[docs]class SHRateLimitWarning(SHRuntimeWarning):
"""A custom runtime warning in case user hit the rate limit for downloads"""
warnings.simplefilter("default", SHDeprecationWarning)
warnings.simplefilter("default", SHUserWarning)
warnings.simplefilter("always", SHRuntimeWarning)
warnings.simplefilter("always", SHRateLimitWarning)
# THIS SHOULD BE REMOVED IN THE FUTURE, after rest of libraries transition away.
[docs]def deprecated_function(
category: type[DeprecationWarning] = SHDeprecationWarning, message_suffix: str | None = None
) -> Callable[[Callable], Callable]:
"""A parametrized function decorator, which signals that the function has been deprecated when called.
Has to use paranthesis even when no custom parameters are used, e.g. `@deprecated_function()`.
"""
def deco(func: Callable) -> Callable:
message = f"Function `{func.__name__}` has been deprecated."
if message_suffix:
message += " " + message_suffix
@functools.wraps(func)
def wrapper(*args: Any, **kwargs: Any) -> Any:
warnings.warn(message, category=category, stacklevel=2)
return func(*args, **kwargs)
return wrapper
return deco
# THIS SHOULD BE REMOVED IN THE FUTURE, after rest of libraries transition away.
[docs]def deprecated_class(
category: type[DeprecationWarning] = SHDeprecationWarning, message_suffix: str | None = None
) -> Callable[[type], type]:
"""A parametrized class decorator, which signals that the class has been deprecated when initialized.
Has to use paranthesis even when no custom parameters are used, e.g. `@deprecated_class()`.
"""
def deco(class_object: type) -> type:
message = f"Class `{class_object.__name__}` has been deprecated."
if message_suffix:
message += " " + message_suffix
old_init = class_object.__init__ # type: ignore[misc]
def warn_and_init(self: Any, *args: Any, **kwargs: Any) -> None:
warnings.warn(message, category=category, stacklevel=2)
old_init(self, *args, **kwargs)
class_object.__init__ = warn_and_init # type: ignore[misc]
return class_object
return deco