From 67dca640d4854dd7f3734e2c4c934b199c7c8937 Mon Sep 17 00:00:00 2001 From: Tom Aldcroft Date: Mon, 26 Dec 2016 17:27:59 -0500 Subject: [PATCH 1/5] Py3 compatibility --- Ska/Shell.py | 22 ++++++++++++---------- test.py | 2 +- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/Ska/Shell.py b/Ska/Shell.py index ce50882..e3b3bfc 100644 --- a/Ska/Shell.py +++ b/Ska/Shell.py @@ -6,7 +6,10 @@ import signal import subprocess -__version__ = '0.3.1' +import six +import pexpect + +__version__ = '0.3.2' class ShellError(Exception): @@ -81,9 +84,6 @@ def _parse_keyvals(keyvals): def _setup_bash_shell(logfile): - # Import pexpect here so that this the other (Spawn) part of this module - # doesn't depend on pexpect (which is not in the std library) - import pexpect prompt1 = r'Bash-\t> ' prompt2 = r'Bash-\t- ' re_prompt = re.compile(r'Bash-\d\d:\d\d:\d\d([->]) ') @@ -92,7 +92,8 @@ def _setup_bash_shell(logfile): os.environ['PS1'] = prompt1 os.environ['PS2'] = prompt2 - shell = pexpect.spawn('/bin/bash --noprofile --norc --noediting', timeout=1e8) + spawn = pexpect.spawn if six.PY2 else pexpect.spawnu + shell = spawn('/bin/bash --noprofile --norc --noediting', timeout=1e8) shell.logfile_read = logfile shell.expect(r'.+') @@ -100,7 +101,6 @@ def _setup_bash_shell(logfile): def _setup_tcsh_shell(logfile): - import pexpect prompt = r'Tcsh-%P> ' prompt2 = r'Tcsh-%P- ' re_prompt = re.compile(r'Tcsh-(\d)?\d:\d\d:\d\d([->]) ') @@ -109,7 +109,8 @@ def _setup_tcsh_shell(logfile): # line that needs to be skipped. pexpect.spawn.sendline_expect = _sendline_expect_func(re_prompt, n_skip=2) - shell = pexpect.spawn('/bin/tcsh -f', timeout=1e8) + spawn = pexpect.spawn if six.PY2 else pexpect.spawnu + shell = spawn('/bin/tcsh -f', timeout=1e8) shell.sendline('set prompt="{}"'.format(prompt)) shell.expect(re_prompt) @@ -427,7 +428,8 @@ def run(self, cmd, timeout=None, catch=None, shell=None): self.exitstatus = None try: - self.process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=stderr, shell=shell) + self.process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=stderr, shell=shell, + universal_newlines=True) prev_alarm_handler = signal.signal(signal.SIGALRM, Spawn._timeout_handler(self.process.pid, timeout)) @@ -439,13 +441,13 @@ def run(self, cmd, timeout=None, catch=None, shell=None): signal.signal(signal.SIGALRM, prev_alarm_handler) - except RunTimeoutError, e: + except RunTimeoutError as e: if catch: self._write('Warning - RunTimeoutError: %s\n' % e) else: raise - except OSError, e: + except OSError as e: if catch: self._write('Warning - OSError: %s\n' % e) else: diff --git a/test.py b/test.py index 2654807..8f76d5d 100644 --- a/test.py +++ b/test.py @@ -1,6 +1,6 @@ import os import unittest -from StringIO import StringIO +from six.moves import cStringIO as StringIO from Ska.Shell import (Spawn, RunTimeoutError, bash, tcsh, getenv, importenv, tcsh_shell, bash_shell) From 5556fad8aaf20b7239a6adfc4b48c353e7f0c3f7 Mon Sep 17 00:00:00 2001 From: Tom Aldcroft Date: Mon, 26 Dec 2016 17:30:47 -0500 Subject: [PATCH 2/5] Revert to having a local pexpect import --- Ska/Shell.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Ska/Shell.py b/Ska/Shell.py index e3b3bfc..1349c7e 100644 --- a/Ska/Shell.py +++ b/Ska/Shell.py @@ -7,7 +7,6 @@ import subprocess import six -import pexpect __version__ = '0.3.2' @@ -84,6 +83,9 @@ def _parse_keyvals(keyvals): def _setup_bash_shell(logfile): + # Import pexpect here so that this the other (Spawn) part of this module + # doesn't depend on pexpect (which is not in the std library) + import pexpect prompt1 = r'Bash-\t> ' prompt2 = r'Bash-\t- ' re_prompt = re.compile(r'Bash-\d\d:\d\d:\d\d([->]) ') @@ -101,6 +103,7 @@ def _setup_bash_shell(logfile): def _setup_tcsh_shell(logfile): + import pexpect prompt = r'Tcsh-%P> ' prompt2 = r'Tcsh-%P- ' re_prompt = re.compile(r'Tcsh-(\d)?\d:\d\d:\d\d([->]) ') From 5427c3d3b751adf1a400363ebed83f562a077863 Mon Sep 17 00:00:00 2001 From: Tom Aldcroft Date: Mon, 26 Dec 2016 20:29:44 -0500 Subject: [PATCH 3/5] Create full package structure and modernize tests --- Ska/Shell/__init__.py | 10 ++++++++++ Ska/{Shell.py => Shell/shell.py} | 0 Ska/Shell/tests/__init__.py | 0 test.py => Ska/Shell/tests/test_shell.py | 0 setup.py | 12 +++++++----- 5 files changed, 17 insertions(+), 5 deletions(-) create mode 100644 Ska/Shell/__init__.py rename Ska/{Shell.py => Shell/shell.py} (100%) create mode 100644 Ska/Shell/tests/__init__.py rename test.py => Ska/Shell/tests/test_shell.py (100%) diff --git a/Ska/Shell/__init__.py b/Ska/Shell/__init__.py new file mode 100644 index 0000000..808a9fd --- /dev/null +++ b/Ska/Shell/__init__.py @@ -0,0 +1,10 @@ +from .shell import * +from .shell import __version__ + + +def test(*args, **kwargs): + ''' + Run py.test unit tests. + ''' + import testr + return testr.test(*args, **kwargs) diff --git a/Ska/Shell.py b/Ska/Shell/shell.py similarity index 100% rename from Ska/Shell.py rename to Ska/Shell/shell.py diff --git a/Ska/Shell/tests/__init__.py b/Ska/Shell/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test.py b/Ska/Shell/tests/test_shell.py similarity index 100% rename from test.py rename to Ska/Shell/tests/test_shell.py diff --git a/setup.py b/setup.py index ed75592..a15dc1c 100755 --- a/setup.py +++ b/setup.py @@ -1,16 +1,18 @@ from setuptools import setup from Ska.Shell import __version__ +try: + from testr.setup_helper import cmdclass +except ImportError: + cmdclass = {} setup(name='Ska.Shell', author='Tom Aldcroft', description='Various shell utilities', author_email='taldcroft@cfa.harvard.edu', - py_modules=['Ska.Shell'], - test_suite='test', version=__version__, zip_safe=False, - packages=['Ska'], - package_dir={'Ska': 'Ska'}, - package_data={} + packages=['Ska', 'Ska.Shell', 'Ska.Shell.tests'], + tests_require=['pytest'], + cmdclass=cmdclass, ) From 4a711c87547014800a23507f1965cbc5eec92b60 Mon Sep 17 00:00:00 2001 From: Tom Aldcroft Date: Fri, 6 Jan 2017 12:57:57 -0500 Subject: [PATCH 4/5] Update version from 0.3.2 to 3.3.1 --- Ska/Shell/__init__.py | 3 ++- Ska/Shell/shell.py | 2 -- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Ska/Shell/__init__.py b/Ska/Shell/__init__.py index 808a9fd..1ed5bcf 100644 --- a/Ska/Shell/__init__.py +++ b/Ska/Shell/__init__.py @@ -1,5 +1,6 @@ from .shell import * -from .shell import __version__ + +__version__ = '3.3.1' def test(*args, **kwargs): diff --git a/Ska/Shell/shell.py b/Ska/Shell/shell.py index 1349c7e..0e98032 100644 --- a/Ska/Shell/shell.py +++ b/Ska/Shell/shell.py @@ -8,8 +8,6 @@ import six -__version__ = '0.3.2' - class ShellError(Exception): pass From 48d867632eea6785efa2ad15b1823a2013d52d42 Mon Sep 17 00:00:00 2001 From: Tom Aldcroft Date: Fri, 6 Jan 2017 12:58:19 -0500 Subject: [PATCH 5/5] Migrate from unittest to pytest --- Ska/Shell/tests/test_shell.py | 46 +++++++++++++++++------------------ 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/Ska/Shell/tests/test_shell.py b/Ska/Shell/tests/test_shell.py index 8f76d5d..87a219e 100644 --- a/Ska/Shell/tests/test_shell.py +++ b/Ska/Shell/tests/test_shell.py @@ -1,5 +1,5 @@ import os -import unittest +import pytest from six.moves import cStringIO as StringIO from Ska.Shell import (Spawn, RunTimeoutError, bash, tcsh, getenv, importenv, tcsh_shell, bash_shell) @@ -7,51 +7,51 @@ outfile = 'ska_shell_test.dat' -class TestSpawn(unittest.TestCase): - def setUp(self): +class TestSpawn: + def setup(self): self.f = StringIO() self.g = StringIO() def test_ok(self): spawn = Spawn(stdout=self.f) spawn.run(['echo', 'hello world']) - self.assertEqual(spawn.exitstatus, 0) - self.assertEqual(spawn.outlines, ['hello world\n']) - self.assertEqual(self.f.getvalue(), 'hello world\n') + assert spawn.exitstatus == 0 + assert spawn.outlines == ['hello world\n'] + assert self.f.getvalue() == 'hello world\n' def test_os_error(self): spawn = Spawn(stdout=None) - self.assertRaises(OSError, spawn.run, 'bad command') - self.assertEqual(spawn.exitstatus, None) + with pytest.raises(OSError): + spawn.run('bad command') + assert spawn.exitstatus == None def test_timeout_error(self): spawn = Spawn(shell=True, timeout=1, stdout=None) - self.assertRaises(RunTimeoutError, spawn.run, 'sleep 5') - self.assertEqual(spawn.exitstatus, None) + with pytest.raises(RunTimeoutError): + spawn.run('sleep 5') + assert spawn.exitstatus == None - def test_grab_stderr(self): - f = open(outfile, 'w') - spawn = Spawn(stderr=f, stdout=None) + def test_grab_stderr(self, tmpdir): + tmp = tmpdir.join("test.out") + spawn = Spawn(stderr=tmp.open('w'), stdout=None) spawn.run('perl -e "print STDERR 123456"', shell=True) - f.close() - f = open(outfile) - self.assertEqual(f.read(), '123456') - self.assertEqual(spawn.exitstatus, 0) - os.unlink(outfile) + + assert tmp.read() == '123456' + assert spawn.exitstatus == 0 def test_multi_stdout(self): spawn = Spawn(stdout=[self.f, self.g]) spawn.run('perl -e "print 123456"', shell=True) - self.assertEqual(self.f.getvalue(), '123456') - self.assertEqual(self.g.getvalue(), '123456') - self.assertEqual(spawn.exitstatus, 0) + assert self.f.getvalue() == '123456' + assert self.g.getvalue() == '123456' + assert spawn.exitstatus == 0 def test_shell_error(self): # With shell=True you don't get an OSError spawn = Spawn(shell=True, stdout=None) spawn.run('sadfasdfasdf') - self.assertNotEqual(spawn.exitstatus, 0) - self.assertNotEqual(spawn.exitstatus, None) + assert spawn.exitstatus != 0 + assert spawn.exitstatus is not None class TestBash: