Commits

Greg Von Kuster  committed 2ec609f Draft

When installing a new repository from the too shed repository to Galaxy or reinstalling an uninstalled repository, handle tool dependencies defined for repository dependencies defined for the repository being installed.

  • Participants
  • Parent commits 530fb4f

Comments (0)

Files changed (6)

File lib/galaxy/util/shed_util.py

         tool_dependencies = None
         missing_tool_dependencies = None
     return tool_dependencies, missing_tool_dependencies
+def get_installed_and_missing_tool_dependencies_for_new_install( trans, all_tool_dependencies ):
+    """Return the lists of installed tool dependencies and missing tool dependencies for a set of repositories being installed into Galaxy."""
+    # FIXME: this method currently populates and returns only missing tool dependencies since tool dependencies defined for complex repository dependency
+    # relationships is not currently supported.  This method should be enhanced to search for installed tool dependencies defined as complex repository
+    # dependency relationships when that feature is implemented.
+    if all_tool_dependencies:
+        tool_dependencies = {}
+        missing_tool_dependencies = {}
+        for td_key, val in all_tool_dependencies.items():
+            # Since we have a new install, missing tool dependencies have never been installed.
+            val[ 'status' ] = trans.model.ToolDependency.installation_status.NEVER_INSTALLED
+            missing_tool_dependencies[ td_key ] = val
+    else:
+        tool_dependencies = None
+        missing_tool_dependencies = None
+    return tool_dependencies, missing_tool_dependencies
 def get_repository_owner( cleaned_repository_url ):
     items = cleaned_repository_url.split( 'repos' )
     repo_path = items[ 1 ]
     """
     Inspect the list of repo_info_dicts for repository dependencies and append a repo_info_dict for each of them to the list.  All
     repository_dependencies entries in each of the received repo_info_dicts includes all required repositories, so only one pass through
-    this methid is required to retrieve all repository dependencies.
+    this method is required to retrieve all repository dependencies.
     """
     all_repo_info_dicts = []
     if repo_info_dicts:
         if k not in [ 'id', 'version', 'name' ]:
             return True
     return False
