Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Allow command line wrappers to send stdout/stderr to files

  • Loading branch information...
commit c4a5796cc33d5c7681bba172fdf965792a65e078 1 parent bba2acb
@peterjc peterjc authored
Showing with 86 additions and 12 deletions.
  1. +22 −12 Bio/Application/__init__.py
  2. +64 −0 Tests/test_Application.py
View
34 Bio/Application/__init__.py
@@ -1,5 +1,5 @@
# Copyright 2001-2004 Brad Chapman.
-# Revisions copyright 2009-2010 by Peter Cock.
+# Revisions copyright 2009-2013 by Peter Cock.
# All rights reserved.
# This code is part of the Biopython distribution and governed by its
# license. Please see the LICENSE file that should have been included
@@ -380,10 +380,11 @@ def __call__(self, stdin=None, stdout=True, stderr=True,
The optional stdin argument should be a string of data which will be
passed to the tool as standard input.
- The optional stdout and stderr argument are treated as a booleans, and
- control if the output should be captured (True, default), or ignored
- by sending it to /dev/null to avoid wasting memory (False). In the
- later case empty string(s) are returned.
+ The optional stdout and stderr argument may be filenames (string),
+ but otherwise are treated as a booleans, and control if the output
+ should be captured as strings (True, default), or ignored by sending
+ it to /dev/null to avoid wasting memory (False). If sent to a file
+ or ignored, then empty string(s) are returned.
The optional cwd argument is a string giving the working directory
to run the command from. See Python's subprocess module documentation
@@ -412,14 +413,23 @@ def __call__(self, stdin=None, stdout=True, stderr=True,
any stdout and stderr strings captured as attributes of the exception
object, since they may be useful for diagnosing what went wrong.
"""
- if stdout:
- stdout_arg = subprocess.PIPE
- else:
+ if not stdout:
stdout_arg = open(os.devnull, "w")
- if stderr:
- stderr_arg = subprocess.PIPE
+ elif isinstance(stdout, basestring):
+ stdout_arg = open(stdout, "w")
else:
+ stdout_arg = subprocess.PIPE
+
+ if not stderr:
stderr_arg = open(os.devnull, "w")
+ elif isinstance(stderr, basestring):
+ if stdout == stderr:
+ stderr_arg = stdout_arg #Write both to the same file
+ else:
+ stderr_arg = open(stderr, "w")
+ else:
+ stderr_arg = subprocess.PIPE
+
#We may not need to supply any piped input, but we setup the
#standard input pipe anyway as a work around for a python
#bug if this is called from a Windows GUI program. For
@@ -435,9 +445,9 @@ def __call__(self, stdin=None, stdout=True, stderr=True,
#Use .communicate as can get deadlocks with .wait(), see Bug 2804
stdout_str, stderr_str = child_process.communicate(stdin)
if not stdout:
- assert not stdout_str
+ assert not stdout_str, stdout_str
if not stderr:
- assert not stderr_str
+ assert not stderr_str, stderr_str
return_code = child_process.returncode
if return_code:
raise ApplicationError(return_code, str(self),
View
64 Tests/test_Application.py
@@ -50,6 +50,70 @@ def test_echo_capture_neither(self):
self.assertEqual(stderr, None)
self.assertEqual(stdout, None)
+ def test_echo_file_stdout(self):
+ cline = EchoApp(text="Hello World")
+ tmp = "echo_stdout.tmp"
+ if os.path.isfile(tmp):
+ os.remove(tmp)
+ stdout, stderr = cline(stdout=tmp)
+ self.assertEqual(stderr, "")
+ self.assertEqual(stdout, None)
+ self.assertTrue(os.path.isfile(tmp))
+ with open(tmp) as h:
+ contents = h.read()
+ self.assertEqual(contents, "Hello World\n")
+ os.remove(tmp)
+
+ def test_echo_file_stderr(self):
+ cline = EchoApp(text="Hello World")
+ tmp = "echo_stderr.tmp"
+ if os.path.isfile(tmp):
+ os.remove(tmp)
+ stdout, stderr = cline(stderr=tmp)
+ self.assertEqual(stderr, None)
+ self.assertEqual(stdout, "Hello World\n")
+ self.assertTrue(os.path.isfile(tmp))
+ with open(tmp) as h:
+ contents = h.read()
+ self.assertEqual(contents, "")
+ os.remove(tmp)
+
+ def test_echo_file_same(self):
+ cline = EchoApp(text="Hello World")
+ tmp = "echo_stdout_stderr.tmp"
+ if os.path.isfile(tmp):
+ os.remove(tmp)
+ stdout, stderr = cline(stdout=tmp, stderr=tmp)
+ self.assertEqual(stderr, None)
+ self.assertEqual(stdout, None)
+ self.assertTrue(os.path.isfile(tmp))
+ with open(tmp) as h:
+ contents = h.read()
+ self.assertEqual(contents, "Hello World\n") #stdout + stderr
+ os.remove(tmp)
+
+ def test_echo_file_both(self):
+ cline = EchoApp(text="Hello World")
+ tmp = "echo_stdout.tmp"
+ if os.path.isfile(tmp):
+ os.remove(tmp)
+ tmp2 = "echo_stderr.tmp"
+ if os.path.isfile(tmp2):
+ os.remove(tmp2)
+ stdout, stderr = cline(stdout=tmp, stderr=tmp2)
+ self.assertEqual(stderr, None)
+ self.assertEqual(stdout, None)
+ self.assertTrue(os.path.isfile(tmp), tmp)
+ with open(tmp) as h:
+ contents = h.read()
+ self.assertEqual(contents, "Hello World\n") #stdout
+ os.remove(tmp)
+ self.assertTrue(os.path.isfile(tmp2), tmp2)
+ with open(tmp2) as h:
+ contents = h.read()
+ self.assertEqual(contents, "") #stderr
+ os.remove(tmp2)
+
if __name__ == "__main__":
runner = unittest.TextTestRunner(verbosity = 2)

0 comments on commit c4a5796

Please sign in to comment.
Something went wrong with that request. Please try again.