Beispiel #1
0
    def findChildren(self, pred, recursive=True, isLambda=False):
        """
        Find all children/descendents satisfying the predicate.
        You can also use lambdas in place of pred that will enable search also against
        pure dogtail Node properties (like showing). I.e: "lambda x: x.roleName == 'menu item'
        and x.showing is True". isLambda does not have to be set, it's kept only for api compatibility.
        """
        # always use lambda search, but we keep isLambda param for api compatibility
        compare_func = None
        if isLambda is True or isinstance(pred, LambdaType):
            compare_func = pred
        else:
            assert isinstance(pred, predicate.Predicate)
            compare_func = pred.satisfiedByNode

        results = []
        numAttempts = 0
        while numAttempts < config.searchCutoffCount:
            if numAttempts >= config.searchWarningThreshold or config.debugSearching:
                logger.log("a11y errors caught, making attempt %i" % numAttempts)
            try:
                if recursive:
                    results = pyatspi.utils.findAllDescendants(self, compare_func)
                else:
                    results = list(filter(compare_func, self.children))
                break
            except (GLib.GError, TypeError):
                numAttempts += 1
                if numAttempts == config.searchCutoffCount:
                    logger.log("warning: errors caught from the a11y tree, giving up search")
                else:
                    sleep(config.searchBackoffDuration)
                continue
        return results
Beispiel #2
0
def selecttab(root, tabname):
    try:
        find_pattern(root, tabname, "page tab").click()
    except:
        vmmlogger.log(
            "Error: failed to select tab : %s in node [%s]" % tabname, root)
        raise
Beispiel #3
0
    def findChildren(self, pred, recursive=True, isLambda=False):
        """
        Find all children/descendents satisfying the predicate.
        You can also use lambdas in place of pred that will enable search also against
        pure dogtail Node properties (like showing). I.e: "lambda x: x.roleName == 'menu item'
        and x.showing is True". isLambda does not have to be set, it's kept only for api compatibility.
        """
        # always use lambda search, but we keep isLambda param for api compatibility
        compare_func = None
        if isLambda is True or isinstance(pred, LambdaType):
            compare_func = pred
        else:
            assert isinstance(pred, predicate.Predicate)
            compare_func = pred.satisfiedByNode

        results = []
        numAttempts = 0
        while numAttempts < config.searchCutoffCount:
            if numAttempts >= config.searchWarningThreshold or config.debugSearching:
                logger.log("a11y errors caught, making attempt %i" % numAttempts)
            try:
                if recursive:
                    results = pyatspi.utils.findAllDescendants(self, compare_func)
                else:
                    results = list(filter(compare_func, self.children))
                break
            except (GLib.GError, TypeError):
                numAttempts += 1
                if numAttempts == config.searchCutoffCount:
                    logger.log("warning: errors caught from the a11y tree, giving up search")
                else:
                    sleep(config.searchBackoffDuration)
                continue
        return results
Beispiel #4
0
 def satisfiedByNode(node):
     # labelled nodes are handled specially:
     if self.label:
         # this reverses the search; we're looking for a node with LABELLED_BY
         # and then checking the label, rather than looking for a label and
         # then returning whatever LABEL_FOR targets
         if node.labeller:
             return stringMatches(self.label, node.labeller.name)
         else:
             return False
     else:
         # Ensure the node matches any criteria that were set:
         try:
             if self.name:
                 if not stringMatches(self.name, node.name):
                     return False
             if self.roleName:
                 if self.roleName != node.roleName:
                     return False
             if self.description:
                 if self.description != node.description:
                     return False
         except GLib.GError as e:
             if re.match(r"name :[0-9]+\.[0-9]+ was not provided", e.message):
                 logger.log("Dogtail: warning: omiting possibly broken at-spi application record")
                 return False
             else:
                 raise e
         return True
Beispiel #5
0
def checkForA11yInteractively():  # pragma: no cover
    """
    Checks if accessibility is enabled, and presents a dialog prompting the
    user if it should be enabled if it is not already, then halts execution.
    """
    if isA11yEnabled():
        return
    dialog = Gtk.Dialog('Enable Assistive Technology Support?',
                        None,
                        Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
                        (Gtk.STOCK_QUIT, Gtk.ResponseType.CLOSE,
                         "_Enable", Gtk.ResponseType.ACCEPT))
    question = """Dogtail requires that Assistive Technology Support be enabled for it to function. Would you like to
enable Assistive Technology support now?

Note that you will have to log out for the change to fully take effect.
    """.strip()
    dialog.set_default_response(Gtk.ResponseType.ACCEPT)
    questionLabel = Gtk.Label(label=question)
    questionLabel.set_line_wrap(True)
    dialog.vbox.pack_start(questionLabel, True, True, 0)
    dialog.show_all()
    result = dialog.run()
    if result == Gtk.ResponseType.ACCEPT:
        logger.log("Enabling accessibility...")
        enableA11y()
    elif result == Gtk.ResponseType.CLOSE:
        bailBecauseA11yIsDisabled()
    dialog.destroy()