-def populate_containers_dict_from_repository_metadata( trans, tool_shed_url, tool_path, repository, reinstalling=False ):
+def populate_containers_dict_from_repository_metadata( trans, tool_shed_url, tool_path, repository, reinstalling=False, required_repo_info_dicts=None ):
     """
     Retrieve necessary information from the received repository's metadata to populate the containers_dict for display.  This method is called only
     from Galaxy (not the tool shed) when displaying repository dependencies for installed repositories and when displaying them for uninstalled
             readme_files_dict = None
         # Handle repository dependencies.
         installed_repository_dependencies, missing_repository_dependencies = get_installed_and_missing_repository_dependencies( trans, repository )
-        # Handle tool dependencies.
-        all_tool_dependencies = metadata.get( 'tool_dependencies', None )
-        installed_tool_dependencies, missing_tool_dependencies = get_installed_and_missing_tool_dependencies( trans, repository, all_tool_dependencies )
+        # Handle the current repository's tool dependencies.
+        repository_tool_dependencies = metadata.get( 'tool_dependencies', None )
+        repository_installed_tool_dependencies, repository_missing_tool_dependencies = \
+            get_installed_and_missing_tool_dependencies( trans, repository, repository_tool_dependencies )
         if reinstalling:
-            # All tool dependencies will be considered missing since we are reinstalling the repository.
-            if installed_tool_dependencies:
-                for td in installed_tool_dependencies:
-                    missing_tool_dependencies.append( td )
-                installed_tool_dependencies = None
+            installed_tool_dependencies = None
+            missing_tool_dependencies = None
+            if repository_installed_tool_dependencies is None:
+                repository_installed_tool_dependencies = {}
+            if repository_missing_tool_dependencies is None:
+                repository_missing_tool_dependencies = {}
+            if required_repo_info_dicts:
+                # Handle the tool dependencies defined for each of the repository's repository dependencies.
+                for rid in required_repo_info_dicts:
+                    for name, repo_info_tuple in rid.items():
+                        description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, repository_dependencies, tool_dependencies = \
+                            suc.get_repo_info_tuple_contents( repo_info_tuple )
+                        if tool_dependencies:
+                            tool_shed = suc.get_tool_shed_from_clone_url( repository_clone_url )
+                            required_repository = suc.get_repository_for_dependency_relationship( trans.app, tool_shed, name, repository_owner, changeset_revision )
+                            if not required_repository:
+                                # The required_repository may have been installed with a different changeset revision.
+                                required_repository, installed_changeset_revision = repository_was_previously_installed( trans,
+                                                                                                                         tool_shed_url,
+                                                                                                                         name,
+                                                                                                                         repo_info_tuple,
+                                                                                                                         clone_dir )
+                            if required_repository:
+                                required_repository_installed_tool_dependencies, required_repository_missing_tool_dependencies = \
+                                    get_installed_and_missing_tool_dependencies( trans, required_repository, tool_dependencies )
+                                if required_repository_installed_tool_dependencies:
+                                    for td_key, td_dict in required_repository_installed_tool_dependencies.items():
+                                        if td_key not in repository_installed_tool_dependencies:
+                                            repository_installed_tool_dependencies[ td_key ] = td_dict
+                                if required_repository_missing_tool_dependencies:
+                                    for td_key, td_dict in required_repository_missing_tool_dependencies.items():
+                                        if td_key not in repository_missing_tool_dependencies:
+                                            repository_missing_tool_dependencies[ td_key ] = td_dict
+            if repository_installed_tool_dependencies:
+                installed_tool_dependencies = repository_installed_tool_dependencies
+            if repository_missing_tool_dependencies:
+                missing_tool_dependencies = repository_missing_tool_dependencies
+        else:
+            installed_tool_dependencies = repository_installed_tool_dependencies
+            missing_tool_dependencies = repository_missing_tool_dependencies
         # Handle valid tools.
         valid_tools = metadata.get( 'tools', None )
         # Handle workflows.
                                                                       tool_dependencies=installed_tool_dependencies,
                                                                       valid_tools=valid_tools,
                                                                       workflows=workflows,
-                                                                      new_install=False )
+                                                                      new_install=False,
+                                                                      reinstalling=reinstalling )
     else:
         containers_dict = dict( datatypes=None,
                                 invalid_tools=None,

File lib/galaxy/util/shed_util_common.py

     return readme_files_dict
 def build_repository_containers_for_galaxy( trans, toolshed_base_url, repository_name, repository_owner, changeset_revision, repository, datatypes,
                                             invalid_tools, missing_repository_dependencies, missing_tool_dependencies, readme_files_dict,
-                                            repository_dependencies, tool_dependencies, valid_tools, workflows, new_install=False ):
+                                            repository_dependencies, tool_dependencies, valid_tools, workflows, new_install=False, reinstalling=False ):
     """Return a dictionary of containers for the received repository's dependencies and readme files for display during installation to Galaxy."""
     containers_dict = dict( datatypes=None,
                             invalid_tools=None,
                                                                                                       tool_dependencies,
                                                                                                       label=label,
                                                                                                       missing=False,
-                                                                                                      new_install=new_install )
+                                                                                                      new_install=new_install,
+                                                                                                      reinstalling=reinstalling )
             containers_dict[ 'tool_dependencies' ] = tool_dependencies_root_folder
         # Missing tool dependencies container.
         if missing_tool_dependencies:
                                                                                                               missing_tool_dependencies,
                                                                                                               label='Missing tool dependencies',
                                                                                                               missing=True,
