コード例 #1
0
    def _execute(self, data=None):
        engine = get_engine()
        words = self._words

        # If an extra was given, retrieve the associated value from
        #  the *data* dict and append it to the static words.
        if self._extra:
            try:
                extra = data[self._extra]
            except KeyError:
                raise ActionError("No extra data available for extra %r"
                                  % self._extra)

            # Append the extra data to the static words depending on
            #  the type of the extra data object.
            if isinstance(extra, engine.DictationContainer):
                words += tuple(extra.words)
            elif isinstance(extra, (tuple, list)):
                words += tuple(extra)
            elif isinstance(extra, string_types):
                words += (extra,)
            else:
                raise ActionError("Invalid extra data type: %r" % extra)

        # Mimic the series of words.
        self._log.debug("Mimicking recognition: %r", words)
        try:
            engine.disable_recognition_observers()
            engine.mimic(words)
            engine.enable_recognition_observers()
        except Exception as e:
            raise ActionError("Mimicking failed: %s" % e)
コード例 #2
0
    def __init__(self, *args, **kwargs):
        """
            Constructor arguments:
             - *args* (variable argument list of *str*'s) --
               these strings are passed to subprocess.Popen()
               to start the application as a child process
             - *cwd* (*str*, default *None*) --
               if not *None*, then start the application in this
               directory
             - *focus_after_start* (*bool*, default *False*) --
               if *True*, then attempt to bring the window to the foreground
               after starting the application.

            A single *list* or *tuple* argument can be used instead of
            variable arguments.

        """
        ActionBase.__init__(self)
        if len(args) == 1 and isinstance(args[0], (tuple, list)):
            args = args[0]  # use the sub-list instead

        self._args = args

        self._cwd = kwargs.pop("cwd", None)
        self._focus_after_start = kwargs.pop("focus_after_start", False)
        if kwargs:
            raise ActionError("Invalid keyword arguments: %r" % kwargs)

        # Expand any variables within path names.
        self._args = [self._interpret(a) for a in self._args]
        if self._cwd:
            self._cwd = self._interpret(self._cwd)

        self._str = str(", ".join(repr(a) for a in self._args))
コード例 #3
0
ファイル: _base.py プロジェクト: tripfish/dragonfly
 def execute(self, window):
     position = self._get_position()
     if not position:
         raise ActionError("Failed to retrieve cursor position.")
     horizontal = position[0] + self.horizontal
     vertical = position[1] + self.vertical
     self._move_mouse(horizontal, vertical)
コード例 #4
0
ファイル: action_key.py プロジェクト: LexiconCode/dragonfly
    def _calc_events_single(self, event_data, use_hardware):
        (keyname, direction, modifiers, inner_pause, repeat,
         outer_pause) = event_data

        # Get a Typeable object for the key, if possible.
        typeable = self._get_typeable(event_data.keyname, use_hardware)

        # Raise an error message if a Typeable could not be retrieved.
        if typeable is None:
            error_message = ("Keyboard interface cannot type this "
                             "character: %r (in %r)" %
                             (keyname, self._spec))
            raise ActionError(error_message)

        # Calculate keyboard events using the Typeable and event data.
        if direction is None:
            if inner_pause is None:
                inner_pause = self.interval_default * self.interval_factor
            if repeat == 0:
                events = []
            else:
                events = []
                for m in modifiers:
                    events.extend(m.on_events())
                for _ in range(repeat - 1):
                    events.extend(typeable.events(inner_pause))
                events.extend(typeable.events(outer_pause))
                for m in modifiers[-1::-1]:
                    events.extend(m.off_events())
        else:
            if direction:
                events = typeable.on_events(outer_pause)
            else:
                events = typeable.off_events(outer_pause)
        return events
コード例 #5
0
    def _execute(self, data=None):
        executable = self.executable
        title = self.title
        index = self.index
        if data and isinstance(data, dict):
            if executable: executable = (executable % data).lower()
            if title: title = (title % data).lower()
            if index: index = (index % data).lower()

        index = int(index) if index else 0

        # Get the first matching window and bring it to the foreground.
        windows = Window.get_matching_windows(executable, title)
        if self.filter_func:
            windows = [
                window for window in windows if self.filter_func(window)
            ]
        if windows and (index < len(windows)):
            window = windows[index]
            if self.focus_only:
                window.set_focus()
            else:
                window.set_foreground()
        else:
            raise ActionError("Failed to find window (%s)." % self._str)