Beispiel #6
0
def checkForA11yInteractively():  # pragma: no cover
    """
    Checks if accessibility is enabled, and presents a dialog prompting the
    user if it should be enabled if it is not already, then halts execution.
    """
    if isA11yEnabled():
        return
    dialog = Gtk.Dialog(
        'Enable Assistive Technology Support?', None,
        Gtk.DialogFlags.MODAL | Gtk.DialogFlags.DESTROY_WITH_PARENT,
        (Gtk.STOCK_QUIT, Gtk.ResponseType.CLOSE, "_Enable",
         Gtk.ResponseType.ACCEPT))
    question = """Dogtail requires that Assistive Technology Support be enabled for it to function. Would you like to
enable Assistive Technology support now?

Note that you will have to log out for the change to fully take effect.
    """.strip()
    dialog.set_default_response(Gtk.ResponseType.ACCEPT)
    questionLabel = Gtk.Label(label=question)
    questionLabel.set_line_wrap(True)
    dialog.vbox.pack_start(questionLabel, True, True, 0)
    dialog.show_all()
    result = dialog.run()
    if result == Gtk.ResponseType.ACCEPT:
        logger.log("Enabling accessibility...")
        enableA11y()
    elif result == Gtk.ResponseType.CLOSE:
        bailBecauseA11yIsDisabled()
    dialog.destroy()
Beispiel #7
0
def detectDistro():
    logger.log("Detecting distribution:", newline=False)

    if os.environ.get("CERTIFIED_GNOMIE", "no") == "yes":
        distro = JHBuild()  # pragma: no cover
    elif os.path.exists("/etc/SuSE-release"):
        distro = Suse()  # pragma: no cover
    elif os.path.exists("/etc/fedora-release"):
        distro = Fedora()  # pragma: no cover
    elif os.path.exists("/etc/redhat-release"):
        distro = RHEL()  # pragma: no cover
    elif os.path.exists("/usr/share/doc/ubuntu-minimal"):
        distro = Ubuntu()
    elif os.path.exists("/etc/debian_version"):  # pragma: no cover
        distro = Debian()  # pragma: no cover
    elif os.path.exists("/etc/gentoo-release"):  # pragma: no cover
        distro = Gentoo()  # pragma: no cover
    elif os.path.exists("/etc/slackware-version"):  # pragma: no cover
        raise DistributionNotSupportedError("Slackware")  # pragma: no cover
    elif os.path.exists("/var/lib/conarydb/conarydb"):  # pragma: no cover
        distro = Conary()  # pragma: no cover
    elif os.path.exists("/etc/release") and \
            re.match(".*Solaris", open("/etc/release").readline()):  # pragma: no cover
        distro = Solaris()  # pragma: no cover
    elif os.path.exists("/etc/os-release") and \
            re.match(".*GNOME-Continuous", open("/etc/os-release").readline()):  # pragma: no cover
        distro = GnomeContinuous()  # pragma: no cover
    else:
        raise DistributionNotSupportedError("Unknown")  # pragma: no cover
    logger.log(distro.__class__.__name__)
    return distro
Beispiel #8
0
 def satisfiedByNode(node):
     try:
         if self.description == None:
             return node.roleName == 'application' and stringMatches(
                 self.appName, node.name)
         else:
             return node.roleName == 'application' and stringMatches(
                 self.appName, node.name) and stringMatches(
                     self.description, node.description)
     except GLib.GError as e:
         if re.match(r"name :[0-9]+\.[0-9]+ was not provided",
                     e.message):
             logger.log(
                 "Dogtail: warning: omiting possibly broken at-spi application record"
             )
             return False
         else:
             try:
                 sleep(config.defaults['searchWarningThreshold'])
                 return node.roleName == 'application' and stringMatches(
                     self.appName, node.name)
             except GLib.GError:
                 logger.log(
                     "Dogtail: warning: application may be hanging")
                 return False
Beispiel #9
0
def absoluteMotionWithTrajectory(source_x, source_y, dest_x, dest_y, mouseDelay=None, check=True):
    """
    Synthetize mouse absolute motion with trajectory. The 'trajectory' means that the whole motion
    is divided into several atomic movements which are synthetized separately.
    """
    if check:
        checkCoordinates(source_x, source_y)
        checkCoordinates(dest_x, dest_y)
    logger.log("Mouse absolute motion with trajectory to (%s,%s)" % (dest_x, dest_y))

    dx = float(dest_x - source_x)
    dy = float(dest_y - source_y)
    max_len = max(abs(dx), abs(dy))
    if max_len == 0:
        # actually, no motion requested
        return
    dx /= max_len
    dy /= max_len
    act_x = float(source_x)
    act_y = float(source_y)

    for _ in range(0, int(max_len)):
        act_x += dx
        act_y += dy
        if mouseDelay:
            doDelay(mouseDelay)
        registry.generateMouseEvent(int(act_x), int(act_y), name='abs')

    if mouseDelay:
        doDelay(mouseDelay)
    else:
        doDelay()