-                                                                                                              new_install=new_install )
+                                                                                                              new_install=new_install,
+                                                                                                              reinstalling=reinstalling )
             containers_dict[ 'missing_tool_dependencies' ] = missing_tool_dependencies_root_folder
         # Valid tools container.
         if valid_tools:
     Return a dictionary that includes all of the information needed to install a repository into a local Galaxy instance.  The dictionary will also
     contain the recursive list of repository dependencies defined for the repository, as well as the defined tool dependencies.  
     
-    This method is called from Galaxy from two places:
+    This method is called from Galaxy in two places:
     1. During the tool shed repository installation process (via the tool shed's get_repository_information() method)- in this case both the received
     repository and repository_metadata will be objects.
     2. When a tool shed repository that was uninstalled from a Galaxy instance is being re-installed - in this case, both repository and
         removed = True
         error_message = ''
     return removed, error_message
+def repository_dependencies_have_tool_dependencies( trans, repository_dependencies ):
+    """
+    repository_dependencies': 
+    {'http://localhost:9009__ESEP__emboss_6__ESEP__test__ESEP__92bedb60b0c9': 
+        [['http://localhost:9009', 'emboss_datatypes', 'test', '27df73fe48a6']], 
+     'root_key': 'http://localhost:9009__ESEP__emboss__ESEP__test__ESEP__06d729cb3f34', 
+     'description': 'required to enable emboss 6 tools', 
+     'http://localhost:9009__ESEP__emboss__ESEP__test__ESEP__06d729cb3f34': 
+         [['http://localhost:9009', 'emboss_6', 'test', '92bedb60b0c9']]}}
+    """
+    rd_tups_processed = []
+    for key, rd_tups in repository_dependencies.items():
+        if key in [ 'root_key', 'description' ]:
+            continue
+        rd_tup = container_util.get_components_from_key( key )
+        if rd_tup not in rd_tups_processed:
+            toolshed, name, owner, changeset_revision = rd_tup
+            repository = get_repository_by_name_and_owner( trans, name, owner )
+            repository_metadata = get_repository_metadata_by_repository_id_changset_revision( trans,
+                                                                                              trans.security.encode_id( repository.id ),
+                                                                                              changeset_revision )
+            if repository_metadata:
+                metadata = repository_metadata.metadata
+                if metadata:
+                    if 'tool_dependencies' in metadata:
+                        return True
+            rd_tups_processed.append( rd_tup )
+        for rd_tup in rd_tups:
+            if rd_tup not in rd_tups_processed:
+                toolshed, name, owner, changeset_revision = rd_tup
+                repository = get_repository_by_name_and_owner( trans, name, owner )
+                repository_metadata = get_repository_metadata_by_repository_id_changset_revision( trans,
+                                                                                                  trans.security.encode_id( repository.id ),
+                                                                                                  changeset_revision )
+                if repository_metadata:
+                    metadata = repository_metadata.metadata
+                    if metadata:
+                        if 'tool_dependencies' in metadata:
+                            return True
+                rd_tups_processed.append( rd_tup )
+    return False
 def reset_all_metadata_on_installed_repository( trans, id ):
     """Reset all metadata on a single tool shed repository installed into a Galaxy instance."""
     repository = get_installed_tool_shed_repository( trans, id )

File lib/galaxy/webapps/community/controllers/repository.py

                          operation='preview_tools_in_changeset',
                          repository_id=repository_id )
         self.valid_repository_grid.operations = [ grids.GridOperation( "Preview and install",
-                                                                            url_args=url_args,
-                                                                            allow_multiple=False,
-                                                                            async_compatible=False ) ]
+                                                                        url_args=url_args,
+                                                                        allow_multiple=False,
+                                                                        async_compatible=False ) ]
         return self.valid_repository_grid( trans, **kwd )
     def __build_allow_push_select_field( self, trans, current_push_list, selected_value='none' ):
         options = []
                      repo_info_dicts=repo_info_dicts )
     @web.json
     def get_required_repo_info_dict( self, trans, encoded_str ):
