diff options
author | Ben Firshman <ben@firshman.co.uk> | 2016-11-07 17:56:02 -0800 |
---|---|---|
committer | Ben Firshman <ben@firshman.co.uk> | 2016-11-22 17:05:43 +0000 |
commit | 1984f68730512a1c07017118f4e229c7949ff8a8 (patch) | |
tree | 00768c0a70d67b4a221333a8566534e8e58a008f /docker/errors.py | |
parent | f32c0c170917518b7e224adf8627e95b5e620a91 (diff) | |
download | docker-py-1984f68730512a1c07017118f4e229c7949ff8a8.tar.gz |
Add new user-focused API
See #1086
Signed-off-by: Ben Firshman <ben@firshman.co.uk>
Diffstat (limited to 'docker/errors.py')
-rw-r--r-- | docker/errors.py | 93 |
1 files changed, 80 insertions, 13 deletions
diff --git a/docker/errors.py b/docker/errors.py index df18d57..8572007 100644 --- a/docker/errors.py +++ b/docker/errors.py @@ -1,21 +1,44 @@ import requests -class APIError(requests.exceptions.HTTPError): - def __init__(self, message, response, explanation=None): +class DockerException(Exception): + """ + A base class from which all other exceptions inherit. + + If you want to catch all errors that the Docker SDK might raise, + catch this base exception. + """ + + +def create_api_error_from_http_exception(e): + """ + Create a suitable APIError from requests.exceptions.HTTPError. + """ + response = e.response + try: + explanation = response.json()['message'] + except ValueError: + explanation = response.content.strip() + cls = APIError + if response.status_code == 404: + if explanation and 'No such image' in str(explanation): + cls = ImageNotFound + else: + cls = NotFound + raise cls(e, response=response, explanation=explanation) + + +class APIError(requests.exceptions.HTTPError, DockerException): + """ + An HTTP error from the API. + """ + def __init__(self, message, response=None, explanation=None): # requests 1.2 supports response as a keyword argument, but # requests 1.1 doesn't super(APIError, self).__init__(message) self.response = response - self.explanation = explanation - if self.explanation is None and response.content: - try: - self.explanation = response.json()['message'] - except ValueError: - self.explanation = response.content.strip() - def __str__(self): message = super(APIError, self).__str__() @@ -32,18 +55,27 @@ class APIError(requests.exceptions.HTTPError): return message + @property + def status_code(self): + if self.response: + return self.response.status_code + def is_client_error(self): - return 400 <= self.response.status_code < 500 + if self.status_code is None: + return False + return 400 <= self.status_code < 500 def is_server_error(self): - return 500 <= self.response.status_code < 600 + if self.status_code is None: + return False + return 500 <= self.status_code < 600 -class DockerException(Exception): +class NotFound(APIError): pass -class NotFound(APIError): +class ImageNotFound(NotFound): pass @@ -76,3 +108,38 @@ class TLSParameterError(DockerException): class NullResource(DockerException, ValueError): pass + + +class ContainerError(DockerException): + """ + Represents a container that has exited with a non-zero exit code. + """ + def __init__(self, container, exit_status, command, image, stderr): + self.container = container + self.exit_status = exit_status + self.command = command + self.image = image + self.stderr = stderr + msg = ("Command '{}' in image '{}' returned non-zero exit status {}: " + "{}").format(command, image, exit_status, stderr) + super(ContainerError, self).__init__(msg) + + +class StreamParseError(RuntimeError): + def __init__(self, reason): + self.msg = reason + + +class BuildError(Exception): + pass + + +def create_unexpected_kwargs_error(name, kwargs): + quoted_kwargs = ["'{}'".format(k) for k in sorted(kwargs)] + text = ["{}() ".format(name)] + if len(quoted_kwargs) == 1: + text.append("got an unexpected keyword argument ") + else: + text.append("got unexpected keyword arguments ") + text.append(', '.join(quoted_kwargs)) + return TypeError(''.join(text)) |