summaryrefslogtreecommitdiff
path: root/docker/errors.py
diff options
context:
space:
mode:
authorBen Firshman <ben@firshman.co.uk>2016-11-07 17:56:02 -0800
committerBen Firshman <ben@firshman.co.uk>2016-11-22 17:05:43 +0000
commit1984f68730512a1c07017118f4e229c7949ff8a8 (patch)
tree00768c0a70d67b4a221333a8566534e8e58a008f /docker/errors.py
parentf32c0c170917518b7e224adf8627e95b5e620a91 (diff)
downloaddocker-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.py93
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))