-        """Retrive a list of dictionaries that each contain all of the information needed to install the list of repositories defined by encoded_str."""
+        """
+        Retrieve and return a dictionary that includes a list of dictionaries that each contain all of the information needed to install the list of
+        repositories defined by the received encoded_str.
+        """
         encoded_required_repository_str = encoding_util.tool_shed_decode( encoded_str )
         encoded_required_repository_tups = encoded_required_repository_str.split( encoding_util.encoding_sep2 )
         decoded_required_repository_tups = []
         return repo_info_dict
     @web.expose
     def get_tool_dependencies( self, trans, **kwd ):
-        """Handle a request from the InstallManager of a local Galaxy instance."""
+        """Handle a request from a Galaxy instance."""
         params = util.Params( kwd )
         message = util.restore_text( params.get( 'message', ''  ) )
         status = params.get( 'status', 'done' )

File lib/galaxy/webapps/community/util/container_util.py

     else:
         tools_root_folder = None
     return folder_id, tools_root_folder
-def build_tool_dependencies_folder( trans, folder_id, tool_dependencies, label='Tool dependencies', missing=False, new_install=False ):
+def build_tool_dependencies_folder( trans, folder_id, tool_dependencies, label='Tool dependencies', missing=False, new_install=False, reinstalling=False ):
     """Return a folder hierarchy containing tool dependencies."""
     # The status will be displayed only if the received value for missing is True.  When this is the case, we're in Galaxy (not the tool shed)
     # and the tool dependencies are not installed or are in an error state, so they are considered missing.  The tool dependency status will be
         folder_id += 1
         folder = Folder( id=folder_id, key='tool_dependencies', label=label, parent=tool_dependencies_root_folder )
         if trans.webapp.name == 'galaxy':
-            if missing:
+            if reinstalling:
+                folder.description = "this repository's tools require handling of these dependencies"
+            elif missing and not reinstalling:
                 folder.description = 'click the name to install the missing dependency'
             else:
                 if new_install:

File lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py

                 decoded_kwd = encoding_util.tool_shed_decode( encoded_kwd )
                 tsr_ids = decoded_kwd[ 'tool_shed_repository_ids' ]
                 tool_panel_section_keys = decoded_kwd[ 'tool_panel_section_keys' ]
+                repo_info_dicts = decoded_kwd[ 'repo_info_dicts' ]
+                filtered_repo_info_dicts = []
                 filtered_tool_panel_section_keys = []
                 repositories_for_installation = []
                 for index, tsr_id in enumerate( tsr_ids ):
                     if repository.status in [ trans.model.ToolShedRepository.installation_status.NEW,
                                               trans.model.ToolShedRepository.installation_status.UNINSTALLED ]:
                         repositories_for_installation.append( repository )
+                        filtered_repo_info_dicts.append( repo_info_dicts[ index ] )
                         filtered_tool_panel_section_keys.append( tool_panel_section_keys[ index ] )
                 if repositories_for_installation:
+                    decoded_kwd[ 'repo_info_dicts' ] = filtered_repo_info_dicts
                     decoded_kwd[ 'tool_panel_section_keys' ] = filtered_tool_panel_section_keys
                     self.install_tool_shed_repositories( trans, repositories_for_installation, reinstalling=reinstalling, **decoded_kwd )
                 else:
             return trans.show_error_message( message )
         message = kwd.get( 'message', ''  )
         status = kwd.get( 'status', 'done' )
-        includes_tools = util.string_as_bool( kwd.get( 'includes_tools', False ) )
         tool_shed_url = kwd[ 'tool_shed_url' ]
         # Handle repository dependencies.
         includes_repository_dependencies = util.string_as_bool( kwd.get( 'includes_repository_dependencies', False ) )
                                 shed_tool_conf=shed_tool_conf,
                                 status=status,
                                 tool_path=tool_path,
