Skip to content

Commit 3963a8a

Browse files
committed
Merge branch 'v2.4-options'
2 parents e66e77d + 7e97e50 commit 3963a8a

File tree

12 files changed

+373
-126
lines changed

12 files changed

+373
-126
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ language: python
22

33
sudo: false
44
python:
5-
- 2.6
65
- 2.7
76
- 3.3
87
- 3.4
@@ -12,6 +11,7 @@ python:
1211
- pypy3.3-5.2-alpha1
1312
env:
1413
- TMUX_VERSION=master
14+
- TMUX_VERSION=2.4
1515
- TMUX_VERSION=2.3
1616
- TMUX_VERSION=2.2
1717
- TMUX_VERSION=2.1

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ Project details
179179

180180
============== ==========================================================
181181
tmux support 1.8, 1.9a, 2.0, 2.1, 2.2, 2.3
182-
python support 2.6, 2.7, >= 3.3, pypy, pypy3
182+
python support 2.7, >= 3.3, pypy, pypy3
183183
Source https://github.com/tony/libtmux
184184
Docs http://libtmux.git-pull.com
185185
API http://libtmux.git-pull.com/api.html

doc/api.rst

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ Pane Object
5252
Internals
5353
---------
5454

55+
56+
.. autodata:: libtmux.common.TMUX_MIN_VERSION
57+
58+
.. autodata:: libtmux.common.TMUX_MAX_VERSION
59+
5560
.. autoclass:: libtmux.common.TmuxRelationalObject
5661
:members:
5762

@@ -63,11 +68,21 @@ Internals
6368

6469
.. autoclass:: libtmux.common.tmux_cmd
6570

66-
.. automethod:: libtmux.common.has_required_tmux_version
67-
6871
.. automethod:: libtmux.common.which
6972

70-
.. automethod:: libtmux.common.is_version
73+
.. automethod:: libtmux.common.has_version
74+
75+
.. automethod:: libtmux.common.has_gt_version
76+
77+
.. automethod:: libtmux.common.has_gte_version
78+
79+
.. automethod:: libtmux.common.has_lt_version
80+
81+
.. automethod:: libtmux.common.has_lte_version
82+
83+
.. automethod:: libtmux.common.has_minimum_version
84+
85+
.. automethod:: libtmux.common.handle_option_error
7186

7287
Exceptions
7388
----------
@@ -76,12 +91,20 @@ Exceptions
7691

7792
.. autoexception:: libtmux.exc.TmuxCommandNotFound
7893

94+
.. autoexception:: libtmux.exc.VersionTooLow
95+
7996
.. autoexception:: libtmux.exc.TmuxSessionExists
8097

8198
.. autoexception:: libtmux.exc.BadSessionName
8299

100+
.. autoexception:: libtmux.exc.OptionError
101+
83102
.. autoexception:: libtmux.exc.UnknownOption
84103

104+
.. autoexception:: libtmux.exc.InvalidOption
105+
106+
.. autoexception:: libtmux.exc.AmbiguousOption
107+
85108
Test tools
86109
----------
87110

doc/developing.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ libtmux uses `travis-ci`_ for continuous integration / automatic unit
170170
testing.
171171

172172
libtmux is tested against tmux 1.8 and the latest git source. Interpretters
173-
tested are 2.6, 2.7 and 3.3. The `travis build site`_ uses this
173+
tested are pypy, pypy3, 2.7 and >= 3.3. The `travis build site`_ uses this
174174
`.travis.yml`_ configuration:
175175

176176
.. literalinclude:: ../.travis.yml

libtmux/common.py

Lines changed: 133 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,23 @@
99
import logging
1010
import os
1111
import re
12-
import sys
1312
import subprocess
14-
from distutils.version import StrictVersion, LooseVersion
13+
import sys
14+
from distutils.version import LooseVersion
1515

1616
from . import exc
1717
from ._compat import console_to_str
1818

1919
logger = logging.getLogger(__name__)
2020

2121

22+
#: Minimum version of tmux required to run libtmux
23+
TMUX_MIN_VERSION = '1.8'
24+
25+
#: Most recent version of tmux supported
26+
TMUX_MAX_VERSION = '2.4'
27+
28+
2229
class EnvironmentMixin(object):
2330

