395 lines
12 KiB
Python
395 lines
12 KiB
Python
# GUI Application automation and testing library
|
|
# Copyright (C) 2006 Mark Mc Mahon
|
|
#
|
|
# This library is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU Lesser General Public License
|
|
# as published by the Free Software Foundation; either version 2.1
|
|
# of the License, or (at your option) any later version.
|
|
#
|
|
# This library is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
# See the GNU Lesser General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU Lesser General Public
|
|
# License along with this library; if not, write to the
|
|
# Free Software Foundation, Inc.,
|
|
# 59 Temple Place,
|
|
# Suite 330,
|
|
# Boston, MA 02111-1307 USA
|
|
|
|
"""Timing settings for all of pywinauto
|
|
|
|
This module has one object that should be used for all timing adjustments
|
|
timings.Timings
|
|
|
|
There are a couple of predefined settings
|
|
|
|
timings.Timings.Fast()
|
|
timings.Timings.Defaults()
|
|
timings.Timings.Slow()
|
|
|
|
The Following are the individual timing settings that can be adjusted:
|
|
|
|
* window_find_timeout (default 3)
|
|
* window_find_retry (default .09)
|
|
|
|
* app_start_timeout (default 10)
|
|
* app_start_retry (default .90)
|
|
|
|
* exists_timeout (default .5)
|
|
* exists_retry (default .3)
|
|
|
|
* after_click_wait (default .09)
|
|
* after_clickinput_wait (default .01)
|
|
|
|
* after_menu_wait (default .05)
|
|
|
|
* after_sendkeys_key_wait (default .01)
|
|
|
|
* after_button_click_wait (default 0)
|
|
|
|
* before_closeclick_wait (default .1)
|
|
* closeclick_retry (default .05)
|
|
* closeclick_dialog_close_wait (default .05)
|
|
* after_closeclick_wait (default .2)
|
|
|
|
* after_windowclose_timeout (default 2)
|
|
* after_windowclose_retry (default .5)
|
|
|
|
* after_setfocus_wait (default .06)
|
|
|
|
* after_setcursorpos_wait (default .01)
|
|
|
|
* sendmessagetimeout_timeout (default .001)
|
|
|
|
* after_tabselect_wait (default .01)
|
|
* after_listviewselect_wait (default .01)
|
|
* after_listviewcheck_wait default(.001)
|
|
|
|
* after_treeviewselect_wait default(.001)
|
|
|
|
* after_toobarpressbutton_wait default(.01)
|
|
|
|
* after_updownchange_wait default(.001)
|
|
|
|
* after_movewindow_wait default(0)
|
|
* after_buttoncheck_wait default(0)
|
|
* after_comboselect_wait default(0)
|
|
* after_listboxselect_wait default(0)
|
|
* after_listboxfocuschange_wait default(0)
|
|
* after_editsetedittext_wait default(0)
|
|
* after_editselect_wait default(0)
|
|
|
|
"""
|
|
|
|
import time
|
|
import operator
|
|
|
|
|
|
__revision__ = "$Revision: 453 $"
|
|
|
|
|
|
#=========================================================================
|
|
class TimeConfig(object):
|
|
"Central storage and minipulation of timing values"
|
|
__default_timing = {
|
|
'window_find_timeout' : 3,
|
|
'window_find_retry' : .09,
|
|
|
|
'app_start_timeout' : 10,
|
|
'app_start_retry' : .90,
|
|
|
|
'exists_timeout' : .5,
|
|
'exists_retry' : .3,
|
|
|
|
'after_click_wait' : .09,
|
|
'after_clickinput_wait' : .01,
|
|
|
|
'after_menu_wait' : .05,
|
|
|
|
'after_sendkeys_key_wait' : .01,
|
|
|
|
'after_button_click_wait' : 0,
|
|
|
|
'before_closeclick_wait' : .1,
|
|
'closeclick_retry' : .05,
|
|
'closeclick_dialog_close_wait' : .05,
|
|
'after_closeclick_wait' : .2,
|
|
|
|
'after_windowclose_timeout': 2,
|
|
'after_windowclose_retry': .5,
|
|
|
|
'after_setfocus_wait' : .06,
|
|
|
|
'after_setcursorpos_wait' : .01,
|
|
|
|
'sendmessagetimeout_timeout' : .001,
|
|
|
|
'after_tabselect_wait': .01,
|
|
|
|
'after_listviewselect_wait': .01,
|
|
'after_listviewcheck_wait': .001,
|
|
|
|
'after_treeviewselect_wait': .001,
|
|
|
|
'after_toobarpressbutton_wait': .01,
|
|
|
|
'after_updownchange_wait': .001,
|
|
|
|
'after_movewindow_wait': 0,
|
|
'after_buttoncheck_wait': 0,
|
|
'after_comboboxselect_wait': 0,
|
|
'after_listboxselect_wait': 0,
|
|
'after_listboxfocuschange_wait': 0,
|
|
'after_editsetedittext_wait': 0,
|
|
'after_editselect_wait': 0,
|
|
}
|
|
|
|
|
|
_timings = __default_timing.copy()
|
|
_cur_speed = 1
|
|
|
|
def __getattr__(self, attr):
|
|
"Get the value for a particular timing"
|
|
if attr in TimeConfig.__default_timing:
|
|
return TimeConfig._timings[attr]
|
|
else:
|
|
raise KeyError(
|
|
"Unknown timing setting: %s" % attr)
|
|
|
|
def __setattr__(self, attr, value):
|
|
"Set a particular timing"
|
|
if attr in TimeConfig.__default_timing:
|
|
TimeConfig._timings[attr] = value
|
|
else:
|
|
raise KeyError(
|
|
"Unknown timing setting: %s" % attr)
|
|
|
|
def Fast(self):
|
|
"""Set fast timing values
|
|
|
|
Currently this changes the timing in the following ways:
|
|
timeouts = 1 second
|
|
waits = 0 seconds
|
|
retries = .001 seconds (minimum!)
|
|
|
|
(if existing times are faster then keep existing times)
|
|
"""
|
|
|
|
for setting in TimeConfig.__default_timing:
|
|
# set timeouts to the min of the current speed or 1 second
|
|
if "_timeout" in setting:
|
|
TimeConfig._timings[setting] = min(1, TimeConfig._timings[setting])
|
|
|
|
if "_wait" in setting:
|
|
TimeConfig._timings[setting] = 0
|
|
|
|
elif setting.endswith("_retry"):
|
|
TimeConfig._timings[setting] = 0.001
|
|
|
|
#self._timings['app_start_timeout'] = .5
|
|
|
|
|
|
def Slow(self):
|
|
"""Set slow timing values
|
|
|
|
Currently this changes the timing in the following ways:
|
|
timeouts = default timeouts * 10
|
|
waits = default waits * 3
|
|
retries = default retries * 3
|
|
|
|
(if existing times are slower then keep existing times)
|
|
"""
|
|
for setting in TimeConfig.__default_timing:
|
|
if "_timeout" in setting:
|
|
TimeConfig._timings[setting] = max(
|
|
TimeConfig.__default_timing[setting] * 10,
|
|
TimeConfig._timings[setting])
|
|
|
|
if "_wait" in setting:
|
|
TimeConfig._timings[setting] = max(
|
|
TimeConfig.__default_timing[setting] * 3,
|
|
TimeConfig._timings[setting])
|
|
|
|
elif setting.endswith("_retry"):
|
|
TimeConfig._timings[setting] = max(
|
|
TimeConfig.__default_timing[setting] * 3,
|
|
TimeConfig._timings[setting])
|
|
|
|
if TimeConfig._timings[setting] < .2:
|
|
TimeConfig._timings[setting]= .2
|
|
|
|
def Defaults(self):
|
|
"Set all timings to the default time"
|
|
TimeConfig._timings = TimeConfig.__default_timing.copy()
|
|
|
|
|
|
Timings = TimeConfig()
|
|
|
|
|
|
#=========================================================================
|
|
class TimeoutError(RuntimeError):
|
|
pass
|
|
|
|
|
|
#=========================================================================
|
|
def WaitUntil(
|
|
timeout,
|
|
retry_interval,
|
|
func,
|
|
value = True,
|
|
op = operator.eq,
|
|
*args):
|
|
|
|
"""Wait until ``op(function(*args), value)`` is True or until timeout
|
|
expires
|
|
|
|
* **timeout** how long the function will try the function
|
|
* **retry_interval** how long to wait between retries
|
|
* **func** the function that will be executed
|
|
* **value** the value to be compared against (defaults to True)
|
|
* **op** the comparison function (defaults to equality)\
|
|
* **args** optional arguments to be passed to func when called
|
|
|
|
Returns the return value of the function
|
|
If the operation times out then the return value of the the function
|
|
is in the 'function_value' attribute of the raised exception.
|
|
|
|
e.g. ::
|
|
|
|
try:
|
|
# wait a maximum of 10.5 seconds for the
|
|
# the objects ItemCount() method to return 10
|
|
# in increments of .5 of a second
|
|
WaitUntil(10.5, .5, self.ItemCount, 10)
|
|
except TimeoutError, e:
|
|
print "timed out"
|
|
|
|
"""
|
|
|
|
start = time.time()
|
|
|
|
func_val = func(*args)
|
|
# while the function hasn't returned what we are waiting for
|
|
while not op(func_val, value):
|
|
|
|
# find how long we have waited
|
|
waited = time.time() - start
|
|
|
|
# if we have to wait some more
|
|
if waited < timeout:
|
|
# wait either the retry_interval or else the amount of
|
|
# time until the timeout expires (whichever is less)
|
|
time.sleep(min(retry_interval, timeout - waited))
|
|
func_val = func(*args)
|
|
else:
|
|
err = TimeoutError("timed out")
|
|
err.function_value = func_val
|
|
raise err
|
|
|
|
return func_val
|
|
|
|
|
|
#def WaitUntilNot(timeout, retry_interval, func, value = True)
|
|
# return WaitUntil(timeout, retry_interval, func, value = True)
|
|
|
|
|
|
def WaitUntilPasses(
|
|
timeout,
|
|
retry_interval,
|
|
func,
|
|
exceptions = (Exception),
|
|
*args):
|
|
|
|
"""Wait until ``func(*args)`` does not raise one of the exceptions in
|
|
exceptions
|
|
|
|
* **timeout** how long the function will try the function
|
|
* **retry_interval** how long to wait between retries
|
|
* **func** the function that will be executed
|
|
* **exceptions** list of exceptions to test against (default: Exception)
|
|
* **args** optional arguments to be passed to func when called
|
|
|
|
Returns the return value of the function
|
|
If the operation times out then the original exception raised is in
|
|
the 'original_exception' attribute of the raised exception.
|
|
|
|
e.g. ::
|
|
|
|
try:
|
|
# wait a maximum of 10.5 seconds for the
|
|
# window to be found in increments of .5 of a second.
|
|
# P.int a message and re-raise the original exception if never found.
|
|
WaitUntilPasses(10.5, .5, self.Exists, (WindowNotFoundError))
|
|
except TimeoutError, e:
|
|
print "timed out"
|
|
raise e.
|
|
|
|
"""
|
|
|
|
start = time.time()
|
|
waited = 0
|
|
|
|
# keep trying until the timeout is passed
|
|
while waited <= timeout:
|
|
try:
|
|
# Call the function with any arguments
|
|
func_val = func(*args)
|
|
|
|
# if this did not raise an exception -then we are finised
|
|
break
|
|
|
|
# An exception was raised - so wait and try again
|
|
except exceptions, e:
|
|
waited = time.time() - start
|
|
|
|
if waited < timeout:
|
|
time.sleep(min(retry_interval, timeout - waited))
|
|
else:
|
|
# re-raise the original exeption
|
|
err = TimeoutError()
|
|
err.original_exception = e
|
|
raise err
|
|
|
|
# return the function value
|
|
return func_val
|
|
|
|
|
|
#
|
|
#
|
|
#
|
|
#def Defaults():
|
|
# _current_timing = __default_timing.copy()
|
|
#
|
|
#
|
|
#def Slow():
|
|
# for setting in __default_timing:
|
|
# if "_timeout" in setting:
|
|
# _current_timing[setting] = _default_timing[setting] * 10
|
|
#
|
|
# if "_wait" in setting:
|
|
# _current_timing[setting] = _default_timing[setting] * 3
|
|
#
|
|
# elif setting.endswith("_retry"):
|
|
# _current_timing[setting] = _default_timing[setting] * 3
|
|
#
|
|
#
|
|
#
|
|
#def SetTiming(**kwargs):
|
|
# ""
|
|
#
|
|
# for setting, time in kwargs.items():
|
|
# if setting in __default_timing:
|
|
# _current_timing[setting] = time
|
|
# else:
|
|
# raise KeyError(
|
|
# "Unknown timing setting: %s" % setting)
|
|
#
|
|
#def Get(setting):
|
|
# if setting in __default_timing:
|
|
# return _current_timing[setting]
|
|
# else:
|
|
# raise KeyError(
|
|
# "Unknown timing setting: %s" % setting)
|