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)
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))
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)
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
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)
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
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)
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)
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())))
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
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))
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))
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)