Beispiel #10
0
 def satisfiedByNode(node):
     # labelled nodes are handled specially:
     if self.label:
         # this reverses the search; we're looking for a node with LABELLED_BY
         # and then checking the label, rather than looking for a label and
         # then returning whatever LABEL_FOR targets
         if node.labeller:
             return stringMatches(self.label, node.labeller.name)
         else:
             return False
     else:
         # Ensure the node matches any criteria that were set:
         try:
             if self.name:
                 if not stringMatches(self.name, node.name):
                     return False
             if self.roleName:
                 if self.roleName != node.roleName:
                     return False
             if self.description:
                 if self.description != node.description:
                     return False
         except GLib.GError as e:
             if re.match(r"name :[0-9]+\.[0-9]+ was not provided",
                         e.message):
                 logger.log(
                     "Dogtail: warning: omiting possibly broken at-spi application record"
                 )
                 return False
             else:
                 raise e
         return True
Beispiel #11
0
def detectDistro():
    logger.log("Detecting distribution:", newline=False)

    if os.environ.get("CERTIFIED_GNOMIE", "no") == "yes":
        distro = JHBuild()  # pragma: no cover
    elif os.path.exists("/etc/SuSE-release"):
        distro = Suse()  # pragma: no cover
    elif os.path.exists("/etc/fedora-release"):
        distro = Fedora()  # pragma: no cover
    elif os.path.exists("/etc/redhat-release"):
        distro = RHEL()  # pragma: no cover
    elif os.path.exists("/usr/share/doc/ubuntu-minimal"):
        distro = Ubuntu()
    elif os.path.exists("/etc/debian_version"):  # pragma: no cover
        distro = Debian()  # pragma: no cover
    elif os.path.exists("/etc/gentoo-release"):  # pragma: no cover
        distro = Gentoo()  # pragma: no cover
    elif os.path.exists("/etc/slackware-version"):  # pragma: no cover
        raise DistributionNotSupportedError("Slackware")  # pragma: no cover
    elif os.path.exists("/var/lib/conarydb/conarydb"):  # pragma: no cover
        distro = Conary()  # pragma: no cover
    elif os.path.exists("/etc/release") and \
            re.match(".*Solaris", open("/etc/release").readline()):  # pragma: no cover
        distro = Solaris()  # pragma: no cover
    elif os.path.exists("/etc/os-release") and \
            re.match(".*GNOME-Continuous", open("/etc/os-release").readline()):  # pragma: no cover
        distro = GnomeContinuous()  # pragma: no cover
    else:
        raise DistributionNotSupportedError("Unknown")  # pragma: no cover
    logger.log(distro.__class__.__name__)
    return distro
Beispiel #12
0
 def doubleClick(self, button=1):
     """
     Generates a raw mouse double-click event, using the specified button.
     """
     clickX = self.position[0] + self.size[0] / 2
     clickY = self.position[1] + self.size[1] / 2
     if config.debugSearching:
         logger.log("raw click on %s %s at (%s,%s)" % (self.name, self.getLogString(), str(clickX), str(clickY)))
     rawinput.doubleClick(clickX, clickY, button)
Beispiel #13
0
    def findChild(self, pred, recursive=True, debugName=None, retry=True, requireResult=True, showingOnly=None):
        """
        Search for a node satisyfing the predicate, returning a Node.

        If retry is True (the default), it makes multiple attempts,
        backing off and retrying on failure, and eventually raises a
        descriptive exception if the search fails.

        If retry is False, it gives up after one attempt.

        If requireResult is True (the default), an exception is raised after all
        attempts have failed. If it is false, the function simply returns None.
        """
        def describeSearch(parent, pred, recursive, debugName):
            """
            Internal helper function
            """
            if recursive:
                noun = "descendent"
            else:
                noun = "child"
            if debugName is None:
                debugName = pred.describeSearchResult()
            return str("%s of %s: %s") % (str(noun), parent.getLogString(), str(debugName))

        compare_func = None
        if isinstance(pred, LambdaType):
            compare_func = pred
            if debugName is None:
                debugName = "child satisyfing a custom lambda function"
        else:
            assert isinstance(pred, predicate.Predicate)
            compare_func = pred.satisfiedByNode

        numAttempts = 0
        while numAttempts < config.searchCutoffCount:
            if numAttempts >= config.searchWarningThreshold or config.debugSearching:
                logger.log(str("searching for %s (attempt %i)") %
                           (describeSearch(self, pred, recursive, debugName), numAttempts))

            result = self._fastFindChild(compare_func, recursive, showingOnly=showingOnly)
            if result:
                assert isinstance(result, Node)
                if debugName:
                    result.debugName = debugName
                else:
                    result.debugName = pred.describeSearchResult()
                return result
            else:
                if not retry:
                    break
                numAttempts += 1
                if config.debugSearching or config.debugSleep:
                    logger.log("sleeping for %f" % config.searchBackoffDuration)
                sleep(config.searchBackoffDuration)
        if requireResult:
            raise SearchError(describeSearch(self, pred, recursive, debugName))