-                                
                                 tool_panel_section_keys=tool_panel_section_keys,
                                 tool_shed_repository_ids=tsrids_list,
                                 tool_shed_url=tool_shed_url )
             raw_text = response.read()
             response.close()
             readme_files_dict = json.from_json_string( raw_text )
-            # Handle the scenario where a repository was installed, then uninstalled and an error occurred during the reinstallation process.
-            # In this case, a record for the repository will exist in the database with the status of 'New'.
             if repository_dependencies:
+                missing_tool_dependencies = {}
+                # Handle the scenario where a repository was installed, then uninstalled and an error occurred during the reinstallation process.
+                # In this case, a record for the repository will exist in the database with the status of 'New'.
                 repository = suc.get_repository_for_dependency_relationship( trans.app, tool_shed_url, name, repository_owner, changeset_revision )
                 if repository and repository.metadata:
                     installed_repository_dependencies, missing_repository_dependencies = \
                 else:
                     installed_repository_dependencies, missing_repository_dependencies = \
                         shed_util.get_installed_and_missing_repository_dependencies_for_new_install( trans, repository_dependencies )
+                # Discover all repository dependencies and retrieve information for installing them.
+                required_repo_info_dicts = shed_util.get_required_repo_info_dicts( tool_shed_url, util.listify( repo_info_dict ) )
+                # Display tool dependencies defined for each of the repository dependencies.
+                if required_repo_info_dicts:
+                    all_tool_dependencies = {}
+                    for rid in required_repo_info_dicts:
+                        for name, repo_info_tuple in rid.items():
+                            description, repository_clone_url, changeset_revision, ctx_rev, repository_owner, repository_dependencies, tool_dependencies = \
+                                suc.get_repo_info_tuple_contents( repo_info_tuple )
+                            if tool_dependencies:
+                                for td_key, td_dict in tool_dependencies.items():
+                                    if td_key not in all_tool_dependencies:
+                                        all_tool_dependencies[ td_key ] = td_dict
+                    if all_tool_dependencies:
+                        if tool_dependencies is None:
+                            tool_dependencies = {}
+                        else:
+                            # Move all tool dependencies to the missing_tool_dependencies container.
+                            for td_key, td_dict in tool_dependencies.items():
+                                if td_key not in missing_tool_dependencies:
+                                    missing_tool_dependencies[ td_key ] = td_dict
+                            tool_dependencies = {}
+                        # Discover and categorize all tool dependencies defined this this repository's repository dependencies.
+                        required_tool_dependencies, required_missing_tool_dependencies = \
+                            shed_util.get_installed_and_missing_tool_dependencies_for_new_install( trans, all_tool_dependencies )
+                        if required_tool_dependencies:
+                            if not includes_tool_dependencies:
+                                includes_tool_dependencies = True
+                            for td_key, td_dict in required_tool_dependencies.items():
+                                if td_key not in tool_dependencies:
+                                    tool_dependencies[ td_key ] = td_dict
+                        if required_missing_tool_dependencies:
+                            if not includes_tool_dependencies:
+                                includes_tool_dependencies = True
+                            for td_key, td_dict in required_missing_tool_dependencies.items():
+                                if td_key not in missing_tool_dependencies:
+                                    missing_tool_dependencies[ td_key ] = td_dict
             else:
                 installed_repository_dependencies = None
                 missing_repository_dependencies = None
