diff --git a/lib/galaxy/objectstore/__init__.py b/lib/galaxy/objectstore/__init__.py index f2cef3073e2..2e340cd361d 100644 --- a/lib/galaxy/objectstore/__init__.py +++ b/lib/galaxy/objectstore/__init__.py @@ -22,9 +22,11 @@ from galaxy.exceptions import ObjectInvalid, ObjectNotFound from galaxy.util import ( directory_hash_id, force_symlink, + umask_fix_perms, +) +from galaxy.util.path import ( safe_makedirs, safe_relpath, - umask_fix_perms, ) from galaxy.util.odict import odict from galaxy.util.sleeper import Sleeper diff --git a/lib/galaxy/objectstore/azure_blob.py b/lib/galaxy/objectstore/azure_blob.py index c3e12a7bd89..02f08b6efbe 100644 --- a/lib/galaxy/objectstore/azure_blob.py +++ b/lib/galaxy/objectstore/azure_blob.py @@ -11,7 +11,8 @@ import time from datetime import datetime from galaxy.exceptions import ObjectInvalid, ObjectNotFound -from galaxy.util import directory_hash_id, safe_relpath, umask_fix_perms +from galaxy.util import directory_hash_id, umask_fix_perms +from galaxy.util.path import safe_relpath from galaxy.util.sleeper import Sleeper from ..objectstore import convert_bytes, ObjectStore diff --git a/lib/galaxy/objectstore/pithos.py b/lib/galaxy/objectstore/pithos.py index 6fd88822326..31a1508eed5 100644 --- a/lib/galaxy/objectstore/pithos.py +++ b/lib/galaxy/objectstore/pithos.py @@ -8,9 +8,9 @@ import shutil from galaxy.exceptions import ObjectInvalid, ObjectNotFound from galaxy.util import ( directory_hash_id, - safe_relpath, umask_fix_perms, ) +from galaxy.util.path import safe_relpath from ..objectstore import ObjectStore try: diff --git a/lib/galaxy/objectstore/rods.py b/lib/galaxy/objectstore/rods.py index fcf61c0f021..f5718f8c743 100644 --- a/lib/galaxy/objectstore/rods.py +++ b/lib/galaxy/objectstore/rods.py @@ -13,7 +13,7 @@ from posixpath import dirname as path_dirname from posixpath import join as path_join from galaxy.exceptions import ObjectInvalid, ObjectNotFound -from galaxy.util import safe_relpath +from galaxy.util.path import safe_relpath from ..objectstore import DiskObjectStore, local_extra_dirs diff --git a/lib/galaxy/objectstore/s3.py b/lib/galaxy/objectstore/s3.py index ea7863ccdb7..ad312fa872a 100644 --- a/lib/galaxy/objectstore/s3.py +++ b/lib/galaxy/objectstore/s3.py @@ -22,11 +22,11 @@ except ImportError: from galaxy.exceptions import ObjectInvalid, ObjectNotFound from galaxy.util import ( directory_hash_id, - safe_relpath, string_as_bool, umask_fix_perms, which, ) +from galaxy.util.path import safe_relpath from galaxy.util.sleeper import Sleeper from .s3_multipart_upload import multipart_upload diff --git a/lib/galaxy/tools/toolbox/base.py b/lib/galaxy/tools/toolbox/base.py index d3fbb617043..52452ed41c9 100644 --- a/lib/galaxy/tools/toolbox/base.py +++ b/lib/galaxy/tools/toolbox/base.py @@ -2,6 +2,7 @@ import logging import os import string import time +from errno import ENOENT from xml.etree.ElementTree import ParseError from markupsafe import escape @@ -544,7 +545,7 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin, object): concrete_path = os.path.join(tool_path, path) if not os.path.exists(concrete_path): # This is a lot faster than attempting to load a non-existing tool - raise IOError + raise IOError(ENOENT, os.strerror(ENOENT)) tool_shed_repository = None can_load_into_panel_dict = True @@ -585,8 +586,8 @@ class AbstractToolBox(Dictifiable, ManagesIntegratedToolPanelMixin, object): labels = item.labels if labels is not None: tool.labels = labels - except IOError: - log.error("Error reading tool configuration file from path: %s" % path) + except (IOError, OSError) as exc: + log.error("Error reading tool configuration file from path '%s': %s", path, exc) except Exception: log.exception("Error reading tool from path: %s", path) diff --git a/lib/galaxy/util/__init__.py b/lib/galaxy/util/__init__.py index 2b617cd558c..24ee2cd9011 100644 --- a/lib/galaxy/util/__init__.py +++ b/lib/galaxy/util/__init__.py @@ -862,13 +862,25 @@ def string_as_bool_or_none(string): def listify(item, do_strip=False): """ - Make a single item a single item list, or return a list if passed a - list. Passing a None returns an empty list. + Make a single item a single item list. + + If *item* is a string, it is split on comma (``,``) characters to produce the list. Optionally, if *do_strip* is + true, any extra whitespace around the split items is stripped. + + If *item* is a list it is returned unchanged. If *item* is a tuple, it is converted to a list and returned. If + *item* evaluates to False, an empty list is returned. + + :type item: object + :param item: object to make a list from + :type do_strip: bool + :param do_strip: strip whitespaces from around split items, if set to ``True`` + :rtype: list + :returns: The input as a list """ if not item: return [] - elif isinstance(item, list): - return item + elif isinstance(item, list) or isinstance(item, tuple): + return list(item) elif isinstance(item, string_types) and item.count(','): if do_strip: return [token.strip() for token in item.split(',')] diff --git a/lib/galaxy/util/script.py b/lib/galaxy/util/script.py new file mode 100644 index 00000000000..4e72a0cf67e --- /dev/null +++ b/lib/galaxy/util/script.py @@ -0,0 +1,57 @@ +"""Utilities for Galaxy scripts +""" +import argparse +import os +import sys + +from galaxy.util.properties import find_config_file, load_app_properties + +DESCRIPTION = None +ACTIONS = None +ARGUMENTS = None +DEFAULT_ACTION = None + + +def main_factory(description=None, actions=None, arguments=None, default_action=None): + global DESCRIPTION, ACTIONS, ARGUMENTS, DEFAULT_ACTION + DESCRIPTION = description + ACTIONS = actions or {} + ARGUMENTS = arguments or [] + DEFAULT_ACTION = default_action + return main + + +def main(argv=None): + """Entry point for conversion process.""" + if argv is None: + argv = sys.argv[1:] + args = _arg_parser().parse_args(argv) + kwargs = _app_properties(args) + action = args.action + action_func = ACTIONS[action] + action_func(args, kwargs) + + +def _app_properties(args): + # FIXME: you can use galaxy.util.path.extensions for this + config_file = args.config_file or find_config_file(args.app) + app_properties = load_app_properties(config_file=config_file, config_section=args.config_section) + return app_properties + + +def _arg_parser(): + parser = argparse.ArgumentParser(description=DESCRIPTION) + parser.add_argument('action', metavar='ACTION', type=str, + choices=ACTIONS.keys(), + default=DEFAULT_ACTION, + nargs='?' if DEFAULT_ACTION is not None else None, + help='action to perform') + parser.add_argument("-c", "--config-file", + default=os.environ.get('GALAXY_CONFIG_FILE', None)) + parser.add_argument("--config-section", + default=os.environ.get('GALAXY_CONFIG_SECTION', None)) + parser.add_argument("--app", + default=os.environ.get('GALAXY_APP', 'galaxy')) + for argument in ARGUMENTS: + parser.add_argument(*argument[0], **argument[1]) + return parser diff --git a/lib/tool_shed/capsule/capsule_manager.py b/lib/tool_shed/capsule/capsule_manager.py index 5daa0b21c04..54385d23575 100644 --- a/lib/tool_shed/capsule/capsule_manager.py +++ b/lib/tool_shed/capsule/capsule_manager.py @@ -12,8 +12,9 @@ from sqlalchemy import and_, false import tool_shed.repository_types.util as rt_util from galaxy import web -from galaxy.util import asbool, build_url, CHUNK_SIZE, safe_relpath +from galaxy.util import asbool, build_url, CHUNK_SIZE from galaxy.util.odict import odict +from galaxy.util.path import safe_relpath from tool_shed.dependencies import attribute_handlers from tool_shed.dependencies.repository.relation_builder import RelationBuilder from tool_shed.galaxy_install.repository_dependencies.repository_dependency_manager import RepositoryDependencyInstallManager diff --git a/scripts/manage_tool_dependencies.py b/scripts/manage_tool_dependencies.py index 40e09217d48..0ff3a6b6a5c 100644 --- a/scripts/manage_tool_dependencies.py +++ b/scripts/manage_tool_dependencies.py @@ -1,4 +1,3 @@ -import argparse import os.path import sys @@ -11,43 +10,16 @@ from galaxy.config import ( parse_dependency_options, ) from galaxy.tools.deps import CachedDependencyManager, DependencyManager, NullDependencyManager -from galaxy.util.properties import find_config_file, load_app_properties +from galaxy.util.script import main_factory DESCRIPTION = "Script to manage tool dependencies (with focus on a Conda environments)." -def main(argv=None): - """Entry point for conversion process.""" - if argv is None: - argv = sys.argv[1:] - args = _arg_parser().parse_args(argv) - action = args.action - action_func = ACTIONS[action] - action_func(args) - - -def _init_if_needed(args): - kwargs = _app_properties(args) - +def _init_if_needed(args, kwargs): # If conda_auto_init is set, simply building the Conda resolver will call handle installation. _build_dependency_manager_no_config(kwargs) -def _app_properties(args): - config_file = find_config_file("config/galaxy.ini", "universe_wsgi.ini", args.config_file) - app_properties = load_app_properties(ini_file=config_file) - return app_properties - - -def _arg_parser(): - parser = argparse.ArgumentParser(description=DESCRIPTION) - parser.add_argument('action', metavar='ACTION', type=str, - choices=ACTIONS.keys(), - help='action to perform') - parser.add_argument("-c", "--config-file", default=None) - return parser - - def _build_dependency_manager_no_config(kwargs): """Simplified variant of build_dependency_manager from galaxy.tools.deps. @@ -84,4 +56,5 @@ ACTIONS = { if __name__ == '__main__': + main = main_factory(description=DESCRIPTION, actions=ACTIONS) main()