Skip to content

Commit 0915680

Browse files
authored
Merge pull request #8 from tony/show-option-error
Add UnknownOption exception, Return None on empty option val
2 parents b81c472 + a23da9a commit 0915680

File tree

8 files changed

+104
-40
lines changed

8 files changed

+104
-40
lines changed

CHANGES

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ Changelog
44

55
Here you can find the recent changes to libtmux
66

7+
- :feature:`8` new exception ``UnknownOption``
8+
- :feature:`8` return ``None`` for options that are valid tmux options,
9+
but unset at that scope.
710
- :support:`6` major documentation overhaul
811

912
- :release:`0.4.1 <2016-05-23>`

doc/about.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ libtmux is an `abstraction layer`_ for tmux.
1313

1414
It builds upon the concept of targets ``-t``, to direct commands against
1515
individual session, windows and panes and ``FORMATS``, template variables
16-
exposed by tmux to describe their properties.
16+
exposed by tmux to describe their properties. Think of ``-t`` analagously
17+
to `scope`_.
1718

1819
:class:`common.TmuxRelationalObject` acts as a container to connect the
1920
relations of :class:`Server`, :class:`Session`, :class:`Window` and
@@ -101,3 +102,4 @@ Reference
101102
- tmux source code http://sourceforge.net/p/tmux/tmux-code/ci/master/tree/
102103

103104
.. _abstraction layer: http://en.wikipedia.org/wiki/Abstraction_layer
105+
.. _scope: https://en.wikipedia.org/wiki/Variable_(computer_science)#Scope_and_extent

doc/api.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ Exceptions
7373

7474
.. autoexception:: libtmux.exc.TmuxSessionExists
7575

76+
.. autoexception:: libtmux.exc.UnknownOption
77+
7678
Test tools
7779
----------
7880

libtmux/exc.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,10 @@ class TmuxSessionExists(LibTmuxException):
1919
"""Session does not exist in the server."""
2020

2121
pass
22+
23+
24+
class UnknownOption(LibTmuxException):
25+
26+
"""Option unknown to tmux show-option(s) or show-window-option(s)."""
27+
28+
pass

libtmux/session.py

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,13 @@ def __init__(self, server=None, **kwargs):
4343
self.server._update_windows()
4444

4545
@property
46-
def _info(self, *args):
46+
def _info(self):
4747

4848
attrs = {
4949
'session_id': str(self._session_id)
5050
}
5151

52-
# from https://github.com/serkanyersen/underscore.py
53-
def by(val, *args):
52+
def by(val):
5453
for key, value in attrs.items():
5554
try:
5655
if attrs[key] != val[key]:
@@ -324,7 +323,7 @@ def attached_pane(self):
324323

325324
return self.attached_window.attached_pane
326325

327-
def set_option(self, option, value):
326+
def set_option(self, option, value, g=False):
328327
"""Set option ``$ tmux set-option <option> <value>``.
329328
330329
todo: needs tests
@@ -334,6 +333,8 @@ def set_option(self, option, value):
334333
:param value: window value. True/False will turn in 'on' and 'off'. You
335334
can also enter 'on' or 'off' directly.
336335
:type value: bool
336+
:param global: check for option globally across all servers (-g)
337+
:type global: bool
337338
338339
"""
339340

@@ -342,14 +343,22 @@ def set_option(self, option, value):
342343
elif isinstance(value, bool) and not value:
343344
value = 'off'
344345

346+
tmux_args = tuple()
347+
348+
if g:
349+
tmux_args += ('-g',)
350+
351+
tmux_args += (option, value,)
352+
345353
proc = self.cmd(
346-
'set-option', option, value
354+
'set-option', *tmux_args
347355
)
348356

349-
if proc.stderr:
350-
if isinstance(proc.stderr, list) and len(proc.stderr) == int(1):
351-
proc.stderr = proc.stderr[0]
352-
raise ValueError('tmux set-option stderr: %s' % proc.stderr)
357+
if isinstance(proc.stderr, list) and len(proc.stderr):
358+
error = proc.stderr[0]
359+
if 'unknown option' in error:
360+
raise exc.UnknownOption(error)
361+
raise ValueError('tmux set-option stderr: %s' % error)
353362

354363
def show_options(self, option=None, g=False):
355364
"""Return a dict of options for the window.
@@ -359,7 +368,7 @@ def show_options(self, option=None, g=False):
359368
360369
:param option: optional. show a single option.
361370
:type option: string
362-
:param g: Pass ``-g`` flag for global variable
371+
:param g: Pass ``-g`` flag for global variable (server-wide)
363372
:type g: bool
364373
:rtype: :py:obj:`dict`
365374
@@ -395,6 +404,8 @@ def show_option(self, option, g=False):
395404
396405
:param option: option to return.
397406
:type option: string
407+
:param global: check for option globally across all servers (-g)
408+
:type global: bool
398409
:rtype: string, int or bool
399410
400411
"""
@@ -404,15 +415,28 @@ def show_option(self, option, g=False):
404415
if g:
405416
tmux_args += ('-g',)
406417

407-
window_option = self.cmd(
408-
'show-options', option, *tmux_args
409-
).stdout
410-
window_option = [tuple(item.split(' ')) for item in window_option][0]
418+
tmux_args += (option,)
419+
420+
cmd = self.cmd(
421+
'show-options', *tmux_args
422+
)
423+
424+
if isinstance(cmd.stderr, list) and len(cmd.stderr):
425+
error = cmd.stderr[0]
426+
if 'unknown option' in error:
427+
raise exc.UnknownOption(error)
428+
else:
429+
raise exc.LibTmuxException(error)
430+
431+
if not len(cmd.stdout):
432+
return None
433+
434+
option = [item.split(' ') for item in cmd.stdout][0]
411435

