133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck#!/usr/bin/env python 233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# Copyright 2012 Google Inc. All Rights Reserved. 333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# 433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# Licensed under the Apache License, Version 2.0 (the "License"); 533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# you may not use this file except in compliance with the License. 633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# You may obtain a copy of the License at 733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# 833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# http://www.apache.org/licenses/LICENSE-2.0 933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# 1033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# Unless required by applicable law or agreed to in writing, software 1133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# distributed under the License is distributed on an "AS IS" BASIS, 1233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# See the License for the specific language governing permissions and 1433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck# limitations under the License. 1533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 1633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 1733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck"""Miscellaneous utility functions.""" 1833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 1933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport inspect 2033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport logging 2133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckimport time 2233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 2333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Recktry: 2433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # pkg_resources (part of setuptools) is needed when WPR is 2533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # distributed as a package. (Resources may need to be extracted from 2633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # the package.) 2733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 2833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck import pkg_resources 2933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 3033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def resource_exists(resource_name): 3133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return pkg_resources.resource_exists(__name__, resource_name) 3233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 3333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def resource_string(resource_name): 3433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return pkg_resources.resource_string(__name__, resource_name) 3533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 3633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckexcept ImportError: 3733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # Import of pkg_resources failed, so fall back to getting resources 3833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck # from the file system. 3933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 4033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck import os 4133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 4233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def _resource_path(resource_name): 4333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck _replay_dir = os.path.dirname(os.path.abspath(__file__)) 4433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return os.path.join(_replay_dir, resource_name) 4533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 4633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def resource_exists(resource_name): 4733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return os.path.exists(_resource_path(resource_name)) 4833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 4933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def resource_string(resource_name): 5033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return open(_resource_path(resource_name)).read() 5133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 5233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 5333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckclass TimeoutException(Exception): 5433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck pass 5533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 5633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 5733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reckdef WaitFor(condition, timeout): 5833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """Waits for up to |timeout| secs for the function |condition| to return True. 5933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 6033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck Polling frequency is (elapsed_time / 10), with a min of .1s and max of 5s. 6133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 6233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck Returns: 6333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck Result of |condition| function (if present). 6433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck """ 6533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck min_poll_interval = 0.1 6633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck max_poll_interval = 5 6733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck output_interval = 300 6833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 6933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck def GetConditionString(): 7033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if condition.__name__ == '<lambda>': 7133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck try: 7233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return inspect.getsource(condition).strip() 7333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck except IOError: 7433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck pass 7533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return condition.__name__ 7633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck 7733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck start_time = time.time() 7833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck last_output_time = start_time 7933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck while True: 8033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck res = condition() 8133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if res: 8233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck return res 8333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck now = time.time() 8433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck elapsed_time = now - start_time 8533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck last_output_elapsed_time = now - last_output_time 8633259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if elapsed_time > timeout: 8733259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck raise TimeoutException('Timed out while waiting %ds for %s.' % 8833259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck (timeout, GetConditionString())) 8933259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck if last_output_elapsed_time > output_interval: 9033259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck logging.info('Continuing to wait %ds for %s. Elapsed: %ds.', 9133259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck timeout, GetConditionString(), elapsed_time) 9233259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck last_output_time = time.time() 9333259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck poll_interval = min(max(elapsed_time / 10., min_poll_interval), 9433259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck max_poll_interval) 9533259e44c8229f70ffe0cf3bb5ca9375c4feb2f9John Reck time.sleep(poll_interval) 96