Beispiel #14
0
def release(x, y, button=1, check=True):
    """
    Synthesize a mouse button release at (x,y)
    """
    if check:
        checkCoordinates(x, y)
    logger.log("Mouse button %s release at (%s,%s)" % (button, x, y))
    registry.generateMouseEvent(x, y, name='b%sr' % button)
    doDelay()
Beispiel #15
0
def doubleClick(x, y, button=1, check=True):
    """
    Synthesize a mouse button double-click at (x,y)
    """
    if check:
        checkCoordinates(x, y)
    logger.log("Mouse button %s doubleclick at (%s,%s)" % (button, x, y))
    registry.generateMouseEvent(x, y, name='b%sd' % button)
    doDelay()
Beispiel #16
0
def click(x, y, button=1, check=True):
    """
    Synthesize a mouse button click at (x,y)
    """
    if check:
        checkCoordinates(x, y)
    logger.log("Mouse button %s click at (%s,%s)" % (button, x, y))
    registry.generateMouseEvent(x, y, name='b%sc' % button)
    doDelay(config.actionDelay)
Beispiel #17
0
def doubleClick(x, y, button=1, check=True):
    """
    Synthesize a mouse button double-click at (x,y)
    """
    if check:
        checkCoordinates(x, y)
    logger.log("Mouse button %s doubleclick at (%s,%s)" % (button, x, y))
    registry.generateMouseEvent(x, y, name='b%sd' % button)
    doDelay()
Beispiel #18
0
 def rootwindow(self):
     if self._rootwindow is None:
         try:
             self._rootwindow = find_pattern(self.root, "New VM", "frame")
         except:
             vmmlogger.log("Failed to set property: %s in vmmAddNewVM" %
                           "rootwindow")
             raise
     return self._rootwindow
Beispiel #19
0
def release(x, y, button=1, check=True):
    """
    Synthesize a mouse button release at (x,y)
    """
    if check:
        checkCoordinates(x, y)
    logger.log("Mouse button %s release at (%s,%s)" % (button, x, y))
    registry.generateMouseEvent(x, y, name='b%sr' % button)
    doDelay()
Beispiel #20
0
def click(x, y, button=1, check=True):
    """
    Synthesize a mouse button click at (x,y)
    """
    if check:
        checkCoordinates(x, y)
    logger.log("Mouse button %s click at (%s,%s)" % (button, x, y))
    registry.generateMouseEvent(x, y, name='b%sc' % button)
    doDelay(config.actionDelay)
Beispiel #21
0
def doDelay(delay=None):
    """
    Utility function to insert a delay (with logging and a configurable
    default delay)
    """
    if delay is None:
        delay = config.defaultDelay
    if config.debugSleep:
        logger.log("sleeping for %f" % delay)
    sleep(delay)
Beispiel #22
0
def doDelay(delay=None):
    """
    Utility function to insert a delay (with logging and a configurable
    default delay)
    """
    if delay is None:
        delay = config.defaultDelay
    if config.debugSleep:
        logger.log("sleeping for %f" % delay)
    sleep(delay)
Beispiel #23
0
 def rootwindow(self):
     if self._rootwindow is None:
         try:
             self._rootwindow = find_pattern(self.root, "Preferences",
                                             "frame")
         except:
             # will replace all print with logging functions
             vmmlogger.log("Failed to set property: %s" % "rootwindow")
             raise
     return self._rootwindow
Beispiel #24
0
def warn(message, caller=True):
    """
    Generate a warning, and pass it to the debug logger.
    """
    frameRec = inspect.stack()[-1]
    message = "Warning: %s:%s: %s" % (frameRec[1], frameRec[2], message)
    if caller and frameRec[1] != '<stdin>' and frameRec[1] != '<string>':
        message = message + ':\n  ' + frameRec[4][0]
    del frameRec
    logger.log(message)
Beispiel #25
0
def warn(message, caller=True):
    """
    Generate a warning, and pass it to the debug logger.
    """
    frameRec = inspect.stack()[-1]
    message = "Warning: %s:%s: %s" % (frameRec[1], frameRec[2], message)
    if caller and frameRec[1] != '<stdin>' and frameRec[1] != '<string>':
        message = message + ':\n  ' + frameRec[4][0]
    del frameRec
    logger.log(message)
Beispiel #26
0
 def doubleClick(self, button=1):
     """
     Generates a raw mouse double-click event, using the specified button.
     """
     clickX = self.position[0] + self.size[0] / 2
     clickY = self.position[1] + self.size[1] / 2
     if config.debugSearching:
         logger.log(str("raw click on %s %s at (%s,%s)") %
                    (str(self.name), self.getLogString(), str(clickX), str(clickY)))
     rawinput.doubleClick(clickX, clickY, button)
