1 new commit in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/9df289e31120/ Changeset: 9df289e31120 User: greg Date: 2014-01-06 22:30:27 Summary: Enhance the tool shed's install and test framework to populate and store information about the installation of each repository dependency in addition to the repository itself. This changeset also include miscellaneous typo fixes and code cleanup. Affected #: 11 files diff -r 7ebebaa348c316203ff7aee7ffa67fdc2db3ff88 -r 9df289e311209975ab34c288d8229096683af0e0 lib/galaxy/model/tool_shed_install/__init__.py --- a/lib/galaxy/model/tool_shed_install/__init__.py +++ b/lib/galaxy/model/tool_shed_install/__init__.py @@ -279,6 +279,10 @@ def is_deactivated_or_installed( self ): return self.status in [ self.installation_status.DEACTIVATED, self.installation_status.INSTALLED ] + + @property + def is_installed( self ): + return self.status == self.installation_status.INSTALLED @property def is_latest_installable_revision( self ): diff -r 7ebebaa348c316203ff7aee7ffa67fdc2db3ff88 -r 9df289e311209975ab34c288d8229096683af0e0 lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py --- a/lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py +++ b/lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py @@ -171,7 +171,7 @@ :param tool_shed_url (required): the base URL of the Tool Shed from which to install the Repository :param name (required): the name of the Repository :param owner (required): the owner of the Repository - :param changset_revision (required): the changset_revision of the RepositoryMetadata object associated with the Repository + :param changeset_revision (required): the changeset_revision of the RepositoryMetadata object associated with the Repository :param new_tool_panel_section_label (optional): label of a new section to be added to the Galaxy tool panel in which to load tools contained in the Repository. Either this parameter must be an empty string or the tool_panel_section_id parameter must be an empty string or both must be an empty @@ -372,7 +372,7 @@ :param tool_shed_urls: the base URLs of the Tool Sheds from which to install a specified Repository :param names: the names of the Repositories to be installed :param owners: the owners of the Repositories to be installed - :param changset_revisions: the changset_revisions of each RepositoryMetadata object associated with each Repository to be installed + :param changeset_revisions: the changeset_revisions of each RepositoryMetadata object associated with each Repository to be installed :param new_tool_panel_section_label: optional label of a new section to be added to the Galaxy tool panel in which to load tools contained in the Repository. Either this parameter must be an empty string or the tool_panel_section_id parameter must be an empty string, as both cannot be used. @@ -454,7 +454,7 @@ :param tool_shed_url (required): the base URL of the Tool Shed from which the Repository was installed :param name (required): the name of the Repository :param owner (required): the owner of the Repository - :param changset_revision (required): the changset_revision of the RepositoryMetadata object associated with the Repository + :param changeset_revision (required): the changeset_revision of the RepositoryMetadata object associated with the Repository """ # Get the information about the repository to be installed from the payload. tool_shed_url = payload.get( 'tool_shed_url', '' ) diff -r 7ebebaa348c316203ff7aee7ffa67fdc2db3ff88 -r 9df289e311209975ab34c288d8229096683af0e0 lib/galaxy/webapps/tool_shed/api/repositories.py --- a/lib/galaxy/webapps/tool_shed/api/repositories.py +++ b/lib/galaxy/webapps/tool_shed/api/repositories.py @@ -60,7 +60,7 @@ :param name: the name of the Repository :param owner: the owner of the Repository - :param changset_revision: the changset_revision of the RepositoryMetadata object associated with the Repository + :param changeset_revision: the changeset_revision of the RepositoryMetadata object associated with the Repository Returns a list of the following dictionaries:: - a dictionary defining the Repository. For example: diff -r 7ebebaa348c316203ff7aee7ffa67fdc2db3ff88 -r 9df289e311209975ab34c288d8229096683af0e0 lib/galaxy/webapps/tool_shed/api/repository_revisions.py --- a/lib/galaxy/webapps/tool_shed/api/repository_revisions.py +++ b/lib/galaxy/webapps/tool_shed/api/repository_revisions.py @@ -30,7 +30,7 @@ :param tool_shed_url (required): the base URL of the Tool Shed from which the Repository was installed :param name (required): the name of the Repository :param owner (required): the owner of the Repository - :param changset_revision (required): the changset_revision of the RepositoryMetadata object associated with the Repository + :param changeset_revision (required): the changeset_revision of the RepositoryMetadata object associated with the Repository :param export_repository_dependencies (optional): whether to export repository dependencies - defaults to False :param download_dir (optional): the local directory to which to download the archive - defaults to /tmp """ diff -r 7ebebaa348c316203ff7aee7ffa67fdc2db3ff88 -r 9df289e311209975ab34c288d8229096683af0e0 lib/tool_shed/util/shed_util_common.py --- a/lib/tool_shed/util/shed_util_common.py +++ b/lib/tool_shed/util/shed_util_common.py @@ -1273,8 +1273,8 @@ """Return a tool shed repository database record defined by the id.""" # This method is used only in Galaxy, not the tool shed. return trans.install_model.context.query( trans.install_model.ToolShedRepository ) \ - .filter( trans.install_model.ToolShedRepository.table.c.id == trans.security.decode_id( repository_id ) ) \ - .first() + .filter( trans.install_model.ToolShedRepository.table.c.id == trans.security.decode_id( repository_id ) ) \ + .first() def get_tool_shed_repository_by_shed_name_owner_changeset_revision( app, tool_shed, name, owner, changeset_revision ): """Return a tool shed repository database record defined by the combination of a tool_shed, repository name, repository owner and current changeet_revision.""" diff -r 7ebebaa348c316203ff7aee7ffa67fdc2db3ff88 -r 9df289e311209975ab34c288d8229096683af0e0 lib/tool_shed/util/tool_dependency_util.py --- a/lib/tool_shed/util/tool_dependency_util.py +++ b/lib/tool_shed/util/tool_dependency_util.py @@ -415,10 +415,13 @@ tool_dependency_name=tool_dependency.name, tool_dependency_version=tool_dependency.version ) if remove_installation_path: - # This will be True only in the case where an exception was encountered during the installation process after the installation - # path was created, but before any information was written to the installation log, and the tool dependency status was not - # set to "Installed" or "Error". + # This will be True only in the case where an exception was encountered during the installation process after + # the installation path was created but before any information was written to the installation log and the + # tool dependency status was not set to "Installed" or "Error". if os.path.exists( install_dir ): + log.debug( 'Attempting to remove installation directory %s for version %s of tool dependency %s %s' % \ + ( str( install_dir ), str( tool_dependency.version ), str( tool_dependency.type ), str( tool_dependency.name ) ) ) + log.debug( 'due to the following installation error:\n%s' % str( error_message ) ) try: shutil.rmtree( install_dir ) except Exception, e: diff -r 7ebebaa348c316203ff7aee7ffa67fdc2db3ff88 -r 9df289e311209975ab34c288d8229096683af0e0 test/install_and_test_tool_shed_repositories/base/twilltestcase.py --- a/test/install_and_test_tool_shed_repositories/base/twilltestcase.py +++ b/test/install_and_test_tool_shed_repositories/base/twilltestcase.py @@ -41,13 +41,10 @@ self.shed_tools_dict = {} self.home() - def initiate_installation_process( self, - install_tool_dependencies=False, - install_repository_dependencies=True, - no_changes=True, + def initiate_installation_process( self, install_tool_dependencies=False, install_repository_dependencies=True, no_changes=True, new_tool_panel_section_label=None ): html = self.last_page() - # Since the installation process is by necessity asynchronous, we have to get the parameters to 'manually' initiate the + # Since the installation process is by necessity asynchronous we have to get the parameters to 'manually' initiate the # installation process. This regex will return the tool shed repository IDs in group(1), the encoded_kwd parameter in # group(2), and the reinstalling flag in group(3) and pass them to the manage_repositories method in the Galaxy # admin_toolshed controller. diff -r 7ebebaa348c316203ff7aee7ffa67fdc2db3ff88 -r 9df289e311209975ab34c288d8229096683af0e0 test/install_and_test_tool_shed_repositories/base/util.py --- a/test/install_and_test_tool_shed_repositories/base/util.py +++ b/test/install_and_test_tool_shed_repositories/base/util.py @@ -289,12 +289,36 @@ else: return suc.INITIAL_CHANGELOG_HASH, error_message +def get_missing_repository_dependencies( repository ): + """ + Return the entire list of missing repository dependencies for the received repository. The entire + dependency tree will be inspected. + """ + log.debug( 'Checking revision %s of repository %s owned by %s for missing repository dependencies.' % \ + ( str( repository.changeset_revision ), str( repository.name ), str( repository.changeset_revision ) ) ) + missing_repository_dependencies = repository.missing_repository_dependencies + for missing_required_repository in missing_repository_dependencies: + log.debug( 'Revision %s of required repository %s owned by %s has status %s.' % \ + ( str( missing_required_repository.changeset_revision ), + str( missing_required_repository.name ), + str( missing_required_repository.owner ), + str( missing_required_repository.status ) ) ) + for repository_dependency in repository.repository_dependencies: + if repository_dependency.missing_repository_dependencies: + missing_repository_dependencies.extend( get_missing_repository_dependencies( repository_dependency ) ) + return missing_repository_dependencies + def get_missing_tool_dependencies( repository ): + """ + Return the entire list of missing tool dependencies for the received repository. The entire + dependency tree will be inspected. + """ log.debug( 'Checking revision %s of repository %s owned by %s for missing tool dependencies.' % \ ( str( repository.changeset_revision ), str( repository.name ), str( repository.changeset_revision ) ) ) missing_tool_dependencies = repository.missing_tool_dependencies - for tool_dependency in repository.tool_dependencies: - log.debug( 'Tool dependency %s version %s has status %s.' % ( tool_dependency.name, tool_dependency.version, tool_dependency.status ) ) + for missing_tool_dependency in missing_tool_dependencies: + log.debug( 'Tool dependency %s version %s has status %s.' % \ + ( str( missing_tool_dependency.name ), str( missing_tool_dependency.version ), str( missing_tool_dependency.status ) ) ) for repository_dependency in repository.repository_dependencies: if repository_dependency.includes_tool_dependencies: missing_tool_dependencies.extend( get_missing_tool_dependencies( repository_dependency ) ) @@ -336,8 +360,7 @@ for baseline_repository_dict in baseline_repository_dicts: # We need to get some details from the tool shed API, such as repository name and owner, to pass on to the # module that will generate the install methods. - repository_dict, error_message = \ - get_repository_dict( galaxy_tool_shed_url, baseline_repository_dict ) + repository_dict, error_message = get_repository_dict( galaxy_tool_shed_url, baseline_repository_dict ) if error_message: log.debug( 'Error getting additional details from the API: %s' % str( error_message ) ) else: @@ -439,6 +462,19 @@ extended_dict[ 'latest_revision' ] = str( latest_changeset_revision ) return extended_dict, error_message +def get_repository_dependencies_dicts( url, encoded_repository_metadata_id ): + """ + Return a list if dictionaries that define the repository dependencies of the repository defined by the + received repository_dict. + """ + error_message = '' + parts = [ 'api', 'repository_revisions', encoded_repository_metadata_id, 'repository_dependencies' ] + api_url = get_api_url( base=url, parts=parts ) + repository_dependencies_dicts, error_message = json_from_url( api_url ) + if error_message: + return None, error_message + return repository_dependencies_dicts, error_message + def get_repository_tuple_from_elem( elem ): attributes = elem.attrib name = attributes.get( 'name', None ) @@ -511,55 +547,6 @@ global_conf.update( get_static_settings() ) return global_conf -def handle_missing_dependencies( app, repository, missing_tool_dependencies, repository_dict, tool_test_results_dicts, - tool_test_results_dict, params, can_update_tool_shed ): - """Handle missing repository or tool dependencies for an installed repository.""" - # If a tool dependency fails to install correctly, this should be considered an installation error, - # and functional tests should be skipped, since the tool dependency needs to be correctly installed - # for the test to be considered reliable. - log.debug( 'The following dependencies of revision %s of repository %s owned by %s are missing.' % \ - ( str( repository.changeset_revision ), str( repository.name ), str( repository.owner ) ) ) - # In keeping with the standard display layout, add the error message to the dict for each tool individually. - for dependency in repository.missing_tool_dependencies: - name = str( dependency.name ) - type = str( dependency.type ) - version = str( dependency.version ) - error_message = unicodify( dependency.error_message ) - log.debug( 'Missing tool dependency %s of type %s version %s: %s' % ( name, type, version, error_message ) ) - missing_tool_dependency_info_dict = dict( type=type, - name=name, - version=version, - error_message=error_message ) - tool_test_results_dict[ 'installation_errors' ][ 'tool_dependencies' ].append( missing_tool_dependency_info_dict ) - for dependency in repository.missing_repository_dependencies: - tool_shed = str( dependency.tool_shed ) - name = str( dependency.name ) - owner = str( dependency.owner ) - changeset_revision = str( dependency.changeset_revision ) - error_message = unicodify( dependency.error_message ) - log.debug( 'Missing repository dependency %s changeset revision %s owned by %s: %s' % \ - ( name, changeset_revision, owner, error_message ) ) - missing_repository_dependency_info_dict = dict( tool_shed=tool_shed, - name=name, - owner=owner, - changeset_revision=changeset_revision, - error_message=error_message ) - tool_test_results_dict[ 'installation_errors' ][ 'repository_dependencies' ]\ - .append( missing_repository_dependency_info_dict ) - # Record the status of this repository in the tool shed. - log.debug('=============================================================' ) - log.debug( 'Inserting the following into tool_test_results for revision %s of repository %s owned by %s:\n%s' % \ - ( str( repository.changeset_revision ), str( repository.name ), str( repository.owner ), str( tool_test_results_dict ) ) ) - response_dict = register_test_result( galaxy_tool_shed_url, - tool_test_results_dicts, - tool_test_results_dict, - repository_dict, - params, - can_update_tool_shed ) - log.debug( 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \ - ( str( repository.changeset_revision ), str( repository.name ), str( repository.owner ), str( response_dict ) ) ) - log.debug('=============================================================' ) - def initialize_install_and_test_statistics_dict( test_framework ): # Initialize a dictionary for the summary that will be printed to stdout. install_and_test_statistics_dict = {} @@ -747,32 +734,42 @@ log.debug( 'The exclude file %s defines no repositories to be excluded from testing.' % str( xml_filename ) ) return exclude_list -def register_installed_and_missing_dependencies( app, repository, repository_identifier_dict, install_and_test_statistics_dict, - tool_test_results_dict ): - # The repository was successfully installed. - log.debug( 'Installation succeeded for revision %s of repository %s owned by %s.' % \ - ( str( repository.changeset_revision ), str( repository.name ), str( repository.owner ) ) ) +def populate_dependency_install_containers( app, repository, repository_identifier_dict, install_and_test_statistics_dict, + tool_test_results_dict ): + """ + Populate the installation containers (successful or errors) for the received repository's (which + itself was successfully installed) immediate repository and tool dependencies. The entire dependency + tree is not handled here. + """ + repository_name = str( repository.name ) + repository_owner = str( repository.owner ) + repository_changeset_revision = str( repository.changeset_revision ) install_and_test_statistics_dict[ 'successful_repository_installations' ].append( repository_identifier_dict ) tool_test_results_dict[ 'successful_installations' ][ 'current_repository' ].append( repository_identifier_dict ) params = dict( test_install_error=False, do_not_test=False ) if repository.missing_repository_dependencies: + log.debug( 'The following repository dependencies for revision %s of repository %s owned by %s have installation errors:' % \ + ( repository_changeset_revision, repository_name, repository_owner ) ) params[ 'test_install_error' ] = True # Keep statistics for this repository's repository dependencies that resulted in installation errors. for missing_repository_dependency in repository.missing_repository_dependencies: tool_shed = str( missing_repository_dependency.tool_shed ) name = str( missing_repository_dependency.name ) owner = str( missing_repository_dependency.owner ) - changset_revision = str( missing_repository_dependency.changeset_revision ) + changeset_revision = str( missing_repository_dependency.changeset_revision ) error_message = unicodify( missing_repository_dependency.error_message ) + log.debug( 'Revision %s of repository %s owned by %s:\n%s' % ( changeset_revision, name, owner, error_message ) ) missing_repository_dependency_info_dict = dict( tool_shed=tool_shed, name=name, owner=owner, - changset_revision=changset_revision, + changeset_revision=changeset_revision, error_message=error_message ) - install_and_test_statistics_dict[ 'repositories_with_installation_error' ].append( missing_repository_dependency_dict ) + install_and_test_statistics_dict[ 'repositories_with_installation_error' ].append( missing_repository_dependency_info_dict ) tool_test_results_dict[ 'installation_errors' ][ 'repository_dependencies' ].append( missing_repository_dependency_info_dict ) if repository.missing_tool_dependencies: + log.debug( 'The following tool dependencies for revision %s of repository %s owned by %s have installation errors:' % \ + ( repository_changeset_revision, repository_name, repository_owner ) ) params[ 'test_install_error' ] = True # Keep statistics for this repository's tool dependencies that resulted in installation errors. for missing_tool_dependency in repository.missing_tool_dependencies: @@ -780,6 +777,7 @@ type = str( missing_tool_dependency.type ) version = str( missing_tool_dependency.version ) error_message = unicodify( missing_tool_dependency.error_message ) + log.debug( 'Version %s of tool dependency %s %s:\n%s' % ( version, type, name, error_message ) ) missing_tool_dependency_info_dict = dict( type=type, name=name, version=version, @@ -787,12 +785,15 @@ install_and_test_statistics_dict[ 'tool_dependencies_with_installation_error' ].append( missing_tool_dependency_info_dict ) tool_test_results_dict[ 'installation_errors' ][ 'tool_dependencies' ].append( missing_tool_dependency_info_dict ) if repository.installed_repository_dependencies: + log.debug( 'The following repository dependencies for revision %s of repository %s owned by %s are installed:' % \ + ( repository_changeset_revision, repository_name, repository_owner ) ) # Keep statistics for this repository's tool dependencies that resulted in successful installations. for repository_dependency in repository.installed_repository_dependencies: tool_shed = str( repository_dependency.tool_shed ) name = str( repository_dependency.name ) owner = str( repository_dependency.owner ) changeset_revision = str( repository_dependency.changeset_revision ) + log.debug( 'Revision %s of repository %s owned by %s.' % ( changeset_revision, name, owner ) ) repository_dependency_info_dict = dict( tool_shed=tool_shed, name=name, owner=owner, @@ -800,12 +801,15 @@ install_and_test_statistics_dict[ 'successful_repository_installations' ].append( repository_dependency_info_dict ) tool_test_results_dict[ 'successful_installations' ][ 'repository_dependencies' ].append( repository_dependency_info_dict ) if repository.installed_tool_dependencies: + log.debug( 'The following tool dependencies for revision %s of repository %s owned by %s are installed:' % \ + ( repository_changeset_revision, repository_name, repository_owner ) ) # Keep statistics for this repository's tool dependencies that resulted in successful installations. for tool_dependency in repository.installed_tool_dependencies: name = str( tool_dependency.name ) type = str( tool_dependency.type ) version = str( tool_dependency.version ) installation_directory = tool_dependency.installation_directory( app ) + log.debug( 'Version %s of tool dependency %s %s is installed in: %s' % ( version, type, name, installation_directory ) ) tool_dependency_info_dict = dict( type=type, name=name, version=version, @@ -814,29 +818,98 @@ tool_test_results_dict[ 'successful_installations' ][ 'tool_dependencies' ].append( tool_dependency_info_dict ) return params, install_and_test_statistics_dict, tool_test_results_dict -def register_test_result( url, tool_test_results_dicts, tool_test_results_dict, repository_dict, params, can_update_tool_shed ): +def populate_install_containers_for_repository_dependencies( app, repository, repository_metadata_id, install_and_test_statistics_dict, + can_update_tool_shed ): """ - Update the repository metadata tool_test_results and appropriate flags using the Tool Shed API. This method - updates tool_test_results with the relevant data, sets the do_not_test and tools_functionally correct flags - to the appropriate values and updates the time_last_tested field to the value of the received time_tested. + The handle_repository_dependencies check box is always checked when a repository is installed, so the + tool_test_results dictionary must be inspected for each dependency to make sure installation containers + (success or errors) have been populated. Since multiple repositories can depend on the same repository, + some of the containers may have been populated during a previous installation. """ - if can_update_tool_shed: - metadata_revision_id = repository_dict.get( 'id', None ) - if metadata_revision_id is not None: - log.debug( 'Updating tool_test_results for repository_metadata id %s.' % str( metadata_revision_id ) ) - tool_test_results_dicts.insert( 0, tool_test_results_dict ) - params[ 'tool_test_results' ] = tool_test_results_dicts - # Set the time_last_tested entry so that the repository_metadata.time_last_tested will be set in the tool shed. - params[ 'time_last_tested' ] = 'This entry will result in this value being set via the Tool Shed API.' - url = '%s' % ( suc.url_join( galaxy_tool_shed_url,'api', 'repository_revisions', str( metadata_revision_id ) ) ) - try: - return update( tool_shed_api_key, url, params, return_formatted=False ) - except Exception, e: - log.exception( 'Error updating tool_test_results for repository_metadata id %s:\n%s' % \ - ( str( metadata_revision_id ), str( e ) ) ) - return {} + # Get the list of dictionaries that define the received repository's repository dependencies + # via the Tool Shed API. + repository_name = str( repository.name ) + repository_owner = str( repository.owner ) + repository_changeset_revision = str( repository.changeset_revision ) + repository_dependencies_dicts, error_message = get_repository_dependencies_dicts( galaxy_tool_shed_url, repository_metadata_id ) + if error_message: + log.debug( 'Cannot check or populate repository dependency install containers for version %s of repository %s owned by %s ' % \ + ( repository_changeset_revision, repository_name, repository_owner ) ) + log.debug( 'due to the following error getting repository_dependencies_dicts:\n%s' % str( error_message ) ) else: - return {} + for repository_dependencies_dict in repository_dependencies_dicts: + name = str( repository_dependencies_dict[ 'name' ] ) + owner = str( repository_dependencies_dict[ 'owner' ] ) + changeset_revision = str( repository_dependencies_dict[ 'changeset_revision' ] ) + log.debug( 'Checking installation containers for revision %s of required repository %s owned by %s' % \ + ( changeset_revision, name, owner ) ) + required_repository_metadata_id = repository_dependencies_dict[ 'id' ] + # Get the current list of tool_test_results dictionaries associated with the repository_metadata + # record in the tool shed. + tool_test_results_dicts, error_message = get_tool_test_results_dicts( galaxy_tool_shed_url, + required_repository_metadata_id ) + if error_message: + log.debug( 'Cannot check install container for version %s of repository %s owned by %s ' % \ + ( changeset_revision, name, owner ) ) + log.debug( 'due to the following error getting tool_test_results:\n%s' % str( error_message ) ) + else: + # Inspect the tool_test_results_dict for the last test run to see if it has not yet been populated + if len( tool_test_results_dicts ) == 0: + populated = False + tool_test_results_dict = initialize_tool_tests_results_dict( app, {} ) + else: + tool_test_results_dict = tool_test_results_dicts[ 0 ] + if len( tool_test_results_dict ) <= 1: + populated = False + tool_test_results_dict = tool_test_results_dicts.pop( 0 ) + elif len( tool_test_results_dict ) == 2 and \ + 'test_environment' in tool_test_results_dict and \ + 'missing_test_components' in tool_test_results_dict: + populated = False + tool_test_results_dict = tool_test_results_dicts.pop( 0 ) + else: + populated = True + if not populated: + # Get the installed repository record from the Galaxy database. + required_repository = \ + suc.get_tool_shed_repository_by_shed_name_owner_changeset_revision( app, + galaxy_tool_shed_url, + name, + owner, + changeset_revision ) + repository_identifier_dict = dict( name=name, owner=owner, changeset_revision=changeset_revision ) + if required_repository.is_installed: + # The required_repository was successfully installed, so populate the installation + # containers (success and error) for the repository's immediate dependencies. + params, install_and_test_statistics_dict, tool_test_results_dict = \ + populate_dependency_install_containers( app, + required_repository, + repository_identifier_dict, + install_and_test_statistics_dict, + tool_test_results_dict ) + response_dict = save_test_results_for_changeset_revision( galaxy_tool_shed_url, + tool_test_results_dicts, + tool_test_results_dict, + repository_dependencies_dict, + params, + can_update_tool_shed ) + log.debug( 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \ + ( changeset_revision, name, owner, str( response_dict ) ) ) + log.debug('\n=============================================================\n' ) + else: + # The required repository's installation failed. + tool_test_results_dict[ 'installation_errors' ][ 'current_repository' ] = str( required_repository.error_message ) + params = dict( test_install_error=True, + do_not_test=False ) + response_dict = save_test_results_for_changeset_revision( galaxy_tool_shed_url, + tool_test_results_dicts, + tool_test_results_dict, + repository_dependencies_dict, + params, + can_update_tool_shed ) + log.debug( 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \ + ( changeset_revision, name, owner, str( response_dict ) ) ) + log.debug('\n=============================================================\n' ) def run_tests( test_config ): loader = nose.loader.TestLoader( config=test_config ) @@ -853,3 +926,34 @@ test_runner = plug_runner result = test_runner.run( tests ) return result, test_config.plugins._plugins + +def save_test_results_for_changeset_revision( url, tool_test_results_dicts, tool_test_results_dict, repository_dict, + params, can_update_tool_shed ): + """ + Update the repository metadata tool_test_results and appropriate flags using the Tool Shed API. This method + updates tool_test_results with the received tool_test_results_dict, sets the do_not_test and tools_functionally + correct flags to the appropriate values and updates the time_last_tested field. + """ + if can_update_tool_shed: + metadata_revision_id = repository_dict.get( 'id', None ) + if metadata_revision_id is not None: + name = str( repository_dict[ 'name' ] ) + owner = str( repository_dict[ 'owner' ] ) + changeset_revision = str( repository_dict[ 'changeset_revision' ] ) + log.debug('\n=============================================================\n' ) + log.debug( 'Inserting the following into tool_test_results for revision %s of repository %s owned by %s:\n%s' % \ + ( changeset_revision, name, owner, str( tool_test_results_dict ) ) ) + log.debug( 'Updating tool_test_results for repository_metadata id %s.' % str( metadata_revision_id ) ) + tool_test_results_dicts.insert( 0, tool_test_results_dict ) + params[ 'tool_test_results' ] = tool_test_results_dicts + # Set the time_last_tested entry so that the repository_metadata.time_last_tested will be set in the tool shed. + params[ 'time_last_tested' ] = 'This entry will result in this value being set via the Tool Shed API.' + url = '%s' % ( suc.url_join( galaxy_tool_shed_url,'api', 'repository_revisions', str( metadata_revision_id ) ) ) + try: + return update( tool_shed_api_key, url, params, return_formatted=False ) + except Exception, e: + log.exception( 'Error updating tool_test_results for repository_metadata id %s:\n%s' % \ + ( str( metadata_revision_id ), str( e ) ) ) + return {} + else: + return {} diff -r 7ebebaa348c316203ff7aee7ffa67fdc2db3ff88 -r 9df289e311209975ab34c288d8229096683af0e0 test/install_and_test_tool_shed_repositories/functional/test_install_repositories.py --- a/test/install_and_test_tool_shed_repositories/functional/test_install_repositories.py +++ b/test/install_and_test_tool_shed_repositories/functional/test_install_repositories.py @@ -7,7 +7,7 @@ class InstallTestRepositories( InstallTestRepository ): - """Abstract test case that installs and uninstalls a predefined list of repositories.""" + """Abstract test case that installs a predefined list of repositories.""" def do_install( self, repository_dict ): self.logout() @@ -21,27 +21,34 @@ def generate_install_method( repository_dict=None ): """Generate abstract test cases for the defined list of repositories.""" + + def make_install_method( repository_dict ): + def test_install_repository( self ): + self.do_install( repository_dict ) + return test_install_repository + if repository_dict is None: return # Push all the toolbox tests to module level G = globals() # Eliminate all previous tests from G. for key, val in G.items(): - if key.startswith( 'TestInstallRepository_' ) or key.startswith( 'TestUninstallRepository_' ) or key.startswith( 'TestForTool_' ): + if key.startswith( 'TestInstallRepository_' ) or key.startswith( 'TestForTool_' ): del G[ key ] - # Create a new subclass with a method named install_repository_XXX that installs the repository specified by the provided dict. - name = "TestInstallRepository_" + repository_dict[ 'name' ] + tool_shed = str( repository_dict[ 'tool_shed_url' ] ) + repository_name = str( repository_dict[ 'name' ] ) + repository_owner = str( repository_dict[ 'owner' ] ) + changeset_revision = str( repository_dict[ 'changeset_revision' ] ) + # Create a new subclass with a method named install_repository_XXX that installs the repository defined + # by the received repository_dict along with all of its dependency hierarchy. + test_name = "TestInstallRepository_" + repository_name baseclasses = ( InstallTestRepositories, ) namespace = dict() - def make_install_method( repository_dict ): - def test_install_repository( self ): - self.do_install( repository_dict ) - return test_install_repository test_method = make_install_method( repository_dict ) - test_method.__doc__ = "Install the repository %s from %s." % \ - ( str( repository_dict[ 'name' ] ), str( repository_dict[ 'tool_shed_url' ] ) ) - namespace[ 'install_repository_%s' % str( repository_dict[ 'name' ] ) ] = test_method + test_method.__doc__ = "Installing revision %s of repository %s owned by %s from tool shed %s." % \ + ( changeset_revision, repository_name, repository_owner, tool_shed ) + namespace[ 'install_repository_%s' % repository_name ] = test_method # The new.classobj function returns a new class object with name name derived # from baseclasses (which should be a tuple of classes) and with namespace dict. - new_class_obj = new.classobj( str( name ), baseclasses, namespace ) - G[ name ] = new_class_obj + new_class_obj = new.classobj( str( test_name ), baseclasses, namespace ) + G[ test_name ] = new_class_obj diff -r 7ebebaa348c316203ff7aee7ffa67fdc2db3ff88 -r 9df289e311209975ab34c288d8229096683af0e0 test/install_and_test_tool_shed_repositories/repositories_with_tools/functional_tests.py --- a/test/install_and_test_tool_shed_repositories/repositories_with_tools/functional_tests.py +++ b/test/install_and_test_tool_shed_repositories/repositories_with_tools/functional_tests.py @@ -180,7 +180,8 @@ install_and_test_base_util.get_tool_test_results_dicts( install_and_test_base_util.galaxy_tool_shed_url, encoded_repository_metadata_id ) if error_message: - log.debug( error_message ) + log.debug( 'Cannot install version %s of repository %s owned by %s due to the following error getting tool_test_results:\n%s' % \ + ( changeset_revision, name, owner, str( error_message ) ) ) else: tool_test_results_dict = install_and_test_base_util.get_tool_test_results_dict( tool_test_results_dicts ) is_excluded, reason = install_and_test_base_util.is_excluded( exclude_list_dicts, @@ -194,18 +195,16 @@ # If this repository is being skipped, register the reason. tool_test_results_dict[ 'not_tested' ] = dict( reason=reason ) params = dict( do_not_test=False ) - log.debug('=============================================================' ) - log.debug( 'Inserting the following into tool_test_results for revision %s of repository %s owned by %s:\n%s' % \ - ( changeset_revision, name, owner, str( tool_test_results_dict ) ) ) - response_dict = install_and_test_base_util.register_test_result( install_and_test_base_util.galaxy_tool_shed_url, - tool_test_results_dicts, - tool_test_results_dict, - repository_dict, - params, - can_update_tool_shed ) + response_dict = \ + install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url, + tool_test_results_dicts, + tool_test_results_dict, + repository_dict, + params, + can_update_tool_shed ) log.debug( 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \ ( changeset_revision, name, owner, str( response_dict ) ) ) - log.debug('=============================================================' ) + log.debug('\n=============================================================\n' ) else: # See if the repository was installed in a previous test. repository = install_and_test_base_util.get_repository( name, owner, changeset_revision ) @@ -219,47 +218,54 @@ log.debug( 'Installation failed for revision %s of repository %s owned by %s.' % ( changeset_revision, name, owner ) ) install_and_test_statistics_dict[ 'repositories_with_installation_error' ].append( repository_identifier_dict ) tool_test_results_dict[ 'installation_errors' ][ 'current_repository' ] = error_message - params = dict( test_install_error=True ) - log.debug('=============================================================' ) - log.debug( 'Inserting the following into tool_test_results for revision %s of repository %s owned by %s:\n%s' % \ - ( changeset_revision, name, owner, str( tool_test_results_dict ) ) ) - response_dict = install_and_test_base_util.register_test_result( install_and_test_base_util.galaxy_tool_shed_url, - tool_test_results_dicts, - tool_test_results_dict, - repository_dict, - params, - can_update_tool_shed ) + params = dict( test_install_error=True, + do_not_test=False ) + response_dict = \ + install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url, + tool_test_results_dicts, + tool_test_results_dict, + repository_dict, + params, + can_update_tool_shed ) log.debug( 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \ ( changeset_revision, name, owner, str( response_dict ) ) ) - log.debug('=============================================================' ) + log.debug('\n=============================================================\n' ) else: # The repository was successfully installed. log.debug( 'Installation succeeded for revision %s of repository %s owned by %s.' % \ ( changeset_revision, name, owner ) ) - params, install_and_test_statistics_dict, tool_test_results_dict = \ - install_and_test_base_util.register_installed_and_missing_dependencies( app, - repository, - repository_identifier_dict, - install_and_test_statistics_dict, - tool_test_results_dict ) # Add an empty 'missing_test_results' entry if it is missing from the tool_test_results_dict. The # ~/tool_shed/scripts/check_repositories_for_functional_tests.py will have entered information in the # 'missing_test_components' entry of the tool_test_results_dict dictionary for repositories that are # missing test components. if 'missing_test_components' not in tool_test_results_dict: tool_test_results_dict[ 'missing_test_components' ] = [] + # Populate the installation containers (success and error) for the repository's immediate dependencies + # (the entire dependency tree is not handled here). + params, install_and_test_statistics_dict, tool_test_results_dict = \ + install_and_test_base_util.populate_dependency_install_containers( app, + repository, + repository_identifier_dict, + install_and_test_statistics_dict, + tool_test_results_dict ) + # Populate the installation containers (success or error) for the repository's immediate repository + # dependencies whose containers are not yet populated. + install_and_test_base_util.populate_install_containers_for_repository_dependencies( app, + repository, + encoded_repository_metadata_id, + install_and_test_statistics_dict, + can_update_tool_shed ) + # Execute the contained tool's functional tests only if the repository's entire dependency + # tree is successfully installed. + missing_repository_dependencies = install_and_test_base_util.get_missing_repository_dependencies( repository ) missing_tool_dependencies = install_and_test_base_util.get_missing_tool_dependencies( repository ) - if missing_tool_dependencies or repository.missing_repository_dependencies: - install_and_test_base_util.handle_missing_dependencies( app=app, - repository=repository, - missing_tool_dependencies=missing_tool_dependencies, - repository_dict=repository_dict, - tool_test_results_dicts=tool_test_results_dicts, - tool_test_results_dict=tool_test_results_dict, - params=params, - can_update_tool_shed=can_update_tool_shed ) + if missing_repository_dependencies or missing_tool_dependencies: + log.debug( 'Cannot execute tests for tools in revision %s of repository %s owned by %s ' % \ + ( changeset_revision, name, owner ) ) + log.debug( 'because one or more dependencies has installation errors.' ) else: - log.debug( 'Installation of %s succeeded, running all defined functional tests.' % str( repository.name ) ) + log.debug( 'Revision %s of repository %s owned by %s installed successfully, so running tool tests.' % \ + ( changeset_revision, name, owner ) ) # Generate the shed_tools_dict that specifies the location of test data contained within this repository. # and configure and run functional tests for this repository. This is equivalent to # sh run_functional_tests.sh -installed @@ -287,19 +293,16 @@ install_and_test_statistics_dict[ 'at_least_one_test_failed' ].append( repository_identifier_dict ) # Record the status of this repository in the tool shed. params[ 'tools_functionally_correct' ] = False - log.debug('=============================================================' ) - log.debug( 'Inserting the following into tool_test_results for revision %s of repository %s owned by %s:\n%s' % \ - ( changeset_revision, name, owner, str( tool_test_results_dict ) ) ) response_dict = \ - install_and_test_base_util.register_test_result( install_and_test_base_util.galaxy_tool_shed_url, - tool_test_results_dicts, - tool_test_results_dict, - repository_dict, - params, - can_update_tool_shed ) + install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url, + tool_test_results_dicts, + tool_test_results_dict, + repository_dict, + params, + can_update_tool_shed ) log.debug( 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \ ( changeset_revision, name, owner, str( response_dict ) ) ) - log.debug('=============================================================' ) + log.debug('\n=============================================================\n' ) else: log.debug( 'Skipped attempt to install revision %s of repository %s owned by %s because ' % \ ( changeset_revision, name, owner ) ) @@ -661,21 +664,19 @@ params = dict( tools_functionally_correct=True, do_not_test=False, test_install_error=False ) - # Call the register_test_result() method to execute a PUT request to the repository_revisions API - # controller with the status of the test. This also sets the do_not_test and tools_functionally - # correct flags and updates the time_last_tested field to today's date. - log.debug('=============================================================' ) - log.debug( 'Inserting the following into tool_test_results for revision %s of repository %s owned by %s:\n%s' % \ - ( changeset_revision, name, owner, str( tool_test_results_dict ) ) ) - response_dict = install_and_test_base_util.register_test_result( install_and_test_base_util.galaxy_tool_shed_url, - tool_test_results_dicts, - tool_test_results_dict, - repository_dict, - params, - can_update_tool_shed ) + # Call the save_test_results_for_changeset_revision() method to execute a PUT request to the + # repository_revisions API controller with the status of the test. This also sets the do_not_test + # and tools_functionally correct flags and updates the time_last_tested field to today's date. + response_dict = \ + install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url, + tool_test_results_dicts, + tool_test_results_dict, + repository_dict, + params, + can_update_tool_shed ) log.debug( 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \ ( changeset_revision, name, owner, str( response_dict ) ) ) - log.debug('=============================================================' ) + log.debug('\n=============================================================\n' ) else: # The get_failed_test_dicts() method returns a list. log.debug( 'Revision %s of repository %s owned by %s installed successfully but did not pass functional tests.' % \ @@ -690,18 +691,16 @@ params = dict( tools_functionally_correct=False, test_install_error=False, do_not_test=str( set_do_not_test ) ) - log.debug('=============================================================' ) - log.debug( 'Inserting the following into tool_test_results for revision %s of repository %s owned by %s:\n%s' % \ - ( changeset_revision, name, owner, str( tool_test_results_dict ) ) ) - response_dict = install_and_test_base_util.register_test_result( install_and_test_base_util.galaxy_tool_shed_url, - tool_test_results_dicts, - tool_test_results_dict, - repository_dict, - params, - can_update_tool_shed ) + response_dict = \ + install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url, + tool_test_results_dicts, + tool_test_results_dict, + repository_dict, + params, + can_update_tool_shed ) log.debug( 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \ ( changeset_revision, name, owner, str( response_dict ) ) ) - log.debug('=============================================================' ) + log.debug('\n=============================================================\n' ) # Remove the just-executed tests so twill will not find and re-test them along with the tools # contained in the next repository. remove_tests( app ) diff -r 7ebebaa348c316203ff7aee7ffa67fdc2db3ff88 -r 9df289e311209975ab34c288d8229096683af0e0 test/install_and_test_tool_shed_repositories/tool_dependency_definitions/functional_tests.py --- a/test/install_and_test_tool_shed_repositories/tool_dependency_definitions/functional_tests.py +++ b/test/install_and_test_tool_shed_repositories/tool_dependency_definitions/functional_tests.py @@ -114,7 +114,8 @@ install_and_test_base_util.get_tool_test_results_dicts( install_and_test_base_util.galaxy_tool_shed_url, encoded_repository_metadata_id ) if error_message: - log.debug( error_message ) + log.debug( 'Cannot install version %s of repository %s owned by %s due to the following error getting tool_test_results:\n%s' % \ + ( changeset_revision, name, owner, str( error_message ) ) ) else: tool_test_results_dict = install_and_test_base_util.get_tool_test_results_dict( tool_test_results_dicts ) is_excluded, reason = install_and_test_base_util.is_excluded( exclude_list_dicts, @@ -128,18 +129,16 @@ ( changeset_revision, name, owner ) ) tool_test_results_dict[ 'not_tested' ] = dict( reason=reason ) params = dict( do_not_test=False ) - log.debug('=============================================================' ) - log.debug( 'Inserting the following into tool_test_results for revision %s of repository %s owned by %s:\n%s' % \ - ( changeset_revision, name, owner, str( tool_test_results_dict ) ) ) - response_dict = install_and_test_base_util.register_test_result( install_and_test_base_util.galaxy_tool_shed_url, - tool_test_results_dicts, - tool_test_results_dict, - repository_dict, - params, - can_update_tool_shed ) + response_dict = \ + install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url, + tool_test_results_dicts, + tool_test_results_dict, + repository_dict, + params, + can_update_tool_shed ) log.debug( 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \ ( changeset_revision, name, owner, str( response_dict ) ) ) - log.debug('=============================================================' ) + log.debug('\n=============================================================\n' ) else: # See if the repository was installed in a previous test. repository = install_and_test_base_util.get_repository( name, owner, changeset_revision ) @@ -153,41 +152,47 @@ log.debug( 'Installation failed for revision %s of repository %s owned by %s.' % ( changeset_revision, name, owner ) ) install_and_test_statistics_dict[ 'repositories_with_installation_error' ].append( repository_identifier_dict ) tool_test_results_dict[ 'installation_errors' ][ 'current_repository' ] = error_message - params = dict( test_install_error=True ) - log.debug('=============================================================' ) - log.debug( 'Inserting the following into tool_test_results for revision %s of repository %s owned by %s:\n%s' % \ - ( changeset_revision, name, owner, str( tool_test_results_dict ) ) ) - response_dict = install_and_test_base_util.register_test_result( install_and_test_base_util.galaxy_tool_shed_url, - tool_test_results_dicts, - tool_test_results_dict, - repository_dict, - params, - can_update_tool_shed ) + params = dict( test_install_error=True, + do_not_test=False ) + response_dict = \ + install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url, + tool_test_results_dicts, + tool_test_results_dict, + repository_dict, + params, + can_update_tool_shed ) log.debug( 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \ ( changeset_revision, name, owner, str( response_dict ) ) ) - log.debug('=============================================================' ) + log.debug('\n=============================================================\n' ) else: # The repository was successfully installed. log.debug( 'Installation succeeded for revision %s of repository %s owned by %s.' % \ ( changeset_revision, name, owner ) ) + # Populate the installation containers (success and error) for the repository's immediate dependencies + # (the entire dependency tree is not handled here). params, install_and_test_statistics_dict, tool_test_results_dict = \ - install_and_test_base_util.register_installed_and_missing_dependencies( app, - repository, - repository_identifier_dict, - install_and_test_statistics_dict, - tool_test_results_dict ) - log.debug('=============================================================' ) - log.debug( 'Inserting the following into tool_test_results for revision %s of repository %s owned by %s:\n%s' % \ - ( changeset_revision, name, owner, str( tool_test_results_dict ) ) ) - response_dict = install_and_test_base_util.register_test_result( install_and_test_base_util.galaxy_tool_shed_url, - tool_test_results_dicts, - tool_test_results_dict, - repository_dict, - params, - can_update_tool_shed ) + install_and_test_base_util.populate_dependency_install_containers( app, + repository, + repository_identifier_dict, + install_and_test_statistics_dict, + tool_test_results_dict ) + response_dict = \ + install_and_test_base_util.save_test_results_for_changeset_revision( install_and_test_base_util.galaxy_tool_shed_url, + tool_test_results_dicts, + tool_test_results_dict, + repository_dict, + params, + can_update_tool_shed ) log.debug( 'Result of inserting tool_test_results for revision %s of repository %s owned by %s:\n%s' % \ ( changeset_revision, name, owner, str( response_dict ) ) ) - log.debug('=============================================================' ) + log.debug('\n=============================================================\n' ) + # Populate the installation containers (success or error) for the repository's immediate repository + # dependencies whose containers are not yet populated. + install_and_test_base_util.populate_install_containers_for_repository_dependencies( app, + repository, + encoded_repository_metadata_id, + install_and_test_statistics_dict, + can_update_tool_shed ) else: log.debug( 'Skipped attempt to install revision %s of repository %s owned by %s because ' % \ ( changeset_revision, name, owner ) ) 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.