Skip to content

Raise exception for bad session names #14

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 16, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ env:
- TMUX_VERSION=2.0
- TMUX_VERSION=1.8
- TMUX_VERSION=1.9a
matrix:
allow_failures:
- env: TMUX_VERSION=master
before_install:
- export PIP_USE_MIRRORS=true
- pip install --upgrade pytest # https://github.com/travis-ci/travis-ci/issues/4873
Expand Down
4 changes: 4 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ Changelog

Here you can find the recent changes to libtmux

- :release:`0.6.0 <2016-09-16>`
- :bug:`-` Remove unused ``target_sesssion`` param in
``Server.attach_session`` and ``Server.switch_client``.

- :release:`0.5.1 <2016-08-18>`
- :bug:`12` - fix logger message when tmux doesn't exist in ``PATH``

Expand Down
21 changes: 21 additions & 0 deletions libtmux/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -420,3 +420,24 @@ def has_required_tmux_version(version=None):
' has %s installed. Upgrade your tmux to use libtmux.' % version
)
return version


def session_check_name(session_name):
"""Raises exception session name invalid, modeled after tmux function.

tmux(1) session names may not be empty, or include periods or colons.
These delimiters are reserved for noting session, window and pane.

:param session_name: name of session
:type session_name: string
:returns: void
:raises: :exc:`exc.BadSessionName`
"""
if not session_name or len(session_name) == 0:
raise exc.BadSessionName("tmux session names may not be empty.")
elif '.' in session_name:
raise exc.BadSessionName(
"tmux session name \"%s\" may not contain periods.", session_name)
elif ':' in session_name:
raise exc.BadSessionName(
"tmux session name \"%s\" may not contain colons.", session_name)
7 changes: 7 additions & 0 deletions libtmux/exc.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ class TmuxSessionExists(LibTmuxException):
pass


class BadSessionName(LibTmuxException):

"""Session name is not allowed."""

pass


class UnknownOption(LibTmuxException):

"""Option unknown to tmux show-option(s) or show-window-option(s)."""
Expand Down
21 changes: 17 additions & 4 deletions libtmux/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
import os

from . import exc, formats
from .common import EnvironmentMixin, TmuxRelationalObject, tmux_cmd
from .common import EnvironmentMixin, TmuxRelationalObject, tmux_cmd, \
session_check_name
from .session import Session

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -318,10 +319,13 @@ def has_session(self, target_session):
"""Return True if session exists. ``$ tmux has-session``.

:param: target_session: str of session name.
:raises: :exc:`exc.BadSessionName`
:rtype: bool

"""

session_check_name(target_session)

proc = self.cmd('has-session', '-t%s' % target_session)

if not proc.stdout:
Expand All @@ -335,6 +339,8 @@ def has_session(self, target_session):
return False
elif 'can\'t find session' in proc.stdout: # tmux 2.1
return False
elif 'bad session name' in proc.stdout: # tmux >= 1.9
return False
elif 'session not found' in proc.stdout:
return False
else:
Expand All @@ -349,10 +355,12 @@ def kill_session(self, target_session=None):

:param: target_session: str. note this accepts ``fnmatch(3)``. 'asdf'
will kill 'asdfasd'.

:raises: :exc:`exc.BadSessionName`
:rtype: :class:`Server`

"""
session_check_name(target_session)

proc = self.cmd('kill-session', '-t%s' % target_session)

if proc.stderr:
Expand All @@ -364,8 +372,9 @@ def switch_client(self, target_session):
"""``$ tmux switch-client``.

:param: target_session: str. name of the session. fnmatch(3) works.

:raises: :exc:`exc.BadSessionName`
"""
session_check_name(target_session)

proc = self.cmd('switch-client', '-t%s' % target_session)

Expand All @@ -376,8 +385,10 @@ def attach_session(self, target_session=None):
"""``$ tmux attach-session`` aka alias: ``$ tmux attach``.

:param: target_session: str. name of the session. fnmatch(3) works.

:raises: :exc:`exc.BadSessionName`
"""
session_check_name(target_session)

tmux_args = tuple()
if target_session:
tmux_args += ('-t%s' % target_session,)
Expand Down Expand Up @@ -418,9 +429,11 @@ def new_session(self,
:param kill_session: Kill current session if ``$ tmux has-session``
Useful for testing workspaces.
:type kill_session: bool
:raises: :exc:`exc.BadSessionName`
:rtype: :class:`Session`

"""
session_check_name(session_name)