Beispiel #27
0
def relativeMotion(x, y, mouseDelay=None):
    """
    Synthetize a relative motion from actual position.
    Note: Does not check if the end coordinates are positive.
    """
    logger.log("Mouse relative motion of (%s,%s)" % (x, y))
    registry.generateMouseEvent(x, y, name='rel')
    if mouseDelay:
        doDelay(mouseDelay)
    else:
        doDelay()
Beispiel #28
0
def relativeMotion(x, y, mouseDelay=None):
    """
    Synthetize a relative motion from actual position.
    Note: Does not check if the end coordinates are positive.
    """
    logger.log("Mouse relative motion of (%s,%s)" % (x, y))
    registry.generateMouseEvent(x, y, name='rel')
    if mouseDelay:
        doDelay(mouseDelay)
    else:
        doDelay()
Beispiel #29
0
 def point(self, mouseDelay=None):
     """
     Move mouse cursor to the center of the widget.
     """
     pointX = self.position[0] + self.size[0] / 2
     pointY = self.position[1] + self.size[1] / 2
     logger.log("Pointing on %s %s at (%s,%s)" % (self.name, self.getLogString(), str(pointX), str(pointY)))
     rawinput.registry.generateMouseEvent(pointX, pointY, "abs")
     if mouseDelay:
         doDelay(mouseDelay)
     else:
         doDelay()
Beispiel #30
0
def absoluteMotion(x, y, mouseDelay=None, check=True):
    """
    Synthesize mouse absolute motion to (x,y)
    """
    if check:
        checkCoordinates(x, y)
    logger.log("Mouse absolute motion to (%s,%s)" % (x, y))
    registry.generateMouseEvent(x, y, name='abs')
    if mouseDelay:
        doDelay(mouseDelay)
    else:
        doDelay()
Beispiel #31
0
def absoluteMotion(x, y, mouseDelay=None, check=True):
    """
    Synthesize mouse absolute motion to (x,y)
    """
    if check:
        checkCoordinates(x, y)
    logger.log("Mouse absolute motion to (%s,%s)" % (x, y))
    registry.generateMouseEvent(x, y, name='abs')
    if mouseDelay:
        doDelay(mouseDelay)
    else:
        doDelay()
Beispiel #32
0
 def rootwindow(self):
     if self._rootwindow is None:
         try:
             #print_nodes(self.root)
             self._rootwindow = find_pattern(self.root,
                                             ".* Connection Details",
                                             "frame")
         except:
             vmmlogger.log(
                 "Failed to set property: %s in vmmConnectionDetails" %
                 "rootwindow")
             raise
     return self._rootwindow
Beispiel #33
0
 def click(self, button=1):
     """
     Generates a raw mouse click event, using the specified button.
         - 1 is left,
         - 2 is middle,
         - 3 is right.
     """
     logger.log("Clicking on %s" % self.getLogString())
     clickX = self.position[0] + self.size[0] / 2
     clickY = self.position[1] + self.size[1] / 2
     if config.debugSearching:
         logger.log("raw click on %s %s at (%s,%s)" % (self.name, self.getLogString(), str(clickX), str(clickY)))
     rawinput.click(clickX, clickY, button)
Beispiel #34
0
 def point(self, mouseDelay=None):
     """
     Move mouse cursor to the center of the widget.
     """
     pointX = self.position[0] + self.size[0] / 2
     pointY = self.position[1] + self.size[1] / 2
     logger.log(str("Pointing on %s %s at (%s,%s)") %
                (str(self.name), self.getLogString(), str(pointX), str(pointY)))
     rawinput.registry.generateMouseEvent(pointX, pointY, 'abs')
     if mouseDelay:
         doDelay(mouseDelay)
     else:
         doDelay()
Beispiel #35
0
def screenshot(file='screenshot.png', timeStamp=True):
    """
    This function wraps the ImageMagick import command to take a screenshot.

    The file argument may be specified as 'foo', 'foo.png', or using any other
    extension that ImageMagick supports. PNG is the default.

    By default, screenshot filenames are in the format of foo_YYYYMMDD-hhmmss.png .
    The timeStamp argument may be set to False to name the file foo.png.
    """
    if not isinstance(timeStamp, bool):
        raise TypeError("timeStampt must be True or False")
    # config is supposed to create this for us. If it's not there, bail.
    assert os.path.isdir(config.scratchDir)

    baseName = ''.join(file.split('.')[0:-1])
    fileExt = file.split('.')[-1].lower()
    if not baseName:
        baseName = file
        fileExt = 'png'

    if timeStamp:
        ts = TimeStamp()
        newFile = ts.fileStamp(baseName) + '.' + fileExt
        path = config.scratchDir + newFile
    else:
        newFile = baseName + '.' + fileExt
        path = config.scratchDir + newFile

    from gi.repository import Gdk
    from gi.repository import GdkPixbuf
    rootWindow = Gdk.get_default_root_window()
    geometry = rootWindow.get_geometry()
    pixbuf = GdkPixbuf.Pixbuf(colorspace=GdkPixbuf.Colorspace.RGB,
                              has_alpha=False,
                              bits_per_sample=8,
                              width=geometry[2],
                              height=geometry[3])

    pixbuf = Gdk.pixbuf_get_from_window(rootWindow, 0, 0, geometry[2],
                                        geometry[3])
    # GdkPixbuf.Pixbuf.save() needs 'jpeg' and not 'jpg'
    if fileExt == 'jpg':
        fileExt = 'jpeg'
    try:
        pixbuf.savev(path, fileExt, [], [])
    except GLib.GError:
        raise ValueError("Failed to save screenshot in %s format" % fileExt)
    assert os.path.exists(path)
    logger.log("Screenshot taken: " + path)
    return path
