projectal.errors

  1from requests import HTTPError
  2
  3try:
  4    from simplejson.errors import JSONDecodeError
  5except ImportError:
  6    from json.decoder import JSONDecodeError
  7
  8
  9class LoginException(Exception):
 10    """Failed to log in with the credentials provided."""
 11
 12    pass
 13
 14
 15class UnsupportedException(Exception):
 16    """The API endpoint is not available for this entity."""
 17
 18    pass
 19
 20
 21class ProjectalException(Exception):
 22    """
 23    The API request failed. This exception will extract the specific
 24    error from the Projectal response if it can find one. To assist
 25    in debugging, the response object is attached to the exception
 26    which you may inspect for more precise details.
 27
 28    In case of failure of a bulk operation, only the error clue for
 29    the first failure is shown. A counter is included to show how
 30    many failed (i.e.: 1 of 25).
 31    """
 32
 33    def __init__(self, response, reason_message=None):
 34        """
 35        `response`: the response object
 36
 37        `reason_message`: if provided, will use this message as the cause
 38        of failure instead of assuming it was a misuse of the API.
 39        """
 40        self.response = response
 41        self.url = response.url
 42        self.body = response.request.body
 43        self.json = None
 44        self.message = None
 45        code = response.status_code
 46
 47        try:
 48            self.json = response.json()
 49        except JSONDecodeError:
 50            pass
 51
 52        # Did we get a 200 response but (manually) raised anyway? The consumer
 53        # method considered this an error. If it did, it MUST tell us why in
 54        # the message parameter. We pass this message on to the user.
 55        if code != 207:
 56            try:
 57                response.raise_for_status()
 58                if reason_message:
 59                    self.message = reason_message
 60                else:
 61                    self.message = "Unexpected response (API client error)"
 62            except HTTPError:
 63                pass
 64
 65        if code == 400 and not self.json:
 66            self.message = "Client request error"
 67        if code == 500:
 68            self.message = "Internal server error"
 69        if self.json and (code == 400 or code == 422 or code == 207):
 70            if self.json.get("feedbackList", False):
 71                self.feedback = [f for f in self.json.get("feedbackList", [])] or None
 72                clue = [
 73                    f["clue"]
 74                    for f in self.json["feedbackList"]
 75                    if f["clue"] not in ["OK", "Created"]
 76                ]
 77                hint = [
 78                    f["hint"].replace("'", '"')
 79                    for f in self.json["feedbackList"]
 80                    if f["clue"] not in ["OK", "Created"]
 81                ]
 82                if len(clue) == 1:
 83                    clue_part = " - Clue: {} ({})".format(clue[0], hint[0])
 84                else:
 85                    clue_part = " - Clue 1 of {}: {} ({})".format(
 86                        len(clue), clue[0], hint[0]
 87                    )
 88            else:
 89                # No feedback list, but clue in top-leel of dict
 90                clue = self.json["jobClue"]["clue"]
 91                hint = self.json["jobClue"]["hint"].replace("'", '"')
 92                clue_part = " - Clue: {} ({})".format(clue, hint)
 93            self.message = self.json["status"] + clue_part
 94
 95        if not self.message:
 96            self.message = "Request error: {}".format(code)
 97        super().__init__(self.message)
 98
 99
100class ProjectalVersionException(Exception):
101    """
102    The Projectal server version is incompatible with the version
103    of this library.
104    """
105
106    pass
107
108
109class UsageException(Exception):
110    """
111    The library was used incorrectly and we were able to detect it
112    before making a request.
113    """
114
115    pass
class LoginException(builtins.Exception):
10class LoginException(Exception):
11    """Failed to log in with the credentials provided."""
12
13    pass

Failed to log in with the credentials provided.

Inherited Members
builtins.Exception
Exception
builtins.BaseException
with_traceback
args
class UnsupportedException(builtins.Exception):
16class UnsupportedException(Exception):
17    """The API endpoint is not available for this entity."""
18
19    pass

The API endpoint is not available for this entity.

