Improvements with Steam.
This commit is contained in:
@@ -44,6 +44,8 @@ class Utilities(ChromiumUtilities):
|
|||||||
def clearSteamVirtualizedListCaches(self) -> None:
|
def clearSteamVirtualizedListCaches(self) -> None:
|
||||||
self.clearContentCache()
|
self.clearContentCache()
|
||||||
self._steamInferredButtonLabels = {}
|
self._steamInferredButtonLabels = {}
|
||||||
|
self._isUselessImage = {}
|
||||||
|
self._shouldFilter = {}
|
||||||
|
|
||||||
def isSteamVirtualizedList(self, obj) -> bool:
|
def isSteamVirtualizedList(self, obj) -> bool:
|
||||||
if not (obj and self.inDocumentContent(obj)):
|
if not (obj and self.inDocumentContent(obj)):
|
||||||
@@ -76,6 +78,21 @@ class Utilities(ChromiumUtilities):
|
|||||||
cache[obj] = inferredLabel
|
cache[obj] = inferredLabel
|
||||||
return inferredLabel
|
return inferredLabel
|
||||||
|
|
||||||
|
def isUselessImage(self, obj) -> bool:
|
||||||
|
if not (obj and self.inDocumentContent(obj)):
|
||||||
|
return super().isUselessImage(obj)
|
||||||
|
|
||||||
|
cached = self._isUselessImage.get(hash(obj))
|
||||||
|
if cached is not None:
|
||||||
|
return cached
|
||||||
|
|
||||||
|
rv = super().isUselessImage(obj)
|
||||||
|
if not rv:
|
||||||
|
rv = self._isRedundantSteamImage(obj)
|
||||||
|
|
||||||
|
self._isUselessImage[hash(obj)] = rv
|
||||||
|
return rv
|
||||||
|
|
||||||
def _shouldInferSteamButtonLabel(self, obj) -> bool:
|
def _shouldInferSteamButtonLabel(self, obj) -> bool:
|
||||||
if not (obj and self.inDocumentContent(obj)):
|
if not (obj and self.inDocumentContent(obj)):
|
||||||
return False
|
return False
|
||||||
@@ -113,6 +130,34 @@ class Utilities(ChromiumUtilities):
|
|||||||
return "Add Friend"
|
return "Add Friend"
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
def _isRedundantSteamImage(self, obj) -> bool:
|
||||||
|
if not AXUtilities.is_image_or_canvas(obj):
|
||||||
|
return False
|
||||||
|
|
||||||
|
if AXObject.get_name(obj) or AXObject.get_description(obj):
|
||||||
|
return False
|
||||||
|
|
||||||
|
if AXObject.get_child_count(obj):
|
||||||
|
return False
|
||||||
|
|
||||||
|
if AXUtilities.is_focusable(obj):
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not AXObject.has_action(obj, "click-ancestor"):
|
||||||
|
return False
|
||||||
|
|
||||||
|
roleDescription = self._normalizeSteamLabelText(AXObject.get_role_description(obj) or "")
|
||||||
|
if roleDescription and roleDescription.casefold() not in ["unlabeled image", "image"]:
|
||||||
|
return False
|
||||||
|
|
||||||
|
nearbyLabel = self._getSteamNearbyImageLabel(obj)
|
||||||
|
if not self._isUsefulSteamLabel(nearbyLabel):
|
||||||
|
return False
|
||||||
|
|
||||||
|
tokens = ["STEAM: Treating redundant image as useless:", obj, "(label:", nearbyLabel, ")"]
|
||||||
|
debug.printTokens(debug.LEVEL_INFO, tokens, True)
|
||||||
|
return True
|
||||||
|
|
||||||
def _getSteamNearbyButtonLabel(self, obj) -> str:
|
def _getSteamNearbyButtonLabel(self, obj) -> str:
|
||||||
parent = AXObject.get_parent(obj)
|
parent = AXObject.get_parent(obj)
|
||||||
if parent is None:
|
if parent is None:
|
||||||
@@ -132,6 +177,25 @@ class Utilities(ChromiumUtilities):
|
|||||||
|
|
||||||
return self._getSteamLabelFromChildren(grandParent, ignore=parent)
|
return self._getSteamLabelFromChildren(grandParent, ignore=parent)
|
||||||
|
|
||||||
|
def _getSteamNearbyImageLabel(self, obj) -> str:
|
||||||
|
parent = AXObject.get_parent(obj)
|
||||||
|
if parent is None:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
siblingLabel = self._getSteamLabelFromChildren(parent, ignore=obj)
|
||||||
|
if siblingLabel:
|
||||||
|
return siblingLabel
|
||||||
|
|
||||||
|
parentLabel = self._getSteamReadableText(parent)
|
||||||
|
if self._isUsefulSteamLabel(parentLabel):
|
||||||
|
return parentLabel
|
||||||
|
|
||||||
|
grandParent = AXObject.get_parent(parent)
|
||||||
|
if grandParent is None:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
return self._getSteamLabelFromChildren(grandParent, ignore=parent)
|
||||||
|
|
||||||
def _getSteamLabelFromChildren(self, obj, ignore=None) -> str:
|
def _getSteamLabelFromChildren(self, obj, ignore=None) -> str:
|
||||||
for child in AXObject.iter_children(obj):
|
for child in AXObject.iter_children(obj):
|
||||||
if child == ignore:
|
if child == ignore:
|
||||||
|
|||||||
@@ -267,5 +267,90 @@ class SteamLabelRecoveryTests(unittest.TestCase):
|
|||||||
self.assertEqual(utilities.displayedLabel(button), "Add Friend")
|
self.assertEqual(utilities.displayedLabel(button), "Add Friend")
|
||||||
|
|
||||||
|
|
||||||
|
class SteamRedundantImageTests(unittest.TestCase):
|
||||||
|
def test_is_useless_image_treats_unlabeled_click_ancestor_image_with_nearby_text_as_useless(self):
|
||||||
|
testScript = mock.Mock(generatorCache={})
|
||||||
|
utilities = steam_script_utilities.Utilities(testScript)
|
||||||
|
image = object()
|
||||||
|
parent = object()
|
||||||
|
entry = object()
|
||||||
|
|
||||||
|
utilities.inDocumentContent = mock.Mock(return_value=True)
|
||||||
|
|
||||||
|
def get_parent(obj):
|
||||||
|
if obj in (image, entry):
|
||||||
|
return parent
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_name(obj):
|
||||||
|
if obj is entry:
|
||||||
|
return "Search for games or profiles..."
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def get_child_count(obj):
|
||||||
|
if obj is parent:
|
||||||
|
return 2
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def has_action(obj, actionName):
|
||||||
|
return obj is image and actionName == "click-ancestor"
|
||||||
|
|
||||||
|
def iter_children(obj, pred=None):
|
||||||
|
children = [image, entry] if obj is parent else []
|
||||||
|
if pred is not None:
|
||||||
|
children = [child for child in children if pred(child)]
|
||||||
|
return iter(children)
|
||||||
|
|
||||||
|
with (
|
||||||
|
mock.patch.object(steam_script_utilities.ChromiumUtilities, "isUselessImage", return_value=False),
|
||||||
|
mock.patch.object(steam_script_utilities.AXObject, "get_parent", side_effect=get_parent),
|
||||||
|
mock.patch.object(steam_script_utilities.AXObject, "get_name", side_effect=get_name),
|
||||||
|
mock.patch.object(steam_script_utilities.AXObject, "get_description", return_value=""),
|
||||||
|
mock.patch.object(steam_script_utilities.AXObject, "get_child_count", side_effect=get_child_count),
|
||||||
|
mock.patch.object(steam_script_utilities.AXObject, "has_action", side_effect=has_action),
|
||||||
|
mock.patch.object(steam_script_utilities.AXObject, "iter_children", side_effect=iter_children),
|
||||||
|
mock.patch.object(steam_script_utilities.AXObject, "supports_text", return_value=False),
|
||||||
|
mock.patch.object(
|
||||||
|
steam_script_utilities.AXObject,
|
||||||
|
"get_role_description",
|
||||||
|
side_effect=lambda obj: "Unlabeled image" if obj is image else "",
|
||||||
|
),
|
||||||
|
mock.patch.object(
|
||||||
|
steam_script_utilities.AXUtilities,
|
||||||
|
"is_image_or_canvas",
|
||||||
|
side_effect=lambda obj: obj is image,
|
||||||
|
),
|
||||||
|
mock.patch.object(steam_script_utilities.AXUtilities, "is_focusable", return_value=False),
|
||||||
|
mock.patch.object(steam_script_utilities.AXUtilities, "is_button", return_value=False),
|
||||||
|
mock.patch.object(steam_script_utilities.AXUtilities, "is_push_button", return_value=False),
|
||||||
|
):
|
||||||
|
self.assertTrue(utilities.isUselessImage(image))
|
||||||
|
|
||||||
|
def test_is_useless_image_defers_to_generic_logic_without_nearby_text(self):
|
||||||
|
testScript = mock.Mock(generatorCache={})
|
||||||
|
utilities = steam_script_utilities.Utilities(testScript)
|
||||||
|
image = object()
|
||||||
|
|
||||||
|
utilities.inDocumentContent = mock.Mock(return_value=True)
|
||||||
|
|
||||||
|
with (
|
||||||
|
mock.patch.object(steam_script_utilities.ChromiumUtilities, "isUselessImage", return_value=False),
|
||||||
|
mock.patch.object(steam_script_utilities.AXObject, "get_parent", return_value=None),
|
||||||
|
mock.patch.object(steam_script_utilities.AXObject, "get_name", return_value=""),
|
||||||
|
mock.patch.object(steam_script_utilities.AXObject, "get_description", return_value=""),
|
||||||
|
mock.patch.object(steam_script_utilities.AXObject, "get_child_count", return_value=0),
|
||||||
|
mock.patch.object(steam_script_utilities.AXObject, "has_action", return_value=True),
|
||||||
|
mock.patch.object(steam_script_utilities.AXObject, "supports_text", return_value=False),
|
||||||
|
mock.patch.object(steam_script_utilities.AXObject, "get_role_description", return_value=""),
|
||||||
|
mock.patch.object(
|
||||||
|
steam_script_utilities.AXUtilities,
|
||||||
|
"is_image_or_canvas",
|
||||||
|
side_effect=lambda obj: obj is image,
|
||||||
|
),
|
||||||
|
mock.patch.object(steam_script_utilities.AXUtilities, "is_focusable", return_value=False),
|
||||||
|
):
|
||||||
|
self.assertFalse(utilities.isUselessImage(image))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Reference in New Issue
Block a user