Warning

This document is for an old release of Galaxy. You can alternatively view this page in the latest release if it exists or view the top of the latest release's documentation.

Source code for galaxy.tool_shed.util.tool_util

import os
import shutil
from typing import Optional

from galaxy import util
from galaxy.datatypes.sniff import is_column_based
from galaxy.tool_shed.util import basic_util
from galaxy.util import checkers
from galaxy.web.form_builder import SelectField


[docs]def build_shed_tool_conf_select_field(app): """Build a SelectField whose options are the keys in app.toolbox.shed_tool_confs.""" options = [] for dynamic_tool_conf_filename in app.toolbox.dynamic_conf_filenames(): if dynamic_tool_conf_filename.startswith("./"): option_label = dynamic_tool_conf_filename.replace("./", "", 1) else: option_label = dynamic_tool_conf_filename options.append((option_label, dynamic_tool_conf_filename)) select_field = SelectField(name="shed_tool_conf") for option_tup in options: select_field.add_option(option_tup[0], option_tup[1]) return select_field
[docs]def build_tool_panel_section_select_field(app): """Build a SelectField whose options are the sections of the current in-memory toolbox.""" options = [] for section_id, section_name in app.toolbox.get_sections(): options.append((section_name, section_id)) select_field = SelectField(name="tool_panel_section_id", field_id="tool_panel_section_select") for option_tup in options: select_field.add_option(option_tup[0], option_tup[1]) return select_field
[docs]def copy_sample_file(tool_data_path: str, filename: str, dest_path: Optional[str] = None) -> str: """ Copies a sample file at `filename` to `the dest_path` directory and strips the '.sample' extensions from `filename`. Returns the path to the copied file (with the .sample extension). """ if dest_path is None: dest_path = tool_data_path assert dest_path sample_file_name = basic_util.strip_path(filename) copied_file = sample_file_name.rsplit(".sample", 1)[0] full_source_path = os.path.abspath(filename) full_destination_path = os.path.join(dest_path, sample_file_name) # Don't copy a file to itself - not sure how this happens, but sometimes it does... if full_source_path != full_destination_path: # It's ok to overwrite the .sample version of the file. shutil.copy(full_source_path, full_destination_path) # Only create the .loc file if it does not yet exist. We don't overwrite it in case it # contains stuff proprietary to the local instance. non_sample_path = os.path.join(dest_path, copied_file) if not os.path.lexists(non_sample_path): shutil.copy(full_source_path, os.path.join(dest_path, copied_file)) return non_sample_path
[docs]def copy_sample_files( tool_data_path: str, sample_files, tool_path: Optional[str] = None, sample_files_copied=None, dest_path: Optional[str] = None, ) -> None: """ Copy all appropriate files to dest_path in the local Galaxy environment that have not already been copied. Those that have been copied are contained in sample_files_copied. The default value for dest_path is ~/tool-data. We need to be careful to copy only appropriate files here because tool shed repositories can contain files ending in .sample that should not be copied to the ~/tool-data directory. """ filenames_not_to_copy = ["tool_data_table_conf.xml.sample"] sample_files_copied = util.listify(sample_files_copied) for filename in sample_files: filename_sans_path = os.path.split(filename)[1] if filename_sans_path not in filenames_not_to_copy and filename not in sample_files_copied: if tool_path: filename = os.path.join(tool_path, filename) # Attempt to ensure we're copying an appropriate file. if _is_data_index_sample_file(filename): copy_sample_file(tool_data_path, filename, dest_path=dest_path)
[docs]def generate_message_for_invalid_tools( app, invalid_file_tups: list, repository, metadata_dict: Optional[dict], as_html: bool = True, displaying_invalid_tool: bool = False, ) -> str: if as_html: new_line = "<br/>" bold_start = "<b>" bold_end = "</b>" else: new_line = "\n" bold_start = "" bold_end = "" message = "" if app.name == "galaxy": tip_rev = str(repository.changeset_revision) else: tip_rev = str(repository.tip()) if not displaying_invalid_tool: if metadata_dict: message += f"Metadata may have been defined for some items in revision '{tip_rev}'. " message += f"Correct the following problems if necessary and reset metadata.{new_line}" else: message += f"Metadata cannot be defined for revision '{tip_rev}' so this revision cannot be automatically " message += ( f"installed into a local Galaxy instance. Correct the following problems and reset metadata.{new_line}" ) for itc_tup in invalid_file_tups: tool_file, exception_msg = itc_tup if exception_msg.find("No such file or directory") >= 0: exception_items = exception_msg.split() missing_file_items = exception_items[7].split("/") missing_file = missing_file_items[-1].rstrip("'") if missing_file.endswith(".loc"): sample_ext = f"{missing_file}.sample" else: sample_ext = missing_file correction_msg = f"This file refers to a missing file {bold_start}{missing_file}{bold_end}. " correction_msg += ( f"Upload a file named {bold_start}{sample_ext}{bold_end} to the repository to correct this error." ) else: if as_html: correction_msg = exception_msg else: correction_msg = ( exception_msg.replace("<br/>", new_line).replace("<b>", bold_start).replace("</b>", bold_end) ) message += f"{bold_start}{tool_file}{bold_end} - {correction_msg}{new_line}" return message
[docs]def handle_missing_index_file(app, tool_path, sample_files, repository_tools_tups, sample_files_copied): """ Inspect each tool to see if it has any input parameters that are dynamically generated select lists that depend on a .loc file. This method is not called from the tool shed, but from Galaxy when a repository is being installed. """ for repository_tools_tup in repository_tools_tups: tup_path, guid, repository_tool = repository_tools_tup params_with_missing_index_file = repository_tool.params_with_missing_index_file for param in params_with_missing_index_file: options = param.options missing_file_name = basic_util.strip_path(options.missing_index_file) if missing_file_name not in sample_files_copied: # The repository must contain the required xxx.loc.sample file. for sample_file in sample_files: sample_file_name = basic_util.strip_path(sample_file) if sample_file_name == f"{missing_file_name}.sample": target_path = copy_sample_file(app.config.tool_data_path, os.path.join(tool_path, sample_file)) if options.tool_data_table and options.tool_data_table.missing_index_file: options.tool_data_table.handle_found_index_file(target_path) sample_files_copied.append(target_path) break return repository_tools_tups, sample_files_copied
def _is_data_index_sample_file(file_path): """ Attempt to determine if a .sample file is appropriate for copying to ~/tool-data when a tool shed repository is being installed into a Galaxy instance. """ # Currently most data index files are tabular, so check that first. We'll assume that # if the file is tabular, it's ok to copy. if is_column_based(file_path): return True # If the file is any of the following, don't copy it. if checkers.check_html(file_path): return False if checkers.check_image(file_path): return False if checkers.check_binary(name=file_path): return False if checkers.is_bz2(file_path): return False if checkers.is_gzip(file_path): return False if checkers.is_zip(file_path): return False # Default to copying the file if none of the above are true. return True
[docs]def panel_entry_per_tool(tool_section_dict): # Return True if tool_section_dict looks like this. # {<Tool guid> : # [{ tool_config : <tool_config_file>, # id: <ToolSection id>, # version : <ToolSection version>, # name : <TooSection name>}]} # But not like this. # { id: <ToolSection id>, version : <ToolSection version>, name : <TooSection name>} if not tool_section_dict: return False if len(tool_section_dict) != 3: return True for k in tool_section_dict.keys(): if k not in ["id", "version", "name"]: return True return False
__all__ = ( "build_shed_tool_conf_select_field", "build_tool_panel_section_select_field", "copy_sample_file", "copy_sample_files", "generate_message_for_invalid_tools", "handle_missing_index_file", "panel_entry_per_tool", )