wait.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. # Licensed to the Software Freedom Conservancy (SFC) under one
  2. # or more contributor license agreements. See the NOTICE file
  3. # distributed with this work for additional information
  4. # regarding copyright ownership. The SFC licenses this file
  5. # to you under the Apache License, Version 2.0 (the
  6. # "License"); you may not use this file except in compliance
  7. # with the License. You may obtain a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing,
  12. # software distributed under the License is distributed on an
  13. # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  14. # KIND, either express or implied. See the License for the
  15. # specific language governing permissions and limitations
  16. # under the License.
  17. import time
  18. from selenium.common.exceptions import NoSuchElementException
  19. from selenium.common.exceptions import TimeoutException
  20. POLL_FREQUENCY = 0.5 # How long to sleep inbetween calls to the method
  21. IGNORED_EXCEPTIONS = (NoSuchElementException,) # exceptions ignored during calls to the method
  22. class WebDriverWait(object):
  23. def __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None):
  24. """Constructor, takes a WebDriver instance and timeout in seconds.
  25. :Args:
  26. - driver - Instance of WebDriver (Ie, Firefox, Chrome or Remote)
  27. - timeout - Number of seconds before timing out
  28. - poll_frequency - sleep interval between calls
  29. By default, it is 0.5 second.
  30. - ignored_exceptions - iterable structure of exception classes ignored during calls.
  31. By default, it contains NoSuchElementException only.
  32. Example:
  33. from selenium.webdriver.support.ui import WebDriverWait \n
  34. element = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id("someId")) \n
  35. is_disappeared = WebDriverWait(driver, 30, 1, (ElementNotVisibleException)).\ \n
  36. until_not(lambda x: x.find_element_by_id("someId").is_displayed())
  37. """
  38. self._driver = driver
  39. self._timeout = timeout
  40. self._poll = poll_frequency
  41. # avoid the divide by zero
  42. if self._poll == 0:
  43. self._poll = POLL_FREQUENCY
  44. exceptions = list(IGNORED_EXCEPTIONS)
  45. if ignored_exceptions is not None:
  46. try:
  47. exceptions.extend(iter(ignored_exceptions))
  48. except TypeError: # ignored_exceptions is not iterable
  49. exceptions.append(ignored_exceptions)
  50. self._ignored_exceptions = tuple(exceptions)
  51. def __repr__(self):
  52. return '<{0.__module__}.{0.__name__} (session="{1}")>'.format(
  53. type(self), self._driver.session_id)
  54. def until(self, method, message=''):
  55. """Calls the method provided with the driver as an argument until the \
  56. return value is not False."""
  57. screen = None
  58. stacktrace = None
  59. end_time = time.time() + self._timeout
  60. while True:
  61. try:
  62. value = method(self._driver)
  63. if value:
  64. return value
  65. except self._ignored_exceptions as exc:
  66. screen = getattr(exc, 'screen', None)
  67. stacktrace = getattr(exc, 'stacktrace', None)
  68. time.sleep(self._poll)
  69. if time.time() > end_time:
  70. break
  71. raise TimeoutException(message, screen, stacktrace)
  72. def until_not(self, method, message=''):
  73. """Calls the method provided with the driver as an argument until the \
  74. return value is False."""
  75. end_time = time.time() + self._timeout
  76. while True:
  77. try:
  78. value = method(self._driver)
  79. if not value:
  80. return value
  81. except self._ignored_exceptions:
  82. return True
  83. time.sleep(self._poll)
  84. if time.time() > end_time:
  85. break
  86. raise TimeoutException(message)