コード例 #6
0
    def _execute_events(self, events):
        """
        Send keyboard events.

        If instance was initialized with *autofmt* True,
        then this method will mimic a word recognition
        and analyze its formatting so as to autoformat
        the text's spacing and capitalization before
        sending it as keyboard events.
        """
        if self._autofmt:
            # Mimic a word, select and copy it to retrieve capitalization.
            get_engine().mimic("test")
            Key("cs-left, c-c/5").execute()
            word = Clipboard.get_system_text()

            # Inspect formatting of the mimicked word.
            index = word.find("test")
            if index == -1:
                index = word.find("Test")
                capitalize = True
                if index == -1:
                    self._log.error("Failed to autoformat.")
                    return False
            else:
                capitalize = False

            # Capitalize given text if necessary.
            text = self._spec
            if capitalize:
                text = text[0].capitalize() + text[1:]

            # Reconstruct autoformatted output and convert it
            #  to keyboard events.
            prefix = word[:index]
            suffix = word[index + 4:]
            events = self._parse_spec(prefix + text + suffix)

        # Calculate keyboard events.
        use_hardware = self.require_hardware_events()
        keyboard_events = []
        for key_symbol in events:
            # Get a Typeable object for each key symbol, if possible.
            typeable = self._get_typeable(key_symbol, use_hardware)

            # Raise an error message if a Typeable could not be retrieved.
            if typeable is None:
                error_message = ("Keyboard interface cannot type this"
                                 " character: %r" % key_symbol)
                raise ActionError(error_message)

            # Get keyboard events using the Typeable.
            keyboard_events.extend(typeable.events(self._pause))

        # Send keyboard events.
        self._keyboard.send_keyboard_events(keyboard_events)
        return True
コード例 #7
0
    def _execute(self, data=None):
        engine = get_engine()

        # Mimic the series of recognitions.
        for words, interval in self._series:
            self._log.debug("Mimicking recognition: %r", words)
            try:
                engine.mimic(words)
                if interval and self._speed:
                    sleep(interval / self._speed)
            except Exception as e:
                raise ActionError("Playback failed: %s" % e)
コード例 #8
0
 def _execute(self, data=None):
     self._log.debug("Waiting for window context: %s" % self)
     start_time = time.time()
     while 1:
         foreground = Window.get_foreground()
         mismatch = False
         for match_name in self._match_functions:
             match_func = getattr(self, match_name)
             if not match_func(foreground):
                 mismatch = True
                 break
         if not mismatch:
             return
         if time.time() - start_time > self._timeout:
             raise ActionError("Timeout while waiting for window context: %s" % self)
コード例 #9
0
    def __init__(self, *words, **kwargs):
        ActionBase.__init__(self)
        self._words = tuple(words)
        if "extra" in kwargs:
            self._extra = kwargs.pop("extra")
        else:
            self._extra = None

        # Set pretty printing string used by __str__ and __unicode__.
        self._str = u", ".join(repr(w) for w in self._words)

        # Make sure that all keyword arguments have been consumed.
        if kwargs:
            raise ActionError("Invalid arguments: %r"
                              % ", ".join(list(kwargs.keys())))
コード例 #10
0
ファイル: action_mouse.py プロジェクト: LexiconCode/dragonfly
 def _parse_spec(self, spec):
     """ Convert the given *spec* to keyboard events. """
     events = []
     parts = self._split_parts(spec)
     for part in parts:
         handled = False
         for handler in self._handlers:
             try:
                 if handler(self, part, events):
                     handled = True
                     break
             except Exception:
                 continue
         if not handled:
             raise ActionError("Invalid mouse spec: %r (in %r)"
                               % (part, spec))
     return events
