99import logging
1010import os
1111import re
12- import sys
1312import subprocess
14- from distutils .version import StrictVersion , LooseVersion
13+ import sys
14+ from distutils .version import LooseVersion
1515
1616from . import exc
1717from ._compat import console_to_str
1818
1919logger = 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+
2229class 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
461523def 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
0 commit comments