Beispiel #36
0
 def satisfiedByNode(node):
     try:
         return node.roleName == 'application' and stringMatches(self.appName, node.name)
     except GLib.GError as e:
         if re.match(r"name :[0-9]+\.[0-9]+ was not provided", e.message):
             logger.log("Dogtail: warning: omiting possibly broken at-spi application record")
             return False
         else:
             try:
                 sleep(config.defaults['searchWarningThreshold'])
                 return node.roleName == 'application' and stringMatches(self.appName, node.name)
             except GLib.GError:
                 logger.log("Dogtail: warning: application may be hanging")
                 return False
Beispiel #37
0
 def text(self, text):
     try:
         if config.debugSearching:
             msg = "Setting text of %s to %s"
             # Let's not get too crazy if 'text' is really large...
             # FIXME: Sometimes the next line screws up Unicode strings.
             if len(text) > 140:
                 txt = text[:134] + " [...]"
             else:
                 txt = text
             logger.log(str(msg) % (self.getLogString(), str("'%s'") % str(txt)))
         self.queryEditableText().setTextContents(text)
     except NotImplementedError:
         raise AttributeError("can't set attribute")
Beispiel #38
0
 def load(packageName, language='', getDependencies=True):
     for moFile in getMoFilesForPackage(packageName, language, getDependencies):
         # Searching the popt mo-files for translations makes gettext bail out,
         # so we ignore them here. This is
         # https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=172155 .
         if not('popt.mo' in moFile or moFile in moFiles):
             try:
                 translationDbs.append(GettextTranslationDb(moFile))
                 moFiles[moFile] = None
             except (AttributeError, IndexError):
                 if config.config.debugTranslation:
                     #import traceback
                     # logger.log(traceback.format_exc())
                     logger.log("Warning: Failed to load mo-file for translation: " + moFile)
Beispiel #39
0
 def click(self, button=1):
     """
     Generates a raw mouse click event, using the specified button.
         - 1 is left,
         - 2 is middle,
         - 3 is right.
     """
     logger.log(str("Clicking on %s") % self.getLogString())
     clickX = self.position[0] + self.size[0] / 2
     clickY = self.position[1] + self.size[1] / 2
     if config.debugSearching:
         logger.log(str("raw click on %s %s at (%s,%s)") %
                    (str(self.name), self.getLogString(), str(clickX), str(clickY)))
     rawinput.click(clickX, clickY, button)
Beispiel #40
0
    def children(self):
        """
        A list of this Accessible's children
        """
        if self.parent and self.parent.roleName == 'hyper link':
            print(self.parent.role)
            return []
        children = []
        childCount = self.childCount
        if childCount > config.childrenLimit:
            global haveWarnedAboutChildrenLimit
            if not haveWarnedAboutChildrenLimit:
                logger.log("Only returning %s children. You may change "
                           "config.childrenLimit if you wish. This message will only"
                           " be printed once." % str(config.childrenLimit))
                haveWarnedAboutChildrenLimit = True
                childCount = config.childrenLimit
        for i in range(childCount):
            # Workaround for GNOME bug #465103
            # also solution for GNOME bug #321273
            try:
                child = self[i]
            except LookupError:
                child = None
            if child:
                children.append(child)

        invalidChildren = childCount - len(children)
        if invalidChildren and config.debugSearching:
            logger.log(str("Skipped %s invalid children of %s") %
                       (invalidChildren, str(self)))
        try:
            ht = self.queryHypertext()
            for li in range(ht.getNLinks()):
                link = ht.getLink(li)
                for ai in range(link.nAnchors):
                    child = link.getObject(ai)
                    if child == self:
                        continue
                    child.__setupUserData()
                    child.user_data['linkAnchor'] = \
                        LinkAnchor(node=child,
                                   hypertext=ht,
                                   linkIndex=li,
                                   anchorIndex=ai)
                    children.append(child)
        except (NotImplementedError, AttributeError):
            pass

        return children
