Best Python code snippet using ATX
android_layout.py
Source:android_layout.py  
...53        for n in self.nodes:54            if n.enabled and n.bounds.is_inside(x, y):55                return n5657    def find_clickable_node(self, x, y):58        for n in self.nodes:59            if n.enabled and n.clickable and n.bounds.is_inside(x, y):60                return n6162    def find_scrollable_node(self, x, y):63        for n in self.nodes:64            if n.enabled and n.scrollable and n.bounds.is_inside(x, y):65                return n6667    def display(self, showall=False):68        if not self.tree or not self.nodes:69            return70        b = self.tree.bounds71        l, t = b.left, b.top72        w, h = b.right - b.left, b.bottom - b.top73        img = np.zeros((h, w, 3), np.uint8)7475        i = 076        for n in self.nodes[::-1]:77            if not showall and not n.clickable and not n.scrollable: continue78            b = n.bounds79            cv2.rectangle(img, (b.left-l, b.top-t), (b.right-l, b.bottom-t), (83, min(255, i*5), 18), 2)80            i += 181        return img8283    def _parse_xml_node(self, node, depth=0):84        __alias = {85            'class': 'className',86            'package': 'packageName',87            'resource-id': 'resourceId',88            'content-desc': 'description',89            'long-clickable': 'longClickable',90        }9192        parsers = {93            'index': int,94            'text': convstr,95            'resourceId': convstr,96            'className': convstr,97            'packageName': convstr,98            'description': convstr,99            'bounds': parse_bounds,100            'checkable': str2bool,101            'checked': str2bool,102            'clickable': str2bool,103            'enabled': str2bool,104            'focusable': str2bool,105            'focused': str2bool,106            'scrollable': str2bool,107            'longClickable': str2bool,108            'password': str2bool,109            'selected': str2bool,110        }111        ks = {}112        for key, value in node.attributes.items():113            key = __alias.get(key, key)114            f = parsers.get(key)115            if value is None:116                ks[key] = None117            elif f:118                ks[key] = f(value)119        for key in parsers.keys():120            ks[key] = ks.get(key)121        ks['children'] = []122        ks['depth'] = depth123        ks['xml'] = node124125        return UINode(**ks)126127    def parse_xmldata(self, xmldata):128        dom = xml.dom.minidom.parseString(xmldata)129        root = dom.documentElement130        self.rotation = int(root.getAttribute('rotation'))131132        idx = [0]133        def walk(node, ui_nodes, depth=0):134            while len(node.childNodes) == 1 and node.getAttribute('bounds') == '':135                node = node.childNodes[0]136                depth += 1137            uinode = self._parse_xml_node(node, depth)138            uinode.iterindex = idx[0]139            idx[0] += 1140            for n in node.childNodes:141                sub = walk(n, ui_nodes, depth+1)142                if sub is not None:143                    uinode.children.append(sub)144                    sub.parent = uinode145            ui_nodes.append(uinode)146            return uinode147148        self.nodes = []149        self.tree = walk(root, self.nodes)150        self.nodes.sort(key=lambda x: x.bounds.area)151        self.node_index = [n.iterindex for n in self.nodes]152153    def find_selector(self, node):154        '''find condition for locate a node, return (postion_node, condition, order)'''155        return self.__find_selector_by_structure(node)156        # return self.__find_selector_by_attrbutes(node)157        # return self.__find_selector_by_score(node)158159    def _filter_nodes(self, cond, nodes=None):160        if nodes is None:161            nodes = self.nodes162        res = []163        for n in nodes:164            match = True165            for k, v in cond.iteritems():166                attr = getattr(n, k)167                if isinstance(v, re._pattern_type) and \168                    isinstance(attr, basestring) and v.match(attr) is None:169                    match = False170                    break171                elif attr != v:172                    match = False173                    break174            if match:175                res.append(n)176        return res177178    def get_index_node(self, idx):179        '''get node with iterindex `idx`'''180        idx = self.node_index.index(idx)181        return self.nodes[idx]182183    def get_node_selector(self, n, sub=False):184        d = {}185        nodes = self.nodes186187        # try text, text in subnode cannot be all numbers188        if n.text and txt_pat.match(n.text) and not (sub and n.text.isdigit()):189            d['text'] = n.text190            nodes = self._filter_nodes(d, nodes)191            if len(nodes) == 1:192                return d, None193194        # try className, which is never blank195        d['className'] = n.className196        nodes = self._filter_nodes(d, nodes)197        if len(nodes) == 1:198            return d, None199200        # try description, like text201        if n.description and txt_pat.match(n.description) and not (sub and n.description.isdigit()):202            d['description'] = n.description203            nodes = self._filter_nodes(d, nodes)204            if len(nodes) == 1:205                return d, None206207        ## try resourceId, but on some phone the resourceId may not be available208        if n.resourceId:209            d['resourceId'] = n.resourceId210            nodes = self._filter_nodes(d, nodes)211            if len(nodes) == 1:212                return d, None213214        # return order in selected nodes under condition d.215        return d, nodes.index(n)216217    def __find_selector_by_structure(self, node):218        # try itself219        d, order = self.get_node_selector(node)220        if order is None:221            return node, d, None222223        # try its non-clickable decendants224        decendants = []225        def walk(n):226            for c in n.children:227                if c.clickable: continue228                decendants.append(c)229                walk(c)230        walk(node)231232        choices = []233        for n in decendants:234            sd, sorder = self.get_node_selector(n, True)235            choices.append((sorder or 0, -n.bounds.area, sorder, sd, n)) # add area to sort236        choices.sort()237238        if choices:239            return choices[0][-1], choices[0][-2], choices[0][-3]240241        # TODO242        # # try if its non-clickable parent243        # def is_decendant(n1, n2):244        #     '''check if n1 is decandant of n2'''245        #     for c in n2.children:246        #         if c == n1 or is_decendant(n1, c):247        #             return True248        #     return False249        #250        # p = node.parent251        # while p and not p.clickable:252        #     pd, porder = self.get_node_selector(p)253        #     if porder is None:254        #         print 'parent node', p.className255        #         for i in range(len(p.children)):256        #             c = p.children[i]257        #             if c == node or is_decendant(node, c):258        #                 print 'child', i, c==node, c.className, c.resourceId, c.text259        #         return pd, porder260        #     p = p.parent261262        return node, d, order263264    def __find_selector_by_attrbutes(self, node):265        # avoid repeat over same attr266267        def attrs(n, name):268            '''get node attribute values'''269            res = set()270            v = getattr(n, name)271            if v: res.add(v)272            for subn in n.children:273                if subn.clickable: continue274                res.update(attrs(subn, name))275            return res276277        def is_decendant(n1, n2):278            '''check if n1 is decandant of n2'''279            for c in n2.children:280                if c == n1 or is_decendant(n1, c):281                    return True282            return False283284        candidates = {}285        def try_attr(top, attr, ignore_filter=None):286            for value in attrs(top, attr):287                if ignore_filter and ignore_filter(value):288                    continue289                tmp = self._filter_nodes({attr:value})290                if len(tmp) == 1:291                    return tmp[0], {attr:value}292                # save candidates293                for n in tmp:294                    if n == top or is_decendant(n, top):295                        candidates.setdefault(n, {})[attr] = len(tmp)296            return None, None297298        # try className299        n, cond = try_attr(node, 'className')300        if n:301            return n, cond, None302303        # try anything with a resourceId304        n, cond = try_attr(node, 'resourceId')305        if n:306            return n, cond, None307308        # try anything with a text309        n, cond = try_attr(node, 'text', lambda s: txt_pat.match(s) is None)310        if n:311            return n, cond, None312313        # try anything with a description314        n, cond = try_attr(node, 'description', lambda s: txt_pat.match(s) is None)315        if n:316            return n, cond, None317318        print 'candidates:', candidates.values()319320        # try combinations321322        return node, self.get_node_selector(node)323324    def __find_selector_by_score(self, node):325        # TODO326        # find candidate selectors and give a score327        candidates = {}328329        def walk(n):330            info = {'depth': n.depth-node.depth}331            d, o = self.get_node_selector(n)332            info['selector'] = d333            info['order'] = o334            info['score'] = 0335            candidates[n] = info336            for c in n.children:337                if c.clickable: continue338                walk(c)339        walk(node)340341        # get top score selector342343if __name__ == '__main__':344    # import subprocess345    # subprocess.check_call('adb shell uiautomator dump /data/local/tmp/window_dump.xml')346    # subprocess.check_call('adb pull /data/local/tmp/window_dump.xml')347    # xmldata = open('window_dump.xml').read()348349    import time350    import traceback351    import locale352353    encoding = locale.getpreferredencoding()354355    from uiautomator import device356    device.dump()357358    layout = AndroidLayout()359    layout.highlight = np.zeros((1, 1, 3), np.uint8)360361    cv2.namedWindow("layout")362363    def on_mouse(event, x, y, flags, param):364        layout, downpos, ismove = param365366        # record downpos367        if event == cv2.EVENT_LBUTTONDOWN:368            print 'click at', x*2, y*2 # picture is half-sized.369            param[1] = (x, y)370            param[2] = False371            return372        # check if is moving373        if event == cv2.EVENT_MOUSEMOVE:374            if ismove: return375            if downpos is None:376                param[2] = False377                return378            _x, _y = downpos379            if (_x-x)**2 + (_y-y)**2 > 64:380                param[2] = True381            return382        if event != cv2.EVENT_LBUTTONUP:383            return384385        # update layout.highlight386        b = layout.tree.bounds387        l, t = b.left, b.top388        w, h = b.right - b.left, b.bottom - b.top389        highlight = np.zeros((h, w, 3), np.uint8)390391        if downpos and ismove: # drag392            node = layout.find_scrollable_node(x*2+l, y*2+t)393            print 'scroll to', x*2, y*2394            if node:395                b = node.bounds396                print 'scrollable node', b, node.index, node.className,397                print 'resource_id:', node.resourceId,398                print 'text:', node.text.encode(encoding, 'ignore'),399                print 'desc:', node.description.encode(encoding, 'ignore')400                cv2.rectangle(highlight, (b.left-l, b.top-t), (b.right-l, b.bottom-t), (0,255,255), 4)401        else:402            node = layout.find_clickable_node(x*2+l, y*2+t)403            if node:404                b = node.bounds405                print 'clickable node', b, node.index, node.className,406                print 'resource_id:', node.resourceId,407                print 'text:', node.text.encode(encoding, 'ignore'),408                print 'desc:', node.description.encode(encoding, 'ignore')409                print device(className=node.className, index=node.index).info410                cv2.rectangle(highlight, (b.left-l, b.top-t), (b.right-l, b.bottom-t), (0,0,255), 4)411                cond, order = layout.find_selector(node)412                if cond:413                    print 'selector', cond, order414                    subnode = layout._filter_nodes(cond)[order or 0]415                    b = subnode.bounds416                    cv2.rectangle(highlight, (b.left-l, b.top-t), (b.right-l, b.bottom-t), (0,180,255), 4)
...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