412-
if window_option[1].isdigit():
413-
window_option = (window_option[0], int(window_option[1]))
436+
if option[1].isdigit():
437+
option = (option[0], int(option[1]))
414438

415-
return window_option[1]
439+
return option[1]
416440

417441
def __repr__(self):
418442
return "%s(%s %s)" % (

libtmux/window.py

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -142,24 +142,26 @@ def set_window_option(self, option, value):
142142
elif isinstance(value, bool) and not value:
143143
value = 'off'
144144

145-
process = self.cmd(
145+
cmd = self.cmd(
146146
'set-window-option',
147147
'-t%s:%s' % (self.get('session_id'), self.index),
148148
# '-t%s' % self.id,
149149
option, value
150150
)
151151

152-
if process.stderr:
153-
if isinstance(process.stderr, list) and len(process.stderr):
154-
process.stderr = process.stderr[0]
152+
if isinstance(cmd.stderr, list) and len(cmd.stderr):
153+
error = cmd.stderr[0]
154+
if 'unknown option' in error:
155+
raise exc.UnknownOption(error)
156+
155157
raise ValueError(
156158
'tmux set-window-option -t%s:%s %s %s\n' % (
157159
self.get('session_id'),
158160
self.index,
159161
option,
160162
value
161163
) +
162-
process.stderr
164+
cmd.stderr
163165
)
164166

165167
def show_window_options(self, option=None, g=False):
@@ -185,13 +187,13 @@ def show_window_options(self, option=None, g=False):
185187
return self.show_window_option(option, g=g)
186188
else:
187189
tmux_args += ('show-window-options',)
188-
window_options = self.cmd(
190+
cmd = self.cmd(
189191
*tmux_args
190192
).stdout
191193

192-
window_options = [tuple(item.split(' ')) for item in window_options]
194+
cmd = [tuple(item.split(' ')) for item in cmd]
193195

194-
window_options = dict(window_options)
196+
window_options = dict(cmd)
195197

196198
for key, value in window_options.items():
197199
if value.isdigit():
@@ -219,20 +221,22 @@ def show_window_option(self, option, g=False):
219221

220222
tmux_args += (option,)
221223

222-
window_option = self.cmd(
224+
cmd = self.cmd(
223225
'show-window-options', *tmux_args
224-
).stdout
226+
)
225227

226-
if window_option:
227-
window_option = [tuple(item.split(' '))
228-
for item in window_option][0]
229-
else:
228+
if len(cmd.stderr) and 'unknown option' in cmd.stderr[0]:
229+
raise exc.UnknownOption(cmd.stderr[0])
230+
231+
if not len(cmd.stdout):
230232
return None
231233

232-
if window_option[1].isdigit():
233-
window_option = (window_option[0], int(window_option[1]))
234+
option = [item.split(' ') for item in cmd.stdout][0]
235+
236+
if option[1].isdigit():
237+
option = (option[0], int(option[1]))
234238

235-
return window_option[1]
239+
return option[1]
236240

237241
def rename_window(self, new_name):
238242
"""Return :class:`Window` object ``$ tmux rename-window <new_name>``.

tests/test_session.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import pytest
1010

11-
from libtmux import Pane, Session, Window
11+
from libtmux import Pane, Session, Window, exc
1212
from libtmux.test import TEST_SESSION_PREFIX, namer
1313

1414
logger = logging.getLogger(__name__)
@@ -130,9 +130,19 @@ def test_set_show_option(session):
130130
assert session.show_option('history-limit') == 40
131131

132132

133+
def test_empty_session_option_returns_None(session):
134+
assert session.show_option('default-shell') is None
135+
136+
137+
def test_show_option_unknown(session):
138+
"""Session.show_option raises UnknownOption for bad option key."""
139+
with pytest.raises(exc.UnknownOption):
140+
session.show_option('moooz')
141+
142+
133143
def test_set_option_bad(session):
134-
"""Session.set_option raises ValueError for bad option key."""
135-
with pytest.raises(ValueError):
144+
"""Session.set_option raises UnknownOption for bad option key."""
145+
with pytest.raises(exc.UnknownOption):
136146
session.set_option('afewewfew', 43)
137147

138148

tests/test_window.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import logging
88
import pytest
99

10-
from libtmux import Pane, Server, Window
10+
from libtmux import Pane, Server, Window, exc
1111

1212

1313
logger = logging.getLogger(__name__)
@@ -169,6 +169,11 @@ def test_set_show_window_options(session):
169169
assert window.show_window_options()['main-pane-height'] == 40
170170

171171

172+
def test_empty_window_option_returns_None(session):
173+
window = session.new_window(window_name='test_window')
174+
assert window.show_window_option('default-shell') is None
175+
176+
172177
def test_show_window_option(session):
173178
"""Set option then Window.show_window_option(key)."""
174179
window = session.new_window(window_name='test_window')
@@ -181,10 +186,17 @@ def test_show_window_option(session):
181186
assert window.show_window_option('main-pane-height') == 40
182187

183188

189+
def test_show_window_option_unknown(session):
190+
"""Window.show_window_option raises UnknownOption for bad option key."""
191+
window = session.new_window(window_name='test_window')
192+
with pytest.raises(exc.UnknownOption):
193+
window.show_window_option('moooz')
194+
195+
184196
def test_set_window_option_bad(session):
185197
"""Window.set_window_option raises ValueError for bad option key."""
186198

187199
window = session.new_window(window_name='test_window')
188200

189-
with pytest.raises(ValueError):
201+
with pytest.raises(exc.UnknownOption):
190202
window.set_window_option('afewewfew', 43)

0 commit comments

Comments
 (0)