Beispiel #41
0
def screenshot(file='screenshot.png', timeStamp=True):
    """
    This function wraps the ImageMagick import command to take a screenshot.

    The file argument may be specified as 'foo', 'foo.png', or using any other
    extension that ImageMagick supports. PNG is the default.

    By default, screenshot filenames are in the format of foo_YYYYMMDD-hhmmss.png .
    The timeStamp argument may be set to False to name the file foo.png.
    """
    if not isinstance(timeStamp, bool):
        raise TypeError("timeStampt must be True or False")
    # config is supposed to create this for us. If it's not there, bail.
    assert os.path.isdir(config.scratchDir)

    baseName = ''.join(file.split('.')[0:-1])
    fileExt = file.split('.')[-1].lower()
    if not baseName:
        baseName = file
        fileExt = 'png'

    if timeStamp:
        ts = TimeStamp()
        newFile = ts.fileStamp(baseName) + '.' + fileExt
        path = config.scratchDir + newFile
    else:
        newFile = baseName + '.' + fileExt
        path = config.scratchDir + newFile

    from gi.repository import Gdk
    from gi.repository import GdkPixbuf
    rootWindow = Gdk.get_default_root_window()
    geometry = rootWindow.get_geometry()
    pixbuf = GdkPixbuf.Pixbuf(colorspace=GdkPixbuf.Colorspace.RGB,
                              has_alpha=False,
                              bits_per_sample=8,
                              width=geometry[2],
                              height=geometry[3])

    pixbuf = Gdk.pixbuf_get_from_window(rootWindow, 0, 0, geometry[2], geometry[3])
    # GdkPixbuf.Pixbuf.save() needs 'jpeg' and not 'jpg'
    if fileExt == 'jpg':
        fileExt = 'jpeg'
    try:
        pixbuf.savev(path, fileExt, [], [])
    except GLib.GError:
        raise ValueError("Failed to save screenshot in %s format" % fileExt)
    assert os.path.exists(path)
    logger.log("Screenshot taken: " + path)
    return path
Beispiel #42
0
def drag(fromXY, toXY, button=1, check=True):
    """
    Synthesize a mouse press, drag, and release on the screen.
    """
    logger.log("Mouse button %s drag from %s to %s" % (button, fromXY, toXY))

    (x, y) = fromXY
    press(x, y, button, check)

    (x, y) = toXY
    absoluteMotion(x, y, check=check)
    doDelay()

    release(x, y, button, check)
    doDelay()
Beispiel #43
0
def drag(fromXY, toXY, button=1, check=True):
    """
    Synthesize a mouse press, drag, and release on the screen.
    """
    logger.log("Mouse button %s drag from %s to %s" % (button, fromXY, toXY))

    (x, y) = fromXY
    press(x, y, button, check)

    (x, y) = toXY
    absoluteMotion(x, y, check=check)
    doDelay()

    release(x, y, button, check)
    doDelay()
Beispiel #44
0
def dragWithTrajectory(fromXY, toXY, button=1, check=True):
    """
    Synthetize a mouse press, drag (including move events), and release on the screen
    """
    logger.log("Mouse button %s drag with trajectory from %s to %s" % (button, fromXY, toXY))

    (x, y) = fromXY
    press(x, y, button, check)

    (x, y) = toXY
    absoluteMotionWithTrajectory(fromXY[0], fromXY[1], x, y, check=check)
    doDelay()

    release(x, y, button, check)
    doDelay()
Beispiel #45
0
def dragWithTrajectory(fromXY, toXY, button=1, check=True):
    """
    Synthetize a mouse press, drag (including move events), and release on the screen
    """
    logger.log("Mouse button %s drag with trajectory from %s to %s" %
               (button, fromXY, toXY))

    (x, y) = fromXY
    press(x, y, button, check)

    (x, y) = toXY
    absoluteMotionWithTrajectory(fromXY[0], fromXY[1], x, y, check=check)
    doDelay()

    release(x, y, button, check)
    doDelay()
Beispiel #46
0
def bailBecauseA11yIsDisabled():
    if sys.argv[0].endswith("pydoc"):
        return
    try:
        with open("/proc/%s/cmdline" % os.getpid(), 'r') as f:
            content = f.read()
        if content.find('epydoc') != -1:
            return  # pragma: no cover
        if content.find('sphinx') != -1:
            return  # pragma: no cover
    except:   # pragma: no cover
        pass  # pragma: no cover
    logger.log("Dogtail requires that Assistive Technology support be enabled."
               "\nYou can enable accessibility with sniff or by running:\n"
               "'gsettings set org.gnome.desktop.interface toolkit-accessibility true'\nAborting...")
    sys.exit(1)
Beispiel #47
0
    def clickForward(self):
        """
        Click on the 'Forward' button to advance to next page of wizard.

        It will log the title of the new page that is reached.

        FIXME: what if it's Next rather than Forward ???

        This will only work if your libgnomeui has accessible buttons;
        see above.
        """
        fwd = self.child("Forward")
        fwd.click()

        # Log the new wizard page; it's helpful when debugging scripts
        logger.log(str("%s is now on '%s' page") % (self, str(self.getPageTitle())))
Beispiel #48
0
 def do(self):
     """
     Performs the given tree.Action, with appropriate delays and logging.
     """
     logger.log(str("%s on %s") % (str(self.name), self.node.getLogString()))
     if not self.node.sensitive:
         if config.ensureSensitivity:
             raise NotSensitiveError(self)
         else:
             nSE = NotSensitiveError(self)
             logger.log("Warning: " + str(nSE))
     if config.blinkOnActions:
         self.node.blink()
     result = self.__action.doAction(self.__index)
     doDelay(config.actionDelay)
     return result
