Skip to content

Commit 9cd9ebc

Browse files
committed
Changes to run_script_before, exceptions and testsuites.
1 parent 12bd6c3 commit 9cd9ebc

File tree

9 files changed

+140
-75
lines changed

9 files changed

+140
-75
lines changed

CHANGES

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

55
Here you can find the recent changes to tmuxp.
66

7+
CURRENT
8+
-------
9+
10+
- [internal]: Improvements to :func:`util.run_script_before`,
11+
:class:`exc.BeforeLoadScriptFailed` behavior to print ``stdout`` and
12+
return ``stderr`` is a non-zero exit is returned.
13+
- [internal]: ``run_script_before`` has moved to ``util``.
14+
- [internal]: ``BeforeLoadScriptFailed`` and ``BeforeLoadScriptNotExists``
15+
has moved to the ``exc`` module.
16+
- [internal]: Tests for ``run_script_before`` refactored.
17+
718
0.1.10
819
------
920

doc/api.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ Exceptions
125125

126126
.. autoexception:: tmuxp.exc.ConfigError
127127

128+
.. autoexception:: tmuxp.exc.BeforeLoadScriptFailed
129+
130+
.. autoexception:: tmuxp.exc.BeforeLoadScriptNotExists
131+
128132
Test tools
129133
----------
130134

tmuxp/_compat.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,16 @@
3333
from string import lower as ascii_lowercase
3434
import urlparse
3535

36+
exec('def reraise(tp, value, tb=None):\n raise tp, value, tb')
37+
38+
def implements_to_string(cls):
39+
cls.__unicode__ = cls.__str__
40+
cls.__str__ = lambda x: x.__unicode__().encode('utf-8')
41+
return cls
42+
3643
def console_to_str(s):
3744
return s.decode('utf_8')
3845

39-
exec('def reraise(tp, value, tb=None):\n raise tp, value, tb')
40-
4146
else:
4247
unichr = chr
4348
text_type = str
@@ -68,6 +73,8 @@ def console_to_str(s):
6873

6974
console_encoding = sys.__stdout__.encoding
7075

76+
implements_to_string = _identity
77+
7178
def console_to_str(s):
7279
""" From pypa/pip project, pip.backwardwardcompat. License MIT. """
7380
try:

tmuxp/exc.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
from __future__ import absolute_import, division, print_function, \
1010
with_statement, unicode_literals
1111

12+
import subprocess
13+
14+
from ._compat import implements_to_string
15+
1216

1317
class TmuxpException(Exception):
1418

@@ -39,3 +43,28 @@ class EmptyConfigException(ConfigError):
3943
"""Configuration is empty."""
4044

4145
pass
46+
47+
48+
class BeforeLoadScriptNotExists(OSError):
49+
50+
def __init__(self, *args, **kwargs):
51+
super(BeforeLoadScriptNotExists, self).__init__(*args, **kwargs)
52+
53+
self.strerror = "before_script file '%s' doesn't exist." % self.strerror
54+
55+
56+
@implements_to_string
57+
class BeforeLoadScriptFailed(subprocess.CalledProcessError):
58+
59+
"""Exception extending :py:class:`subprocess.CalledProcessError` for
60+
:meth:`util.run_before_script`.
61+
"""
62+
63+
def __init__(self, *args, **kwargs):
64+
super(BeforeLoadScriptFailed, self).__init__(*args, **kwargs)
65+
66+
def __str__(self):
67+
return "before_script failed (%s): %s." \
68+
"\nError Output: \n%s" % (
69+
self.returncode, self.cmd, self.output
70+
)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
#!/bin/bash
22

3+
4+
echoerr() { echo "$@" 1>&2; }
5+
echoerr An error has occured
6+
37
exit 113 # Will return 113 to shell.
48
# To verify this, type "echo $?" after script terminates.

tmuxp/testsuite/util.py

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,21 @@
1212
import random
1313
import logging
1414
import unittest
15+
import subprocess
16+
import os
1517

1618
from .. import exc
17-
from ..util import has_required_tmux_version
19+
from ..util import has_required_tmux_version, run_before_script
20+
from ..exc import BeforeLoadScriptNotExists, BeforeLoadScriptFailed
1821

19-
from .helpers import TmuxTestCase
22+
23+
from .helpers import TmuxTestCase, TestCase
2024

