Skip to content

Commit c750123

Browse files
authored
Merge pull request #14 from tony/bad-session-name
Raise exception for bad session names
2 parents 0814211 + 72ce93f commit c750123

File tree

8 files changed

+113
-16
lines changed

8 files changed

+113
-16
lines changed

.travis.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ env:
1414
- TMUX_VERSION=2.0
1515
- TMUX_VERSION=1.8
1616
- TMUX_VERSION=1.9a
17+
matrix:
18+
allow_failures:
19+
- env: TMUX_VERSION=master
1720
before_install:
1821
- export PIP_USE_MIRRORS=true
1922
- pip install --upgrade pytest # https://github.com/travis-ci/travis-ci/issues/4873

CHANGES

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

55
Here you can find the recent changes to libtmux
66

7+
- :release:`0.6.0 <2016-09-16>`
8+
- :bug:`-` Remove unused ``target_sesssion`` param in
9+
``Server.attach_session`` and ``Server.switch_client``.
10+
711
- :release:`0.5.1 <2016-08-18>`
812
- :bug:`12` - fix logger message when tmux doesn't exist in ``PATH``
913

libtmux/common.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,3 +420,24 @@ def has_required_tmux_version(version=None):
420420
' has %s installed. Upgrade your tmux to use libtmux.' % version
421421
)
422422
return version
423+
424+
425+
def session_check_name(session_name):
426+
"""Raises exception session name invalid, modeled after tmux function.
427+
428+
tmux(1) session names may not be empty, or include periods or colons.
429+
These delimiters are reserved for noting session, window and pane.
430+
431+
:param session_name: name of session
432+
:type session_name: string
433+
:returns: void
434+
:raises: :exc:`exc.BadSessionName`
435+
"""
436+
if not session_name or len(session_name) == 0:
437+
raise exc.BadSessionName("tmux session names may not be empty.")
438+
elif '.' in session_name:
439+
raise exc.BadSessionName(
440+
"tmux session name \"%s\" may not contain periods.", session_name)
441+
elif ':' in session_name:
442+
raise exc.BadSessionName(
443+
"tmux session name \"%s\" may not contain colons.", session_name)

libtmux/exc.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ class TmuxSessionExists(LibTmuxException):
2020
pass
2121

2222

23+
class BadSessionName(LibTmuxException):
24+
25+
"""Session name is not allowed."""
26+
27+
pass
28+
29+
2330
class UnknownOption(LibTmuxException):
2431

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

libtmux/server.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
import os
1212

1313
from . import exc, formats
14-
from .common import EnvironmentMixin, TmuxRelationalObject, tmux_cmd
14+
from .common import EnvironmentMixin, TmuxRelationalObject, tmux_cmd, \
15+
session_check_name
1516
from .session import Session
1617

1718
logger = logging.getLogger(__name__)
@@ -318,10 +319,13 @@ def has_session(self, target_session):
318319
"""Return True if session exists. ``$ tmux has-session``.
319320
320321
:param: target_session: str of session name.
322+
:raises: :exc:`exc.BadSessionName`
321323
:rtype: bool
322324
323325
"""
324326

327+
session_check_name(target_session)
328+
325329
proc = self.cmd('has-session', '-t%s' % target_session)
326330

327331
if not proc.stdout:
@@ -335,6 +339,8 @@ def has_session(self, target_session):
335339
return False
336340
elif 'can\'t find session' in proc.stdout: # tmux 2.1
337341
return False
342+
elif 'bad session name' in proc.stdout: # tmux >= 1.9
343+
return False
338344
elif 'session not found' in proc.stdout:
339345
return False
340346
else:
@@ -349,10 +355,12 @@ def kill_session(self, target_session=None):
349355
350356
:param: target_session: str. note this accepts ``fnmatch(3)``. 'asdf'
351357
will kill 'asdfasd'.
352-
358+
:raises: :exc:`exc.BadSessionName`
353359
:rtype: :class:`Server`
354360
355361
"""
362+
session_check_name(target_session)
363+
356364
proc = self.cmd('kill-session', '-t%s' % target_session)
357365

358366
if proc.stderr:
@@ -364,8 +372,9 @@ def switch_client(self, target_session):
364372
"""``$ tmux switch-client``.
365373
366374
:param: target_session: str. name of the session. fnmatch(3) works.
367-
375+
:raises: :exc:`exc.BadSessionName`
368376
"""
377+
session_check_name(target_session)
369378

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

@@ -376,8 +385,10 @@ def attach_session(self, target_session=None):
376385
"""``$ tmux attach-session`` aka alias: ``$ tmux attach``.
377386
378387
:param: target_session: str. name of the session. fnmatch(3) works.
379-
388+
:raises: :exc:`exc.BadSessionName`
380389
"""
390+
session_check_name(target_session)
391+
381392
tmux_args = tuple()
382393
if target_session:
383394
tmux_args += ('-t%s' % target_session,)
@@ -418,9 +429,11 @@ def new_session(self,
418429
:param kill_session: Kill current session if ``$ tmux has-session``
419430
Useful for testing workspaces.
420431
:type kill_session: bool
432+
:raises: :exc:`exc.BadSessionName`
421433
:rtype: :class:`Session`
422434
423435
"""
436+
session_check_name(session_name)
424437

