[kupfer] commands: Implement Run (Get Output) using AsyncCommand
- From: Ulrik Sverdrup <usverdrup src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [kupfer] commands: Implement Run (Get Output) using AsyncCommand
- Date: Tue, 4 May 2010 23:08:12 +0000 (UTC)
commit c61f81f808b5241357504f2960c789d8234a8c49
Author: Ulrik Sverdrup <ulrik sverdrup gmail com>
Date: Wed May 5 01:01:25 2010 +0200
commands: Implement Run (Get Output) using AsyncCommand
Finally we have implemented "Get results from commandline" in a sane
way: completely asynchronous, with a timeout to kill the process, and
with asynchronous return of output to the user. (Kupfer is starting to
get good :-)
(Also change the from os import (..) in commands, it doesn't make any
sense now.)
kupfer/plugin/commands.py | 47 ++++++++++++++++++++++++++++++++++++++++----
kupfer/utils.py | 11 ++++++++-
2 files changed, 51 insertions(+), 7 deletions(-)
---
diff --git a/kupfer/plugin/commands.py b/kupfer/plugin/commands.py
index 80312d4..c1edbb8 100644
--- a/kupfer/plugin/commands.py
+++ b/kupfer/plugin/commands.py
@@ -6,15 +6,51 @@ __version__ = ""
__author__ = "Ulrik Sverdrup <ulrik sverdrup gmail com>"
import os
-# import symbols in tight loop to local namespace
-from os import access, R_OK, X_OK, path
+import shlex
import gobject
-from kupfer.objects import TextSource, Leaf, TextLeaf
+from kupfer.objects import TextSource, Leaf, TextLeaf, Action
from kupfer.obj.fileactions import Execute
from kupfer import utils, icons
+from kupfer import commandexec
+from kupfer import kupferstring
+from kupfer import pretty
+def unicode_shlex_split(ustr, **kwargs):
+ """shlex.split is depressingly broken on unicode input"""
+ s_str = ustr.encode("UTF-8")
+ return [kupferstring.tounicode(t) for t in shlex.split(s_str, **kwargs)]
+
+
+class GetOutput (Action):
+ def __init__(self):
+ Action.__init__(self, _("Run (Get Output)"))
+
+ def activate(self, leaf):
+ # use shlex to allow simple quoting
+ commandline = leaf.object
+ try:
+ argv = unicode_shlex_split(commandline)
+ except ValueError:
+ # Exception raised on unpaired quotation marks
+ if " " in commandline:
+ argv = commandline.split(None, 1)
+ else:
+ argv = [commandline]
+ ctx = commandexec.DefaultActionExecutionContext()
+ token = ctx.get_async_token()
+ pretty.print_debug(__name__, "Spawning with timeout 15 seconds")
+ acom = utils.AsyncCommand(argv, self.finish_callback, 15)
+ acom.token = token
+
+ def finish_callback(self, acommand, output):
+ ctx = commandexec.DefaultActionExecutionContext()
+ leaf = TextLeaf(kupferstring.fromlocale(output))
+ ctx.register_late_result(acommand.token, leaf)
+
+ def get_description(self):
+ return _("Run program and return its output")
class Command (TextLeaf):
def __init__(self, exepath, name):
@@ -24,6 +60,7 @@ class Command (TextLeaf):
def get_actions(self):
yield Execute(quoted=False)
yield Execute(in_terminal=True, quoted=False)
+ yield GetOutput()
def get_description(self):
args = u" ".join(unicode(self).split(None, 1)[1:])
@@ -54,10 +91,10 @@ class CommandTextSource (TextSource):
# iterate over $PATH directories
PATH = os.environ.get("PATH") or os.defpath
for execdir in PATH.split(os.pathsep):
- exepath = path.join(execdir, firstword)
+ exepath = os.path.join(execdir, firstword)
# use filesystem encoding here
exepath = gobject.filename_from_utf8(exepath)
- if access(exepath, R_OK | X_OK) and path.isfile(exepath):
+ if os.access(exepath, os.R_OK|os.X_OK) and os.path.isfile(exepath):
yield Command(exepath, text)
break
def get_description(self):
diff --git a/kupfer/utils.py b/kupfer/utils.py
index 6ca51d9..69bd5b4 100644
--- a/kupfer/utils.py
+++ b/kupfer/utils.py
@@ -70,6 +70,10 @@ def locale_sort(seq, key=unicode):
seq.sort(cmp=locale_cmp)
return seq
+def _argv_to_locale(argv):
+ "encode unicode strings in @argv according to the locale encoding"
+ return [kupferstring.tolocale(A) if isinstance(A, unicode) else A
+ for A in argv]
class AsyncCommand (object):
# the maximum input (bytes) we'll read in one shot (one io_callback)
@@ -90,6 +94,10 @@ class AsyncCommand (object):
self.killed = False
self.finished = False
self.finish_callback = finish_callback
+
+ argv = _argv_to_locale(argv)
+ pretty.print_debug(__name__, "AsyncCommand:", argv)
+
flags = (glib.SPAWN_SEARCH_PATH | glib.SPAWN_STDERR_TO_DEV_NULL |
glib.SPAWN_DO_NOT_REAP_CHILD)
pid, stdin_fd, stdout_fd, stderr_fd = \
@@ -132,8 +140,7 @@ class AsyncCommand (object):
def spawn_async(argv, in_dir="."):
pretty.print_debug(__name__, "Spawn commandline", argv, in_dir)
- argv = [kupferstring.tolocale(A) if isinstance(A, unicode) else A
- for A in argv]
+ argv = _argv_to_locale(argv)
try:
return gobject.spawn_async (argv, working_directory=in_dir,
flags=gobject.SPAWN_SEARCH_PATH)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]