2125
logger = logging.getLogger(__name__)
2226

27+
current_dir = os.path.abspath(os.path.dirname(__file__))
28+
fixtures_dir = os.path.abspath(os.path.join(current_dir, 'fixtures'))
29+
2330

2431
class TmuxVersionTest(TmuxTestCase):
2532

@@ -54,7 +61,47 @@ def test_error_version_less_1_7(self):
5461
has_required_tmux_version('1.9a')
5562

5663

64+
class RunBeforeScript(TestCase):
65+
66+
def test_raise_BeforeLoadScriptNotExists_if_not_exists(self):
67+
script_file = os.path.join(fixtures_dir, 'script_noexists.sh')
68+
69+
with self.assertRaises(BeforeLoadScriptNotExists):
70+
run_before_script(script_file)
71+
72+
with self.assertRaises(OSError):
73+
run_before_script(script_file)
74+
75+
def test_raise_BeforeLoadScriptFailed_if_retcode(self):
76+
script_file = os.path.join(fixtures_dir, 'script_failed.sh')
77+
78+
with self.assertRaises(BeforeLoadScriptFailed):
79+
run_before_script(script_file)
80+
81+
def test_return_stdout_if_ok(self):
82+
script_file = os.path.join(fixtures_dir, 'script_complete.sh')
83+
84+
run_before_script(script_file)
85+
86+
87+
class BeforeLoadScriptFailedTestCase(TestCase):
88+
89+
def test_returncode(self):
90+
script_file = os.path.join(fixtures_dir, 'script_failed.sh')
91+
92+
with self.assertRaisesRegexp(subprocess.CalledProcessError, "113"):
93+
run_before_script(script_file)
94+
95+
def test_returns_stderr_messages(self):
96+
script_file = os.path.join(fixtures_dir, 'script_failed.sh')
97+
98+
with self.assertRaisesRegexp(subprocess.CalledProcessError, "An error has occured"):
99+
run_before_script(script_file)
100+
101+
57102
def suite():
58103
suite = unittest.TestSuite()
104+
suite.addTest(unittest.makeSuite(BeforeLoadScriptFailedTestCase))
105+
suite.addTest(unittest.makeSuite(RunBeforeScript))
59106
suite.addTest(unittest.makeSuite(TmuxVersionTest))
60107
return suite

tmuxp/testsuite/workspacebuilder.py

