1import collections 2import json 3 4from typing import ClassVar, DefaultDict, Type 5 6 7class WebDriverException(Exception): 8 # The status_code class variable is used to map the JSON Error Code (see 9 # https://w3c.github.io/webdriver/#errors) to a WebDriverException subclass. 10 # However, http_status need not match, and both are set as instance 11 # variables, shadowing the class variables. TODO: Match on both http_status 12 # and status_code and let these be class variables only. 13 http_status = None # type: ClassVar[int] 14 status_code = None # type: ClassVar[str] 15 16 def __init__(self, http_status=None, status_code=None, message=None, stacktrace=None): 17 super(WebDriverException, self) 18 19 if http_status is not None: 20 self.http_status = http_status 21 if status_code is not None: 22 self.status_code = status_code 23 self.message = message 24 self.stacktrace = stacktrace 25 26 def __repr__(self): 27 return "<%s http_status=%s>" % (self.__class__.__name__, self.http_status) 28 29 def __str__(self): 30 message = "%s (%s)" % (self.status_code, self.http_status) 31 32 if self.message is not None: 33 message += ": %s" % self.message 34 message += "\n" 35 36 if self.stacktrace: 37 message += ("\nRemote-end stacktrace:\n\n%s" % self.stacktrace) 38 39 return message 40 41 42class DetachedShadowRootException(WebDriverException): 43 http_status = 404 44 status_code = "detached shadow root" 45 46 47class ElementClickInterceptedException(WebDriverException): 48 http_status = 400 49 status_code = "element click intercepted" 50 51 52class ElementNotSelectableException(WebDriverException): 53 http_status = 400 54 status_code = "element not selectable" 55 56 57class ElementNotVisibleException(WebDriverException): 58 http_status = 400 59 status_code = "element not visible" 60 61 62class InsecureCertificateException(WebDriverException): 63 http_status = 400 64 status_code = "insecure certificate" 65 66 67class InvalidArgumentException(WebDriverException): 68 http_status = 400 69 status_code = "invalid argument" 70 71 72class InvalidCookieDomainException(WebDriverException): 73 http_status = 400 74 status_code = "invalid cookie domain" 75 76 77class InvalidElementCoordinatesException(WebDriverException): 78 http_status = 400 79 status_code = "invalid element coordinates" 80 81 82class InvalidElementStateException(WebDriverException): 83 http_status = 400 84 status_code = "invalid element state" 85 86 87class InvalidSelectorException(WebDriverException): 88 http_status = 400 89 status_code = "invalid selector" 90 91 92class InvalidSessionIdException(WebDriverException): 93 http_status = 404 94 status_code = "invalid session id" 95 96 97class JavascriptErrorException(WebDriverException): 98 http_status = 500 99 status_code = "javascript error" 100 101 102class MoveTargetOutOfBoundsException(WebDriverException): 103 http_status = 500 104 status_code = "move target out of bounds" 105 106 107class NoSuchAlertException(WebDriverException): 108 http_status = 404 109 status_code = "no such alert" 110 111 112class NoSuchCookieException(WebDriverException): 113 http_status = 404 114 status_code = "no such cookie" 115 116 117class NoSuchElementException(WebDriverException): 118 http_status = 404 119 status_code = "no such element" 120 121 122class NoSuchFrameException(WebDriverException): 123 http_status = 404 124 status_code = "no such frame" 125 126 127class NoSuchShadowRootException(WebDriverException): 128 http_status = 404 129 status_code = "no such shadow root" 130 131 132class NoSuchWindowException(WebDriverException): 133 http_status = 404 134 status_code = "no such window" 135 136 137class ScriptTimeoutException(WebDriverException): 138 http_status = 500 139 status_code = "script timeout" 140 141 142class SessionNotCreatedException(WebDriverException): 143 http_status = 500 144 status_code = "session not created" 145 146 147class StaleElementReferenceException(WebDriverException): 148 http_status = 404 149 status_code = "stale element reference" 150 151 152class TimeoutException(WebDriverException): 153 http_status = 500 154 status_code = "timeout" 155 156 157class UnableToSetCookieException(WebDriverException): 158 http_status = 500 159 status_code = "unable to set cookie" 160 161 162class UnexpectedAlertOpenException(WebDriverException): 163 http_status = 500 164 status_code = "unexpected alert open" 165 166 167class UnknownErrorException(WebDriverException): 168 http_status = 500 169 status_code = "unknown error" 170 171 172class UnknownCommandException(WebDriverException): 173 http_status = 404 174 status_code = "unknown command" 175 176 177class UnknownMethodException(WebDriverException): 178 http_status = 405 179 status_code = "unknown method" 180 181 182class UnsupportedOperationException(WebDriverException): 183 http_status = 500 184 status_code = "unsupported operation" 185 186 187def from_response(response): 188 """ 189 Unmarshals an error from a ``Response``'s `body`, failing 190 if not all three required `error`, `message`, and `stacktrace` 191 fields are given. Defaults to ``WebDriverException`` if `error` 192 is unknown. 193 """ 194 if response.status == 200: 195 raise UnknownErrorException( 196 response.status, 197 None, 198 "Response is not an error:\n" 199 "%s" % json.dumps(response.body)) 200 201 if "value" in response.body: 202 value = response.body["value"] 203 else: 204 raise UnknownErrorException( 205 response.status, 206 None, 207 "Expected 'value' key in response body:\n" 208 "%s" % json.dumps(response.body)) 209 210 # all fields must exist, but stacktrace can be an empty string 211 code = value["error"] 212 message = value["message"] 213 stack = value["stacktrace"] or None 214 215 cls = get(code) 216 return cls(response.status, code, message, stacktrace=stack) 217 218 219def get(error_code): 220 """ 221 Gets exception from `error_code`, falling back to 222 ``WebDriverException`` if it is not found. 223 """ 224 return _errors.get(error_code, WebDriverException) 225 226 227_errors: DefaultDict[str, Type[WebDriverException]] = collections.defaultdict() 228for item in list(locals().values()): 229 if type(item) == type and issubclass(item, WebDriverException): 230 _errors[item.status_code] = item 231