Some caching for optimization
This commit is contained in:
parent
61b73a783f
commit
0139ecf371
|
@ -130,7 +130,7 @@ class HwndWrapper(object):
|
|||
C function - and it will get converted to a Long with the value of
|
||||
it's handle (see ctypes, _as_parameter_)"""
|
||||
|
||||
friendlyclassname = ''
|
||||
friendlyclassname = None
|
||||
handle = None
|
||||
|
||||
#-----------------------------------------------------------
|
||||
|
@ -143,6 +143,7 @@ class HwndWrapper(object):
|
|||
If the handle is not valid then an InvalidWindowHandle error
|
||||
is raised.
|
||||
"""
|
||||
|
||||
# handle if hwnd is actually a HwndWrapper
|
||||
try:
|
||||
self.handle = hwnd.handle
|
||||
|
@ -156,6 +157,8 @@ class HwndWrapper(object):
|
|||
# make it so that ctypes conversion happens correctly
|
||||
self._as_parameter_ = self.handle
|
||||
|
||||
#win32functions.WaitGuiThreadIdle(self)
|
||||
|
||||
# specify whether we need to grab an image of ourselves
|
||||
# when asked for properties
|
||||
self._NeedsImageProp = False
|
||||
|
@ -165,6 +168,8 @@ class HwndWrapper(object):
|
|||
|
||||
self.appdata = None
|
||||
|
||||
self._cache = {}
|
||||
|
||||
# build the list of default properties to be written
|
||||
# Derived classes can either modify this list or override
|
||||
# GetProperties depending on how much control they need.
|
||||
|
@ -200,15 +205,16 @@ class HwndWrapper(object):
|
|||
For example Checkboxes are implemented as Buttons - so the class
|
||||
of a CheckBox is "Button" - but the friendly class is "CheckBox"
|
||||
"""
|
||||
if not self.friendlyclassname:
|
||||
return handleprops.classname(self)
|
||||
else:
|
||||
return self.friendlyclassname
|
||||
if self.friendlyclassname is None:
|
||||
self.friendlyclassname = handleprops.classname(self)
|
||||
return self.friendlyclassname
|
||||
|
||||
#-----------------------------------------------------------
|
||||
def Class(self):
|
||||
"""Return the class name of the window"""
|
||||
return handleprops.classname(self)
|
||||
if not self._cache.has_key("class"):
|
||||
self._cache['class'] = handleprops.classname(self)
|
||||
return self._cache['class']
|
||||
|
||||
#-----------------------------------------------------------
|
||||
def WindowText(self):
|
||||
|
@ -377,7 +383,11 @@ class HwndWrapper(object):
|
|||
#-----------------------------------------------------------
|
||||
def IsDialog(self):
|
||||
"Return true if the control is a top level window"
|
||||
return handleprops.is_toplevel_window(self)
|
||||
|
||||
if not self._cache.has_key("isdialog"):
|
||||
self._cache['isdialog'] = handleprops.is_toplevel_window(self)
|
||||
|
||||
return self._cache['isdialog']
|
||||
|
||||
#-----------------------------------------------------------
|
||||
def Parent(self):
|
||||
|
@ -390,12 +400,19 @@ class HwndWrapper(object):
|
|||
To get the main (or top level) window then use
|
||||
HwndWrapper.TopLevelParent().
|
||||
"""
|
||||
parent_hwnd = handleprops.parent(self)
|
||||
|
||||
if parent_hwnd:
|
||||
return WrapHandle(parent_hwnd)
|
||||
else:
|
||||
return None
|
||||
if not self._cache.has_key("parent"):
|
||||
|
||||
parent_hwnd = handleprops.parent(self)
|
||||
|
||||
if parent_hwnd:
|
||||
#return WrapHandle(parent_hwnd)
|
||||
|
||||
self._cache["parent"] = WrapHandle(parent_hwnd)
|
||||
else:
|
||||
self._cache["parent"] = None
|
||||
|
||||
return self._cache["parent"]
|
||||
|
||||
#-----------------------------------------------------------
|
||||
def TopLevelParent(self):
|
||||
|
@ -410,18 +427,27 @@ class HwndWrapper(object):
|
|||
no top level parent then the control itself is returned - as it is
|
||||
a top level window already!)
|
||||
"""
|
||||
if self.IsDialog():
|
||||
return self
|
||||
|
||||
parent = self.Parent()
|
||||
if not self._cache.has_key("top_level_parent"):
|
||||
|
||||
if not parent:
|
||||
return self
|
||||
parent = self.Parent()
|
||||
|
||||
if not parent.IsDialog():
|
||||
return parent.TopLevelParent()
|
||||
else:
|
||||
return parent
|
||||
if self.IsDialog():
|
||||
self._cache["top_level_parent"] = self
|
||||
#return self
|
||||
|
||||
elif not parent:
|
||||
self._cache["top_level_parent"] = self
|
||||
#return self
|
||||
|
||||
elif not parent.IsDialog():
|
||||
self._cache["top_level_parent"] = parent.TopLevelParent()
|
||||
#return parent.TopLevelParent()
|
||||
else:
|
||||
self._cache["top_level_parent"] = parent
|
||||
#return parent
|
||||
|
||||
return self._cache["top_level_parent"]
|
||||
|
||||
#-----------------------------------------------------------
|
||||
def Texts(self):
|
||||
|
|
|
@ -51,7 +51,7 @@ class MatchError(IndexError):
|
|||
"Could not find '%s' in '%s'"% (tofind, self.items))
|
||||
|
||||
|
||||
|
||||
_cache = {}
|
||||
|
||||
# given a list of texts return the match score for each
|
||||
# and the best score and text with best score
|
||||
|
@ -67,17 +67,32 @@ def _get_match_ratios(texts, match_against):
|
|||
best_ratio = 0
|
||||
best_text = ''
|
||||
|
||||
global cache
|
||||
|
||||
for text in texts:
|
||||
# set up the SequenceMatcher with other text
|
||||
ratio_calc.set_seq2(text)
|
||||
|
||||
# try using the levenshtein distance instead
|
||||
#lev_dist = levenshtein_distance(unicode(match_against), unicode(text))
|
||||
#ratio = 1 - lev_dist / 10.0
|
||||
#ratios[text] = ratio
|
||||
if 0:
|
||||
pass
|
||||
|
||||
# calculate ratio and store it
|
||||
ratios[text] = ratio_calc.ratio()
|
||||
if (text, match_against) in _cache:
|
||||
ratios[text] = _cache[(text, match_against)]
|
||||
|
||||
elif(match_against, text) in _cache:
|
||||
ratios[text] = _cache[(match_against, text)]
|
||||
|
||||
else:
|
||||
# set up the SequenceMatcher with other text
|
||||
ratio_calc.set_seq2(text)
|
||||
|
||||
# try using the levenshtein distance instead
|
||||
#lev_dist = levenshtein_distance(unicode(match_against), unicode(text))
|
||||
#ratio = 1 - lev_dist / 10.0
|
||||
#ratios[text] = ratio
|
||||
|
||||
# calculate ratio and store it
|
||||
ratios[text] = ratio_calc.ratio()
|
||||
|
||||
_cache[(match_against, text)] = ratios[text]
|
||||
|
||||
# if this is the best so far then update best stats
|
||||
if ratios[text] > best_ratio:
|
||||
|
@ -325,6 +340,13 @@ class UniqueDict(dict):
|
|||
best_ratio = 0
|
||||
best_texts = []
|
||||
|
||||
ratio_offset = 1
|
||||
if clean:
|
||||
ratio_offset *= .9
|
||||
|
||||
if ignore_case:
|
||||
ratio_offset *= .9
|
||||
|
||||
for text_ in self:
|
||||
|
||||
# make a copy of the text as we need the original later
|
||||
|
@ -336,12 +358,31 @@ class UniqueDict(dict):
|
|||
if ignore_case:
|
||||
text = text.lower()
|
||||
|
||||
# set up the SequenceMatcher with other text
|
||||
ratio_calc.set_seq2(text)
|
||||
# check if this item is in the cache - if yes, then retrieve it
|
||||
if (text, search_text) in _cache:
|
||||
ratios[text_] = _cache[(text, search_text)]
|
||||
|
||||
# calculate ratio and store it
|
||||
ratios[text_] = ratio_calc.ratio()
|
||||
elif(search_text, text) in _cache:
|
||||
ratios[text_] = _cache[(search_text, text)]
|
||||
|
||||
# not in the cache - calculate it and add it to the cache
|
||||
else:
|
||||
# set up the SequenceMatcher with other text
|
||||
ratio_calc.set_seq2(text)
|
||||
|
||||
# if a very quick check reveals that this is not going
|
||||
# to match then
|
||||
ratio = ratio_calc.real_quick_ratio()
|
||||
|
||||
if ratio * ratio_offset > find_best_control_match_cutoff:
|
||||
ratio = ratio_calc.quick_ratio() * ratio_offset
|
||||
|
||||
if ratio * ratio_offset > find_best_control_match_cutoff:
|
||||
ratio = ratio_calc.ratio()
|
||||
|
||||
# save the match we got and store it in the cache
|
||||
ratios[text_] = ratio
|
||||
_cache[(text, search_text)] = ratio
|
||||
|
||||
# try using the levenshtein distance instead
|
||||
#lev_dist = levenshtein_distance(unicode(search_text), unicode(text))
|
||||
|
@ -357,11 +398,7 @@ class UniqueDict(dict):
|
|||
elif ratios[text_] == best_ratio:
|
||||
best_texts.append(text_)
|
||||
|
||||
if clean:
|
||||
best_ratio *= .9
|
||||
|
||||
if ignore_case:
|
||||
best_ratio *= .9
|
||||
best_ratio *= ratio_offset
|
||||
|
||||
return best_ratio, best_texts
|
||||
|
||||
|
@ -404,14 +441,14 @@ def find_best_control_matches(search_text, controls):
|
|||
name_control_map = build_unique_dict(controls)
|
||||
|
||||
|
||||
# collect all the possible names for all controls
|
||||
# and build a list of them
|
||||
for ctrl in controls:
|
||||
ctrl_names = get_control_names(ctrl, controls)
|
||||
|
||||
# for each of the names
|
||||
for name in ctrl_names:
|
||||
name_control_map[name] = ctrl
|
||||
# # collect all the possible names for all controls
|
||||
# # and build a list of them
|
||||
# for ctrl in controls:
|
||||
# ctrl_names = get_control_names(ctrl, controls)
|
||||
#
|
||||
# # for each of the names
|
||||
# for name in ctrl_names:
|
||||
# name_control_map[name] = ctrl
|
||||
|
||||
|
||||
best_ratio, best_texts = name_control_map.FindBestMatches(search_text)
|
||||
|
|
Loading…
Reference in New Issue