425438
if self.has_session(session_name):
426439
if kill_session:

libtmux/session.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
import os
1212

1313
from . import exc, formats
14-
from .common import EnvironmentMixin, TmuxMappingObject, TmuxRelationalObject
14+
from .common import EnvironmentMixin, TmuxMappingObject, \
15+
TmuxRelationalObject, session_check_name
1516
from .window import Window
1617

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

78-
def attach_session(self, target_session=None):
79-
"""Return ``$ tmux attach-session`` aka alias: ``$ tmux attach``.
80-
81-
:param: target_session: str. name of the session. fnmatch(3) works.
82-
83-
"""
79+
def attach_session(self):
80+
"""Return ``$ tmux attach-session`` aka alias: ``$ tmux attach``."""
8481
proc = self.cmd('attach-session', '-t%s' % self.id)
8582

8683
if proc.stderr:
@@ -94,10 +91,11 @@ def kill_session(self):
9491
if proc.stderr:
9592
raise exc.LibTmuxException(proc.stderr)
9693

97-
def switch_client(self, target_session=None):
94+
def switch_client(self):
9895
"""``$ tmux switch-client``.
9996
10097
:param: target_session: str. note this accepts fnmatch(3).
98+
:raises: :exc:`exc.LibTmuxException`
10199
"""
102100
proc = self.cmd('switch-client', '-t%s' % self.id)
103101

@@ -107,11 +105,14 @@ def switch_client(self, target_session=None):
107105
def rename_session(self, new_name):
108106
"""Rename session and return new :class:`Session` object.
109107
110-
:param rename_session: new session name
111-
:type rename_session: string
108+
:param new_name: new session name
109+
:type new_name: string
110+
:raises: :exc:`exc.BadSessionName`
112111
:rtype: :class:`Session`
113112
114113
"""
114+
session_check_name(new_name)
115+
115116
proc = self.cmd(
116117
'rename-session',
117118
'-t%s' % self.id,

tests/test_common.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
import pytest
77

8-
from libtmux.common import has_required_tmux_version, which
9-
from libtmux.exc import LibTmuxException
8+
from libtmux.common import has_required_tmux_version, which, session_check_name
9+
from libtmux.exc import LibTmuxException, BadSessionName
1010

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

@@ -50,3 +50,20 @@ def test_which_no_tmuxp_found(monkeypatch):
5050
monkeypatch.setenv("PATH", "/")
5151
which('tmuxp')
5252
which('tmuxp', '/')
53+
54+
55+
@pytest.mark.parametrize("session_name,raises,exc_msg_regex", [
56+
('', True, 'may not be empty'),
57+
(None, True, 'may not be empty'),
58+
("my great session.", True, 'may not contain periods'),
59+
("name: great session", True, 'may not contain colons'),
60+
("new great session", False, None),
61+
("ajf8a3fa83fads,,,a", False, None),
62+
])
63+
def test_session_check_name(session_name, raises, exc_msg_regex):
64+
if raises:
65+
with pytest.raises(BadSessionName) as exc_info:
66+
session_check_name(session_name)
67+
assert exc_info.match(exc_msg_regex)
68+
else:
69+
session_check_name(session_name)

tests/test_session.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,34 @@ def test_unset_environment(session):
184184
assert session.show_environment('BAM') == 'OK'
185185
session.unset_environment('BAM')
186186
assert session.show_environment('BAM') is None
187+
188+
189+
@pytest.mark.parametrize("session_name,raises", [
190+
('hey.period', True),
191+
('hey:its a colon', True),
192+
('hey moo', False),
193+
])
194+
def test_periods_raise_badsessionname(server, session, session_name, raises):
195+
new_name = session_name + 'moo' # used for rename / switch
196+
if raises:
197+
with pytest.raises(exc.BadSessionName):
198+
session.rename_session(new_name)
199+
200+
with pytest.raises(exc.BadSessionName):
201+
server.new_session(session_name)
202+
203+
with pytest.raises(exc.BadSessionName):
204+
server.has_session(session_name)
205+
206+
with pytest.raises(exc.BadSessionName):
207+
server.switch_client(new_name)
208+
209+
with pytest.raises(exc.BadSessionName):
210+
server.attach_session(new_name)
211+
212+
else:
213+
server.new_session(session_name)
214+
server.has_session(session_name)
215+
session.rename_session(new_name)
216+
with pytest.raises(exc.LibTmuxException):
217+
server.switch_client(new_name)

0 commit comments

Comments
 (0)