コード例 #11
0
    def _execute(self, data=None):
        arguments = dict(self._defaults)
        if isinstance(data, dict):
            arguments.update(data)

        # Remap specified names.
        if arguments and self._remap_data:
            for old_name, new_name in self._remap_data.items():
                if old_name in data:
                    arguments[new_name] = arguments.pop(old_name)

        if self._filter_keywords:
            invalid_keywords = set(arguments.keys()) - self._valid_keywords
            for key in invalid_keywords:
                del arguments[key]

        try:
            self._function(**arguments)
        except Exception as e:
            self._log.exception("Exception from function %s:",
                                self._function.__name__)
            raise ActionError("%s: %s" % (self, e))
コード例 #12
0
 def _start_app_process(self):
     try:
         return Popen(self._args, cwd=self._cwd)
     except Exception as e:
         raise ActionError("Failed to start app %s: %s" % (self._str, e))
コード例 #13
0
ファイル: action_key.py プロジェクト: LexiconCode/dragonfly
    def _parse_single(self, spec):
        # pylint: disable=R0912,R0914,R0915
        # Suppress warnings about too many branches, variables and
        # statements.

        # Remove leading and trailing whitespace.
        spec = spec.strip()
        if not spec:
            return None

        # Parse modifier prefix.
        index = spec.find(self._modifier_prefix_delimiter)
        if index != -1:
            s = spec[:index]
            index += 1
            modifiers = []
            for c in s:
                if c not in self._modifier_prefix_characters:
                    raise ActionError("Invalid modifier"
                                      " prefix character: %r" % c)
                m = self._modifier_prefix_characters[c]
                if m in modifiers:
                    raise ActionError("Double modifier"
                                      " prefix character: %r" % c)
                modifiers.append(m)
        else:
            index = 0
            modifiers = ()

        inner_pause = None
        special = None
        outer_pause = None

        delimiters = [(c, i + index) for i, c in enumerate(spec[index:])
                      if c in self._delimiter_characters]
        delimiter_sequence = "".join([d[0] for d in delimiters])
        delimiter_index = [d[1] for d in delimiters]

        if delimiter_sequence == "":
            keyname = spec[index:]
        elif delimiter_sequence == "/":
            keyname = spec[index:delimiter_index[0]]
            outer_pause = spec[delimiter_index[0]+1:]
        elif delimiter_sequence == "/:":
            keyname = spec[index:delimiter_index[0]]
            inner_pause = spec[delimiter_index[0]+1:delimiter_index[1]]
            special = spec[delimiter_index[1]+1:]
        elif delimiter_sequence == "/:/":
            keyname = spec[index:delimiter_index[0]]
            inner_pause = spec[delimiter_index[0]+1:delimiter_index[1]]
            special = spec[delimiter_index[1]+1:delimiter_index[2]]
            outer_pause = spec[delimiter_index[2]+1:]
        elif delimiter_sequence == ":":
            keyname = spec[index:delimiter_index[0]]
            special = spec[delimiter_index[0]+1:]
        elif delimiter_sequence == ":/":
            keyname = spec[index:delimiter_index[0]]
            special = spec[delimiter_index[0]+1:delimiter_index[1]]
            outer_pause = spec[delimiter_index[1]+1:]
        else:
            raise ActionError("Invalid key spec: %s" % spec)

        if inner_pause is not None:
            s = inner_pause
            try:
                inner_pause = float(s) * self.interval_factor
                if inner_pause < 0: raise ValueError
            except ValueError:
                raise ActionError("Invalid inner pause value: %r,"
                                  " should be a positive number." % s)
        if outer_pause is not None:
            s = outer_pause
            try:
                outer_pause = float(s) * self.interval_factor
                if outer_pause < 0: raise ValueError
            except ValueError:
                raise ActionError("Invalid outer pause value: %r,"
                                  " should be a positive number." % s)
        else:
            outer_pause = self.interval_default * self.interval_factor

        direction = None; repeat = 1
        if special is not None:
            if special == "down":   direction = True
            elif special == "up":   direction = False
            else:
                s = special
                try:
                    repeat = int(s)
                    if repeat < 0: raise ValueError
                except ValueError:
                    raise ActionError("Invalid repeat value: %r,"
                                      " should be a positive integer." % s)

        if direction is not None:
            if modifiers:
                raise ActionError("Cannot use direction with modifiers.")
            if inner_pause is not None:
                raise ActionError("Cannot use direction with inner pause.")

        return self.EventData(keyname, direction, modifiers, inner_pause,
                              repeat, outer_pause)