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
16
17"""Miscellaneous utility functions."""
18
19import inspect
20import logging
21import time
22
23try:
24  # pkg_resources (part of setuptools) is needed when WPR is
25  # distributed as a package. (Resources may need to be extracted from
26  # the package.)
27
28  import pkg_resources
29
30  def resource_exists(resource_name):
31    return pkg_resources.resource_exists(__name__, resource_name)
32
33  def resource_string(resource_name):
34    return pkg_resources.resource_string(__name__, resource_name)
35
36except ImportError:
37  # Import of pkg_resources failed, so fall back to getting resources
38  # from the file system.
39
40  import os
41
42  def _resource_path(resource_name):
43    _replay_dir = os.path.dirname(os.path.abspath(__file__))
44    return os.path.join(_replay_dir, resource_name)
45
46  def resource_exists(resource_name):
47    return os.path.exists(_resource_path(resource_name))
48
49  def resource_string(resource_name):
50    return open(_resource_path(resource_name)).read()
51
52
53class TimeoutException(Exception):
54  pass
55
56
57def WaitFor(condition, timeout):
58  """Waits for up to |timeout| secs for the function |condition| to return True.
59
60  Polling frequency is (elapsed_time / 10), with a min of .1s and max of 5s.
61
62  Returns:
63    Result of |condition| function (if present).
64  """
65  min_poll_interval = 0.1
66  max_poll_interval = 5
67  output_interval = 300
68
69  def GetConditionString():
70    if condition.__name__ == '<lambda>':
71      try:
72        return inspect.getsource(condition).strip()
73      except IOError:
74        pass
75    return condition.__name__
76
77  start_time = time.time()
78  last_output_time = start_time
79  while True:
80    res = condition()
81    if res:
82      return res
83    now = time.time()
84    elapsed_time = now - start_time
85    last_output_elapsed_time = now - last_output_time
86    if elapsed_time > timeout:
87      raise TimeoutException('Timed out while waiting %ds for %s.' %
88                                        (timeout, GetConditionString()))
89    if last_output_elapsed_time > output_interval:
90      logging.info('Continuing to wait %ds for %s. Elapsed: %ds.',
91                   timeout, GetConditionString(), elapsed_time)
92      last_output_time = time.time()
93    poll_interval = min(max(elapsed_time / 10., min_poll_interval),
94                        max_poll_interval)
95    time.sleep(poll_interval)
96