if self.has_session(session_name):
if kill_session:
Expand Down
21 changes: 11 additions & 10 deletions libtmux/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
import os

from . import exc, formats
from .common import EnvironmentMixin, TmuxMappingObject, TmuxRelationalObject
from .common import EnvironmentMixin, TmuxMappingObject, \
TmuxRelationalObject, session_check_name
from .window import Window

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -75,12 +76,8 @@ def cmd(self, *args, **kwargs):
kwargs['-t'] = self.id
return self.server.cmd(*args, **kwargs)

def attach_session(self, target_session=None):
"""Return ``$ tmux attach-session`` aka alias: ``$ tmux attach``.

:param: target_session: str. name of the session. fnmatch(3) works.

"""
def attach_session(self):
"""Return ``$ tmux attach-session`` aka alias: ``$ tmux attach``."""
proc = self.cmd('attach-session', '-t%s' % self.id)

if proc.stderr:
Expand All @@ -94,10 +91,11 @@ def kill_session(self):
if proc.stderr:
raise exc.LibTmuxException(proc.stderr)

def switch_client(self, target_session=None):
def switch_client(self):
"""``$ tmux switch-client``.

:param: target_session: str. note this accepts fnmatch(3).
:raises: :exc:`exc.LibTmuxException`
"""
proc = self.cmd('switch-client', '-t%s' % self.id)

Expand All @@ -107,11 +105,14 @@ def switch_client(self, target_session=None):
def rename_session(self, new_name):
"""Rename session and return new :class:`Session` object.

:param rename_session: new session name
:type rename_session: string
:param new_name: new session name
:type new_name: string
:raises: :exc:`exc.BadSessionName`
:rtype: :class:`Session`

"""
session_check_name(new_name)

proc = self.cmd(
'rename-session',
'-t%s' % self.id,
Expand Down
21 changes: 19 additions & 2 deletions tests/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

import pytest

from libtmux.common import has_required_tmux_version, which
from libtmux.exc import LibTmuxException
from libtmux.common import has_required_tmux_version, which, session_check_name
from libtmux.exc import LibTmuxException, BadSessionName

version_regex = re.compile(r'[0-9]\.[0-9]')

Expand Down Expand Up @@ -50,3 +50,20 @@ def test_which_no_tmuxp_found(monkeypatch):
monkeypatch.setenv("PATH", "/")
which('tmuxp')
which('tmuxp', '/')


@pytest.mark.parametrize("session_name,raises,exc_msg_regex", [
('', True, 'may not be empty'),
(None, True, 'may not be empty'),
("my great session.", True, 'may not contain periods'),
("name: great session", True, 'may not contain colons'),
("new great session", False, None),
("ajf8a3fa83fads,,,a", False, None),
])
def test_session_check_name(session_name, raises, exc_msg_regex):
if raises:
with pytest.raises(BadSessionName) as exc_info:
session_check_name(session_name)
assert exc_info.match(exc_msg_regex)
else:
session_check_name(session_name)
31 changes: 31 additions & 0 deletions tests/test_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,3 +184,34 @@ def test_unset_environment(session):
assert session.show_environment('BAM') == 'OK'
session.unset_environment('BAM')
assert session.show_environment('BAM') is None


@pytest.mark.parametrize("session_name,raises", [
('hey.period', True),
('hey:its a colon', True),
('hey moo', False),
])
def test_periods_raise_badsessionname(server, session, session_name, raises):
new_name = session_name + 'moo' # used for rename / switch
if raises:
with pytest.raises(exc.BadSessionName):
session.rename_session(new_name)

with pytest.raises(exc.BadSessionName):
server.new_session(session_name)

with pytest.raises(exc.BadSessionName):
server.has_session(session_name)

with pytest.raises(exc.BadSessionName):
server.switch_client(new_name)

with pytest.raises(exc.BadSessionName):
server.attach_session(new_name)

else:
server.new_session(session_name)
server.has_session(session_name)
session.rename_session(new_name)
with pytest.raises(exc.LibTmuxException):
server.switch_client(new_name)