diff --git a/lib/galaxy/tools/deps/commands.py b/lib/galaxy/tools/deps/commands.py index 62898bf7c1d..1ae7502a7c3 100644 --- a/lib/galaxy/tools/deps/commands.py +++ b/lib/galaxy/tools/deps/commands.py @@ -1,16 +1,21 @@ +"""Generic I/O and shell processing code used by Galaxy tool dependencies.""" import os import subprocess import sys as _sys + from galaxy.util import which +STDOUT_INDICATOR = "-" + def redirecting_io(sys=_sys): + """Predicate to determine if we are redicting I/O in process.""" assert sys is not None - # We are redirecting standard out and standard error. return not hasattr(sys.stdout, "fileno") def redirect_aware_commmunicate(p, sys=_sys): + """Variant of process.communicate that works with in process I/O redirection.""" assert sys is not None out, err = p.communicate() if redirecting_io(sys=sys): @@ -24,6 +29,7 @@ def redirect_aware_commmunicate(p, sys=_sys): def shell(cmds, env=None, **kwds): + """Run shell commands with `shell_process` and wait.""" sys = kwds.get("sys", _sys) assert sys is not None p = shell_process(cmds, env, **kwds) @@ -36,6 +42,11 @@ def shell(cmds, env=None, **kwds): def shell_process(cmds, env=None, **kwds): + """A high-level method wrapping subprocess.Popen. + + Handles details such as environment extension and in process I/O + redirection. + """ sys = kwds.get("sys", _sys) popen_kwds = dict( shell=True, @@ -55,10 +66,14 @@ def shell_process(cmds, env=None, **kwds): def execute(cmds): - return __wait(cmds, shell=False) + """Execute commands and throw an exception on a non-zero exit. + + Return the standard output if the commands are successful + """ + return _wait(cmds, shell=False) -def __wait(cmds, **popen_kwds): +def _wait(cmds, **popen_kwds): p = subprocess.Popen(cmds, **popen_kwds) stdout, stderr = p.communicate() if p.returncode != 0: @@ -66,19 +81,34 @@ def __wait(cmds, **popen_kwds): return stdout -def download_command(url, quote_url=False): +def download_command(url, to=STDOUT_INDICATOR, quote_url=False): + """Build a command line to download a URL. + + By default the URL will be downloaded to standard output but a specific + file can be specified with the `to` argument. + """ if quote_url: url = "'%s'" % url + if to != STDOUT_INDICATOR: + to = "'%s'" % to if which("wget"): - download_cmd = ["wget", "-q", "--recursive", "-O" "-", url] + download_cmd = ["wget", "-q"] + if to == STDOUT_INDICATOR: + download_cmd += ["-O" , STDOUT_INDICATOR, url] + else: + download_cmd += ["--recursive", "-O" , to, url] else: download_cmd = ["curl", "-L", url] + if to != STDOUT_INDICATOR: + download_cmd += ["-o", to] return download_cmd class CommandLineException(Exception): + """An exception indicating a non-zero command-line exit.""" def __init__(self, command, stdout, stderr): + """Construct a CommandLineException from command and standard I/O.""" self.command = command self.stdout = stdout self.stderr = stderr @@ -92,6 +122,7 @@ class CommandLineException(Exception): ) % (command, stderr, stdout) def __str__(self): + """Return a verbose error message indicating the command problem.""" return self.message diff --git a/lib/galaxy/tools/deps/conda_util.py b/lib/galaxy/tools/deps/conda_util.py index 022b4a0cf0e..da18710f3f9 100644 --- a/lib/galaxy/tools/deps/conda_util.py +++ b/lib/galaxy/tools/deps/conda_util.py @@ -260,10 +260,9 @@ def hash_conda_packages(conda_packages, conda_target=None): # these commands as Python def install_conda(conda_context=None): conda_context = _ensure_conda_context(conda_context) - download_cmd = " ".join(commands.download_command(conda_link(), quote_url=True)) f, script_path = tempfile.mkstemp(suffix=".bash", prefix="conda_install") os.close(f) - download_cmd = "%s >> '%s'" % (download_cmd, script_path) + download_cmd = " ".join(commands.download_command(conda_link(), to=script_path, quote_url=True)) install_cmd = "bash '%s' -b -p '%s'" % (script_path, conda_context.conda_prefix) full_command = "%s; %s" % (download_cmd, install_cmd) try: diff --git a/test/unit/tools/test_conda_resolution.py b/test/unit/tools/test_conda_resolution.py index fa4bab657f2..5550333f844 100644 --- a/test/unit/tools/test_conda_resolution.py +++ b/test/unit/tools/test_conda_resolution.py @@ -1,12 +1,8 @@ import os import shutil -from sys import version_info from tempfile import mkdtemp -if version_info < (2, 7): - import unittest2 as unittest -else: - import unittest as unittest +import unittest as unittest from galaxy.tools.deps import DependencyManager from galaxy.tools.deps.resolvers.conda import CondaDependencyResolver