util.py 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. #!/usr/bin/env python
  2. # Copyright 2012 Google Inc. All Rights Reserved.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. """Miscellaneous utility functions."""
  16. import inspect
  17. import logging
  18. import time
  19. try:
  20. # pkg_resources (part of setuptools) is needed when WPR is
  21. # distributed as a package. (Resources may need to be extracted from
  22. # the package.)
  23. import pkg_resources
  24. def resource_exists(resource_name):
  25. return pkg_resources.resource_exists(__name__, resource_name)
  26. def resource_string(resource_name):
  27. return pkg_resources.resource_string(__name__, resource_name)
  28. except ImportError:
  29. # Import of pkg_resources failed, so fall back to getting resources
  30. # from the file system.
  31. import os
  32. def _resource_path(resource_name):
  33. _replay_dir = os.path.dirname(os.path.abspath(__file__))
  34. return os.path.join(_replay_dir, resource_name)
  35. def resource_exists(resource_name):
  36. return os.path.exists(_resource_path(resource_name))
  37. def resource_string(resource_name):
  38. return open(_resource_path(resource_name)).read()
  39. class TimeoutException(Exception):
  40. pass
  41. def WaitFor(condition, timeout):
  42. """Waits for up to |timeout| secs for the function |condition| to return True.
  43. Polling frequency is (elapsed_time / 10), with a min of .1s and max of 5s.
  44. Returns:
  45. Result of |condition| function (if present).
  46. """
  47. min_poll_interval = 0.1
  48. max_poll_interval = 5
  49. output_interval = 300
  50. def GetConditionString():
  51. if condition.__name__ == '<lambda>':
  52. try:
  53. return inspect.getsource(condition).strip()
  54. except IOError:
  55. pass
  56. return condition.__name__
  57. start_time = time.time()
  58. last_output_time = start_time
  59. while True:
  60. res = condition()
  61. if res:
  62. return res
  63. now = time.time()
  64. elapsed_time = now - start_time
  65. last_output_elapsed_time = now - last_output_time
  66. if elapsed_time > timeout:
  67. raise TimeoutException('Timed out while waiting %ds for %s.' %
  68. (timeout, GetConditionString()))
  69. if last_output_elapsed_time > output_interval:
  70. logging.info('Continuing to wait %ds for %s. Elapsed: %ds.',
  71. timeout, GetConditionString(), elapsed_time)
  72. last_output_time = time.time()
  73. poll_interval = min(max(elapsed_time / 10., min_poll_interval),
  74. max_poll_interval)
  75. time.sleep(poll_interval)