Best Python code snippet using fMBT_python
fmbtwindows.py
Source:fmbtwindows.py  
...306                  using this parameter limits the properties collection.307                  By default (0), all sub-children's properties values will be collected.308        """309        self._checkUIautomation()310        data = self._view._device._conn.recvViewItemItems(311            self.id(), propertyName, separator, filterSubChildClassName, maxSubChildren)312        return data[0]313    def collapse(self):314        """315        Collapses a widget which supports this kind of operation, like a TreeView.316        """317        self._checkUIautomation()318        self._view._device._conn.sendCollapse(self.id())319    def expand(self):320        """321        Expands a widget which supports this kind of operation, like a TreeView.322        """323        self._checkUIautomation()324        self._view._device._conn.sendExpand(self.id())325    def containerItems(self, propertyName, separator="\n", filterSubChildClassName="", maxSubChildren="0", scroll=False):326        """327        Returns a list of the given property from all widget's direct328        children.329        Like the items() method, but all children, even the currently330        not displayed ones, will be reported.331        If a child isn't displayed when it's evaluated, it will332        have no sub-children, so no information about them will be333        reported. To fully render/display a child, the new scroll334        parameter should be used, so the item display area will be335        scrolled until the child is finally rendered. After that, all336        information about its sub-children are available and will be337        retrieved.338        Parameters:339          propertyName, separator, filterSubChildClassName, maxSubChildren:340                  refer to ViewItem.items() documentation.341          scroll (bool, optional):342                  Allows children scrolling, to make them visible.343                  By default (false), no children scrolling is made.344        Note: If a widget has many children, scrolling all of them will be slow.345        """346        self._checkUIautomation()347        data = self._view._device._conn.recvViewItemContainerItems(348            self.id(), propertyName, separator, filterSubChildClassName, maxSubChildren, scroll)349        return data[0]350    def selectedItems(self, propertyName, separator="\n", filterSubChildClassName="", maxSubChildren="0", scroll=False):351        """352        Returns a list of the given property from all widget's direct353        children which are selected.354        Like containerItems(), but only selected children will be355        reported.356        """357        self._checkUIautomation()358        data = self._view._device._conn.recvViewItemSelectedItems(359            self.id(), propertyName, separator, filterSubChildClassName, maxSubChildren, scroll)360        return data[0]361    def longText(self, maxLength=65536):362        """363        Returns the text from widgets like a RichTextEdit or a Document,364        that normally don't allow to report the text using the usual text() method.365        Parameters:366          maxLength (integer, optional):367                  The maximum number of characters to be reported, to368                  limit the transferred data.  The default is 64K characters.369        """370        self._checkUIautomation()371        data = self._view._device._conn.recvViewItemText(self.id(), maxLength)372        return data[0].popitem()[1] if data else None373    def setValue(self, value):374        """375        Sets the value of a widget. For example the text for a TextBlock,376        or the text of a ComboBox.377        It doesn't work for more complex widgets like a RichTextEdit or a Document.378        Parameters:379          value (string):380                  The value to be set.381        """382        self._checkUIautomation()383        self._view._device._conn.recvViewItemSetValue(self.id(), value)384        self._properties['Value'] = str(value)385class View(object):386    def __init__(self, dumpFilename, itemTree, itemOnScreen=None, device=None, freeDumps=False):387        self._dumpFilename = dumpFilename388        self._itemTree = itemTree389        self._rootItem = None390        self._rootItems = []391        self._viewItems = {}392        self._device = device393        self._freeDumps = freeDumps394        if itemOnScreen == None:395            self._itemOnScreen = lambda item: True396        else:397            self._itemOnScreen = itemOnScreen398        if isinstance(itemTree, dict):399            # data from enumchildwindows:400            self._viewSource = "enumchildwindows"401            for itemId, winfoList in itemTree.iteritems():402                for winfo in winfoList:403                    itemId, parentId, className, text, bbox = winfo404                    self._viewItems[itemId] = ViewItem(405                        self, itemId, parentId, className, text, bbox, dumpFilename)406            self._rootItem = self._viewItems[self._itemTree["root"][0][0]]407            self._rootItems.append(self._rootItem)408        elif isinstance(itemTree, list):409            # data from uiautomation410            # list of dictionaries, each of which contains properties of an item411            self._viewSource = "uiautomation"412            for elt in itemTree:413                self._insertItem(elt)414            if not self._rootItem and not freeDumps:415                raise ValueError("no root item in view data")416    def _insertItem(self, elt):417        bboxString = elt.get("BoundingRectangle", "0;0;0;0")418        bboxSeparator = ";" if ";" in bboxString else ","419        try:420            bbox = [int(coord) for coord in bboxString.split(bboxSeparator)]421            bbox[2] = bbox[0] + bbox[2] # width to right422            bbox[3] = bbox[1] + bbox[3] # height to bottom423            bbox = tuple(bbox)424        except Exception, e:425            bbox = 0, 0, 0, 0426        text = elt.get("Value") or elt.get("Name", "")427        vi = ViewItem(428            self, int(elt["hash"]), int(elt["parent"]),429            elt.get("ClassName", ""),430            text,431            bbox,432            self._dumpFilename,433            elt)434        self._viewItems[int(elt["hash"])] = vi435        if not vi.parent():436            self._rootItem = vi437            self._rootItems.append(vi)438        return vi439    def _checkUIautomation(self):440        if not self._viewSource.startswith("uiautomation"):441            raise NotImplementedError(442                "This method works only for uiautomation at the moment")443    def cachedItem(self, id_):444        """445        Retrieves an automation element from the server cache, passing its id.446        If the item was already into the view, it's updated.447        """448        self._checkUIautomation()449        data = self._device._conn.recvViewCachedItem(id_)450        if data:451            return self._insertItem(data[0])452    def _intCoords(self, *args):453        # TODO: relative coordinates like (0.5, 0.9)454        return [int(c) for c in args[0]]455    def filename(self):456        return self._dumpFilename457    def rootItem(self):458        return self._rootItem459    def _dumpTree(self, rootItem, indentation=''):460        yield "%s|-- %s" % (indentation, rootItem.dump())461        indentation += '|   '462        for child in rootItem.children():463            for dump in self._dumpTree(child, indentation):464                yield dump465    def dumpTree(self, rootItem=None):466        """467        Returns item tree as a string468        """469        if rootItem:470            return "\n".join(self._dumpTree(rootItem))471        else:472            if self._rootItems:473                rootsDumps = ("\n".join(self._dumpTree(rootItem)) for rootItem in self._rootItems)474            else:475                rootsDumps = ("\n".join(self._dumpTree(rootItem)) for rootItem in self._viewItems.itervalues())476            return "\n".join(rootsDumps)477    def __str__(self):478        return "View(%r, %s items)" % (self._dumpFilename, len(self._viewItems))479    def findItems(self, comparator, count=-1, searchRootItem=None, searchItems=None, onScreen=False):480        foundItems = []481        if count == 0: return foundItems482        if searchRootItem != None:483            if comparator(searchRootItem) and (484                    not onScreen or (self._itemOnScreen(searchRootItem))):485                foundItems.append(searchRootItem)486            for c in searchRootItem.children():487                foundItems.extend(self.findItems(comparator, count=count-len(foundItems), searchRootItem=c, onScreen=onScreen))488        else:489            if searchItems:490                domain = iter(searchItems)491            else:492                domain = self._viewItems.itervalues493            for i in domain():494                if comparator(i) and (not onScreen or (self._itemOnScreen(i))):495                    foundItems.append(i)496                    if count > 0 and len(foundItems) >= count:497                        break498        return foundItems499    def findItemsByText(self, text, partial=False, count=-1, searchRootItem=None, searchItems=None, onScreen=False):500        if partial:501            c = lambda item: (text in item._text)502        else:503            c = lambda item: (text == item._text)504        return self.findItems(c, count=count, searchRootItem=searchRootItem, searchItems=searchItems, onScreen=onScreen)505    def findItemsByClass(self, className, partial=False, count=-1, searchRootItem=None, searchItems=None, onScreen=False):506        if partial:507            c = lambda item: (className in item._className)508        else:509            c = lambda item: (className == item._className)510        return self.findItems(c, count=count, searchRootItem=searchRootItem, searchItems=searchItems, onScreen=onScreen)511    def findItemsById(self, itemId, count=-1, searchRootItem=None, searchItems=None, onScreen=False):512        c = lambda item: (itemId == item._itemId or itemId == item.properties().get("AutomationId", None))513        return self.findItems(c, count=count, searchRootItem=searchRootItem, searchItems=searchItems, onScreen=onScreen)514    def findItemsByProperties(self, properties, count=-1, searchRootItem=None, searchItems=None, onScreen=False):515        """516        Returns ViewItems where every property matches given properties517        Parameters:518          properties (dictionary):519                  names and required values of properties520        Example:521          view.findItemsByProperties({"Value": "HELLO", "Name": "File name:"})522        See also:523          viewitem.dumpProperties()524        Notes:525          - requires uiautomation (refreshView(viewSource="uiautomation"))526          - all names and values are strings527        """528        c = lambda item: 0 == len([key for key in properties529                                   if properties[key] != item.properties().get(key, None)])530        return self.findItems(c, count=count, searchRootItem=searchRootItem, searchItems=searchItems, onScreen=onScreen)531    def findItemsByPos(self, pos, count=-1, searchRootItem=None, searchItems=None, onScreen=False):532        """533        Returns list of ViewItems whose bounding box contains the position.534        Parameters:535          pos (pair of floats (0.0..0.1) or integers (x, y)):536                  coordinates that fall in the bounding box of found items.537          other parameters: refer to findItems documentation.538        Items are listed in ascending order based on area. They may539        or may not be from the same branch in the widget hierarchy.540        """541        x, y = self._intCoords(pos)542        c = lambda item: (item.bbox()[0] <= x <= item.bbox()[2] and item.bbox()[1] <= y <= item.bbox()[3])543        items = self.findItems(c, count=count, searchRootItem=searchRootItem, searchItems=searchItems, onScreen=onScreen)544        # sort from smallest to greatest area545        area_items = [((i.bbox()[2] - i.bbox()[0]) * (i.bbox()[3] - i.bbox()[1]), i) for i in items]546        return [i for _, i in sorted(area_items)]547    def items(self):548        """549        Returns list of all items in the view550        """551        return fmbtgti.sortItems(self._viewItems.values(), "topleft")552    def save(self, fileOrDirName):553        """554        Save view dump to a file.555        """556        shutil.copy(self._dumpFilename, fileOrDirName)557class Device(fmbtgti.GUITestInterface):558    def __init__(self, connspec=None, password=None, screenshotSize=(None, None),559                 connect=True, **kwargs):560        """Connect to windows device under test.561        Parameters:562          connspec (string or None, optional):563                  specification for connecting to a pythonshare564                  server that will run fmbtwindows-agent. The format is565                  "[socket://][password@]<host>[:<port>][/namespace]".566                  The default is None: run the agent on host, do not567                  connect to a pythonshare server (works only on Windows).568          password (string or None, optional):569                  authenticate to pythonshare server with given570                  password. The default is None (no authentication).571          rotateScreenshot (integer, optional)572                  rotate new screenshots by rotateScreenshot degrees.573                  Example: rotateScreenshot=-90. The default is 0 (no574                  rotation).575          connect (boolean, optional):576                  Immediately establish connection to the device. The577                  default is True.578        To prepare a windows device for connection, launch there579        python pythonshare-server --password mysecretpwd580        When not on trusted network, consider ssh port forward, for581        instance.582        """583        fmbtgti.GUITestInterface.__init__(self, **kwargs)584        self._defaultViewSource = _g_viewSources[1]585        self._refreshViewDefaults = kwargs586        self._lastView = None587        self._lastViewStats = {}588        self._refreshViewRetryLimit = 1589        self._connspec = connspec590        self._password = password591        if connect:592            self.setConnection(WindowsConnection(593                self._connspec, self._password, self))594        else:595            self.setConnection(None)596    def closeWindow(self, window):597        """598        Send WM_CLOSE to window599        Parameters:600          window (window title (string) or handle (integer)):601                  window to which the command will be sent.602        Returns True on success, otherwise False.603        """604        return self.existingConnection().sendCloseWindow(window)605    def setCacheMode(self, mode="lastwindow"):606        """607        Sets the server policy for caching AutomationElements.608        Parameters:609          mode (string, optional. Default is "lastwindow"):610                  Defines the cache policy, and can be one of:611                      "none", "lastdump", "lastwindow", "all".612                  "none" disables caching.613                  "lastdump" caches only the last dump.614                  "lastwindow" caches all elements of a window.615                      If a new window is dumped, the cache is616                      cleared.617                  "all" caches all element of all windows.618        """619        if mode not in ("none", "lastdump", "lastwindow", "all"):620            raise FMBTWindowsError("Unknown cache mode: %s" % mode)621        return self.existingConnection().sendSetCacheMode(mode)622    def clearCache(self):623        """624        Clears the server AutomationElements cache.625        """626        return self.existingConnection().sendClearCache()627    def errorReporting(self):628        """629        Returns Windows error reporting (WER) settings in a dictionary630        See also: setErrorReporting()631                  MSDN WER Settings.632        """633        supported_settings = ["DisableArchive",634                              "Disabled",635                              "DisableQueue",636                              "DontShowUI",637                              "DontSendAdditionalData",638                              "LoggingDisabled",639                              "MaxArchiveCount",640                              "MaxQueueCount"]641        settings = {}642        for setting in supported_settings:643            settings[setting] = self.getRegistry(644                r"HKEY_CURRENT_USER\Software\Microsoft\Windows\Windows Error Reporting",645                setting)[0]646        return settings647    def existingView(self):648        if self._lastView:649            return self._lastView650        else:651            raise FMBTWindowsError("view is not available. Missing refreshView()?")652    def fileProperties(self, filepath):653        """654        Returns file properties as a dictionary.655        Parameters:656          filepath (string):657                  full path to the file.658        """659        escapedFilename = filepath.replace('/', '\\').replace('\\', r'\\\\')660        return self.existingConnection().evalPython(661            '''wmicGet("datafile",'''662            '''componentArgs=("where", "name='%s'"))''' %663            escapedFilename)664    def getFile(self, remoteFilename, localFilename=None, compress=False):665        """666        Fetch file from the device.667        Parameters:668          remoteFilename (string):669                  file to be fetched on device670          localFilename (optional, string or None):671                  file to be saved to local filesystem. If None,672                  return contents of the file without saving them.673          compress (optional, boolean or integer):674                  if True, file contents will be compressed for the transfer.675                  Integer (0-9) defines compression level. The default is676                  False: transfer without compression.677        """678        return self._conn.recvFile(remoteFilename, localFilename, compress)679    def getMatchingPaths(self, pathnamePattern):680        """681        Returns list of paths matching pathnamePattern on the device.682        Parameters:683          pathnamePattern (string):684                  Pattern for matching files and directories on the device.685        Example:686          getMatchingPaths("c:/windows/*.ini")687        Implementation runs glob.glob(pathnamePattern) on remote device.688        """689        return self._conn.recvMatchingPaths(pathnamePattern)690    def getClipboard(self):691        """692        Returns clipboard contents in text format.693        See also: setClipboard()694        """695        return self.existingConnection().evalPython("getClipboardText()")696    def itemOnScreen(self, guiItem, relation="touch", topWindowBbox=None):697        """698        Returns True if bbox of guiItem is non-empty and on the screen699        Parameters:700          relation (string, optional):701                  One of the following:702                  - "overlap": item intersects the screen and the window.703                  - "touch": mid point (the default touch point) of the item704                             is within the screen and the window.705                  - "within": the screen and the window includes the item.706                  The default is "touch".707        """708        if guiItem.properties().get("IsOffscreen", False) == "True":709            return False710        if relation == "touch":711            x1, y1, x2, y2 = guiItem.bbox()712            if x1 == x2 or y1 == y2:713                return False # a dimension is missing => empty item714            itemBox = (guiItem.coords()[0], guiItem.coords()[1],715                       guiItem.coords()[0] + 1, guiItem.coords()[1] + 1)716            partial = True717        elif relation == "overlap":718            itemBox = guiItem.bbox()719            partial = True720        elif relation == "within":721            itemBox = guiItem.bbox()722            partial = False723        else:724            raise ValueError('invalid itemOnScreen relation: "%s"' % (relation,))725        maxX, maxY = self.screenSize()726        if topWindowBbox == None:727            try:728                topWindowBbox = self.topWindowProperties()['bbox']729            except TypeError:730                topWindowBbox = (0, 0, maxX, maxY)731        return (fmbtgti._boxOnRegion(itemBox, (0, 0, maxX, maxY), partial=partial) and732                fmbtgti._boxOnRegion(itemBox, topWindowBbox, partial=partial))733    def kill(self, pid):734        """735        Terminate process736        Parameters:737          pid (integer):738                  ID of the process to be terminated.739        """740        try:741            return self.existingConnection().evalPython(742                "kill(%s)" % (repr(pid),))743        except:744            return False745    def keyNames(self):746        """747        Returns list of key names recognized by pressKey748        """749        return sorted(_g_keyNames)750    def osProperties(self):751        """752        Returns OS properties as a dictionary753        """754        return self.existingConnection().evalPython(755            "wmicGet('os')")756    def pinch(self, (x, y), startDistance, endDistance,757              finger1Dir=90, finger2Dir=270, movePoints=20,758              duration=0.75):759        """760        Pinch (open or close) on coordinates (x, y).761        Parameters:762          x, y (integer):763                  the central point of the gesture. Values in range764                  [0.0, 1.0] are scaled to full screen width and765                  height.766          startDistance, endDistance (float):767                  distance from both finger tips to the central point768                  of the gesture, at the start and at the end of the769                  gesture. Values in range [0.0, 1.0] are scaled up to770                  the distance from the coordinates to the edge of the771                  screen. Both finger tips will reach an edge if772                  distance is 1.0.773          finger1Dir, finger2Dir (integer, optional):774                  directions for finger tip movements, in range [0,775                  360]. 0 is to the east, 90 to the north, etc. The776                  defaults are 90 and 270.777          movePoints (integer, optional):778                  number of points to which finger tips are moved779                  after laying them to the initial positions. The780                  default is 20.781          duration (float, optional):782                  duration of the gesture in seconds, the default is 0.75.783        """784        screenWidth, screenHeight = self.screenSize()785        screenDiagonal = math.sqrt(screenWidth**2 + screenHeight**2)786        if x == None: x = 0.5787        if y == None: y = 0.5788        x, y = self.intCoords((x, y))789        if type(startDistance) == float and 0.0 <= startDistance <= 1.0:790            startDistanceInPixels = (791                startDistance *792                min(fmbtgti._edgeDistanceInDirection((x, y), self.screenSize(), finger1Dir),793                    fmbtgti._edgeDistanceInDirection((x, y), self.screenSize(), finger2Dir)))794        else:795            startDistanceInPixels = int(startDistance)796        if type(endDistance) == float and 0.0 <= endDistance <= 1.0:797            endDistanceInPixels = (798                endDistance *799                min(fmbtgti._edgeDistanceInDirection((x, y), self.screenSize(), finger1Dir),800                    fmbtgti._edgeDistanceInDirection((x, y), self.screenSize(), finger2Dir)))801        else:802            endDistanceInPixels = int(endDistance)803        finger1startX = int(x + math.cos(math.radians(finger1Dir)) * startDistanceInPixels)804        finger1startY = int(y - math.sin(math.radians(finger1Dir)) * startDistanceInPixels)805        finger1endX = int(x + math.cos(math.radians(finger1Dir)) * endDistanceInPixels)806        finger1endY = int(y - math.sin(math.radians(finger1Dir)) * endDistanceInPixels)807        finger2startX = int(x + math.cos(math.radians(finger2Dir)) * startDistanceInPixels)808        finger2startY = int(y - math.sin(math.radians(finger2Dir)) * startDistanceInPixels)809        finger2endX = int(x + math.cos(math.radians(finger2Dir)) * endDistanceInPixels)810        finger2endY = int(y - math.sin(math.radians(finger2Dir)) * endDistanceInPixels)811        self.existingConnection().sendPinch(812            (finger1startX, finger1startY), (finger1endX, finger1endY),813            (finger2startX, finger2startY), (finger2endX, finger2endY),814            movePoints, duration)815        return True816    def pinchOpen(self, (x, y) = (0.5, 0.5), startDistance=0.1, endDistance=0.5, **pinchKwArgs):817        """818        Make the open pinch gesture.819        Parameters:820          x, y (integer, optional):821                  the central point of the gesture, the default is in822                  the middle of the screen.823          startDistance, endDistance (float, optional):824                  refer to pinch documentation. The default is 0.1 and825                  0.5.826          for the rest of the parameters, refer to pinch documentation.827        """828        return self.pinch((x, y), startDistance, endDistance, **pinchKwArgs)829    def pinchClose(self, (x, y) = (0.5, 0.5), startDistance=0.5, endDistance=0.1, **pinchKwArgs):830        """831        Make the close pinch gesture.832        Parameters:833          x, y (integer, optional):834                  the central point of the gesture, the default is in835                  the middle of the screen.836          startDistance, endDistance (float, optional):837                  refer to pinch documentation. The default is 0.5 and838                  0.1.839          rest of the parameters: refer to pinch documentation.840        """841        return self.pinch((x, y), startDistance, endDistance, **pinchKwArgs)842    def putFile(self, localFilename, remoteFilepath, data=None):843        """844        Send local file to the device.845        Parameters:846          localFilename (string):847                  file to be sent.848          remoteFilepath (string):849                  destination on the device. If destination is an850                  existing directory, the file will be saved to the851                  directory with its original local name. Otherwise the file852                  will be saved with remoteFilepath as new name.853          data (string, optional):854                  data to be stored to remoteFilepath. The default is855                  the data in the local file.856        Example: Copy local /tmp/file.txt to c:/temp857          putFile("/tmp/file.txt", "c:/temp/")858        Example: Create new remote file859          putFile(None, "c:/temp/file.txt", "remote file contents")860        """861        return self._conn.sendFile(localFilename, remoteFilepath, data)862    def rmFile(self, remoteFilepath):863        """864        Remove a file from the device.865        Parameters:866          remoteFilepath (string):867                  file to be removed from the device.868        """869        return self.existingConnection().evalPython(870            "os.remove(%s)" % (repr(remoteFilepath),))871    def reconnect(self, connspec=None, password=None):872        """873        Close connections to the device and reconnect.874        Parameters:875          connspec (string, optional):876                  Specification for new connection. The default is current877                  connspec.878          password (string, optional):879                  Password for new connection. The default is current password.880        """881        self.setConnection(None)882        import gc883        gc.collect()884        if connspec != None:885            self._connspec = connspec886        if password != None:887            self._password = password888        if self._connspec == None:889            _adapterLog("reconnect failed: missing connspec")890            return False891        try:892            self.setConnection(WindowsConnection(893                self._connspec, self._password, self))894            return True895        except Exception, e:896            _adapterLog("reconnect failed: %s" % (e,))897            return False898    def getDumpFilename(self, suffix):899        if self.screenshotDir() == None:900            self.setScreenshotDir(self._screenshotDirDefault)901        if self.screenshotSubdir() == None:902            self.setScreenshotSubdir(self._screenshotSubdirDefault)903        return self._newScreenshotFilepath()[:-3] + suffix904    def refreshView(self, window=None, forcedView=None, viewSource=None,905                    items=None, properties=None, area=None,906                    filterType="none", filterCondition="",907                    dumpChildClass="", dumpChildName="", doNotDump=False):908        """909        (Re)reads widgets on the top window and updates the latest view.910        Parameters:911          window (integer (hWnd) or string (title), optional):912                  read widgets from given window instead of the top window.913          forcedView (View or filename, optional):914                  use given View object or view file instead of reading the915                  items from the device.916          viewSource (string, optional):917                  source of UI information. Supported sources are:918                  "uiautomation" the UIAutomation framework.919                  "enumchildwindows" less data920                  but does not require UIAutomation.921                  The default is "uiautomation".922                  You can define TreeWalker used by "uiautomation" by defining923                  viewSource as "uiautomation/raw", "uiautomation/control" or924                  "uiautomation/content".925                  See also setViewSource().926          items (list of view items, optional):927                  update only contents of these items in the view.928                  Works only for "uiautomation" view source.929          properties (list of property names, optional):930                  read only given properties from items, the default931                  is to read all available properties.932                  Works only for "uiautomation" view source.933                  See also setViewSource().934          area ((left, top, right, bottom), optional):935                  refresh only items that intersect the area.936                  The default is None: locations do not affect refreshed937                  items.938          filterType (string, optional):939                  specify how the widgets should be filtered.940                  Supported values are:941                  "none", which is the default, which means that all widgets942                  will be retrieved.943                  "first": only the first element which satisfy the condition944                  defined by the filterCondition parameter is returned.945                  "all": all elements which satisfy the condition defined by946                  the filterCondition parameter are returned.947                  "first" and "all" allow to specify an additional "+children"948                  qualifier, which returns also all element's children.949                  So, passing "first+children" as filterType, then the element950                  all its children are returned, if the element (and only it)951                  satisfy filterCondition.952                  It's import to underline that the conditions defined by the953                  items, properties, and area, parameters are still all954                  applied on top of filterType and filterCondition.955          filterCondition (string, optional):956                  specify the condition for filtering the widgets.957                  It only works if filterType is not "none".958                  Currently only a basic filter conditions are supported, that959                  allows to specify a property name, the == operator, and960                  a double-quoted string with the value to be compared.961                  Filter conditions can be chained together using the "and"962                  operator; this allows more fine-grained filtering.963                  For example:964                      'ClassName == "ToolBar" and Name == "Explorer"'965                  matches all widgets whose "ClassName" property is equal966                  to "ToolBar" and the Name is "Explorer".967                  The list of currently allowed properties is the following:968                  AutomationId, ClassName, HelpText, LabeledBy, Name.969          dumpChildClass (string, optional):970                if specified, only widgets of this class will be dumped /971                reported. Otherwise all widgets will be dumped (if no other972                dumping option is given. See below).973                For example, setting dumpChildClass to "TextBlock" will974                return only this kind of widgets.975                Imagine a big ListView, where a single ListViewItem is a976                complex container / panel which incorporates several widgets,977                but you don't want to dump all of them, and you're interested978                only to the ones which carry textual information.979                You can do this using the filtering options to catch the980                ListView widget and visiting all its children/descendants,981                but setting dumpChildClass will give back only the TextBlocks.982                So, this is quite different from the above filtering options,983                because filtering only defines how the UI widgets are984                traversed (and eventually cached), whereas dumping defines985                what widgets will be really reported back and collected by986                the view.987                Filtering reduces the amount of widgets that will be988                evaluated. On top of that, dumping reduces the number of989                widgets that will be returned back to the view.990          dumpChildName (string, optional):991                if specified, only widgets with this name will be dumped /992                reported. Otherwise all widgets will be dumped (if no other993                dumping option is given).994                It works exactly like dumpChildClass, but works on the Name995                property. So, the same logic applies.996                It can be combined with dumpChildClass to further reduce the997                number of returned widgets.998                For example, dumpChildName = "Foo" will give back all widgets999                which have "Foo" as Name.1000          doNotDump (boolean, optional):1001                if specified, no widgets will be dumped / reported, regarding1002                of all other dump options.1003                It's used to only cache the widgets in the server. All widgets1004                will be traversed and cached (if a cache option is defined).1005        See also setRefreshViewDefaults().1006        Returns View object.1007        """1008        if window == None:1009            window = self._refreshViewDefaults.get("window", None)1010        if forcedView == None:1011            forcedView = self._refreshViewDefaults.get("forcedView", None)1012        if viewSource == None:1013            viewSource = self.viewSource()1014        if not viewSource in _g_viewSources:1015            raise ValueError('invalid view source "%s"' % (viewSource,))1016        if items == None:1017            items = self._refreshViewDefaults.get("items", [])1018        if properties == None:1019            properties = self._refreshViewDefaults.get("properties", None)1020        if area == None:1021            area = self._refreshViewDefaults.get("area", None)1022        if forcedView != None:1023            retryCount = 01024            startTime = time.time()1025            lastStartTime = startTime1026            viewFilename = forcedView1027            if isinstance(forcedView, View):1028                self._lastView = forcedView1029            elif type(forcedView) in [str, unicode]:1030                try:1031                    self._lastView = View(1032                        forcedView, ast.literal_eval(file(viewFilename).read()),1033                        device=self, freeDumps=dumpChildClass or dumpChildName or doNotDump)1034                except Exception:1035                    self._lastView = None1036            endTime = time.time()1037        else:1038            viewFilename = self.getDumpFilename("view")1039            retryCount = 01040            startTime = time.time()1041            lastStartTime = startTime1042            while True:1043                try:1044                    topWindowBbox = self.topWindowProperties()['bbox']1045                except TypeError:1046                    topWindowBbox = None # top window unavailable1047                if area:1048                    leftTopRightBottom = (1049                        self.intCoords((area[0], area[1])) +1050                        self.intCoords((area[2], area[3])))1051                else:1052                    leftTopRightBottom = None1053                if viewSource == "enumchildwindows":1054                    viewData = self._conn.recvViewData(window)1055                else:1056                    if "/" in viewSource:1057                        walker = viewSource.split("/")[1]1058                    else:1059                        walker = "raw"1060                    if properties != None:1061                        if properties == "all":1062                            viewItemProperties = None1063                        elif properties == "fast":1064                            viewItemProperties = ["AutomationId",1065                                                   "BoundingRectangle",1066                                                   "ClassName",1067                                                   "HelpText",1068                                                   "ToggleState",1069                                                   "Value",1070                                                   "Minimum",1071                                                   "Maximum",1072                                                   "Name"]1073                        elif isinstance(properties, list) or isinstance(properties, tuple):1074                            viewItemProperties = list(properties)1075                        else:1076                            raise ValueError('invalid properties argument, expected "all", '1077                                             '"fast" or a list')1078                    else:1079                        viewItemProperties = properties1080                    viewData = self._conn.recvViewUIAutomation(1081                        window, items, viewItemProperties, leftTopRightBottom, walker,1082                        filterType, filterCondition, dumpChildClass, dumpChildName, doNotDump)1083                file(viewFilename, "w").write(repr(viewData))1084                try:1085                    self._lastView = View(1086                        viewFilename, viewData,1087                        itemOnScreen=lambda i: self.itemOnScreen(i, topWindowBbox=topWindowBbox),1088                        device=self, freeDumps=dumpChildClass or dumpChildName or doNotDump)1089                    break1090                except Exception, e:1091                    self._lastView = None1092                    _adapterLog(1093                        "refreshView %s failed (%s), source=%s topWindow=%s" %1094                        (retryCount, e, repr(viewSource), self.topWindow()))1095                    retryCount += 11096                    if retryCount < self._refreshViewRetryLimit:1097                        time.sleep(0.2)1098                    else:1099                        break1100                lastStartTime = time.time()1101            endTime = time.time()1102        itemCount = -11103        if self._lastView:1104            itemCount = len(self._lastView._viewItems)1105        self._lastViewStats = {1106            "retries": retryCount,1107            "timestamp": endTime,1108            "total time": endTime - startTime,1109            "last time": endTime - lastStartTime,1110            "filename": viewFilename,1111            "source": viewSource,1112            "forced": (forcedView != None),1113            "window": window,1114            "view": str(self._lastView),1115            "item count": itemCount}1116        return self._lastView1117    def refreshViewDefaults(self):1118        """Returns default arguments for refreshView() calls.1119        See also setRefreshViewDefaults().1120        """1121        return dict(self._refreshViewDefaults)1122    def setClipboard(self, data):1123        """1124        Set text on clipboard1125        Parameters:1126          data (string):1127                  data to be set on the clipboard.1128        Note: any type of data on clipboard will be emptied.1129        See also: getClipboard()1130        """1131        return self.existingConnection().evalPython(1132            "setClipboardText(%s)" % (repr(data),))1133    def setErrorReporting(self, settings):1134        """1135        Modify Windows error reporting settings (WER)1136        Parameters:1137          settings (dictionary):1138                  WER settings and values to be set.1139        Example: disable showing interactive crash dialogs1140          setErrorReporting({"DontShowUI": 1})1141        See also: errorReporting(),1142                  MSDN WER Settings.1143        """1144        for setting in settings:1145            self.setRegistry(1146                r"HKEY_CURRENT_USER\Software\Microsoft\Windows\Windows Error Reporting",1147                setting, settings[setting])1148        return True1149    def setDisplaySize(self, size):1150        """1151        Transform coordinates of synthesized events (like a tap) from1152        screenshot resolution to display input area size. By default1153        events are synthesized directly to screenshot coordinates.1154        Parameters:1155          size (pair of integers: (width, height)):1156                  width and height of display in pixels. If not given,1157                  values from EnumDisplayMonitors are used.1158        Returns None.1159        """1160        width, height = size1161        screenWidth, screenHeight = self.screenSize()1162        self._conn.setScreenToDisplayCoords(1163            lambda x, y: (x * width / screenWidth,1164                          y * height / screenHeight))1165        self._conn.setDisplayToScreenCoords(1166            lambda x, y: (x * screenWidth / width,1167                          y * screenHeight / height))1168    def setForegroundWindow(self, window):1169        """1170        Set a window with the title as a foreground window1171        Parameters:1172          window (title (string) or hwnd (integer):1173                  title or handle of the window to be raised1174                  foreground.1175        Returns True if the window was brought to the foreground,1176        otherwise False.1177        Notes: calls SetForegroundWindow in user32.dll.1178        """1179        return self.existingConnection().sendSetForegroundWindow(window)1180    def setRefreshViewDefaults(self, **kwargs):1181        """Set new default arguments for refreshView() calls1182        Parameters:1183          **kwargs (keyword arguments)1184                  new default values for optional refreshView() parameters.1185        Note: default arguments are overridden by arguments given1186        directly in refreshView calls.1187        Note: setViewSource() can change the default arguments.1188        Example:1189          setRefreshViewDefaults(window="My app title",1190                                 viewSource="uiautomation/content")1191        """1192        self._refreshViewDefaults = kwargs1193    def findRegistry(self, rootKey, key=None, valueName=None, limit=1):1194        """Search for key and/or valueName from the registry.1195        Returns a list of matching (fullKeyPath, valueName) pairs1196        found under the rootKey. The list has at most limit items, the1197        default is 1.1198        Parameters:1199          rootKey (string):1200                  root key path for the search. Example:1201                  "HKEY_LOCAL_MACHINE".1202          key (string, optional):1203                  key name to be searched for under the rootKey.1204                  The key is a regular expression that is searched for1205                  from full key path. Use "\\name$" to require exact1206                  match.1207                  If not given, valueName should be defined.1208          valueName (string, optional):1209                  value name to be searched for under the rootKey.1210                  The value can be a regular expression.1211                  If not given, key should be defined and1212                  returned valueName will be None.1213          limit (integer, optional):1214                  maximum number of matches to be returned. The1215                  default is 1. limit=None returns all matching1216                  pairs.1217        Example:1218          findRegistry("HKEY_LOCAL_MACHINE", key="\\Windows$")1219        """1220        if key == None and valueName == None:1221            raise ValueError("either key or valueName must be provided")1222        return self.existingConnection().evalPython(1223            'findRegistry(%s, key=%s, valueName=%s, limit=%s)' % (1224                repr(rootKey), repr(key), repr(valueName), repr(limit)))1225    def setRegistry(self, key, valueName, value, valueType=None):1226        """1227        Set Windows registry value.1228        Parameters:1229          key (string):1230                  full key name.1231          valueName (string):1232                  name of the value to be set.1233          value (string):1234                  string that specifies the new value.1235          valueType (string, optional for str and int values):1236                  REG_BINARY, REG_DWORD, REG_DWORD_LITTLE_ENDIAN,1237                  REG_DWORD_BIG_ENDIAN, REG_EXPAND_SZ, REG_LINK,1238                  REG_MULTI_SZ, REG_NONE, REG_RESOURCE_LIST or REG_SZ.1239                  Default types for storing str and int values1240                  are REG_SZ and REG_DWORD.1241        Example:1242          setRegistry(r"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet"1243                       "\Control\Session Manager\Environment",1244                       "PATH", r"C:\MyExecutables", "REG_EXPAND_SZ")1245        Returns True on success.1246        """1247        return self.existingConnection().evalPython(1248            "setRegistry(%s,%s,%s,%s)" % (repr(key), repr(valueName),1249                                          repr(value), repr(valueType)))1250    def getRegistry(self, key, valueName):1251        """1252        Return Windows registry value and type1253        Parameters:1254          key (string):1255                  full key name.1256          valueName (string):1257                  name of the value to be read.1258        Returns a pair (value, valueType)1259        Example:1260          getRegistry(r"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet"1261                       "\Control\Session Manager\Environment", "PATH")1262        """1263        return self.existingConnection().evalPython(1264            "getRegistry(%s,%s)" % (repr(key), repr(valueName)))1265    def processList(self):1266        """1267        Return list of processes running on the device.1268        Returns list of dictionaries with keys:1269          "pid": process ID, and1270          "ProcessImageFileName": full path to the executable in win32 format.1271        """1272        return self.existingConnection().evalPython("processList()")1273    def processStatus(self, pid):1274        """1275        Return status of a process1276        Parameters:1277          pid (integer):1278                  Process ID of the process1279        Returns properties in a dictionary.1280        Example:1281          print "Memory usage:", processStatus(4242)["WorkingSetSize"]1282        """1283        return self.existingConnection().evalPython(1284            "processStatus(%s)" % (repr(pid),))1285    def productList(self):1286        """1287        Return list of products installed or advertised in the system1288        Returns list of dictionaries, each containing properties of a product.1289        """1290        return self.existingConnection().evalPython("products()")1291    def pycosh(self, command):1292        """1293        Run command in pycosh shell on the device.1294        Parameters:1295          command (string):1296                  pycosh command to be executed. Pycosh implements1297                  stripped-down versions of zip, tar, find, md5sum, diff,1298                  grep, head, tail, curl,... the usual handy shell utils.1299                  For information on pycosh commands, try1300                  device.pycosh("help") or run in shell:1301                  echo help | python -m pycosh.1302        """1303        return self.existingConnection().pycosh(command)1304    def setScreenshotSize(self, size):1305        """1306        Force screenshots from device to use given resolution.1307        Overrides detected monitor resolution on device.1308        Parameters:1309          size (pair of integers: (width, height)):1310                  width and height of screenshot.1311        """1312        self._conn.setScreenshotSize(size)1313    def setTopWindow(self, window):1314        """1315        Set a window as a foreground window and bring it to front.1316        Parameters:1317          window (title (string) or hwnd (integer):1318                  title or handle of the window to be raised1319                  foreground.1320        Returns True if the window was brought to the foreground,1321        otherwise False.1322        Notes: calls SetForegroundWindow in user32.dll.1323        """1324        return self.existingConnection().sendSetTopWindow(window)1325    def setViewSource(self, source, properties=None):1326        """1327        Set default view source for refreshView()1328        Parameters:1329          source (string):1330                  default source, "enumchildwindow" or "uiautomation",1331                  "uiautomation/raw", "uiautomation/control",1332                  "uiautomation/content".1333          properties (string or list of strings, optional):1334                  set list of view item properties to be read.1335                  "all" reads all available properties for each item.1336                  "fast" reads a set of preselected properties.1337                  list of strings reads properties in the list.1338                  The default is "all".1339        Returns None.1340        See also refreshView(), viewSource(), refreshViewDefaults().1341        """1342        if not source in _g_viewSources:1343            raise ValueError(1344                'invalid view source "%s", expected one of: "%s"' %1345                (source, '", "'.join(_g_viewSources)))1346        if properties != None:1347            self._refreshViewDefaults["properties"] = properties1348        self._refreshViewDefaults["viewSource"] = source1349    def shell(self, command):1350        """1351        Execute command in Windows.1352        Parameters:1353          command (string or list of strings):1354                  command to be executed. Will be forwarded directly1355                  to subprocess.check_output.  If command is a string,1356                  then it will be executed in subshell, otherwise without1357                  shell.1358        Returns what is printed by the command.1359        If you wish to receive exitstatus or standard output and error1360        separated from command, refer to shellSOE().1361        """1362        return self._conn.evalPython('shell(%s)' % (repr(command),))1363    def shellSOE(self, command, asyncStatus=None, asyncOut=None,1364                 asyncError=None, cwd=None, timeout=None):1365        """Execute command on Windows.1366        Parameters:1367          command (string or list of strings):1368                  command to be executed. If command is a list of1369                  string, it will be executed without shell1370                  (subprocess.check_output with shell=False).1371                  If command is a single-line string, it will be1372                  executed in shell (subprocess.check_output with1373                  shell=True).1374                  If command is a multiline string, it will be written1375                  to a BAT file and executed as a script.1376          asyncStatus (string, True or None)1377                  filename (on device) to which the status of1378                  asynchronously executed shellCommand will be1379                  written. If True, the command will be executed1380                  asynchronously but exit status will not be1381                  saved. The default is None, that is, command will be1382                  run synchronously, and status will be returned in1383                  the tuple.1384          asyncOut (string, True or None)1385                  filename (on device) to which the standard output of1386                  asynchronously executed shellCommand will be1387                  written. If True, the command will be executed1388                  asynchronously but output will not saved. The1389                  default is None.1390          asyncError (string, True or None)1391                  filename (on device) to which the standard error of1392                  asynchronously executed shellCommand will be1393                  written. If True, the command will be executed1394                  asynchronously but standard error will not be1395                  saved. The default is None.1396          cwd (string, optional)1397                  current working directory in which the command1398                  will be executed. If not given, the cwd defaults1399                  to the current working directory of the pythonshare1400                  server process on the device, or the cwd of the Python1401                  process if executed on host without pythonshare-server.1402          timeout (float, optional)1403                  forcefully kill child processes and return after1404                  given time (in seconds). If timed out, returned output1405                  and error strings contain what was printed until processes1406                  were killed. Returned status is a fmbtwindows.Timeout1407                  instance. Asynchronous executions cannot be timed out.1408                  The default is None (no timeout).1409        Returns triplet: exit status, standard output and standard error1410        (int, str, str) from the command.1411        If executing command fails, returns (None, None, None).1412        If execution is timed out, returns (fmbtwindows.Timeout, str, str)1413        or (fmbtwindows.Timeout, None, None) if outputs could not be read.1414        """1415        if (timeout != None and1416            (asyncStatus, asyncOut, asyncError) != (None, None, None)):1417            raise NotImplementedError(1418                "timeout for asynchronous execution is not supported")1419        s, o, e = self._conn.evalPython(1420            'shellSOE(%s, asyncStatus=%s, asyncOut=%s, asyncError=%s, '1421            'cwd=%s, timeout=%s)'1422            % (repr(command),1423               repr(asyncStatus), repr(asyncOut), repr(asyncError),1424               repr(cwd), repr(timeout)))1425        if isinstance(s, str) and s.startswith("TIMEOUT"):1426            s = Timeout(command=command[:1024*8],1427                        pid=int(s.split()[-1]))1428        return s, o, e1429    def showWindow(self, window, showCmd=SW_NORMAL):1430        """1431        Send showCmd to window.1432        Parameters:1433          window (window title (string) or handle (integer)):1434                  window to which the command will be sent.1435          showCmd (integer or string):1436                  command to be sent. Valid commands are 0..11:1437                  SW_HIDE, SW_NORMAL, SW_MINIMIZED, SW_MAXIMIZE,1438                  SW_NOACTIVATE, SW_SHOW SW_MINIMIZE, SW_MINNOACTIVE,1439                  SW_SHOWNA, SW_RESTORE, SW_DEFAULT, SW_FORCEMINIMIZE.1440        Returns True if the window was previously visible,1441        otherwise False.1442        Notes: calls ShowWindow in user32.dll.1443        """1444        return self.existingConnection().sendShowWindow(window, showCmd)1445    def tapText(self, text, partial=False, **tapKwArgs):1446        """1447        Find an item with given text from the latest view, and tap it.1448        Parameters:1449          partial (boolean, optional):1450                  refer to verifyText documentation. The default is1451                  False.1452          tapPos (pair of floats (x, y)):1453                  refer to tapItem documentation.1454          button, long, hold, count, delayBetweenTaps (optional):1455                  refer to tap documentation.1456        Returns True if successful, otherwise False.1457        """1458        items = self.existingView().findItemsByText(text, partial=partial, count=1, onScreen=True)1459        if len(items) == 0: return False1460        return self.tapItem(items[0], **tapKwArgs)1461    def topWindow(self):1462        """1463        Returns a handle to the window.1464        """1465        return self.existingConnection().evalPython(1466            "ctypes.windll.user32.GetForegroundWindow()")1467    def topWindowProperties(self):1468        """1469        Return properties of the top window as a dictionary1470        """1471        return self._conn.recvTopWindowProperties()1472    def verifyText(self, text, partial=False):1473        """1474        Verify that the last view has at least one item with given1475        text.1476        Parameters:1477          text (string):1478                  text to be searched for in items.1479          partial (boolean, optional):1480                  if True, match items if item text contains given1481                  text, otherwise match only if item text is equal to1482                  the given text. The default is False (exact match).1483        """1484        assert self._lastView != None, "View required."1485        return self._lastView.findItemsByText(text, partial=partial, count=1, onScreen=True) != []1486    def viewSource(self):1487        """1488        Returns current default view source.1489        See also refreshView(), setViewSource().1490        """1491        return self._refreshViewDefaults.get(1492            "viewSource", self._defaultViewSource)1493    def windowList(self):1494        """1495        Return list of properties of windows (dictionaries)1496        Example: list window handles and titles:1497          for props in d.windowList():1498              print props["hwnd"], props["title"]1499        """1500        return self._conn.recvWindowList()1501    def windowProperties(self, window):1502        """1503        Returns properties of a window.1504        Parameters:1505          window (title (string) or hwnd (integer):1506                  The window whose properties will be returned.1507        Returns properties in a dictionary.1508        """1509        return self.existingConnection().recvWindowProperties(window)1510    def windowStatus(self, window):1511        """1512        Returns status of a window.1513        Parameters:1514          window (title (string) or hwnd (integer):1515                  The window whose properties will be returned.1516        Returns status in a dictionary.1517        """1518        return self.existingConnection().recvWindowStatus(window)1519    def view(self):1520        return self._lastView1521    def viewStats(self):1522        return self._lastViewStats1523class _NoPythonshareConnection(object):1524    """Fake Pythonshare connection, evaluate everything locally"""1525    def __init__(self, namespace="default"):1526        self._namespaces = {}1527        self._ns = namespace1528    def exec_in(self, ns, code):1529        if not ns in self._namespaces:1530            self._namespaces[ns] = {}1531        exec code in self._namespaces[ns]1532    def eval_in(self, ns, expr):1533        if not ns in self._namespaces:1534            self._namespaces[ns] = {}1535        return eval(expr, self._namespaces[ns])1536    def namespace(self):1537        return self._ns1538class WindowsConnection(fmbtgti.GUITestConnection):1539    def __init__(self, connspec, password, device):1540        fmbtgti.GUITestConnection.__init__(self)1541        self._device = device1542        self._screenshotSize = (None, None) # autodetect1543        self._pycosh_sent_to_dut = False1544        if connspec != None:1545            self._agent = pythonshare.connect(connspec, password=password)1546        else:1547            if os.name != "nt":1548                raise ValueError("connecting to host works only on Windows")1549            self._agent = _NoPythonshareConnection()1550        self._agent_ns = self._agent.namespace()1551        agentFilename = os.path.join(1552            os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))),1553            "fmbtwindows_agent.py")1554        self._agent.exec_in(self._agent_ns, file(agentFilename).read())1555        self.setScreenToDisplayCoords(lambda x, y: (x, y))1556        self.setDisplayToScreenCoords(lambda x, y: (x, y))1557    def pycosh(self, command):1558        if not self._pycosh_sent_to_dut:1559            # upload pycosh module to DUT1560            try:1561                self.evalPython("len(_g_pycosh_source)")1562            except pythonshare.RemoteEvalError:1563                self.execPython(file(inspect.getsourcefile(pycosh)).read())1564            self._pycosh_sent_to_dut = True1565        return self.evalPython("pycosh_eval(%s)" % (repr(command),))1566    def setScreenshotSize(self, screenshotSize):1567        self._screenshotSize = screenshotSize1568        screenW, screenH = self._screenshotSize1569        inputW, inputH = self._agent.eval_in(self._agent_ns, "_mouse_input_area")1570        self.setScreenToDisplayCoords(1571            lambda x, y: (x * inputW / screenW, y * inputH / screenH))1572        self.setDisplayToScreenCoords(1573            lambda x, y: (x * screenW / inputW, y * screenH / inputH))1574    def execPython(self, code):1575        return self._agent.exec_in(self._agent_ns, code)1576    def evalPython(self, code):1577        return self._agent.eval_in(self._agent_ns, code)1578    def recvFile(self, remoteFilename, localFilename=None, compress=False):1579        if compress:1580            if isinstance(compress, int):1581                compressLevel = compress1582            else:1583                compressLevel = 31584            data_b64_z = self._agent.eval_in(1585                self._agent_ns,1586                "base64.b64encode(zlib.compress(file(%s, 'rb').read(), %s))" % (1587                    repr(remoteFilename), compressLevel))1588            data = zlib.decompress(base64.b64decode(data_b64_z))1589        else:1590            data_b64 = self._agent.eval_in(1591                self._agent_ns,1592                "base64.b64encode(file(%s, 'rb').read())" % (repr(remoteFilename),))1593            data = base64.b64decode(data_b64)1594        if localFilename:1595            file(localFilename, "wb").write(data)1596            return True1597        else:1598            return data1599    def sendFile(self, localFilename, remoteFilepath, data=None):1600        sendBlockMaxLen = 10 * 1024 * 1024 # Send at most 10 MB at a time1601        sendDataFromFile = False1602        if data == None:1603            fileSize = os.stat(localFilename).st_size1604            if fileSize < sendBlockMaxLen:1605                data = open(localFilename, "rb").read()1606            else:1607                data = ""1608                dataFile = open(localFilename, "rb")1609                sendDataFromFile = True1610        if localFilename:1611            basename = os.path.basename(localFilename)1612        else:1613            basename = localFilename1614        if sendDataFromFile:1615            dataLen = fileSize1616        else:1617            dataLen = len(data)1618        sendIndex = 01619        while sendIndex < dataLen or dataLen == 0:1620            if sendDataFromFile:1621                sendData = dataFile.read(sendBlockMaxLen)1622            else:1623                sendData = data[sendIndex:sendIndex + sendBlockMaxLen]1624            rv = self.evalPython(1625                'saveFile(%s, %s, base64.b64decode(%s), append=%s)' %1626                (repr(basename),1627                 repr(remoteFilepath),1628                 repr(base64.b64encode(sendData)),1629                 repr(sendIndex != 0)))1630            sendIndex += sendBlockMaxLen1631            if not rv or dataLen == 0:1632                break1633        if sendDataFromFile:1634            dataFile.close()1635        return rv1636    def recvMatchingPaths(self, pathnamePattern):1637        filepaths = self._agent.eval_in(1638            self._agent_ns,1639            "glob.glob(%s)" % (repr(pathnamePattern),))1640        if "/" in pathnamePattern:1641            # Unix-style directory naming in input,1642            # stick with it and fix mixed / and \ that might1643            # come out from glob.glob.1644            return [p.replace('\\', '/') for p in filepaths]1645        else:1646            # use glob output as it is1647            return filepaths1648    def recvScreenshot(self, filename, screenshotSize=(None, None)):1649        ppmfilename = filename + ".ppm"1650        if screenshotSize == (None, None):1651            screenshotSize = self._screenshotSize1652        width, height, zdata = self._agent.eval_in(1653            self._agent_ns, "screenshotZYBGR(%s)" % (repr(screenshotSize),))1654        data = zlib.decompress(zdata)1655        fmbtgti.eye4graphics.wbgr2rgb(data, width, height)1656        if fmbtpng != None:1657            file(filename, "wb").write(1658                fmbtpng.raw2png(data, width, height, 8, "RGB"))1659        else:1660            ppm_header = "P6\n%d %d\n%d\n" % (width, height, 255)1661            f = file(filename + ".ppm", "wb")1662            f.write(ppm_header)1663            f.write(data)1664            f.close()1665            _run([fmbt_config.imagemagick_convert, ppmfilename, filename], expectedExitStatus=[0])1666            os.remove(ppmfilename)1667        return True1668    def recvTopWindowProperties(self):1669        return self.evalPython("topWindowProperties()")1670    def recvWindowProperties(self, window):1671        hwnd = self._window2hwnd(window)1672        return self.evalPython("windowProperties(%s)" % (hwnd,))1673    def recvWindowStatus(self, window):1674        hwnd = self._window2hwnd(window)1675        return self.evalPython("windowStatus(%s)" % (hwnd,))1676    def recvViewData(self, window=None):1677        rv = None1678        if window == None:1679            rv = self.evalPython("topWindowWidgets()")1680        elif isinstance(window, int):1681            rv = self.evalPython("windowWidgets(%s)" % (repr(window),))1682        elif isinstance(window, str) or isinstance(window, unicode):1683            wlist = self.evalPython("windowList()")1684            for w in wlist:1685                if w["title"] == window:1686                    rv = self.evalPython("windowWidgets(%s)" % (repr(w["hwnd"]),))1687                    break1688            else:1689                raise ValueError('no window with title "%s"' % (window,))1690        else:1691            raise ValueError('illegal window "%s", expected integer or string (hWnd or title)' % (window,))1692        return rv1693    def _parseDumps(self, dumps, dump_suffix, error_template):1694        dumpFilename = self._device.getDumpFilename(dump_suffix) + '.log'1695        error_message = ''1696        rv = []1697        prop_data = {}1698        items = None1699        with open(dumpFilename, 'w') as f:1700            for dump in dumps:1701                f.write(dump + '\n')1702                for line in dump.split('\0'):1703                    if line.startswith('!'):1704                        error_message = line[1:]1705                        continue1706                    if line.startswith('#'):  # It's a comment / debug output: skip it!1707                        continue1708                    if line == '[':1709                        items = []1710                        continue1711                    if line == ']':1712                        rv.append(items)1713                        continue1714                    if items is not None:1715                        items.append(line)1716                    if "=" not in line:1717                        continue1718                    prop_name, prop_value = line.split("=", 1)1719                    if prop_name == "hash" and prop_data:1720                        rv.append(prop_data)1721                        prop_data = {}1722                    prop_data[prop_name] = prop_value.replace(r"\r\n", "\n").replace(r"\\", "\\")1723        if prop_data:1724            rv.append(prop_data)1725        if error_message:1726            raise FMBTWindowsError(error_template % error_message)1727        return rv1728    def recvViewUIAutomation(self, window=None, items=[], properties=None, area=None, walker="raw",1729        filterType="none", filterCondition="", dumpChildClass="", dumpChildName="", doNotDump=False):1730        """returns list of dictionaries, each of which contains properties of1731        an item"""1732        if not walker in ["raw", "control", "content"]:1733            raise ValueError('invalid walker %r' % walker)1734        hwnd = self._window2hwnd(window) if window else None1735        if properties is None:1736            properties = []1737        else:1738            # make sure certain properties are always included1739            properties = list(frozenset(properties) | frozenset(["BoundingRectangle"]))1740        dumps = []1741        if items:1742            for item in items:1743                dumps.append(self.evalPython("dumpUIAutomationElements(%r, %r, %r, %r, %r, %r, %r, %r, %r, %r)" % (1744                    hwnd,1745                    [str(item.id()) for item in item.branch()],1746                    properties,1747                    area,1748                    walker,1749                    filterType,1750                    filterCondition,1751                    dumpChildClass,1752                    dumpChildName,1753                    doNotDump)))1754        else:1755            dumps.append(self.evalPython("dumpUIAutomationElements(%r, %r, %r, %r, %r, %r, %r, %r, %r, %r)" % (1756                hwnd,1757                [],1758                properties,1759                area,1760                walker,1761                filterType,1762                filterCondition,1763                dumpChildClass,1764                dumpChildName,1765                doNotDump)))1766        return self._parseDumps(dumps, "dumpUIAutomationElements",1767            "view is not available. An error happened while collecting UI elements with refreshView().\n%s")1768    def sendSetCacheMode(self, mode):1769        dump = self.evalPython("serverSetCacheMode(%r)" % mode)1770        self._parseDumps([dump], "serverSetCacheMode",1771            "An error happened while setting the cache mode.\n%s")1772    def sendClearCache(self):1773        dump = self.evalPython("serverClearCache()")1774        self._parseDumps([dump], "serverClearCache",1775            "An error happened while clearing the cache.\n%s")1776    def sendSetFocus(self, eltHash):1777        dump = self.evalPython("setAutomationElementFocus(%s)" % eltHash)1778        self._parseDumps([dump], "setAutomationElementFocus",1779            "An error happened while setting the focus.\n%s")1780    def sendCollapse(self, eltHash):1781        dump = self.evalPython("AutomationElementCollapse(%s)" % eltHash)1782        self._parseDumps([dump], "AutomationElementCollapse",1783            "An error happened while collapsing the viewitem.\n%s")1784    def sendExpand(self, eltHash):1785        dump = self.evalPython("AutomationElementExpand(%s)" % eltHash)1786        self._parseDumps([dump], "AutomationElementExpand",1787            "An error happened while expanding the viewitem.\n%s")1788    def recvViewCachedItem(self, eltHash):1789        dump = self.evalPython("getCachedAutomationElement(%s)" % eltHash)1790        return self._parseDumps([dump], "getCachedAutomationElement",1791            "viewitem is not available. An error happened while dumping it with cachedElement().\n%s")1792    def recvViewItemPatterns(self, eltHash):1793        dump = self.evalPython("getAutomationElementPatterns(%s)" % eltHash)1794        return self._parseDumps([dump], "getAutomationElementPatterns",1795            "viewitem patterns are not available. An error happened while collecting them with patterns().\n%s")1796    def recvViewItemProperties(self, eltHash):1797        dump = self.evalPython("getAutomationElementProperties(%s)" % eltHash)1798        return self._parseDumps([dump], "getAutomationElementProperties",1799            "viewitem properties are not available. An error happened while collecting them with refresh().\n%s")1800    def recvViewItemItems(self, eltHash, propertyName, separator, filterSubChildClassName, maxSubChildren):1801        dump = self.evalPython("getAutomationElementItems(%s, %r, %r, %r, %r)" % (1802            eltHash, propertyName, separator, filterSubChildClassName, maxSubChildren))1803        return self._parseDumps([dump], "getAutomationElementItems",1804            "viewitem items aren't available. An error happened while getting it with items().\n%s")1805    def recvViewItemContainerItems(self, eltHash, propertyName, separator, filterSubChildClassName, maxSubChildren, scroll):1806        dump = self.evalPython("getAutomationElementContainerItems(%s, %r, %r, %r, %r, %r)" % (1807            eltHash, propertyName, separator, filterSubChildClassName, maxSubChildren, scroll))1808        return self._parseDumps([dump], "getAutomationElementContainerItems",1809            "viewitem items aren't available. An error happened while getting it with containerItems().\n%s")1810    def recvViewItemSelectedItems(self, eltHash, propertyName, separator, filterSubChildClassName, maxSubChildren, scroll):1811        dump = self.evalPython("getAutomationElementSelectedItems(%s, %r, %r, %r, %r, %r)" % (1812            eltHash, propertyName, separator, filterSubChildClassName, maxSubChildren, scroll))1813        return self._parseDumps([dump], "getAutomationElementSelectedItems",1814            "viewitem selected items aren't available. An error happened while getting it with selectedItems().\n%s")...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!!
