Source code for poco.freezeui.hierarchy

# coding=utf-8

from poco.sdk.AbstractDumper import AbstractDumper
from poco.sdk.AbstractNode import AbstractNode
from poco.sdk.Attributor import Attributor
from poco.sdk.Selector import Selector
from poco.sdk.exceptions import UnableToSetAttributeException
from poco.sdk.interfaces.hierarchy import HierarchyInterface


__all__ = ['FrozenUIDumper', 'FrozenUIHierarchy']


[docs]class FrozenUIDumper(AbstractDumper): """ Partially implementation of IDumper. This is only a helper that helps to make dumper work with local nodes just like with remote nodes. The local nodes is an implementation of :py:class:`AbstractNode <poco.sdk.AbstractNode>` locally with fixed hierarchy data in arbitrary data type. In a word, this class is not going to crawl hierarchy from target app, but to perform like a ordinary dumper. """
[docs] def dumpHierarchy(self, onlyVisibleNode=True): raise NotImplementedError
[docs] def getRoot(self): """ Dump a hierarchy immediately from target runtime and store into a Node (subclass of :py:class:`AbstractNode <poco.sdk.AbstractNode>`) object. Returns: :py:class:`inherit from AbstractNode <Node>`: Each time a new node instance is created by latest hierarchy data. """ root = Node(self.dumpHierarchy()) self._linkParent(root) return root
def _linkParent(self, root): parent = root.getChildren() if parent: for child in parent: child.setParent(root) self._linkParent(child)
[docs]class FrozenUIHierarchy(HierarchyInterface): """ Locally implementation of hierarchy interface with a given dumper and all other behaviours by default. As all information can only be retrieve from a fixed UI hierarchy data created by dumper and all UI elements are immutable, this class is called frozen hierarchy. With the help of this class, only very few of the methods are required to implement. See :py:class:`AbstractNode <poco.sdk.AbstractNode>` or poco-sdk integration guide to get more details about this. This class makes it much easier to integrate poco-sdk and optimizes performance in some situations, but it is not sensitive enough to the changes of UI hierarchy in the app. For example, you should call ``select`` explicitly to re-crawl a new UI hierarchy when some UI elements changed on screen. Otherwise you are using attributes that are out of date. """ def __init__(self, dumper, attributor=None): super(FrozenUIHierarchy, self).__init__() self.dumper = dumper self.selector = Selector(self.dumper) self.attributor = attributor or Attributor()
[docs] def dump(self): return self.dumper.dumpHierarchy()
[docs] def getAttr(self, nodes, name): """ get node attribute """ return self.attributor.getAttr(nodes, name)
[docs] def setAttr(self, nodes, name, value): """ set node attribute """ return self.attributor.setAttr(nodes, name, value)
[docs] def select(self, query, multiple=False): """ select nodes by query """ return self.selector.select(query, multiple)
class Node(AbstractNode): def __init__(self, node): super(Node, self).__init__() self.node = node def setParent(self, p): self.node['__parent__'] = p def getParent(self): return self.node.get('__parent__') def getChildren(self): for child in self.node.get('children') or []: yield Node(child) def getAttr(self, attrName): return self.node['payload'].get(attrName) def setAttr(self, attrName, val): # cannot set any attributes on local nodes raise UnableToSetAttributeException(attrName, self.node) def getAvailableAttributeNames(self): return self.node['payload'].keys()