+                missing_tool_dependencies = None
+                required_repo_info_dicts = None
             # Since we are installing a new repository, no tool dependencies will be considered "missing".  Most of the repository contents
             # are set to None since we don't yet know what they are.
             containers_dict = suc.build_repository_containers_for_galaxy( trans=trans,
                                                                           datatypes=None,
                                                                           invalid_tools=None,
                                                                           missing_repository_dependencies=missing_repository_dependencies,
-                                                                          missing_tool_dependencies=None,
+                                                                          missing_tool_dependencies=missing_tool_dependencies,
                                                                           readme_files_dict=readme_files_dict,
                                                                           repository_dependencies=installed_repository_dependencies,
                                                                           tool_dependencies=tool_dependencies,
                                                                           valid_tools=None,
                                                                           workflows=None,
-                                                                          new_install=True )
+                                                                          new_install=True,
+                                                                          reinstalling=False )
             # We're handling 1 of 2 scenarios here: (1) we're installing a tool shed repository for the first time, so we're retrieved the list of installed
             # and missing repository dependencies from the database (2) we're handling the scenario where an error occurred during the installation process,
             # so we have a tool_shed_repository record in the database with associated repository dependency records.  Since we have the repository
             # each displayed repository dependency will display a status, whether installed or missing.
             containers_dict = suc.merge_missing_repository_dependencies_to_installed_container( containers_dict )
         else:
