1 new changeset in galaxy-central: http://bitbucket.org/galaxy/galaxy-central/changeset/898f4f57223d/ changeset: 898f4f57223d user: greg date: 2011-09-23 16:01:18 summary: Add 2 new attributes to dynamically generated select lists; "missing_tool_data_table_name" will include a value (e.g., tmap_indexes) if the select list requires a missing entry in the tool_data_table_conf.xml file, and "missing_index_file" will include a value (e.g., tmap_indexes.loc) if the select list requires a missing index file. Tools that used to not load in index files were missing will now load, although they will not properly execute. Work remaining is for a check to be performed against these new "missing" attributes and a message displayed on the tool form - not quite sure if this should be a validator or not... Define a list in the Tool class to keep track of all input parameters (tool.input_params). These differ from the inputs dictionary (tool.inputs) in that inputs can be page elements like conditionals, but input_params are basic parameters like SelectField objects. This enables us to more easily ensure that parameter dependencies like index files or tool_data_table_conf.xml entries exist. Add the ability to append new entries into the tool_data_table_conf.xml file in real time and add the same entries into the in-memory tool_data_tables dictionary. affected #: 4 files (-1 bytes) --- a/lib/galaxy/tools/__init__.py Fri Sep 23 09:36:57 2011 -0400 +++ b/lib/galaxy/tools/__init__.py Fri Sep 23 10:01:18 2011 -0400 @@ -360,13 +360,18 @@ tool_type = 'default' def __init__( self, config_file, root, app, guid=None ): - """ - Load a tool from the config named by `config_file` - """ + """Load a tool from the config named by `config_file`""" # Determine the full path of the directory where the tool config is self.config_file = config_file self.tool_dir = os.path.dirname( config_file ) self.app = app + # Define a place to keep track of all input parameters. These + # differ from the inputs dictionary in that inputs can be page + # elements like conditionals, but input_params are basic form + # parameters like SelectField objects. This enables us to more + # easily ensure that parameter dependencies like index files or + # tool_data_table_conf.xml entries exist. + self.input_params = [] # Parse XML element containing configuration self.parse( root, guid=guid ) @@ -698,7 +703,6 @@ name = attrib.pop( 'name', None ) if name is None: raise Exception( "Test output does not have a 'name'" ) - assert_elem = output_elem.find("assert_contents") assert_list = None # Trying to keep testing patch as localized as @@ -713,13 +717,10 @@ for child_elem in child_elems: converted_children.append( convert_elem(child_elem) ) return {"tag" : tag, "attributes" : attributes, "children" : converted_children} - if assert_elem is not None: assert_list = [] for assert_child in list(assert_elem): assert_list.append(convert_elem(assert_child)) - - file = attrib.pop( 'file', None ) # File no longer required if an list of assertions was present. if assert_list is None and file is None: @@ -734,8 +735,6 @@ attributes['sort'] = util.string_as_bool( attrib.pop( 'sort', False ) ) attributes['extra_files'] = [] attributes['assert_list'] = assert_list - - if 'ftype' in attrib: attributes['ftype'] = attrib['ftype'] for extra in output_elem.findall( 'extra_files' ): @@ -862,6 +861,7 @@ rval[param.name] = param if hasattr( param, 'data_ref' ): param.ref_input = context[ param.data_ref ] + self.input_params.append( param ) return rval def parse_param_elem( self, input_elem, enctypes, context ): --- a/lib/galaxy/tools/data/__init__.py Fri Sep 23 09:36:57 2011 -0400 +++ b/lib/galaxy/tools/data/__init__.py Fri Sep 23 10:01:18 2011 -0400 @@ -12,34 +12,64 @@ log = logging.getLogger( __name__ ) class ToolDataTableManager( object ): - """ - Manages a collection of tool data tables - """ - + """Manages a collection of tool data tables""" def __init__( self, config_filename=None ): self.data_tables = {} if config_filename: - self.add_from_config_file( config_filename ) - + self.load_from_config_file( config_filename ) def __getitem__( self, key ): return self.data_tables.__getitem__( key ) - def __contains__( self, key ): return self.data_tables.__contains__( key ) - - def add_from_config_file( self, config_filename ): + def load_from_config_file( self, config_filename ): tree = util.parse_xml( config_filename ) root = tree.getroot() + table_elems = [] for table_elem in root.findall( 'table' ): type = table_elem.get( 'type', 'tabular' ) assert type in tool_data_table_types, "Unknown data table type '%s'" % type + table_elems.append( table_elem ) table = tool_data_table_types[ type ]( table_elem ) - self.data_tables[ table.name ] = table - log.debug( "Loaded tool data table '%s", table.name ) + if table.name not in self.data_tables: + self.data_tables[ table.name ] = table + log.debug( "Loaded tool data table '%s", table.name ) + return table_elems + def add_new_entries_from_config_file( self, config_filename ): + """ + We have 2 cases to handle, files whose root tag is <tables>, for example: + <tables> + <!-- Location of Tmap files --> + <table name="tmap_indexes" comment_char="#"> + <columns>value, dbkey, name, path</columns> + <file path="tool-data/tmap_index.loc" /> + </table> + </tables> + and files whose root tag is <table>, for example: + <!-- Location of Tmap files --> + <table name="tmap_indexes" comment_char="#"> + <columns>value, dbkey, name, path</columns> + <file path="tool-data/tmap_index.loc" /> + </table> + """ + tree = util.parse_xml( config_filename ) + root = tree.getroot() + if root.tag == 'tables': + table_elems = self.load_from_config_file( config_filename ) + else: + table_elems = [] + type = root.get( 'type', 'tabular' ) + assert type in tool_data_table_types, "Unknown data table type '%s'" % type + table_elems.append( root ) + table = tool_data_table_types[ type ]( root ) + if table.name not in self.data_tables: + self.data_tables[ table.name ] = table + log.debug( "Loaded tool data table '%s", table.name ) + return table_elems class ToolDataTable( object ): def __init__( self, config_element ): self.name = config_element.get( 'name' ) + self.missing_index_file = None class TabularToolDataTable( ToolDataTable ): """ @@ -58,7 +88,6 @@ def __init__( self, config_element ): super( TabularToolDataTable, self ).__init__( config_element ) self.configure_and_load( config_element ) - def configure_and_load( self, config_element ): """ Configure and load table from an XML element. @@ -71,15 +100,14 @@ all_rows = [] for file_element in config_element.findall( 'file' ): filename = file_element.get( 'path' ) - if not os.path.exists( filename ): + if os.path.exists( filename ): + all_rows.extend( self.parse_file_fields( open( filename ) ) ) + else: + self.missing_index_file = filename log.warn( "Cannot find index file '%s' for tool data table '%s'" % ( filename, self.name ) ) - else: - all_rows.extend( self.parse_file_fields( open( filename ) ) ) self.data = all_rows - def get_fields( self ): return self.data - def parse_column_spec( self, config_element ): """ Parse column definitions, which can either be a set of 'column' elements @@ -109,7 +137,6 @@ assert 'value' in self.columns, "Required 'value' column missing from column def" if 'name' not in self.columns: self.columns['name'] = self.columns['value'] - def parse_file_fields( self, reader ): """ Parse separated lines from file and return a list of tuples. --- a/lib/galaxy/tools/parameters/dynamic_options.py Fri Sep 23 09:36:57 2011 -0400 +++ b/lib/galaxy/tools/parameters/dynamic_options.py Fri Sep 23 10:01:18 2011 -0400 @@ -399,23 +399,29 @@ self.separator = elem.get( 'separator', '\t' ) self.line_startswith = elem.get( 'startswith', None ) data_file = elem.get( 'from_file', None ) + self.missing_index_file = None dataset_file = elem.get( 'from_dataset', None ) from_parameter = elem.get( 'from_parameter', None ) tool_data_table_name = elem.get( 'from_data_table', None ) - # Options are defined from a data table loaded by the app self.tool_data_table = None + self.missing_tool_data_table_name = None if tool_data_table_name: app = tool_param.tool.app - assert tool_data_table_name in app.tool_data_tables, \ - "Data table named '%s' is required by tool but not configured" % tool_data_table_name - self.tool_data_table = app.tool_data_tables[ tool_data_table_name ] - # Column definitions are optional, but if provided override those from the table - if elem.find( "column" ) is not None: - self.parse_column_definitions( elem ) + if tool_data_table_name in app.tool_data_tables: + self.tool_data_table = app.tool_data_tables[ tool_data_table_name ] + # Set self.missing_index_file if the index file to + # which the tool_data_table refers does not exist. + if self.tool_data_table.missing_index_file: + self.missing_index_file = self.tool_data_table.missing_index_file + # Column definitions are optional, but if provided override those from the table + if elem.find( "column" ) is not None: + self.parse_column_definitions( elem ) + else: + self.columns = self.tool_data_table.columns else: - self.columns = self.tool_data_table.columns - + self.missing_tool_data_table_name = tool_data_table_name + log.warn( "Data table named '%s' is required by tool but not configured" % tool_data_table_name ) # Options are defined by parsing tabular text data from an data file # on disk, a dataset, or the value of another parameter elif data_file is not None or dataset_file is not None or from_parameter is not None: @@ -423,8 +429,11 @@ if data_file is not None: data_file = data_file.strip() if not os.path.isabs( data_file ): - data_file = os.path.join( self.tool_param.tool.app.config.tool_data_path, data_file ) - self.file_fields = self.parse_file_fields( open( data_file ) ) + full_path = os.path.join( self.tool_param.tool.app.config.tool_data_path, data_file ) + if os.path.exists( full_path ): + self.file_fields = self.parse_file_fields( open( full_path ) ) + else: + self.missing_index_file = data_file elif dataset_file is not None: self.dataset_ref_name = dataset_file self.has_dataset_dependencies = True --- a/lib/galaxy/tools/parameters/output.py Fri Sep 23 09:36:57 2011 -0400 +++ b/lib/galaxy/tools/parameters/output.py Fri Sep 23 10:01:18 2011 -0400 @@ -206,13 +206,16 @@ super( FromDataTableOutputActionOption, self ).__init__( parent, elem ) self.name = elem.get( 'name', None ) assert self.name is not None, "Required 'name' attribute missing from FromDataTableOutputActionOption" - assert self.name in self.tool.app.tool_data_tables, "Data table named '%s' is required by tool but not configured" % self.name - self.options = self.tool.app.tool_data_tables[ self.name ].get_fields() - self.column = elem.get( 'column', None ) - assert self.column is not None, "Required 'column' attribute missing from FromDataTableOutputActionOption" - self.column = int( self.column ) - self.offset = elem.get( 'offset', -1 ) - self.offset = int( self.offset ) + self.missing_tool_data_table_name = None + if self.name in self.tool.app.tool_data_tables: + self.options = self.tool.app.tool_data_tables[ self.name ].get_fields() + self.column = elem.get( 'column', None ) + assert self.column is not None, "Required 'column' attribute missing from FromDataTableOutputActionOption" + self.column = int( self.column ) + self.offset = elem.get( 'offset', -1 ) + self.offset = int( self.offset ) + else: + self.missing_tool_data_table_name = self.name def get_value( self, other_values ): options = self.options for filter in self.filters: Repository URL: https://bitbucket.org/galaxy/galaxy-central/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email.