| import collections |
| import json |
| |
| from typing import ClassVar, DefaultDict, Type |
| |
| |
| class WebDriverException(Exception): |
| # The status_code class variable is used to map the JSON Error Code (see |
| # https://w3c.github.io/webdriver/#errors) to a WebDriverException subclass. |
| # However, http_status need not match, and both are set as instance |
| # variables, shadowing the class variables. TODO: Match on both http_status |
| # and status_code and let these be class variables only. |
| http_status = None # type: ClassVar[int] |
| status_code = None # type: ClassVar[str] |
| |
| def __init__(self, http_status=None, status_code=None, message=None, stacktrace=None): |
| super(WebDriverException, self) |
| |
| if http_status is not None: |
| self.http_status = http_status |
| if status_code is not None: |
| self.status_code = status_code |
| self.message = message |
| self.stacktrace = stacktrace |
| |
| def __repr__(self): |
| return "<%s http_status=%s>" % (self.__class__.__name__, self.http_status) |
| |
| def __str__(self): |
| message = "%s (%s)" % (self.status_code, self.http_status) |
| |
| if self.message is not None: |
| message += ": %s" % self.message |
| message += "\n" |
| |
| if self.stacktrace: |
| message += ("\nRemote-end stacktrace:\n\n%s" % self.stacktrace) |
| |
| return message |
| |
| |
| class DetachedShadowRootException(WebDriverException): |
| http_status = 404 |
| status_code = "detached shadow root" |
| |
| |
| class ElementClickInterceptedException(WebDriverException): |
| http_status = 400 |
| status_code = "element click intercepted" |
| |
| |
| class ElementNotSelectableException(WebDriverException): |
| http_status = 400 |
| status_code = "element not selectable" |
| |
| |
| class ElementNotVisibleException(WebDriverException): |
| http_status = 400 |
| status_code = "element not visible" |
| |
| |
| class InsecureCertificateException(WebDriverException): |
| http_status = 400 |
| status_code = "insecure certificate" |
| |
| |
| class InvalidArgumentException(WebDriverException): |
| http_status = 400 |
| status_code = "invalid argument" |
| |
| |
| class InvalidCookieDomainException(WebDriverException): |
| http_status = 400 |
| status_code = "invalid cookie domain" |
| |
| |
| class InvalidElementCoordinatesException(WebDriverException): |
| http_status = 400 |
| status_code = "invalid element coordinates" |
| |
| |
| class InvalidElementStateException(WebDriverException): |
| http_status = 400 |
| status_code = "invalid element state" |
| |
| |
| class InvalidSelectorException(WebDriverException): |
| http_status = 400 |
| status_code = "invalid selector" |
| |
| |
| class InvalidSessionIdException(WebDriverException): |
| http_status = 404 |
| status_code = "invalid session id" |
| |
| |
| class JavascriptErrorException(WebDriverException): |
| http_status = 500 |
| status_code = "javascript error" |
| |
| |
| class MoveTargetOutOfBoundsException(WebDriverException): |
| http_status = 500 |
| status_code = "move target out of bounds" |
| |
| |
| class NoSuchAlertException(WebDriverException): |
| http_status = 404 |
| status_code = "no such alert" |
| |
| |
| class NoSuchCookieException(WebDriverException): |
| http_status = 404 |
| status_code = "no such cookie" |
| |
| |
| class NoSuchElementException(WebDriverException): |
| http_status = 404 |
| status_code = "no such element" |
| |
| |
| class NoSuchFrameException(WebDriverException): |
| http_status = 404 |
| status_code = "no such frame" |
| |
| |
| class NoSuchShadowRootException(WebDriverException): |
| http_status = 404 |
| status_code = "no such shadow root" |
| |
| |
| class NoSuchWindowException(WebDriverException): |
| http_status = 404 |
| status_code = "no such window" |
| |
| |
| class ScriptTimeoutException(WebDriverException): |
| http_status = 500 |
| status_code = "script timeout" |
| |
| |
| class SessionNotCreatedException(WebDriverException): |
| http_status = 500 |
| status_code = "session not created" |
| |
| |
| class StaleElementReferenceException(WebDriverException): |
| http_status = 404 |
| status_code = "stale element reference" |
| |
| |
| class TimeoutException(WebDriverException): |
| http_status = 500 |
| status_code = "timeout" |
| |
| |
| class UnableToSetCookieException(WebDriverException): |
| http_status = 500 |
| status_code = "unable to set cookie" |
| |
| |
| class UnexpectedAlertOpenException(WebDriverException): |
| http_status = 500 |
| status_code = "unexpected alert open" |
| |
| |
| class UnknownErrorException(WebDriverException): |
| http_status = 500 |
| status_code = "unknown error" |
| |
| |
| class UnknownCommandException(WebDriverException): |
| http_status = 404 |
| status_code = "unknown command" |
| |
| |
| class UnknownMethodException(WebDriverException): |
| http_status = 405 |
| status_code = "unknown method" |
| |
| |
| class UnsupportedOperationException(WebDriverException): |
| http_status = 500 |
| status_code = "unsupported operation" |
| |
| |
| def from_response(response): |
| """ |
| Unmarshals an error from a ``Response``'s `body`, failing |
| if not all three required `error`, `message`, and `stacktrace` |
| fields are given. Defaults to ``WebDriverException`` if `error` |
| is unknown. |
| """ |
| if response.status == 200: |
| raise UnknownErrorException( |
| response.status, |
| None, |
| "Response is not an error:\n" |
| "%s" % json.dumps(response.body)) |
| |
| if "value" in response.body: |
| value = response.body["value"] |
| else: |
| raise UnknownErrorException( |
| response.status, |
| None, |
| "Expected 'value' key in response body:\n" |
| "%s" % json.dumps(response.body)) |
| |
| # all fields must exist, but stacktrace can be an empty string |
| code = value["error"] |
| message = value["message"] |
| stack = value["stacktrace"] or None |
| |
| cls = get(code) |
| return cls(response.status, code, message, stacktrace=stack) |
| |
| |
| def get(error_code): |
| """ |
| Gets exception from `error_code`, falling back to |
| ``WebDriverException`` if it is not found. |
| """ |
| return _errors.get(error_code, WebDriverException) |
| |
| |
| _errors: DefaultDict[str, Type[WebDriverException]] = collections.defaultdict() |
| for item in list(locals().values()): |
| if type(item) == type and issubclass(item, WebDriverException): |
| _errors[item.status_code] = item |