Inherited Members
builtins.Exception
Exception
builtins.BaseException
with_traceback
args
class ProjectalException(builtins.Exception):
22class ProjectalException(Exception):
23    """
24    The API request failed. This exception will extract the specific
25    error from the Projectal response if it can find one. To assist
26    in debugging, the response object is attached to the exception
27    which you may inspect for more precise details.
28
29    In case of failure of a bulk operation, only the error clue for
30    the first failure is shown. A counter is included to show how
31    many failed (i.e.: 1 of 25).
32    """
33
34    def __init__(self, response, reason_message=None):
35        """
36        `response`: the response object
37
38        `reason_message`: if provided, will use this message as the cause
39        of failure instead of assuming it was a misuse of the API.
40        """
41        self.response = response
42        self.url = response.url
43        self.body = response.request.body
44        self.json = None
45        self.message = None
46        code = response.status_code
47
48        try:
49            self.json = response.json()
50        except JSONDecodeError:
51            pass
52
53        # Did we get a 200 response but (manually) raised anyway? The consumer
54        # method considered this an error. If it did, it MUST tell us why in
55        # the message parameter. We pass this message on to the user.
56        if code != 207:
57            try:
58                response.raise_for_status()
59                if reason_message:
60                    self.message = reason_message
61                else:
62                    self.message = "Unexpected response (API client error)"
63            except HTTPError:
64                pass
65
66        if code == 400 and not self.json:
67            self.message = "Client request error"
68        if code == 500:
69            self.message = "Internal server error"
70        if self.json and (code == 400 or code == 422 or code == 207):
71            if self.json.get("feedbackList", False):
72                self.feedback = [f for f in self.json.get("feedbackList", [])] or None
73                clue = [
74                    f["clue"]
75                    for f in self.json["feedbackList"]
76                    if f["clue"] not in ["OK", "Created"]
77                ]
78                hint = [
79                    f["hint"].replace("'", '"')
80                    for f in self.json["feedbackList"]
81                    if f["clue"] not in ["OK", "Created"]
82                ]
83                if len(clue) == 1:
84                    clue_part = " - Clue: {} ({})".format(clue[0], hint[0])
85                else:
86                    clue_part = " - Clue 1 of {}: {} ({})".format(
87                        len(clue), clue[0], hint[0]
88                    )
89            else:
90                # No feedback list, but clue in top-leel of dict
91                clue = self.json["jobClue"]["clue"]
92                hint = self.json["jobClue"]["hint"].replace("'", '"')
93                clue_part = " - Clue: {} ({})".format(clue, hint)
94            self.message = self.json["status"] + clue_part
95
96        if not self.message:
97            self.message = "Request error: {}".format(code)
98        super().__init__(self.message)

The API request failed. This exception will extract the specific error from the Projectal response if it can find one. To assist in debugging, the response object is attached to the exception which you may inspect for more precise details.

In case of failure of a bulk operation, only the error clue for the first failure is shown. A counter is included to show how many failed (i.e.: 1 of 25).

ProjectalException(response, reason_message=None)
34    def __init__(self, response, reason_message=None):
35        """
36        `response`: the response object
37
38        `reason_message`: if provided, will use this message as the cause
39        of failure instead of assuming it was a misuse of the API.
40        """
41        self.response = response
42        self.url = response.url
43        self.body = response.request.body
44        self.json = None
45        self.message = None
46        code = response.status_code
47
48        try:
49            self.json = response.json()
50        except JSONDecodeError:
51            pass
52
53        # Did we get a 200 response but (manually) raised anyway? The consumer
54        # method considered this an error. If it did, it MUST tell us why in
55        # the message parameter. We pass this message on to the user.
56        if code != 207:
57            try:
58                response.raise_for_status()
59                if reason_message:
60                    self.message = reason_message
61                else:
62                    self.message = "Unexpected response (API client error)"
63            except HTTPError:
64                pass
65
66        if code == 400 and not self.json:
67            self.message = "Client request error"
68        if code == 500:
69            self.message = "Internal server error"
70        if self.json and (code == 400 or code == 422 or code == 207):
71            if self.json.get("feedbackList", False):
72                self.feedback = [f for f in self.json.get("feedbackList", [])] or None
73                clue = [
74                    f["clue"]
75                    for f in self.json["feedbackList"]
76                    if f["clue"] not in ["OK", "Created"]
77                ]
78                hint = [
79                    f["hint"].replace("'", '"')
80                    for f in self.json["feedbackList"]
81                    if f["clue"] not in ["OK", "Created"]
82                ]
83                if len(clue) == 1:
84                    clue_part = " - Clue: {} ({})".format(clue[0], hint[0])
85                else:
86                    clue_part = " - Clue 1 of {}: {} ({})".format(
87                        len(clue), clue[0], hint[0]
88                    )
89            else:
90                # No feedback list, but clue in top-leel of dict
91                clue = self.json["jobClue"]["clue"]
92                hint = self.json["jobClue"]["hint"].replace("'", '"')
93                clue_part = " - Clue: {} ({})".format(clue, hint)
94            self.message = self.json["status"] + clue_part
95
96        if not self.message:
97            self.message = "Request error: {}".format(code)
98        super().__init__(self.message)

response: the response object

reason_message: if provided, will use this message as the cause of failure instead of assuming it was a misuse of the API.

response
url
body
json
message
Inherited Members
builtins.BaseException
with_traceback
args
class ProjectalVersionException(builtins.Exception):
101class ProjectalVersionException(Exception):
102    """
103    The Projectal server version is incompatible with the version
104    of this library.
105    """
106
107    pass

The Projectal server version is incompatible with the version of this library.

Inherited Members
builtins.Exception
Exception
builtins.BaseException
with_traceback
args
class UsageException(builtins.Exception):
110class UsageException(Exception):
111    """
112    The library was used incorrectly and we were able to detect it
113    before making a request.
114    """
115
116    pass

The library was used incorrectly and we were able to detect it before making a request.

Inherited Members
builtins.Exception
Exception
builtins.BaseException
with_traceback
args