diff options
Diffstat (limited to 'meta/lib/oe/terminal.py')
-rw-r--r-- | meta/lib/oe/terminal.py | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/meta/lib/oe/terminal.py b/meta/lib/oe/terminal.py new file mode 100644 index 0000000000..3767935586 --- /dev/null +++ b/meta/lib/oe/terminal.py | |||
@@ -0,0 +1,101 @@ | |||
1 | import logging | ||
2 | import os | ||
3 | import oe.classutils | ||
4 | import shlex | ||
5 | from bb.process import Popen, ExecutionError | ||
6 | |||
7 | logger = logging.getLogger('BitBake.OE.Terminal') | ||
8 | |||
9 | |||
10 | class UnsupportedTerminal(StandardError): | ||
11 | pass | ||
12 | |||
13 | class NoSupportedTerminals(StandardError): | ||
14 | pass | ||
15 | |||
16 | |||
17 | class Registry(oe.classutils.ClassRegistry): | ||
18 | command = None | ||
19 | |||
20 | def __init__(cls, name, bases, attrs): | ||
21 | super(Registry, cls).__init__(name.lower(), bases, attrs) | ||
22 | |||
23 | @property | ||
24 | def implemented(cls): | ||
25 | return bool(cls.command) | ||
26 | |||
27 | |||
28 | class Terminal(Popen): | ||
29 | __metaclass__ = Registry | ||
30 | |||
31 | def __init__(self, command, title=None, env=None): | ||
32 | self.format_command(command, title) | ||
33 | |||
34 | try: | ||
35 | Popen.__init__(self, self.command, env=env) | ||
36 | except OSError as exc: | ||
37 | import errno | ||
38 | if exc.errno == errno.ENOENT: | ||
39 | raise UnsupportedTerminal(self.name) | ||
40 | else: | ||
41 | raise | ||
42 | |||
43 | def format_command(self, command, title): | ||
44 | fmt = {'title': title or 'Terminal', 'command': command} | ||
45 | if isinstance(self.command, basestring): | ||
46 | self.command = shlex.split(self.command.format(**fmt)) | ||
47 | else: | ||
48 | self.command = [element.format(**fmt) for element in self.command] | ||
49 | |||
50 | class XTerminal(Terminal): | ||
51 | def __init__(self, command, title=None, env=None): | ||
52 | Terminal.__init__(self, command, title, env) | ||
53 | if not os.environ.get('DISPLAY'): | ||
54 | raise UnsupportedTerminal(self.name) | ||
55 | |||
56 | class Gnome(XTerminal): | ||
57 | command = 'gnome-terminal --disable-factory -t "{title}" -x {command}' | ||
58 | priority = 2 | ||
59 | |||
60 | class Konsole(XTerminal): | ||
61 | command = 'konsole -T "{title}" -e {command}' | ||
62 | priority = 2 | ||
63 | |||
64 | class XTerm(XTerminal): | ||
65 | command = 'xterm -T "{title}" -e {command}' | ||
66 | priority = 1 | ||
67 | |||
68 | class Rxvt(XTerminal): | ||
69 | command = 'rxvt -T "{title}" -e {command}' | ||
70 | priority = 1 | ||
71 | |||
72 | class Screen(Terminal): | ||
73 | command = 'screen -D -m -t "{title}" {command}' | ||
74 | |||
75 | |||
76 | def prioritized(): | ||
77 | return Registry.prioritized() | ||
78 | |||
79 | def spawn_preferred(command, title=None, env=None): | ||
80 | """Spawn the first supported terminal, by priority""" | ||
81 | for terminal in prioritized(): | ||
82 | try: | ||
83 | spawn(terminal.name, command, title, env) | ||
84 | break | ||
85 | except UnsupportedTerminal: | ||
86 | continue | ||
87 | else: | ||
88 | raise NoSupportedTerminals() | ||
89 | |||
90 | def spawn(name, command, title=None, env=None): | ||
91 | """Spawn the specified terminal, by name""" | ||
92 | logger.debug(1, 'Attempting to spawn terminal "%s"', name) | ||
93 | try: | ||
94 | terminal = Registry.registry[name] | ||
95 | except KeyError: | ||
96 | raise UnsupportedTerminal(name) | ||
97 | |||
98 | pipe = terminal(command, title, env) | ||
99 | output = pipe.communicate()[0] | ||
100 | if pipe.returncode != 0: | ||
101 | raise ExecutionError(pipe.command, pipe.returncode, output) | ||