2431
"""Mixin class for managing session and server level environment
@@ -274,8 +281,8 @@ class TmuxRelationalObject(object):
274281
Object .children method
275282
================ ========================= =================================
276283
:class:`Server` :attr:`Server._sessions` :meth:`Server.list_sessions`
277-
:class:`Session` :attr:`Sessions._windows` :meth:`Session.list_windows`
278-
:class:`Window` :attr:`Windows._panes` :meth:`Window.list_panes`
284+
:class:`Session` :attr:`Session._windows` :meth:`Session.list_windows`
285+
:class:`Window` :attr:`Window._panes` :meth:`Window.list_panes`
279286
:class:`Pane` n/a n/a
280287
================ ========================= =================================
281288
@@ -395,67 +402,122 @@ def _is_executable_file_or_link(exe):
395402
return None
396403

397404

398-
def is_version(version):
405+
def get_version():
406+
"""Return tmux version.
407+
408+
If tmux is built from git master, the version returned will be the latest
409+
version appended with -master, e.g. ``2.4-master``.
410+
411+
If using OpenBSD's base system tmux, the version will have ``-openbsd``
412+
appended to the latest version, e.g. ``2.4-openbsd``.
413+
414+
:returns: tmux version
415+
:rtype: :class:`distutils.version.LooseVersion`
416+
"""
417+
proc = tmux_cmd('-V')
418+
if proc.stderr:
419+
if proc.stderr[0] == 'tmux: unknown option -- V':
420+
if sys.platform.startswith("openbsd"): # openbsd has no tmux -V
421+
return LooseVersion('%s-openbsd' % TMUX_MAX_VERSION)
422+
raise exc.LibTmuxException(
423+
'libtmux supports tmux %s and greater. This system'
424+
' is running tmux 1.3 or earlier.' % TMUX_MIN_VERSION
425+
)
426+
raise exc.VersionTooLow(proc.stderr)
427+
428+
version = proc.stdout[0].split('tmux ')[1]
429+
430+
# Allow latest tmux HEAD
431+
if version == 'master':
432+
return LooseVersion('%s-master' % TMUX_MAX_VERSION)
433+
434+
version = re.sub(r'[a-z]', '', version)
435+
436+
return LooseVersion(version)
437+
438+
439+
def has_version(version):
399440
"""Return True if tmux version installed.
400441
401442
:param version: version, '1.8'
402-
:param type: string
443+
:type version: string
444+
:returns: True if version matches
403445
:rtype: bool
446+
"""
447+
return get_version() == LooseVersion(version)
448+
404449

450+
def has_gt_version(min_version):
451+
"""Return True if tmux version greater than minimum.
452+
453+
:param min_version: version, e.g. '1.8'
454+
:type min_version: string
455+
:returns: True if version above min_version
456+
:rtype: bool
405457
"""
406-
if sys.platform.startswith("openbsd"):
407-
if LooseVersion(version) > LooseVersion('2.1'):
408-
return 'openbsd'
409-
else:
410-
return False
458+
return get_version() > LooseVersion(min_version)
411459

412-
proc = tmux_cmd('-V')
413460

414-
if proc.stderr:
415-
raise exc.LibTmuxException(proc.stderr)
461+
def has_gte_version(min_version):
462+
"""Return True if tmux version greater or equal to minimum.
416463
417-
installed_version = proc.stdout[0].split('tmux ')[1]
464+
:param min_version: version, e.g. '1.8'
465+
:type min_version: string
466+
:returns: True if version above or equal to min_version
467+
:rtype: bool
468+
"""
469+
return get_version() >= LooseVersion(min_version)
418470

419-
return LooseVersion(installed_version) == LooseVersion(version)
420471

472+
def has_lte_version(max_version):
473+
"""Return True if tmux version less or equal to minimum.
421474
422-
def has_required_tmux_version(version=None):
423-
"""Return if tmux meets version requirement. Version >1.8 or above.
475+
:param max_version: version, e.g. '1.8'
476+
:type max_version: string
477+
:returns: True if version below or equal to max_version
478+
:rtype: bool
479+
"""
480+
return get_version() <= LooseVersion(max_version)
424481

425-
:versionchanged: 0.1.7
426-
Versions will now remove trailing letters per `Issue 55`_.
427482

428-
.. _Issue 55: https://github.com/tony/tmuxp/issues/55.
483+
def has_lt_version(max_version):
484+
"""Return True if tmux version less than minimum.
429485
486+
:param max_version: version, e.g. '1.8'
487+
:type max_version: string
488+
:returns: True if version below max_version
489+
:rtype: bool
430490
"""
491+
return get_version() < LooseVersion(max_version)
431492