Beispiel #49
0
def translate(srcString):
    """
    Look up srcString in the various translation databases (if any), returning
    a list of all matches found (potentially the empty list)
    """
    # Use a dict to get uniqueness:
    results = {}
    # Try to translate the string:
    for translationDb in translationDbs:
        for result in translationDb.getTranslationsOf(srcString):
            results[result] = True

    # No translations found:
    if len(results) == 0:
        if config.config.debugTranslation:
            logger.log('Translation not found for "%s"' % srcString)
    return list(results.keys())
Beispiel #50
0
def bailBecauseA11yIsDisabled():
    if sys.argv[0].endswith("pydoc"):
        return
    try:
        with open("/proc/%s/cmdline" % os.getpid(), 'r') as f:
            content = f.read()
        if content.find('epydoc') != -1:
            return  # pragma: no cover
        if content.find('sphinx') != -1:
            return  # pragma: no cover
    except:  # pragma: no cover
        pass  # pragma: no cover
    logger.log(
        "Dogtail requires that Assistive Technology support be enabled."
        "\nYou can enable accessibility with sniff or by running:\n"
        "'gsettings set org.gnome.desktop.interface toolkit-accessibility true'\nAborting..."
    )
    sys.exit(1)
Beispiel #51
0
    def getRelativeSearch(self):
        """
        Get a (ancestorNode, predicate, isRecursive) triple that identifies the
        best way to find this Node uniquely.
        FIXME: or None if no such search exists?
        FIXME: may need to make this more robust
        FIXME: should this be private?
        """
        if config.debugSearchPaths:
            logger.log("getRelativeSearchPath(%s)" % self)

        assert self
        assert self.parent

        isRecursive = False
        ancestor = self.parent

        # iterate up ancestors until you reach an identifiable one,
        # setting the search to be isRecursive if need be:
        while not self.__nodeIsIdentifiable(ancestor):
            ancestor = ancestor.parent
            isRecursive = True

        # Pick the most appropriate predicate for finding this node:
        if self.labellee:
            if self.labellee.name:
                return (ancestor, predicate.IsLabelledAs(self.labellee.name), isRecursive)

        if self.roleName == 'menu':
            return (ancestor, predicate.IsAMenuNamed(self.name), isRecursive)
        elif self.roleName == 'menu item' or self.roleName == 'check menu item':
            return (ancestor, predicate.IsAMenuItemNamed(self.name), isRecursive)
        elif self.roleName == 'text':
            return (ancestor, predicate.IsATextEntryNamed(self.name), isRecursive)
        elif self.roleName == 'push button':
            return (ancestor, predicate.IsAButtonNamed(self.name), isRecursive)
        elif self.roleName == 'frame':
            return (ancestor, predicate.IsAWindowNamed(self.name), isRecursive)
        elif self.roleName == 'dialog':
            return (ancestor, predicate.IsADialogNamed(self.name), isRecursive)
        else:
            pred = predicate.GenericPredicate(
                name=self.name, roleName=self.roleName)
            return (ancestor, pred, isRecursive)
Beispiel #52
0
    def getAbsoluteSearchPath(self):
        """
        FIXME: this needs rewriting...
        Generate a SearchPath instance giving the 'best'
        way to find the Accessible wrapped by this node again, starting
        at the root and applying each search in turn.

        This is somewhat analagous to an absolute path in a filesystem,
        except that some of searches may be recursive, rather than just
        searching direct children.

        Used by the recording framework for identifying nodes in a
        persistent way, independent of the style of script being
        written.

        FIXME: try to ensure uniqueness
        FIXME: need some heuristics to get 'good' searches, whatever
        that means
        """
        if config.debugSearchPaths:
            logger.log("getAbsoluteSearchPath(%s)" % self)

        if self.roleName == 'application':
            result = path.SearchPath()
            result.append(predicate.IsAnApplicationNamed(self.name), False)
            return result
        else:
            if self.parent:
                (ancestor, pred, isRecursive) = self.getRelativeSearch()
                if config.debugSearchPaths:
                    logger.log("got ancestor: %s" % ancestor)

                ancestorPath = ancestor.getAbsoluteSearchPath()
                ancestorPath.append(pred, isRecursive)
                return ancestorPath
            else:
                # This should be the root node:
                return path.SearchPath()
Beispiel #53
0
 def keyCombo(self, comboString):
     if config.debugSearching:
         logger.log("Pressing keys '%s' into %s" % (comboString, self.getLogString()))
     if self.focusable:
         if not self.focused:
             try:
                 self.grabFocus()
             except Exception:
                 logger.log("Node is focusable but I can't grabFocus!")
     else:
         logger.log("Node is not focusable; trying key combo anyway")
     rawinput.keyCombo(comboString)