+            # FIXME: support the intallation of repository dependencies and tool dependencies for a list of tool shed repositories being installed.
             containers_dict = dict( datatypes=None,
                                     invalid_tools=None,
                                     readme_files_dict=None,
         tool_panel_section_key = None
         tool_panel_section_keys = []
         metadata = tool_shed_repository.metadata
+        # Keep track of tool dependencies define dfor the current repository or those defined for any of it's repository dependencies.
+        includes_tool_dependencies = tool_shed_repository.includes_tool_dependencies
         if tool_shed_repository.includes_tools:
             # Handle the selected tool panel location for loading tools included in the tool shed repository.
             tool_section, new_tool_panel_section, tool_panel_section_key = \
             if isinstance( repo_info_dict, basestring ):
                 repo_info_dict = encoding_util.tool_shed_decode( repo_info_dict )
         else:
-            # Entering this else block used to happen only if the tool_shed_repository does not include any valid tools.  After repository dependencies
-            # were introduced, it may never happen, but we'll keep the block just in case.
+            # Entering this else block occurs only if the tool_shed_repository does not include any valid tools.
             if install_repository_dependencies:
                 repository_dependencies = self.get_repository_dependencies( trans=trans,
                                                                             repository_id=repository_id,
             filtered_repo_info_dicts = [ repo_info_dict for repo_info_dict in repo_info_dicts ]
             created_or_updated_tool_shed_repositories = [ tool_shed_repository ]
             tool_panel_section_keys.append( tool_panel_section_key )
-        # Defaulot the selected tool panel location for loading tools included in each newly installed required tool shed repository to the location
+        # Default the selected tool panel location for loading tools included in each newly installed required tool shed repository to the location
         # selected for the repository selected for reinstallation.
         for index, tps_key in enumerate( tool_panel_section_keys ):
             if tps_key is None:
                 tool_panel_section_keys[ index ] = tool_panel_section_key
         encoded_repository_ids = [ trans.security.encode_id( r.id ) for r in created_or_updated_tool_shed_repositories ]
-        new_kwd = dict( includes_tool_dependencies=tool_shed_repository.includes_tool_dependencies,
+        new_kwd = dict( includes_tool_dependencies=includes_tool_dependencies,
                         includes_tools=tool_shed_repository.includes_tools,
                         install_tool_dependencies=install_tool_dependencies,
                         repo_info_dicts=filtered_repo_info_dicts,
                                                     repository_metadata=None,
                                                     metadata=metadata,
                                                     repository_dependencies=repository_dependencies )
+        if includes_repository_dependencies:
+            # Discover all repository dependencies and retrieve information for installing them.
+            required_repo_info_dicts = shed_util.get_required_repo_info_dicts( tool_shed_url, util.listify( repo_info_dict ) )
+        else:
+            required_repo_info_dicts = None
         # Get the location in the tool panel in which the tool was originally loaded.
         if 'tool_panel_section' in metadata:
             tool_panel_dict = metadata[ 'tool_panel_section' ]
             if tool_panel_dict:
                 if shed_util.panel_entry_per_tool( tool_panel_dict ):
-                    # TODO: Fix this to handle the case where the tools are distributed across in more than 1 ToolSection.  The
-                    # following assumes everything was loaded into 1 section (or no section) in the tool panel.
+                    # The following forces everything to be loaded into 1 section (or no section) in the tool panel.
                     tool_section_dicts = tool_panel_dict[ tool_panel_dict.keys()[ 0 ] ]
                     tool_section_dict = tool_section_dicts[ 0 ]
                     original_section_name = tool_section_dict[ 'name' ]
             message += "The tools contained in your <b>%s</b> repository were last loaded into the tool panel outside of any sections.  " % tool_shed_repository.name
             message += "Uncheck the <b>No changes</b> check box and select a tool panel section to load the tools into that section.  "
             status = 'warning'
-        containers_dict = shed_util.populate_containers_dict_from_repository_metadata( trans, tool_shed_url, tool_path, tool_shed_repository, reinstalling=True )
+        # Populate the containers_dict from the metadata for the tool shed repository we're reinstalling, but make sure to include tool dependencies defined for
+        # all of the repository's repository dependencies.
+        containers_dict = shed_util.populate_containers_dict_from_repository_metadata( trans=trans,
+                                                                                       tool_shed_url=tool_shed_url,
+                                                                                       tool_path=tool_path,
+                                                                                       repository=tool_shed_repository,
+                                                                                       reinstalling=True,
+                                                                                       required_repo_info_dicts=required_repo_info_dicts )
         # Since we're reinstalling we'll merge the list of missing repository dependencies into the list of installed repository dependencies since each displayed
         # repository dependency will display a status, whether installed or missing.
         containers_dict = suc.merge_missing_repository_dependencies_to_installed_container( containers_dict )

File templates/admin/tool_shed_repository/common.mako

 
         repository_dependencies_root_folder = containers_dict[ 'repository_dependencies' ]
         tool_dependencies_root_folder = containers_dict[ 'tool_dependencies' ]
+        missing_tool_dependencies_root_folder = containers_dict[ 'missing_tool_dependencies' ]
         env_settings_heaader_row_displayed = False
         package_header_row_displayed = False
     %>
             <div style="clear: both"></div>
         </div>
     %endif
-    %if tool_dependencies_root_folder:
+    %if tool_dependencies_root_folder or missing_tool_dependencies_root_folder:
         %if install_tool_dependencies_check_box is not None:
             <div class="form-row">
                 <label>Handle tool dependencies?</label>
             </div>
             <div style="clear: both"></div>
         %endif
-        <div class="form-row">
-            <p/>
-            <% row_counter = RowCounter() %>
-            <table cellspacing="2" cellpadding="2" border="0" width="100%" class="tables container-table" id="dependency_table">
-                ${render_folder( tool_dependencies_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )}
-            </table>
-            <div style="clear: both"></div>
-        </div>
+        %if tool_dependencies_root_folder:
+            <div class="form-row">
+                <p/>
+                <% row_counter = RowCounter() %>
+                <table cellspacing="2" cellpadding="2" border="0" width="100%" class="tables container-table" id="dependency_table">
+                    ${render_folder( tool_dependencies_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )}
+                </table>
+                <div style="clear: both"></div>
+            </div>
+        %endif
+        %if missing_tool_dependencies_root_folder:
+            <div class="form-row">
+                <p/>
+                <% row_counter = RowCounter() %>
+                <table cellspacing="2" cellpadding="2" border="0" width="100%" class="tables container-table" id="dependency_table">
+                    ${render_folder( missing_tool_dependencies_root_folder, 0, parent=None, row_counter=row_counter, is_root_folder=True )}
+                </table>
+                <div style="clear: both"></div>
+            </div>
+        %endif
     %endif
 </%def>