432-
if not version:
433-
if sys.platform.startswith("openbsd"): # openbsd has no tmux -V
434-
return '2.3'
435493

436-
proc = tmux_cmd('-V')
494+
def has_minimum_version(raises=True):
495+
"""Return if tmux meets version requirement. Version >1.8 or above.
437496
438-
if proc.stderr:
439-
if proc.stderr[0] == 'tmux: unknown option -- V':
440-
raise exc.LibTmuxException(
441-
'libtmux supports tmux 1.8 and greater. This system'
442-
' is running tmux 1.3 or earlier.')
443-
raise exc.LibTmuxException(proc.stderr)
497+
:param raises: Will raise exception if version too low, default ``True``
498+
:type raises: bool
499+
:returns: True if tmux meets minimum required version
500+
:rtype: bool
444501
445-
version = proc.stdout[0].split('tmux ')[1]
502+
:versionchanged: 0.7.0
503+
No longer returns version, returns True or False
504+
:versionchanged: 0.1.7
505+
Versions will now remove trailing letters per `Issue 55`_.
446506
447-
# Allow latest tmux HEAD
448-
if version == 'master':
449-
return version
507+
.. _Issue 55: https://github.com/tony/tmuxp/issues/55.
450508
451-
version = re.sub(r'[a-z]', '', version)
509+
"""
452510

453-
if StrictVersion(version) <= StrictVersion("1.7"):
454-
raise exc.LibTmuxException(
455-
'libtmux only supports tmux 1.8 and greater. This system'
456-
' has %s installed. Upgrade your tmux to use libtmux.' % version
457-
)
458-
return version
511+
if get_version() < LooseVersion(TMUX_MIN_VERSION):
512+
if raises:
513+
raise exc.VersionTooLow(
514+
'libtmux only supports tmux %s and greater. This system'
515+
' has %s installed. Upgrade your tmux to use libtmux.' %
516+
(TMUX_MIN_VERSION, get_version())
517+
)
518+
else:
519+
return False
520+
return True
459521

460522

461523
def session_check_name(session_name):
@@ -477,3 +539,32 @@ def session_check_name(session_name):
477539
elif ':' in session_name:
478540
raise exc.BadSessionName(
479541
"tmux session name \"%s\" may not contain colons.", session_name)
542+
543+
544+
def handle_option_error(error):
545+
"""Raises exception if error in option command found.
546+
547+
Purpose: As of tmux 2.4, there are now 3 different types of option errors:
548+
549+
- unknown option
550+
- invalid option
551+
- ambiguous option
552+
553+
Before 2.4, unknown option was the user.
554+
555+
All errors raised will have the base error of :exc:`exc.OptionError`. So to
556+
catch any option error, use ``except exc.OptionError``.
557+
558+
:param error: error response from subprocess call
559+
:type error: str
560+
:raises: :exc:`exc.OptionError`, :exc:`exc.UnknownOption`,
561+
:exc:`exc.InvalidOption`, :exc:`excAmbiguousOption`
562+
"""
563+
if 'unknown option' in error:
564+
raise exc.UnknownOption(error)
565+
elif 'invalid option' in error:
566+
raise exc.InvalidOption(error)
567+
elif 'ambiguous option' in error:
568+
raise exc.AmbiguousOption(error)
569+
else:
570+
raise exc.OptionError(error) # Raise generic option error

libtmux/exc.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,43 @@ class TmuxCommandNotFound(LibTmuxException):
2727
pass
2828

2929

30+
class VersionTooLow(LibTmuxException):
31+
32+
"""Raised if tmux below the minimum version to use libtmux."""
33+
34+
pass
35+
36+
3037
class BadSessionName(LibTmuxException):
3138

3239
"""Disallowed session name for tmux (empty, contains periods or colons)."""
3340

3441
pass
3542

3643

37-
class UnknownOption(LibTmuxException):
44+
class OptionError(LibTmuxException):
45+
46+
"""Root error for any error involving invalid, ambiguous or bad options."""
47+
48+
pass
49+
50+
51+
class UnknownOption(OptionError):
3852

3953
"""Option unknown to tmux show-option(s) or show-window-option(s)."""
4054

4155
pass
56+
57+
58+
class InvalidOption(OptionError):
59+
60+
"""Option invalid to tmux, introduced in tmux v2.4."""
61+
62+
pass
63+
64+
65+
class AmbiguousOption(OptionError):
66+
67+
"""Option that could potentially match more than one."""
68+
69+
pass

0 commit comments

Comments
 (0)