Lines changed: 3 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,7 @@ class BeforeLoadScript(TmuxTestCase):
587587
- pane
588588
"""
589589

590-
def test_throw_error_if_retcode_false(self):
590+
def test_throw_error_if_retcode_error(self):
591591

592592
sconfig = kaptan.Kaptan(handler='yaml')
593593
yaml = self.config_script_fails.format(
@@ -602,7 +602,7 @@ def test_throw_error_if_retcode_false(self):
602602
with self.temp_session() as sess:
603603
session_name = sess.get('session_name')
604604

605-
with self.assertRaises(subprocess.CalledProcessError):
605+
with self.assertRaises((exc.BeforeLoadScriptFailed, subprocess.CalledProcessError)):
606606
builder.build(session=sess)
607607

608608
result = self.server.has_session(session_name)
@@ -628,7 +628,7 @@ def test_throw_error_if_file_not_exists(self):
628628
temp_session_exists = self.server.has_session(sess.get('session_name'))
629629
self.assertTrue(temp_session_exists)
630630
with self.assertRaisesRegexp(
631-
(BeforeLoadScriptNotExists, OSError),
631+
(exc.BeforeLoadScriptNotExists, OSError),
632632
'No such file or directory'
633633
):
634634
builder.build(session=sess)
@@ -654,40 +654,9 @@ def test_true_if_test_passes(self):
654654
builder.build(session=self.session)
655655

656656

657-
from ..workspacebuilder import run_before_script, BeforeLoadScriptNotExists, \
658-
BeforeLoadScriptFailed
659-
660-
661-
class RunBeforeScript(TestCase):
662-
663-
def test_raise_BeforeLoadScriptNotExists_if_not_exists(self):
664-
script_file = os.path.join(fixtures_dir, 'script_noexists.sh')
665-
666-
with self.assertRaises(BeforeLoadScriptNotExists):
667-
run_before_script(script_file)
668-
669-
with self.assertRaises(OSError):
670-
run_before_script(script_file)
671-
672-
def test_raise_BeforeLoadScriptFailed_if_retcode(self):
673-
script_file = os.path.join(fixtures_dir, 'script_failed.sh')
674-
675-
with self.assertRaises(BeforeLoadScriptFailed):
676-
run_before_script(script_file)
677-
678-
with self.assertRaises(subprocess.CalledProcessError):
679-
run_before_script(script_file)
680-
681-
def test_return_stdout_if_exits_zero(self):
682-
script_file = os.path.join(fixtures_dir, 'script_complete.sh')
683-
684-
run_before_script(script_file)
685-
686-
687657
def suite():
688658
suite = unittest.TestSuite()
689659
suite.addTest(unittest.makeSuite(BeforeLoadScript))
690-
suite.addTest(unittest.makeSuite(RunBeforeScript))
691660
suite.addTest(unittest.makeSuite(BlankPaneTest))
692661
suite.addTest(unittest.makeSuite(FocusAndPaneIndexTest))
693662
suite.addTest(unittest.makeSuite(PaneOrderingTest))

tmuxp/util.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,35 @@
2727
PY2 = sys.version_info[0] == 2
2828

2929

30+
def run_before_script(script_file):
31+
"""Function to wrap try/except for subprocess.check_call()."""
32+
try:
33+
proc = subprocess.Popen(
34+
script_file,
35+
# stdout=subprocess.PIPE,
36+
stderr=subprocess.PIPE
37+
)
38+
proc.wait()
39+
40+
if proc.returncode:
41+
stderr = proc.stderr.read()
42+
proc.stderr.close()
43+
stderr = console_to_str(stderr).split('\n')
44+
stderr = '\n'.join(list(filter(None, stderr))) # filter empty values
45+
46+
# python 2.6 doesn't have a third "output" argument.
47+
error = exc.BeforeLoadScriptFailed(proc.returncode, script_file)
48+
error.output = stderr
49+
50+
raise(error)
51+
return proc.returncode
52+
except OSError as e:
53+
if e.errno == 2:
54+
raise exc.BeforeLoadScriptNotExists(e, script_file)
55+
else:
56+
raise(e)
57+
58+
3059
class tmux(object):
3160

3261
""":py:mod:`subprocess` for :term:`tmux(1)`.

tmuxp/workspacebuilder.py

Lines changed: 2 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -14,47 +14,12 @@
1414
import subprocess
1515

1616
from . import exc, config, Window, Pane, Session, Server
17-
from ._compat import PY2
17+
from ._compat import PY2, console_to_str
18+
from .util import run_before_script
1819

1920
logger = logging.getLogger(__name__)
2021

2122

22-
class BeforeLoadScriptNotExists(OSError):
23-
24-
def __init__(self, *args, **kwargs):
25-
super(BeforeLoadScriptNotExists, self).__init__(*args, **kwargs)
26-
27-
self.strerror = "before_script file '%s' doesn't exist." % self.strerror
28-
29-
30-
class BeforeLoadScriptFailed(subprocess.CalledProcessError):
31-
32-
def __init__(self, *args, **kwargs):
33-
super(BeforeLoadScriptFailed, self).__init__(*args, **kwargs)
34-
35-
def __unicode__(self):
36-
return "before_script failed (%s): %s. Output: \n%s" % (
37-
self.returncode, self.cmd, self.output
38-
)
39-
40-
if PY2:
41-
def __str__(self):
42-
return self.__unicode__().encode('utf-8')
43-
44-
45-
def run_before_script(script_file):
46-
"""Function to wrap try/except for subprocess.check_call()."""
47-
try:
48-
return subprocess.check_call(script_file, stdout=subprocess.PIPE)
49-
except subprocess.CalledProcessError as e:
50-
raise BeforeLoadScriptFailed(e.returncode, e.cmd)
51-
except OSError as e:
52-
if e.errno == 2:
53-
raise BeforeLoadScriptNotExists(e, script_file)
54-
else:
55-
raise(e)
56-
57-
5823
class WorkspaceBuilder(object):
5924

6025
"""Load workspace from session :py:obj:`dict`.

0 commit comments

Comments
 (0)