galaxy-commits
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
November 2013
- 1 participants
- 208 discussions
commit/galaxy-central: greg: Fix for rendering Skip tool tests" form on the manage_repository page in the tool shed.
by commits-noreply@bitbucket.org 25 Nov '13
by commits-noreply@bitbucket.org 25 Nov '13
25 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/011df6fa309e/
Changeset: 011df6fa309e
User: greg
Date: 2013-11-25 22:53:40
Summary: Fix for rendering Skip tool tests" form on the manage_repository page in the tool shed.
Affected #: 1 file
diff -r 11eb2e028791aca01c206fa5e898e1feb28f4651 -r 011df6fa309e9b4a052d5342218e888deabd063f templates/webapps/tool_shed/repository/manage_repository.mako
--- a/templates/webapps/tool_shed/repository/manage_repository.mako
+++ b/templates/webapps/tool_shed/repository/manage_repository.mako
@@ -209,7 +209,7 @@
<div class="toolFormTitle">Automated tool tests</div>
%endif
<div class="toolFormBody">
- <form name="skip_tool_tests" id="skip_tool_tests" action="${h.url_for( controller='repository', action='manage_repository', id=trans.security.encode_id( repository.id ), changeset_revision=repository_metadata.changeset_revision )}" method="post" >
+ <form name="skip_tool_tests" id="skip_tool_tests" action="${h.url_for( controller='repository', action='manage_repository', id=trans.security.encode_id( repository.id ), changeset_revision=changeset_revision )}" method="post" ><div class="form-row">
%if repository.type == TOOL_DEPENDENCY_DEFINITION:
<label>Skip automated testing of this tool dependency recipe</label>
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.
1
0
commit/galaxy-central: greg: Minor fixes for the prep script for installing and testing tool shed repositories of type tool_dependency_definition.
by commits-noreply@bitbucket.org 25 Nov '13
by commits-noreply@bitbucket.org 25 Nov '13
25 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/11eb2e028791/
Changeset: 11eb2e028791
User: greg
Date: 2013-11-25 22:43:01
Summary: Minor fixes for the prep script for installing and testing tool shed repositories of type tool_dependency_definition.
Affected #: 1 file
diff -r ec2a03eea18ee82c71618d291394da81414cfb45 -r 11eb2e028791aca01c206fa5e898e1feb28f4651 lib/tool_shed/scripts/check_tool_dependency_definition_repositories.py
--- a/lib/tool_shed/scripts/check_tool_dependency_definition_repositories.py
+++ b/lib/tool_shed/scripts/check_tool_dependency_definition_repositories.py
@@ -28,7 +28,9 @@
from base.util import get_database_version
from base.util import get_repository_current_revision
from base.util import get_test_environment
-from galaxy.model.orm import and_, not_, select
+from galaxy.model.orm import and_
+from galaxy.model.orm import not_
+from galaxy.model.orm import select
from galaxy.web import url_for
from tool_shed.repository_types.util import TOOL_DEPENDENCY_DEFINITION
@@ -138,21 +140,6 @@
app.model.RepositoryMetadata.table.c.repository_id.in_( tool_dependency_defintion_repository_ids ),
not_( app.model.RepositoryMetadata.table.c.id.in_( skip_metadata_ids ) ) ) ):
records_checked += 1
- # Create the repository_status dictionary, using the dictionary from the previous test run if available.
- if repository_metadata.tool_test_results:
- repository_status = repository_metadata.tool_test_results
- else:
- repository_status = {}
- # Initialize the repository_status dictionary with the information about the current test environment.
- last_test_environment = repository_status.get( 'test_environment', None )
- if last_test_environment is None:
- test_environment = get_test_environment()
- else:
- test_environment = get_test_environment( last_test_environment )
- test_environment[ 'tool_shed_database_version' ] = get_database_version( app )
- test_environment[ 'tool_shed_mercurial_version' ] = __version__.version
- test_environment[ 'tool_shed_revision' ] = get_repository_current_revision( os.getcwd() )
- repository_status[ 'test_environment' ] = test_environment
# Check the next repository revision.
changeset_revision = str( repository_metadata.changeset_revision )
name = repository.name
@@ -174,7 +161,18 @@
print 'Revision %s of %s owned by %s has invalid metadata.' % ( changeset_revision, name, owner )
invalid_metadata += 1
if not info_only:
- repository_metadata.tool_test_results = repository_status
+ # Create the tool_test_results_dict dictionary, using the dictionary from the previous test run if available.
+ if repository_metadata.tool_test_results:
+ tool_test_results_dict = repository_metadata.tool_test_results
+ else:
+ tool_test_results_dict = {}
+ # Initialize the tool_test_results_dict dictionary with the information about the current test environment.
+ test_environment_dict = tool_test_results_dict.get( 'test_environment', {} )
+ test_environment_dict[ 'tool_shed_database_version' ] = get_database_version( app )
+ test_environment_dict[ 'tool_shed_mercurial_version' ] = __version__.version
+ test_environment_dict[ 'tool_shed_revision' ] = get_repository_current_revision( os.getcwd() )
+ tool_test_results_dict[ 'test_environment' ] = test_environment_dict
+ repository_metadata.tool_test_results = tool_test_results_dict
app.sa_session.add( repository_metadata )
app.sa_session.flush()
stop = time.time()
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.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f8fc2bc86635/
Changeset: f8fc2bc86635
User: Dave Bouvier
Date: 2013-11-25 22:23:51
Summary: Add API method to list datatype sniffers. Add functional tests for repositories defining datatype sniffers.
Affected #: 1 file
diff -r d0a3879c0708983fccb24b809bfe29d96a8dbb59 -r f8fc2bc8663593075a820157606cca11b905e0e9 test/tool_shed/test_data/proteomics_datatypes/proteomics_datatypes.tar
Binary file test/tool_shed/test_data/proteomics_datatypes/proteomics_datatypes.tar has changed
https://bitbucket.org/galaxy/galaxy-central/commits/ec2a03eea18e/
Changeset: ec2a03eea18e
User: Dave Bouvier
Date: 2013-11-25 22:29:41
Summary: Add API method to list datatype sniffers. Add functional tests for repositories defining datatype sniffers.
Affected #: 4 files
diff -r f8fc2bc8663593075a820157606cca11b905e0e9 -r ec2a03eea18ee82c71618d291394da81414cfb45 lib/galaxy/webapps/galaxy/api/datatypes.py
--- a/lib/galaxy/webapps/galaxy/api/datatypes.py
+++ b/lib/galaxy/webapps/galaxy/api/datatypes.py
@@ -4,20 +4,45 @@
from galaxy import web
from galaxy.web.base.controller import BaseAPIController
+from galaxy.util import asbool
import logging
log = logging.getLogger( __name__ )
+
class DatatypesController( BaseAPIController ):
+
@web.expose_api_anonymous
def index( self, trans, **kwd ):
"""
GET /api/datatypes
- Return an object containing datatypes.
+ Return an object containing upload datatypes.
"""
+ upload_only = asbool( kwd.get( 'upload_only', True ) )
try:
- return trans.app.datatypes_registry.upload_file_formats
+ if upload_only:
+ return trans.app.datatypes_registry.upload_file_formats
+ else:
+ return [ ext for ext in trans.app.datatypes_registry.datatypes_by_extension ]
except Exception, exception:
log.error( 'could not get datatypes: %s', str( exception ), exc_info=True )
trans.response.status = 500
return { 'error': str( exception ) }
+
+ @web.expose_api_anonymous
+ def sniffers( self, trans, **kwd ):
+ '''
+ GET /api/datatypes/sniffers
+ Return a list of sniffers.
+ '''
+ try:
+ rval = []
+ for sniffer_elem in trans.app.datatypes_registry.sniffer_elems:
+ datatype = sniffer_elem.get( 'type' )
+ if datatype is not None:
+ rval.append( datatype )
+ return rval
+ except Exception, exception:
+ log.error( 'could not get datatypes: %s', str( exception ), exc_info=True )
+ trans.response.status = 500
+ return { 'error': str( exception ) }
diff -r f8fc2bc8663593075a820157606cca11b905e0e9 -r ec2a03eea18ee82c71618d291394da81414cfb45 lib/galaxy/webapps/galaxy/buildapp.py
--- a/lib/galaxy/webapps/galaxy/buildapp.py
+++ b/lib/galaxy/webapps/galaxy/buildapp.py
@@ -163,7 +163,11 @@
webapp.mapper.resource( 'workflow', 'workflows', path_prefix='/api' )
webapp.mapper.resource_with_deleted( 'history', 'histories', path_prefix='/api' )
webapp.mapper.resource( 'configuration', 'configuration', path_prefix='/api' )
- webapp.mapper.resource( 'datatype', 'datatypes', path_prefix='/api' )
+ webapp.mapper.resource( 'datatype',
+ 'datatypes',
+ path_prefix='/api',
+ collection={ 'sniffers': 'GET' },
+ parent_resources=dict( member_name='datatype', collection_name='datatypes' ) )
#webapp.mapper.connect( 'run_workflow', '/api/workflow/{workflow_id}/library/{library_id}', controller='workflows', action='run', workflow_id=None, library_id=None, conditions=dict(method=["GET"]) )
webapp.mapper.resource( 'search', 'search', path_prefix='/api' )
diff -r f8fc2bc8663593075a820157606cca11b905e0e9 -r ec2a03eea18ee82c71618d291394da81414cfb45 test/tool_shed/base/twilltestcase.py
--- a/test/tool_shed/base/twilltestcase.py
+++ b/test/tool_shed/base/twilltestcase.py
@@ -618,13 +618,11 @@
return temp_path
def get_datatypes_count( self ):
- url = '/admin/view_datatypes_registry'
+ url = '/api/datatypes?upload_only=false'
self.visit_galaxy_url( url )
html = self.last_page()
- datatypes_count = re.search( 'registry contains (\d+) data types', html )
- if datatypes_count:
- return datatypes_count.group( 1 )
- return None
+ datatypes = from_json_string( html )
+ return len( datatypes )
def get_env_sh_path( self, tool_dependency_name, tool_dependency_version, repository ):
'''Return the absolute path to an installed repository's env.sh file.'''
@@ -735,6 +733,13 @@
repo = self.get_hg_repo( self.get_repo_path( repository ) )
return str( repo.changectx( repo.changelog.tip() ) )
+ def get_sniffers_count( self ):
+ url = '/api/datatypes/sniffers'
+ self.visit_galaxy_url( url )
+ html = self.last_page()
+ sniffers = from_json_string( html )
+ return len( sniffers )
+
def get_tools_from_repository_metadata( self, repository, include_invalid=False ):
'''Get a list of valid and (optionally) invalid tool dicts from the repository metadata.'''
valid_tools = []
diff -r f8fc2bc8663593075a820157606cca11b905e0e9 -r ec2a03eea18ee82c71618d291394da81414cfb45 test/tool_shed/functional/test_1450_installing_datatypes_sniffers.py
--- /dev/null
+++ b/test/tool_shed/functional/test_1450_installing_datatypes_sniffers.py
@@ -0,0 +1,191 @@
+from tool_shed.base.twilltestcase import ShedTwillTestCase, common, os
+import tool_shed.base.test_db_util as test_db_util
+
+repository_name = 'proteomics_datatypes_1450'
+repository_description = "Proteomics datatypes"
+repository_long_description = "Datatypes used in proteomics"
+
+category_name = 'Test 1450 Datatype Sniffers'
+category_description = 'Test 1450 - Installing Datatype Sniffers'
+
+
+'''
+1. Get a count of datatypes and sniffers.
+2. Install proteomics_datatypes_1450.
+3. Verify the count of datatypes and sniffers is the previous count + the datatypes contained within proteomics_datatypes_1450.
+4. Deactivate proteomics_datatypes_1450, verify the count of datatypes and sniffers is equal to the count determined in step 1.
+5. Reactivate proteomics_datatypes_1450, verify that the count of datatypes and sniffers has been increased by the contents of the repository.
+6. Uninstall proteomics_datatypes_1450, verify the count of datatypes and sniffers is equal to the count determined in step 1.
+7. Reinstall proteomics_datatypes_1450, verify that the count of datatypes and sniffers has been increased by the contents of the repository.
+'''
+
+base_datatypes_count = 0
+repository_datatypes_count = 0
+base_sniffers_count = 0
+
+
+class TestInstallDatatypesSniffers( ShedTwillTestCase ):
+ '''Test installing a repository that defines datatypes and datatype sniffers.'''
+
+ def test_0000_initiate_users( self ):
+ """Create necessary user accounts."""
+ global base_datatypes_count
+ self.logout()
+ self.login( email=common.test_user_1_email, username=common.test_user_1_name )
+ test_user_1 = test_db_util.get_user( common.test_user_1_email )
+ assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % test_user_1_email
+ test_user_1_private_role = test_db_util.get_private_role( test_user_1 )
+ self.logout()
+ self.login( email=common.admin_email, username=common.admin_username )
+ admin_user = test_db_util.get_user( common.admin_email )
+ assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email
+ admin_user_private_role = test_db_util.get_private_role( admin_user )
+ self.galaxy_logout()
+ self.galaxy_login( email=common.admin_email, username=common.admin_username )
+ galaxy_admin_user = test_db_util.get_galaxy_user( common.admin_email )
+ assert galaxy_admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email
+ galaxy_admin_user_private_role = test_db_util.get_galaxy_private_role( galaxy_admin_user )
+ base_datatypes_count = self.get_datatypes_count()
+ base_sniffers_count = self.get_sniffers_count()
+
+ def test_0005_ensure_repositories_and_categories_exist( self ):
+ '''Create the 1450 category and proteomics_datatypes_1450 repository.'''
+ global repository_datatypes_count
+ category = self.create_category( name=category_name, description=category_description )
+ self.logout()
+ self.login( email=common.test_user_1_email, username=common.test_user_1_name )
+ repository = self.get_or_create_repository( name=repository_name,
+ description=repository_description,
+ long_description=repository_long_description,
+ owner=common.test_user_1_name,
+ category_id=self.security.encode_id( category.id ),
+ strings_displayed=[] )
+ if self.repository_is_new( repository ):
+ self.upload_file( repository,
+ filename='proteomics_datatypes/proteomics_datatypes.tar',
+ filepath=None,
+ valid_tools_only=True,
+ uncompress_file=False,
+ remove_repo_files_not_in_tar=False,
+ commit_message='Uploaded datatype and sniffer definitions.',
+ strings_displayed=[],
+ strings_not_displayed=[] )
+ repository_datatypes_count = self.get_repository_datatypes_count( repository )
+
+ def test_0010_install_datatypes_repository( self ):
+ '''Install the proteomics_datatypes_1450 repository into the Galaxy instance.'''
+ '''
+ This includes steps 1 and 2 - Get a count of datatypes and sniffers.
+ Store a count of the current datatypes registry and sniffers in global variables, to compare with the updated count
+ after changing the installation status of the proteomics_datatypes_1450 repository.
+ '''
+ global repository_datatypes_count
+ global base_datatypes_count
+ global base_sniffers_count
+ base_sniffers_count = self.get_sniffers_count()
+ self.galaxy_logout()
+ self.galaxy_login( email=common.admin_email, username=common.admin_username )
+ strings_displayed = [ 'proteomics' ]
+ self.install_repository( 'proteomics_datatypes_1450',
+ common.test_user_1_name,
+ category_name,
+ strings_displayed=strings_displayed,
+ new_tool_panel_section='test_1450' )
+ installed_repository = test_db_util.get_installed_repository_by_name_owner( 'proteomics_datatypes_1450', common.test_user_1_name )
+ strings_displayed = [ 'user1',
+ self.url.replace( 'http://', '' ),
+ installed_repository.installed_changeset_revision ]
+ self.display_galaxy_browse_repositories_page( strings_displayed=strings_displayed )
+
+ def test_0015_verify_datatypes_count( self ):
+ '''Verify that datatypes were added in the previous step.'''
+ '''
+ This is step 3 - Verify the count of datatypes and sniffers is the previous count + the datatypes
+ contained within proteomics_datatypes_1450.
+ Compare the current datatypes registry and sniffers with the values that were retrieved in the previous step.
+ '''
+ current_datatypes = self.get_datatypes_count()
+ assert current_datatypes == base_datatypes_count + repository_datatypes_count, \
+ 'Found %d datatypes, expected %d.' % ( current_datatypes, base_datatypes_count + repository_datatypes_count )
+ current_sniffers = self.get_sniffers_count()
+ assert current_sniffers > base_sniffers_count, \
+ 'Sniffer count after installing proteomics_datatypes_1450 is %d, which is not greater than %d' % \
+ ( current_sniffers, base_sniffers_count )
+
+ def test_0020_deactivate_datatypes_repository( self ):
+ '''Deactivate the installed proteomics_datatypes_1450 repository.'''
+ '''
+ This is step 4 - Deactivate proteomics_datatypes_1450, verify the count of datatypes and sniffers is equal to
+ the count determined in step 1.
+ Deactivate proteomics_datatypes_1450 and check that the in-memory datatypes and sniffers match the base values
+ determined in the first step.
+ '''
+ repository = test_db_util.get_installed_repository_by_name_owner( repository_name, common.test_user_1_name )
+ global repository_datatypes_count
+ global base_datatypes_count
+ global base_sniffers_count
+ self.uninstall_repository( repository, remove_from_disk=False )
+ new_datatypes_count = self.get_datatypes_count()
+ assert new_datatypes_count == base_datatypes_count, 'Expected %d datatypes, got %d' % ( base_datatypes_count, new_datatypes_count )
+ current_sniffers = self.get_sniffers_count()
+ assert current_sniffers == base_sniffers_count, \
+ 'Sniffer count after deactivating proteomics_datatypes_1450 is %d, expected %d' % \
+ ( current_sniffers, base_sniffers_count )
+
+ def test_0025_reactivate_datatypes_repository( self ):
+ '''Reactivate the deactivated proteomics_datatypes_1450 repository.'''
+ '''
+ This is step 5 - Reactivate proteomics_datatypes, verify that the count of datatypes and sniffers has been
+ increased by the contents of the repository.
+ '''
+ repository = test_db_util.get_installed_repository_by_name_owner( repository_name, common.test_user_1_name )
+ global repository_datatypes_count
+ global base_datatypes_count
+ global base_sniffers_count
+ self.reactivate_repository( repository )
+ new_datatypes_count = self.get_datatypes_count()
+ assert new_datatypes_count == base_datatypes_count + repository_datatypes_count, \
+ 'Found %d datatypes, expected %d.' % ( new_datatypes_count, base_datatypes_count + repository_datatypes_count )
+ current_sniffers = self.get_sniffers_count()
+ assert current_sniffers > base_sniffers_count, \
+ 'Sniffer count after reactivating proteomics_datatypes_1450 is %d, which is not greater than %d' % \
+ ( current_sniffers, base_sniffers_count )
+
+ def test_0030_uninstall_datatypes_repository( self ):
+ '''Uninstall the installed proteomics_datatypes_1450 repository.'''
+ '''
+ This is step 6 - Uninstall proteomics_datatypes_1450, verify the count of datatypes and sniffers is equal
+ to the count determined in step 1.
+ Uninstall proteomics_datatypes_1450 and check that the in-memory datatypes and sniffers match the base values
+ determined in the first step.
+ '''
+ repository = test_db_util.get_installed_repository_by_name_owner( repository_name, common.test_user_1_name )
+ global repository_datatypes_count
+ global base_datatypes_count
+ self.uninstall_repository( repository, remove_from_disk=True )
+ new_datatypes_count = self.get_datatypes_count()
+ assert new_datatypes_count == base_datatypes_count, 'Expected %d datatypes, got %d' % ( base_datatypes_count, new_datatypes_count )
+ current_sniffers = self.get_sniffers_count()
+ assert current_sniffers == base_sniffers_count, \
+ 'Sniffer count after uninstalling proteomics_datatypes_1450 is %d, expected %d' % \
+ ( current_sniffers, base_sniffers_count )
+
+ def test_0035_reinstall_datatypes_repository( self ):
+ '''Reinstall the uninstalled proteomics_datatypes_1450 repository.'''
+ '''
+ This is step 7 - Reinstall proteomics_datatypes_1450, verify that the count of datatypes and sniffers has been
+ increased by the contents of the repository.
+ '''
+ repository = test_db_util.get_installed_repository_by_name_owner( repository_name, common.test_user_1_name )
+ global repository_datatypes_count
+ global base_datatypes_count
+ self.reinstall_repository( repository )
+ new_datatypes_count = self.get_datatypes_count()
+ assert new_datatypes_count == base_datatypes_count + repository_datatypes_count, \
+ 'Found %d datatypes, expected %d.' % ( new_datatypes_count, base_datatypes_count + repository_datatypes_count )
+ current_sniffers = self.get_sniffers_count()
+ assert current_sniffers > base_sniffers_count, \
+ 'Sniffer count after reinstalling proteomics_datatypes_1450 is %d, which is not greater than %d' % \
+ ( current_sniffers, base_sniffers_count )
+
+
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.
1
0
commit/galaxy-central: guerler: UI: Refresh history on history switch
by commits-noreply@bitbucket.org 25 Nov '13
by commits-noreply@bitbucket.org 25 Nov '13
25 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d0a3879c0708/
Changeset: d0a3879c0708
User: guerler
Date: 2013-11-25 21:37:46
Summary: UI: Refresh history on history switch
Affected #: 1 file
diff -r 61eacb9ce6d54a3cc217e7d826963a9a7370adf7 -r d0a3879c0708983fccb24b809bfe29d96a8dbb59 templates/grid_base.mako
--- a/templates/grid_base.mako
+++ b/templates/grid_base.mako
@@ -221,8 +221,7 @@
<%def name="grid_javascripts()">
${h.js("libs/jquery/jquery.autocomplete", "galaxy.autocom_tagging", "libs/jquery/jquery.rating" )}
- ${handle_refresh_frames()}
-
+
<script type="text/javascript">
var gridView = null;
function add_tag_to_grid_filter (tag_name, tag_value)
@@ -470,6 +469,8 @@
});
});
</script>
+
+ ${handle_refresh_frames()}
</%def>
## Render grid table footer contents.
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.
1
0
commit/galaxy-central: greg: More fixes for the tool shed's install and test framework - the test environment including time last tested should now display correctly again (among other fixes).
by commits-noreply@bitbucket.org 25 Nov '13
by commits-noreply@bitbucket.org 25 Nov '13
25 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/61eacb9ce6d5/
Changeset: 61eacb9ce6d5
User: greg
Date: 2013-11-25 21:09:50
Summary: More fixes for the tool shed's install and test framework - the test environment including time last tested should now display correctly again (among other fixes).
Affected #: 5 files
diff -r 1fbb0cb8dd5865185b186e609d747668510a25a8 -r 61eacb9ce6d54a3cc217e7d826963a9a7370adf7 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
@@ -170,6 +170,7 @@
if key in [ 'tools_functionally_correct', 'time_last_tested' ]:
# Automatically update repository_metadata.time_last_tested.
repository_metadata.time_last_tested = datetime.datetime.utcnow()
+ flush_needed = True
flush_needed = True
if flush_needed:
trans.sa_session.add( repository_metadata )
diff -r 1fbb0cb8dd5865185b186e609d747668510a25a8 -r 61eacb9ce6d54a3cc217e7d826963a9a7370adf7 lib/tool_shed/scripts/check_repositories_for_functional_tests.py
--- a/lib/tool_shed/scripts/check_repositories_for_functional_tests.py
+++ b/lib/tool_shed/scripts/check_repositories_for_functional_tests.py
@@ -7,7 +7,6 @@
import tempfile
import time
-from datetime import datetime
from optparse import OptionParser
from time import strftime
@@ -119,21 +118,11 @@
missing_test_components = []
repository = repository_metadata.repository
records_checked += 1
- # Create the repository_status dictionary, using the dictionary from the previous test run if available.
+ # Create the tool_test_results_dict dictionary, using the dictionary from the previous test run if available.
if repository_metadata.tool_test_results:
- repository_status = repository_metadata.tool_test_results
+ tool_test_results_dict = repository_metadata.tool_test_results
else:
- repository_status = {}
- # Initialize the repository_status dictionary with the information about the current test environment.
- last_test_environment = repository_status.get( 'test_environment', None )
- if last_test_environment is None:
- test_environment = get_test_environment()
- else:
- test_environment = get_test_environment( last_test_environment )
- test_environment[ 'tool_shed_database_version' ] = get_database_version( app )
- test_environment[ 'tool_shed_mercurial_version' ] = __version__.version
- test_environment[ 'tool_shed_revision' ] = get_repository_current_revision( os.getcwd() )
- repository_status[ 'test_environment' ] = test_environment
+ tool_test_results_dict = {}
# Check the next repository revision.
changeset_revision = str( repository_metadata.changeset_revision )
name = repository.name
@@ -262,6 +251,11 @@
if 'missing_components' in invalid_test:
print '# %s' % invalid_test[ 'missing_components' ]
if not info_only:
+ test_environment_dict = tool_test_results_dict.get( 'test_environment', {} )
+ test_environment_dict[ 'tool_shed_database_version' ] = get_database_version( app )
+ test_environment_dict[ 'tool_shed_mercurial_version' ] = __version__.version
+ test_environment_dict[ 'tool_shed_revision' ] = get_repository_current_revision( os.getcwd() )
+ tool_test_results_dict[ 'test_environment' ] = test_environment_dict
# The repository_metadata.time_last_tested column is not changed by this script since no testing is performed here.
if missing_test_components:
# If functional test definitions or test data are missing, set do_not_test = True if no tool with valid tests has been
@@ -278,8 +272,8 @@
repository_metadata.do_not_test = True
repository_metadata.tools_functionally_correct = False
repository_metadata.missing_test_components = True
- repository_status[ 'missing_test_components' ] = missing_test_components
- repository_metadata.tool_test_results = repository_status
+ tool_test_results_dict[ 'missing_test_components' ] = missing_test_components
+ repository_metadata.tool_test_results = tool_test_results_dict
app.sa_session.add( repository_metadata )
app.sa_session.flush()
stop = time.time()
diff -r 1fbb0cb8dd5865185b186e609d747668510a25a8 -r 61eacb9ce6d54a3cc217e7d826963a9a7370adf7 lib/tool_shed/util/container_util.py
--- a/lib/tool_shed/util/container_util.py
+++ b/lib/tool_shed/util/container_util.py
@@ -235,7 +235,7 @@
class TestEnvironment( object ):
"""Tool test environment object"""
- def __init__( self, id=None, architecture=None, galaxy_database_version=None, galaxy_revision=None, python_version=None, system=None, time_last_tested=None,
+ def __init__( self, id=None, architecture=None, galaxy_database_version=None, galaxy_revision=None, python_version=None, system=None, time_tested=None,
tool_shed_database_version=None, tool_shed_mercurial_version=None, tool_shed_revision=None ):
self.id = id
self.architecture = architecture
@@ -243,7 +243,7 @@
self.galaxy_revision = galaxy_revision
self.python_version = python_version
self.system = system
- self.time_last_tested = time_last_tested
+ self.time_tested = time_tested
self.tool_shed_database_version = tool_shed_database_version
self.tool_shed_mercurial_version = tool_shed_mercurial_version
self.tool_shed_revision = tool_shed_revision
@@ -743,11 +743,6 @@
)
if repository_metadata:
metadata = repository_metadata.metadata
- tool_test_results = repository_metadata.tool_test_results
- try:
- time_last_tested = time_ago( repository_metadata.time_last_tested )
- except:
- time_last_tested = None
lock = threading.Lock()
lock.acquire( True )
try:
@@ -836,12 +831,17 @@
label='Valid tools' )
containers_dict[ 'valid_tools' ] = valid_tools_root_folder
# Tool test results container.
- if 'tool_test_results' not in exclude and tool_test_results and len( tool_test_results ) > 1:
- # Only create and populate this folder if there are actual tool test results to display, since the display of the 'Test environment'
- # folder by itself can be misleading. We check for more than a single entry in the tool_test_results dictionary because it may have
- # only the "test_environment" entry, but we want at least 1 of "passed_tests", "failed_tests", "installation_errors", "missing_test_components"
- # "skipped_tests", "not_tested" or any other entry that may be added in the future.
- folder_id, tool_test_results_root_folder = build_tool_test_results_folder( trans, folder_id, tool_test_results, time_last_tested=time_last_tested )
+ tool_test_results = repository_metadata.tool_test_results
+ # Only create and populate this folder if there are actual tool test results to display.
+ if can_display_tool_test_results( tool_test_results, exclude=exclude ):
+ time_tested = repository_metadata.time_last_tested
+ if time_tested is not None:
+ time_tested = time_ago( time_tested )
+ folder_id, tool_test_results_root_folder = build_tool_test_results_folder( trans,
+ folder_id,
+ tool_test_results,
+ time_tested,
+ label='Tool test results' )
containers_dict[ 'tool_test_results' ] = tool_test_results_root_folder
# Workflows container.
if metadata:
@@ -1052,30 +1052,39 @@
tool_dependencies_root_folder = None
return folder_id, tool_dependencies_root_folder
-def build_tool_test_results_folder( trans, folder_id, tool_test_results_dict, label='Tool test results', time_last_tested=None ):
+def build_tool_test_results_folder( trans, folder_id, tool_test_results_dict, time_tested, label='Tool test results' ):
"""Return a folder hierarchy containing tool dependencies."""
# This container is displayed only in the tool shed.
if tool_test_results_dict:
folder_id += 1
tool_test_results_root_folder = Folder( id=folder_id, key='root', label='root', parent=None )
test_environment_dict = tool_test_results_dict.get( 'test_environment', None )
- if test_environment_dict:
+ if test_environment_dict is not None:
folder_id += 1
test_results_folder = Folder( id=folder_id, key='test_results', label=label, parent=tool_test_results_root_folder )
tool_test_results_root_folder.folders.append( test_results_folder )
folder_id += 1
folder = Folder( id=folder_id, key='test_environment', label='Automated test environment', parent=test_results_folder )
test_results_folder.folders.append( folder )
+ architecture = test_environment_dict.get( 'architecture', '' )
+ galaxy_database_version = test_environment_dict.get( 'galaxy_database_version', '' )
+ galaxy_revision = test_environment_dict.get( 'galaxy_revision', '' )
+ python_version = test_environment_dict.get( 'python_version', '' )
+ system = test_environment_dict.get( 'system', '' )
+ time_tested = time_tested
+ tool_shed_database_version = test_environment_dict.get( 'tool_shed_database_version', '' )
+ tool_shed_mercurial_version = test_environment_dict.get( 'tool_shed_mercurial_version', '' )
+ tool_shed_revision = test_environment_dict.get( 'tool_shed_revision', '' )
test_environment = TestEnvironment( id=1,
- architecture=test_environment_dict.get( 'architecture', '' ),
- galaxy_database_version=test_environment_dict.get( 'galaxy_database_version', '' ),
- galaxy_revision=test_environment_dict.get( 'galaxy_revision', '' ),
- python_version=test_environment_dict.get( 'python_version', '' ),
- system=test_environment_dict.get( 'system', '' ),
- time_last_tested=time_last_tested,
- tool_shed_database_version=test_environment_dict.get( 'tool_shed_database_version', '' ),
- tool_shed_mercurial_version=test_environment_dict.get( 'tool_shed_mercurial_version', '' ),
- tool_shed_revision=test_environment_dict.get( 'tool_shed_revision', '' ) )
+ architecture=architecture,
+ galaxy_database_version=galaxy_database_version,
+ galaxy_revision=galaxy_revision,
+ python_version=python_version,
+ system=system,
+ time_tested=time_tested,
+ tool_shed_database_version=tool_shed_database_version,
+ tool_shed_mercurial_version=tool_shed_mercurial_version,
+ tool_shed_revision=tool_shed_revision )
folder.test_environments.append( test_environment )
not_tested_dict = tool_test_results_dict.get( 'not_tested', {} )
if not_tested_dict:
@@ -1238,6 +1247,26 @@
workflows_root_folder = None
return folder_id, workflows_root_folder
+def can_display_tool_test_results( tool_test_results_dict, exclude=None ):
+ # Only create and populate the tool_test_results container if there are actual tool test results to display.
+ if exclude is None:
+ exclude = []
+ if 'tool_test_results' in exclude:
+ return False
+ if tool_test_results_dict:
+ # We check for more than a single entry in the tool_test_results dictionary because it may have
+ # only the "test_environment" entry, but we want at least 1 of "passed_tests", "failed_tests",
+ # "installation_errors", "missing_test_components" "skipped_tests", "not_tested" or any other
+ # entry that may be added in the future.
+ display_entries = [ 'failed_tests', 'installation_errors', 'missing_test_components', 'not_tested', 'passed_tests', 'skipped_tests' ]
+ for k, v in tool_test_results_dict.items():
+ if k in display_entries:
+ # We've discovered an entry that can be displayed, so see if it has a value since displaying
+ # empty lists is not desired.
+ if v:
+ return True
+ return False
+
def cast_empty_repository_dependency_folders( folder, repository_dependency_id ):
"""
Change any empty folders contained within the repository dependencies container into a repository dependency since it has no repository dependencies
diff -r 1fbb0cb8dd5865185b186e609d747668510a25a8 -r 61eacb9ce6d54a3cc217e7d826963a9a7370adf7 templates/webapps/tool_shed/repository/common.mako
--- a/templates/webapps/tool_shed/repository/common.mako
+++ b/templates/webapps/tool_shed/repository/common.mako
@@ -909,7 +909,7 @@
id="libraryItem-rte-${encoded_id}"><td style="padding-left: ${pad+20}px;"><table class="grid" id="test_environment">
- <tr><td><b>Time tested:</b> ${test_environment.time_last_tested | h}</td></tr>
+ <tr><td><b>Time tested:</b> ${test_environment.time_tested | h}</td></tr><tr><td><b>System:</b> ${test_environment.system | h}</td></tr><tr><td><b>Architecture:</b> ${test_environment.architecture | h}</td></tr><tr><td><b>Python version:</b> ${test_environment.python_version | h}</td></tr>
diff -r 1fbb0cb8dd5865185b186e609d747668510a25a8 -r 61eacb9ce6d54a3cc217e7d826963a9a7370adf7 test/install_and_test_tool_shed_repositories/functional_tests.py
--- a/test/install_and_test_tool_shed_repositories/functional_tests.py
+++ b/test/install_and_test_tool_shed_repositories/functional_tests.py
@@ -21,7 +21,6 @@
import threading
import unittest
import urllib
-import urllib2
from time import strftime
# Assume we are run from the galaxy root directory, add lib to the python path
@@ -42,8 +41,8 @@
sys.path = new_path
from functional_tests import generate_config_file
+
from galaxy import eggs
-from galaxy.util import unicodify
eggs.require( "nose" )
eggs.require( "NoseHTML" )
@@ -53,10 +52,14 @@
eggs.require( "PasteDeploy" )
eggs.require( "Cheetah" )
eggs.require( "simplejson" )
+eggs.require( 'mercurial' )
import simplejson
import twill
+from datetime import datetime
+from mercurial import __version__
+
# This should not be required, but it is under certain conditions, thanks to this bug: http://code.google.com/p/python-nose/issues/detail?id=284
eggs.require( "pysqlite" )
@@ -76,13 +79,20 @@
import tool_shed.util.shed_util_common as suc
from tool_shed.util import tool_dependency_util
+from galaxy.web.framework.helpers import time_ago
+
import nose.core
import nose.config
import nose.loader
import nose.plugins.manager
from nose.plugins import Plugin
-from base.util import parse_tool_panel_config, get_database_version, get_test_environment, get_repository_current_revision
+from base.util import get_database_version
+from base.util import get_repository_current_revision
+from base.util import get_test_environment
+from base.util import parse_tool_panel_config
+
+from galaxy.util import unicodify
from common import update
@@ -472,29 +482,27 @@
return repository_dicts, error_message
def get_tool_info_from_test_id( test_id ):
- '''
- Test IDs come in the form test_tool_number (functional.test_toolbox.TestForTool_toolshed_url/repos/owner/repository_name/tool_id/tool_version)
+ """
+ Test IDs come in the form test_tool_number
+ (functional.test_toolbox.TestForTool_toolshed_url/repos/owner/repository_name/tool_id/tool_version)
We want the tool ID and tool version.
- '''
+ """
parts = test_id.replace( ')', '' ).split( '/' )
tool_version = parts[ -1 ]
tool_id = parts[ -2 ]
return tool_id, tool_version
-def get_tool_test_results_from_api( tool_shed_url, metadata_revision_id ):
+def get_tool_test_results_dict( tool_shed_url, encoded_repository_metadata_id ):
error_message = ''
- api_path = [ 'api', 'repository_revisions', metadata_revision_id ]
+ api_path = [ 'api', 'repository_revisions', encoded_repository_metadata_id ]
api_url = get_api_url( base=tool_shed_url, parts=api_path )
repository_metadata, error_message = json_from_url( api_url )
if error_message:
return None, error_message
tool_test_results = repository_metadata.get( 'tool_test_results', {} )
- # If, for some reason, the script that checks for functional tests has not run, tool_test_results will be None.
- if tool_test_results is None:
- return {}, error_message
return tool_test_results, error_message
-def handle_missing_dependencies( app, repository, missing_tool_dependencies, repository_dict, repository_status_dict, results_dict ):
+def handle_missing_dependencies( app, repository, missing_tool_dependencies, repository_dict, tool_test_results_dict, results_dict ):
"""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
@@ -508,7 +516,7 @@
name=dependency.name,
version=dependency.version,
error_message=dependency.error_message )
- repository_status_dict[ 'installation_errors' ][ 'tool_dependencies' ].append( test_result )
+ tool_test_results_dict[ 'installation_errors' ][ 'tool_dependencies' ].append( test_result )
for dependency in repository.missing_repository_dependencies:
log.debug( 'Missing repository dependency %s changeset revision %s owned by %s: %s' % \
( str( dependency.name ), str( dependency.changeset_revision ), str( dependency.owner ), unicodify( dependency.error_message ) ) )
@@ -517,12 +525,12 @@
owner=dependency.owner,
changeset_revision=dependency.changeset_revision,
error_message=dependency.error_message )
- repository_status_dict[ 'installation_errors' ][ 'repository_dependencies' ].append( test_result )
+ tool_test_results_dict[ 'installation_errors' ][ 'repository_dependencies' ].append( test_result )
# Record the status of this repository in the tool shed.
params = dict( tools_functionally_correct=False,
do_not_test=False,
test_install_error=True )
- register_test_result( galaxy_tool_shed_url, repository_status_dict, repository_dict, params )
+ register_test_result( galaxy_tool_shed_url, tool_test_results_dict, repository_dict, params )
# Since this repository is missing components, we do not want to test it, so deactivate it or uninstall it.
# The deactivate flag is set to True if the environment variable GALAXY_INSTALL_TEST_KEEP_TOOL_DEPENDENCIES
# is set to 'true'.
@@ -629,27 +637,13 @@
# "tool_shed_url": "http://toolshed.local:10001",
# "url": "/api/repository_revisions/529fd61ab1c6cc36",
# "user_id": "529fd61ab1c6cc36" }
- metadata_revision_id = repository_dict.get( 'id', None )
+ encoded_repository_metadata_id = repository_dict.get( 'id', None )
# Add the URL for the tool shed we're installing from, so the automated installation methods go to the right place.
repository_dict[ 'tool_shed_url' ] = galaxy_tool_shed_url
# Get the name and owner out of the repository info dict.
name = str( repository_dict[ 'name' ] )
owner = str( repository_dict[ 'owner' ] )
changeset_revision = str( repository_dict[ 'changeset_revision' ] )
- # Populate the repository_status_dict.
- repository_status_dict, error_message = get_tool_test_results_from_api( galaxy_tool_shed_url, metadata_revision_id )
- if error_message:
- return None, error_message
- if 'test_environment' not in repository_status_dict:
- repository_status_dict[ 'test_environment' ] = {}
- test_environment = get_test_environment( repository_status_dict[ 'test_environment' ] )
- test_environment[ 'galaxy_database_version' ] = get_database_version( app )
- test_environment[ 'galaxy_revision'] = get_repository_current_revision( os.getcwd() )
- repository_status_dict[ 'test_environment' ] = test_environment
- repository_status_dict[ 'passed_tests' ] = []
- repository_status_dict[ 'failed_tests' ] = []
- repository_status_dict[ 'skip_reason' ] = None
- repository_status_dict[ 'installation_errors' ] = dict( current_repository=[], repository_dependencies=[], tool_dependencies=[] )
# See if this repository should be skipped for any reason.
skip_this_repository = False
skip_reason = None
@@ -661,82 +655,104 @@
skip_reason = reason
break
if skip_this_repository:
- repository_status_dict[ 'not_tested' ] = dict( reason=skip_reason )
+ tool_test_results_dict[ 'not_tested' ] = dict( reason=skip_reason )
params = dict( tools_functionally_correct=False,
do_not_test=False )
- register_test_result( galaxy_tool_shed_url, repository_status_dict, repository_dict, params )
+ register_test_result( galaxy_tool_shed_url, tool_test_results_dict, repository_dict, params )
log.debug( "Not testing revision %s of repository %s owned by %s." % ( changeset_revision, name, owner ) )
else:
- repository, error_message = install_repository( app, repository_dict )
+ # Populate the tool_test_results_dict.
+ tool_test_results_dict, error_message = get_tool_test_results_dict( galaxy_tool_shed_url, encoded_repository_metadata_id )
if error_message:
- repository_status_dict[ 'installation_errors' ][ 'current_repository' ] = error_message
-
- # Even if the repository failed to install, execute the uninstall method, in case a dependency did succeed.
- log.debug( 'Attempting to uninstall repository %s owned by %s.' % ( name, owner ) )
- try:
- repository = test_db_util.get_installed_repository_by_name_owner_changeset_revision( name, owner, changeset_revision )
- except Exception, e:
- error_message = 'Unable to find installed repository %s owned by %s: %s.' % ( name, owner, str( e ) )
- log.exception( error_message )
- test_result = dict( tool_shed=galaxy_tool_shed_url,
- name=name,
- owner=owner,
- changeset_revision=changeset_revision,
- error_message=error_message )
- repository_status_dict[ 'installation_errors' ][ 'repository_dependencies' ].append( test_result )
- params = dict( tools_functionally_correct=False,
- test_install_error=True,
- do_not_test=False )
- register_test_result( galaxy_tool_shed_url, repository_status_dict, repository_dict, params )
- try:
- if deactivate:
- # We are deactivating this repository and all of its repository dependencies.
- deactivate_repository( app, repository_dict )
+ log.debug( error_message )
+ else:
+ # The preparation script ~/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. We need to be careful to not lose this information. For all other repositories,
+ # no changes will have been made to this dictionary by the preparation script, and tool_test_results_dict will be None.
+ # Initialize the tool_test_results_dict dictionary with the information about the current test environment.
+ test_environment_dict = tool_test_results_dict.get( 'test_environent', None )
+ test_environment_dict = get_test_environment( test_environment_dict )
+ test_environment_dict[ 'galaxy_database_version' ] = get_database_version( app )
+ test_environment_dict[ 'galaxy_revision' ] = get_repository_current_revision( os.getcwd() )
+ tool_test_results_dict[ 'test_environment' ] = test_environment_dict
+ tool_test_results_dict[ 'passed_tests' ] = []
+ tool_test_results_dict[ 'failed_tests' ] = []
+ tool_test_results_dict[ 'installation_errors' ] = dict( current_repository=[], repository_dependencies=[], tool_dependencies=[] )
+ repository, error_message = install_repository( app, repository_dict )
+ if error_message:
+ tool_test_results_dict[ 'installation_errors' ][ 'current_repository' ] = error_message
+ # Even if the repository failed to install, execute the uninstall method, in case a dependency did succeed.
+ log.debug( 'Attempting to uninstall repository %s owned by %s.' % ( name, owner ) )
+ try:
+ repository = test_db_util.get_installed_repository_by_name_owner_changeset_revision( name, owner, changeset_revision )
+ except Exception, e:
+ error_message = 'Unable to find installed repository %s owned by %s: %s.' % ( name, owner, str( e ) )
+ log.exception( error_message )
+ test_result = dict( tool_shed=galaxy_tool_shed_url,
+ name=name,
+ owner=owner,
+ changeset_revision=changeset_revision,
+ error_message=error_message )
+ tool_test_results_dict[ 'installation_errors' ][ 'repository_dependencies' ].append( test_result )
+ params = dict( tools_functionally_correct=False,
+ test_install_error=True,
+ do_not_test=False )
+
+ register_test_result( galaxy_tool_shed_url, tool_test_results_dict, repository_dict, params )
+ try:
+ if deactivate:
+ # We are deactivating this repository and all of its repository dependencies.
+ deactivate_repository( app, repository_dict )
+ else:
+ # We are uninstalling this repository and all of its repository dependencies.
+ uninstall_repository( app, repository_dict )
+ except:
+ log.exception( 'Encountered error attempting to deactivate or uninstall %s.', str( repository_dict[ 'name' ] ) )
+ results_dict[ 'repositories_failed_install' ].append( dict( name=name, owner=owner, changeset_revision=changeset_revision ) )
+ log.debug( 'Repository %s failed to install correctly.' % str( name ) )
+ else:
+ # Configure and run functional tests for this repository. This is equivalent to sh run_functional_tests.sh -installed
+ remove_install_tests()
+ log.debug( 'Installation of %s succeeded, running all defined functional tests.' % str( repository.name ) )
+ # Generate the shed_tools_dict that specifies the location of test data contained within this repository. If the repository
+ # does not have a test-data directory, this will return has_test_data = False, and we will set the do_not_test flag to True,
+ # and the tools_functionally_correct flag to False, as well as updating tool_test_results.
+ file( galaxy_shed_tools_dict, 'w' ).write( to_json_string( {} ) )
+ has_test_data, shed_tools_dict = parse_tool_panel_config( galaxy_shed_tool_conf_file,
+ from_json_string( file( galaxy_shed_tools_dict, 'r' ).read() ) )
+ # 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' ] = []
+ missing_tool_dependencies = get_missing_tool_dependencies( repository )
+ if missing_tool_dependencies or repository.missing_repository_dependencies:
+ results_dict = handle_missing_dependencies( app,
+ repository,
+ missing_tool_dependencies,
+ repository_dict,
+ tool_test_results_dict,
+ results_dict )
else:
- # We are uninstalling this repository and all of its repository dependencies.
- uninstall_repository( app, repository_dict )
- except:
- log.exception( 'Encountered error attempting to deactivate or uninstall %s.', str( repository_dict[ 'name' ] ) )
- results_dict[ 'repositories_failed_install' ].append( dict( name=name, owner=owner, changeset_revision=changeset_revision ) )
- log.debug( 'Repository %s failed to install correctly.' % str( name ) )
- else:
- # Configure and run functional tests for this repository. This is equivalent to sh run_functional_tests.sh -installed
- remove_install_tests()
- log.debug( 'Installation of %s succeeded, running all defined functional tests.' % str( repository.name ) )
- # Generate the shed_tools_dict that specifies the location of test data contained within this repository. If the repository
- # does not have a test-data directory, this will return has_test_data = False, and we will set the do_not_test flag to True,
- # and the tools_functionally_correct flag to False, as well as updating tool_test_results.
- file( galaxy_shed_tools_dict, 'w' ).write( to_json_string( {} ) )
- has_test_data, shed_tools_dict = parse_tool_panel_config( galaxy_shed_tool_conf_file,
- from_json_string( file( galaxy_shed_tools_dict, 'r' ).read() ) )
- if 'missing_test_components' not in repository_status_dict:
- repository_status_dict[ 'missing_test_components' ] = []
- missing_tool_dependencies = get_missing_tool_dependencies( repository )
- if missing_tool_dependencies or repository.missing_repository_dependencies:
- results_dict = handle_missing_dependencies( app,
- repository,
- missing_tool_dependencies,
- repository_dict,
- repository_status_dict,
- results_dict )
- else:
- # If the repository has a test-data directory we write the generated shed_tools_dict to a file, so the functional
- # test framework can find it.
- file( galaxy_shed_tools_dict, 'w' ).write( to_json_string( shed_tools_dict ) )
- log.debug( 'Saved generated shed_tools_dict to %s\nContents: %s' % ( str( galaxy_shed_tools_dict ), str( shed_tools_dict ) ) )
- try:
- results_dict = test_repository_tools( app, repository, repository_dict, repository_status_dict, results_dict )
- except Exception, e:
- exception_message = 'Error executing tests for repository %s: %s' % ( name, str( e ) )
- log.exception( exception_message )
- repository_status_dict[ 'failed_tests' ].append( exception_message )
- # Record the status of this repository in the tool shed.
- params = dict( tools_functionally_correct=False,
- do_not_test=False,
- test_install_error=False )
- register_test_result( galaxy_tool_shed_url, repository_status_dict, repository_dict, params )
- results_dict[ 'repositories_failed' ].append( dict( name=name, owner=owner, changeset_revision=changeset_revision ) )
- total_repositories_tested += 1
+ # If the repository has a test-data directory we write the generated shed_tools_dict to a file, so the functional
+ # test framework can find it.
+ file( galaxy_shed_tools_dict, 'w' ).write( to_json_string( shed_tools_dict ) )
+ log.debug( 'Saved generated shed_tools_dict to %s\nContents: %s' % ( str( galaxy_shed_tools_dict ), str( shed_tools_dict ) ) )
+ try:
+ results_dict = test_repository_tools( app, repository, repository_dict, tool_test_results_dict, results_dict )
+ except Exception, e:
+ exception_message = 'Error executing tests for repository %s: %s' % ( name, str( e ) )
+ log.exception( exception_message )
+ tool_test_results_dict[ 'failed_tests' ].append( exception_message )
+ # Record the status of this repository in the tool shed.
+ params = dict( tools_functionally_correct=False,
+ do_not_test=False,
+ test_install_error=False )
+ register_test_result( galaxy_tool_shed_url, tool_test_results_dict, repository_dict, params )
+ results_dict[ 'repositories_failed' ].append( dict( name=name, owner=owner, changeset_revision=changeset_revision ) )
+ total_repositories_tested += 1
results_dict[ 'total_repositories_tested' ] = total_repositories_tested
return results_dict, error_message
@@ -794,12 +810,20 @@
return exclude_list
def register_test_result( url, test_results_dict, repository_dict, params ):
- """Update the repository metadata tool_test_results and appropriate flags using the API."""
+ """
+ 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.
+ """
if '-info_only' in sys.argv or 'GALAXY_INSTALL_TEST_INFO_ONLY' in os.environ:
return {}
else:
metadata_revision_id = repository_dict.get( 'id', None )
+ log.debug("RRR In register_test_result, metadata_revision_id: %s" % str( metadata_revision_id ))
if metadata_revision_id is not None:
+ # Set the time_last_tested entry so that the repository_metadata.time_last_tested will be set in the tool shed.
+ time_tested = datetime.utcnow()
+ test_results_dict[ 'time_last_tested' ] = time_ago( time_tested )
params[ 'tool_test_results' ] = test_results_dict
url = '%s' % ( suc.url_join( galaxy_tool_shed_url,'api', 'repository_revisions', str( metadata_revision_id ) ) )
try:
@@ -876,7 +900,7 @@
for repository in repositories_by_owner[ owner ]:
print "# %s owned by %s, changeset revision %s" % ( repository[ 'name' ], repository[ 'owner' ], repository[ 'changeset_revision' ] )
-def test_repository_tools( app, repository, repository_dict, repository_status_dict, results_dict ):
+def test_repository_tools( app, repository, repository_dict, tool_test_results_dict, results_dict ):
"""Test tools contained in the received repository."""
name = str( repository.name )
owner = str( repository.owner )
@@ -898,12 +922,12 @@
test_identifier = '%s/%s' % ( owner, name )
passed_tests = plugin.getTestStatus( test_identifier )
break
- repository_status_dict[ 'passed_tests' ] = []
+ tool_test_results_dict[ 'passed_tests' ] = []
for test_id in passed_tests:
# Normalize the tool ID and version display.
tool_id, tool_version = get_tool_info_from_test_id( test_id )
test_result = dict( test_id=test_id, tool_id=tool_id, tool_version=tool_version )
- repository_status_dict[ 'passed_tests' ].append( test_result )
+ tool_test_results_dict[ 'passed_tests' ].append( test_result )
if success:
# This repository's tools passed all functional tests. Update the repository_metadata table in the tool shed's database
# to reflect that. Call the register_test_result method, which executes a PUT request to the repository_revisions API
@@ -913,20 +937,16 @@
params = dict( tools_functionally_correct=True,
do_not_test=False,
test_install_error=False )
- register_test_result( galaxy_tool_shed_url, repository_status_dict, repository_dict, params )
+ register_test_result( galaxy_tool_shed_url, tool_test_results_dict, repository_dict, params )
log.debug( 'Revision %s of repository %s installed and passed functional tests.' % ( str( changeset_revision ), str( name ) ) )
else:
- repository_status_dict[ 'failed_tests' ].append( extract_log_data( result, from_tool_test=True ) )
- # Call the register_test_result method, which executes a PUT request to the repository_revisions API controller with the outcome
- # of the tests, and updates tool_test_results with the relevant log data.
- # This also sets the do_not_test and tools_functionally correct flags to the appropriate values, and updates the time_last_tested
- # field to today's date.
+ tool_test_results_dict[ 'failed_tests' ].append( extract_log_data( result, from_tool_test=True ) )
results_dict[ 'repositories_failed' ].append( dict( name=name, owner=owner, changeset_revision=changeset_revision ) )
set_do_not_test = not is_latest_downloadable_revision( galaxy_tool_shed_url, repository_dict )
params = dict( tools_functionally_correct=False,
test_install_error=False,
do_not_test=str( set_do_not_test ) )
- register_test_result( galaxy_tool_shed_url, repository_status_dict, repository_dict, params )
+ register_test_result( galaxy_tool_shed_url, tool_test_results_dict, repository_dict, params )
log.debug( 'Revision %s of repository %s installed successfully but did not pass functional tests.' % \
( str( changeset_revision ), str( name ) ) )
# Run the uninstall method. This removes tool functional test methods from the test_toolbox module and uninstalls the
@@ -1256,7 +1276,7 @@
return 1
if __name__ == "__main__":
- # The repository_status_dict should always have the following structure:
+ # The tool_test_results_dict should always have the following structure:
# {
# "test_environment":
# {
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.
1
0
commit/galaxy-central: carlfeberhard: UI: revert changes from 3f630f9 that broke links in PopupMenus
by commits-noreply@bitbucket.org 25 Nov '13
by commits-noreply@bitbucket.org 25 Nov '13
25 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/1fbb0cb8dd58/
Changeset: 1fbb0cb8dd58
User: carlfeberhard
Date: 2013-11-25 20:59:51
Summary: UI: revert changes from 3f630f9 that broke links in PopupMenus
Affected #: 2 files
diff -r 01b5a1a68ae6901936b6948769aa66b446e52e53 -r 1fbb0cb8dd5865185b186e609d747668510a25a8 static/scripts/mvc/ui.js
--- a/static/scripts/mvc/ui.js
+++ b/static/scripts/mvc/ui.js
@@ -232,7 +232,7 @@
// if the option has 'func', call that function when the anchor is clicked
if( option.func ){
- $( this ).children( 'a.popupmenu-option' ).mousedown( function( event ){
+ $( this ).children( 'a.popupmenu-option' ).click( function( event ){
option.func.call( menu, event, option );
// bubble up so that an option click will call the close behavior
//return false;
@@ -292,7 +292,7 @@
// function to close popup and unbind itself
var menu = this;
var closePopupWhenClicked = function( $elClicked ){
- $elClicked.one( "mousedown.close_popup", function(){
+ $elClicked.one( "click.close_popup", function(){
menu.remove();
});
};
diff -r 01b5a1a68ae6901936b6948769aa66b446e52e53 -r 1fbb0cb8dd5865185b186e609d747668510a25a8 static/scripts/packed/mvc/ui.js
--- a/static/scripts/packed/mvc/ui.js
+++ b/static/scripts/packed/mvc/ui.js
@@ -1,1 +1,1 @@
-var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,is_menu_button:true,id:null,href:null,target:null,enabled:true,visible:true,tooltip_config:{}}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=this.template(this.model.toJSON());a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(_.isFunction(this.model.get("on_click"))){this.model.get("on_click")(a);return false}return true},template:function(b){var a='title="'+b.title+'" class="icon-button';if(b.is_menu_button){a+=" menu-button"}a+=" "+b.icon_class;if(!b.enabled){a+="_disabled"}a+='"';if(b.id){a+=' id="'+b.id+'"'}a+=' href="'+b.href+'"';if(b.target){a+=' target="'+b.target+'"'}if(!b.visible){a+=' style="display: none;"'}if(b.enabled){a="<a "+a+"/>"}else{a="<span "+a+"/>"}return $(a)}});var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var PopupMenu=Backbone.View.extend({initialize:function(b,a){this.$button=b||$("<div/>");this.options=a||[];var c=this;this.$button.click(function(d){c._renderAndShow(d);return false})},_renderAndShow:function(a){this.render();this.$el.appendTo("body");this.$el.css(this._getShownPosition(a));this._setUpCloseBehavior();this.$el.show()},render:function(){this.$el.addClass("popmenu-wrapper").hide().css({position:"absolute"}).html(this.template(this.$button.attr("id"),this.options));if(this.options.length){var a=this;this.$el.find("li").each(function(c,b){var d=a.options[c];if(d.func){$(this).children("a.popupmenu-option").mousedown(function(e){d.func.call(a,e,d)})}})}return this},template:function(b,a){return['<ul id="',b,'-menu" class="dropdown-menu">',this._templateOptions(a),"</ul>"].join("")},_templateOptions:function(a){if(!a.length){return"<li>(no options)</li>"}return _.map(a,function(d){if(d.divider){return'<li class="divider"></li>'}else{if(d.header){return['<li class="head"><a href="javascript:void(0);">',d.html,"</a></li>"].join("")}}var c=d.href||"javascript:void(0);",e=(d.target)?(' target="'+d.target+'"'):(""),b=(d.checked)?('<span class="fa fa-check"></span>'):("");return['<li><a class="popupmenu-option" href="',c,'"',e,">",b,d.html,"</a></li>"].join("")}).join("")},_getShownPosition:function(b){var c=this.$el.width();var a=b.pageX-c/2;a=Math.min(a,$(document).scrollLeft()+$(window).width()-c-5);a=Math.max(a,$(document).scrollLeft()+5);return{top:b.pageY,left:a}},_setUpCloseBehavior:function(){var b=this;var a=function(c){c.one("mousedown.close_popup",function(){b.remove()})};a($(window.document));a($(window.top.document));_.each(window.top.frames,function(c){a($(c.document))})},addItem:function(b,a){a=(a>=0)?a:this.options.length;this.options.splice(a,0,b);return this},removeItem:function(a){if(a>=0){this.options.splice(a,1)}return this},findIndexByHtml:function(b){for(var a=0;a<this.options.length;a++){if(_.has(this.options[a],"html")&&(this.options[a].html===b)){return a}}return null},findItemByHtml:function(a){return this.options[(this.findIndexByHtml(a))]},toString:function(){return"PopupMenu"}});PopupMenu.make_popupmenu=function(b,c){var a=[];_.each(c,function(f,d){var e={html:d};if(f===null){e.header=true}else{if(jQuery.type(f)==="function"){e.func=f}}a.push(e)});return new PopupMenu($(b),a)};PopupMenu.convertLinksToOptions=function(c,a){c=$(c);a=a||"a";var b=[];c.find(a).each(function(g,e){var f={},d=$(g);f.html=d.text();if(d.attr("href")){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;break;default:window.location=j}}}b.push(f)});return b};PopupMenu.fromExistingDom=function(d,c,a){d=$(d);c=$(c);var b=PopupMenu.convertLinksToOptions(c,a);c.remove();return new PopupMenu(d,b)};PopupMenu.make_popup_menus=function(c,b,d){c=c||document;b=b||"div[popupmenu]";d=d||function(e,f){return"#"+e.attr("popupmenu")};var a=[];$(c).find(b).each(function(){var e=$(this),f=$(c).find(d(e,c));a.push(PopupMenu.fromDom(f,e));f.addClass("popup")});return a};var faIconButton=function(a){a=a||{};a.tooltipConfig=a.tooltipConfig||{placement:"bottom"};a.classes=["icon-btn"].concat(a.classes||[]);if(a.disabled){a.classes.push("disabled")}var b=['<a class="',a.classes.join(" "),'"',((a.title)?(' title="'+a.title+'"'):("")),((a.target)?(' target="'+a.target+'"'):("")),' href="',((a.href)?(a.href):("javascript:void(0);")),'">','<span class="fa ',a.faIcon,'"></span>',"</a>"].join("");var c=$(b).tooltip(a.tooltipConfig);if(_.isFunction(a.onclick)){c.click(a.onclick)}return c};var searchInput=function(k){var a=27,h=13,i=$("<div/>"),b={initialVal:"",name:"search",placeholder:"search",classes:"",onclear:function(){},onsearch:function(l){},minSearchLen:0,escWillClear:true,oninit:function(){}};if(jQuery.type(k)==="object"){k=jQuery.extend(true,b,k)}function d(l){var m=$(this).parent().children("input");m.val("");m.trigger("clear:searchInput");k.onclear()}function j(m,l){$(this).trigger("search:searchInput",l);k.onsearch(l)}function c(){return['<input type="text" name="',k.name,'" placeholder="',k.placeholder,'" ','class="search-query ',k.classes,'" ',"/>"].join("")}function g(){return $(c()).css({width:"100%","padding-right":"24px"}).focus(function(l){$(this).select()}).keyup(function(m){if(m.which===a&&k.escWillClear){d.call(this,m)}else{var l=$(this).val();if((m.which===h)||(k.minSearchLen&&l.length>=k.minSearchLen)){j.call(this,m,l)}else{if(!l.length){d.call(this,m)}}}}).val(k.initialVal)}function f(){return'<span class="search-clear fa fa-times-circle"></span>'}function e(){return $(f()).css({position:"absolute",right:"15px","font-size":"1.4em","line-height":"23px",color:"grey"}).click(function(l){d.call(this,l)})}return i.append([g(),e()])};function LoadingIndicator(a,c){var b=this;c=jQuery.extend({cover:false},c||{});function d(){var e=['<div class="loading-indicator">','<div class="loading-indicator-text">','<span class="fa fa-spinner fa-spin fa-lg"></span>','<span class="loading-indicator-message">loading...</span>',"</div>","</div>"].join("\n");var g=$(e).hide().css(c.css||{position:"fixed"}),f=g.children(".loading-indicator-text");if(c.cover){g.css({"z-index":2,top:a.css("top"),bottom:a.css("bottom"),left:a.css("left"),right:a.css("right"),opacity:0.5,"background-color":"white","text-align":"center"});f=g.children(".loading-indicator-text").css({"margin-top":"20px"})}else{f=g.children(".loading-indicator-text").css({margin:"12px 0px 0px 10px",opacity:"0.85",color:"grey"});f.children(".loading-indicator-message").css({margin:"0px 8px 0px 0px","font-style":"italic"})}return g}b.show=function(f,e,g){f=f||"loading...";e=e||"fast";b.$indicator=d().insertBefore(a);b.message(f);b.$indicator.fadeIn(e,g);return b};b.message=function(e){b.$indicator.find("i").text(e)};b.hide=function(e,f){e=e||"fast";if(b.$indicator&&b.$indicator.size()){b.$indicator.fadeOut(e,function(){b.$indicator.remove();if(f){f()}})}else{if(f){f()}}return b};return b};
\ No newline at end of file
+var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,is_menu_button:true,id:null,href:null,target:null,enabled:true,visible:true,tooltip_config:{}}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=this.template(this.model.toJSON());a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(_.isFunction(this.model.get("on_click"))){this.model.get("on_click")(a);return false}return true},template:function(b){var a='title="'+b.title+'" class="icon-button';if(b.is_menu_button){a+=" menu-button"}a+=" "+b.icon_class;if(!b.enabled){a+="_disabled"}a+='"';if(b.id){a+=' id="'+b.id+'"'}a+=' href="'+b.href+'"';if(b.target){a+=' target="'+b.target+'"'}if(!b.visible){a+=' style="display: none;"'}if(b.enabled){a="<a "+a+"/>"}else{a="<span "+a+"/>"}return $(a)}});var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var PopupMenu=Backbone.View.extend({initialize:function(b,a){this.$button=b||$("<div/>");this.options=a||[];var c=this;this.$button.click(function(d){c._renderAndShow(d);return false})},_renderAndShow:function(a){this.render();this.$el.appendTo("body");this.$el.css(this._getShownPosition(a));this._setUpCloseBehavior();this.$el.show()},render:function(){this.$el.addClass("popmenu-wrapper").hide().css({position:"absolute"}).html(this.template(this.$button.attr("id"),this.options));if(this.options.length){var a=this;this.$el.find("li").each(function(c,b){var d=a.options[c];if(d.func){$(this).children("a.popupmenu-option").click(function(e){d.func.call(a,e,d)})}})}return this},template:function(b,a){return['<ul id="',b,'-menu" class="dropdown-menu">',this._templateOptions(a),"</ul>"].join("")},_templateOptions:function(a){if(!a.length){return"<li>(no options)</li>"}return _.map(a,function(d){if(d.divider){return'<li class="divider"></li>'}else{if(d.header){return['<li class="head"><a href="javascript:void(0);">',d.html,"</a></li>"].join("")}}var c=d.href||"javascript:void(0);",e=(d.target)?(' target="'+d.target+'"'):(""),b=(d.checked)?('<span class="fa fa-check"></span>'):("");return['<li><a class="popupmenu-option" href="',c,'"',e,">",b,d.html,"</a></li>"].join("")}).join("")},_getShownPosition:function(b){var c=this.$el.width();var a=b.pageX-c/2;a=Math.min(a,$(document).scrollLeft()+$(window).width()-c-5);a=Math.max(a,$(document).scrollLeft()+5);return{top:b.pageY,left:a}},_setUpCloseBehavior:function(){var b=this;var a=function(c){c.one("click.close_popup",function(){b.remove()})};a($(window.document));a($(window.top.document));_.each(window.top.frames,function(c){a($(c.document))})},addItem:function(b,a){a=(a>=0)?a:this.options.length;this.options.splice(a,0,b);return this},removeItem:function(a){if(a>=0){this.options.splice(a,1)}return this},findIndexByHtml:function(b){for(var a=0;a<this.options.length;a++){if(_.has(this.options[a],"html")&&(this.options[a].html===b)){return a}}return null},findItemByHtml:function(a){return this.options[(this.findIndexByHtml(a))]},toString:function(){return"PopupMenu"}});PopupMenu.make_popupmenu=function(b,c){var a=[];_.each(c,function(f,d){var e={html:d};if(f===null){e.header=true}else{if(jQuery.type(f)==="function"){e.func=f}}a.push(e)});return new PopupMenu($(b),a)};PopupMenu.convertLinksToOptions=function(c,a){c=$(c);a=a||"a";var b=[];c.find(a).each(function(g,e){var f={},d=$(g);f.html=d.text();if(d.attr("href")){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;break;default:window.location=j}}}b.push(f)});return b};PopupMenu.fromExistingDom=function(d,c,a){d=$(d);c=$(c);var b=PopupMenu.convertLinksToOptions(c,a);c.remove();return new PopupMenu(d,b)};PopupMenu.make_popup_menus=function(c,b,d){c=c||document;b=b||"div[popupmenu]";d=d||function(e,f){return"#"+e.attr("popupmenu")};var a=[];$(c).find(b).each(function(){var e=$(this),f=$(c).find(d(e,c));a.push(PopupMenu.fromDom(f,e));f.addClass("popup")});return a};var faIconButton=function(a){a=a||{};a.tooltipConfig=a.tooltipConfig||{placement:"bottom"};a.classes=["icon-btn"].concat(a.classes||[]);if(a.disabled){a.classes.push("disabled")}var b=['<a class="',a.classes.join(" "),'"',((a.title)?(' title="'+a.title+'"'):("")),((a.target)?(' target="'+a.target+'"'):("")),' href="',((a.href)?(a.href):("javascript:void(0);")),'">','<span class="fa ',a.faIcon,'"></span>',"</a>"].join("");var c=$(b).tooltip(a.tooltipConfig);if(_.isFunction(a.onclick)){c.click(a.onclick)}return c};var searchInput=function(k){var a=27,h=13,i=$("<div/>"),b={initialVal:"",name:"search",placeholder:"search",classes:"",onclear:function(){},onsearch:function(l){},minSearchLen:0,escWillClear:true,oninit:function(){}};if(jQuery.type(k)==="object"){k=jQuery.extend(true,b,k)}function d(l){var m=$(this).parent().children("input");m.val("");m.trigger("clear:searchInput");k.onclear()}function j(m,l){$(this).trigger("search:searchInput",l);k.onsearch(l)}function c(){return['<input type="text" name="',k.name,'" placeholder="',k.placeholder,'" ','class="search-query ',k.classes,'" ',"/>"].join("")}function g(){return $(c()).css({width:"100%","padding-right":"24px"}).focus(function(l){$(this).select()}).keyup(function(m){if(m.which===a&&k.escWillClear){d.call(this,m)}else{var l=$(this).val();if((m.which===h)||(k.minSearchLen&&l.length>=k.minSearchLen)){j.call(this,m,l)}else{if(!l.length){d.call(this,m)}}}}).val(k.initialVal)}function f(){return'<span class="search-clear fa fa-times-circle"></span>'}function e(){return $(f()).css({position:"absolute",right:"15px","font-size":"1.4em","line-height":"23px",color:"grey"}).click(function(l){d.call(this,l)})}return i.append([g(),e()])};function LoadingIndicator(a,c){var b=this;c=jQuery.extend({cover:false},c||{});function d(){var e=['<div class="loading-indicator">','<div class="loading-indicator-text">','<span class="fa fa-spinner fa-spin fa-lg"></span>','<span class="loading-indicator-message">loading...</span>',"</div>","</div>"].join("\n");var g=$(e).hide().css(c.css||{position:"fixed"}),f=g.children(".loading-indicator-text");if(c.cover){g.css({"z-index":2,top:a.css("top"),bottom:a.css("bottom"),left:a.css("left"),right:a.css("right"),opacity:0.5,"background-color":"white","text-align":"center"});f=g.children(".loading-indicator-text").css({"margin-top":"20px"})}else{f=g.children(".loading-indicator-text").css({margin:"12px 0px 0px 10px",opacity:"0.85",color:"grey"});f.children(".loading-indicator-message").css({margin:"0px 8px 0px 0px","font-style":"italic"})}return g}b.show=function(f,e,g){f=f||"loading...";e=e||"fast";b.$indicator=d().insertBefore(a);b.message(f);b.$indicator.fadeIn(e,g);return b};b.message=function(e){b.$indicator.find("i").text(e)};b.hide=function(e,f){e=e||"fast";if(b.$indicator&&b.$indicator.size()){b.$indicator.fadeOut(e,function(){b.$indicator.remove();if(f){f()}})}else{if(f){f()}}return b};return b};
\ No newline at end of file
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.
1
0
commit/galaxy-central: carlfeberhard: History panel: use SessionStorageModel, remove PersistentStorage
by commits-noreply@bitbucket.org 25 Nov '13
by commits-noreply@bitbucket.org 25 Nov '13
25 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/01b5a1a68ae6/
Changeset: 01b5a1a68ae6
User: carlfeberhard
Date: 2013-11-25 20:24:14
Summary: History panel: use SessionStorageModel, remove PersistentStorage
Affected #: 5 files
diff -r 0e1d539dcfcb3246f144258514a43e07a514b52e -r 01b5a1a68ae6901936b6948769aa66b446e52e53 static/scripts/mvc/base-mvc.js
--- a/static/scripts/mvc/base-mvc.js
+++ b/static/scripts/mvc/base-mvc.js
@@ -92,18 +92,30 @@
/** Backbone model that syncs to the browser's sessionStorage API.
*/
var SessionStorageModel = Backbone.Model.extend({
- initialize : function( hash, x, y, z ){
- if( !hash || !hash.hasOwnProperty( 'id' ) ){
- throw new Error( 'SessionStorageModel needs an id on init' );
- }
- // immed. save the passed in model and save on any change to it
- this.save();
+ initialize : function( initialAttrs ){
+ // create unique id if none provided
+ initialAttrs.id = ( !_.isString( initialAttrs.id ) )?( _.uniqueId() ):( initialAttrs.id );
+ this.id = initialAttrs.id;
+
+ // load existing from storage (if any), clear any attrs set by bbone before init is called,
+ // layer initial over existing and defaults, and save
+ var existing = ( !this.isNew() )?( this._read( this ) ):( {} );
+ this.clear({ silent: true });
+ this.save( _.extend( {}, this.defaults, existing, initialAttrs ), { silent: true });
+
+ // save on any change to it immediately
this.on( 'change', function(){
this.save();
});
},
+
+ /** override of bbone sync to save to sessionStorage rather than REST
+ * bbone options (success, errror, etc.) should still apply
+ */
sync : function( method, model, options ){
- model.trigger('request', model, {}, options);
+ if( !options.silent ){
+ model.trigger( 'request', model, {}, options );
+ }
var returned;
switch( method ){
case 'create' : returned = this._create( model ); break;
@@ -118,23 +130,41 @@
}
return returned;
},
+
+ /** set storage to the stringified item */
_create : function( model ){
var json = model.toJSON(),
set = sessionStorage.setItem( model.id, JSON.stringify( json ) );
return ( set === null )?( set ):( json );
},
+
+ /** read and parse json from storage */
_read : function( model ){
- return JSON.parse( sessionStorage.getItem( model.id, JSON.stringify( model.toJSON() ) ) );
+ return JSON.parse( sessionStorage.getItem( model.id ) );
},
+
+ /** set storage to the item (alias to create) */
_update : function( model ){
return model._create( model );
},
+
+ /** remove the item from storage */
_delete : function( model ){
return sessionStorage.removeItem( model.id );
},
+
+ /** T/F whether sessionStorage contains the model's id (data is present) */
isNew : function(){
return !sessionStorage.hasOwnProperty( this.id );
+ },
+
+ _log : function(){
+ return JSON.stringify( this.toJSON(), null, ' ' );
+ },
+ toString : function(){
+ return 'SessionStorageModel(' + this.id + ')';
}
+
});
(function(){
SessionStorageModel.prototype = _.omit( SessionStorageModel.prototype, 'url', 'urlRoot' );
@@ -142,136 +172,6 @@
//==============================================================================
-/**
- * @class persistent storage adapter.
- * Provides an easy interface to object based storage using method chaining.
- * Allows easy change of the storage engine used (h5's local storage?).
- * @augments StorageRecursionHelper
- *
- * @param {String} storageKey : the key the storage engine will place the storage object under
- * @param {Object} storageDefaults : [optional] initial object to set up storage with
- *
- * @example
- * // example of construction and use
- * HistoryPanel.storage = new PersistanStorage( HistoryPanel.toString(), { visibleItems, {} });
- * itemView.bind( 'toggleBodyVisibility', function( id, visible ){
- * if( visible ){
- * HistoryPanel.storage.get( 'visibleItems' ).set( id, true );
- * } else {
- * HistoryPanel.storage.get( 'visibleItems' ).deleteKey( id );
- * }
- * });
- * @constructor
- */
-var PersistentStorage = function( storageKey, storageDefaults ){
- if( !storageKey ){
- throw( "PersistentStorage needs storageKey argument" );
- }
- storageDefaults = storageDefaults || {};
-
- // ~constants for the current engine
- var STORAGE_ENGINE = sessionStorage,
- STORAGE_ENGINE_GETTER = function sessionStorageGet( key ){
- var item = this.getItem( key );
- return ( item !== null )?( JSON.parse( this.getItem( key ) ) ):( null );
- },
- STORAGE_ENGINE_SETTER = function sessionStorageSet( key, val ){
- return this.setItem( key, JSON.stringify( val ) );
- },
- STORAGE_ENGINE_KEY_DELETER = function sessionStorageDel( key ){ return this.removeItem( key ); };
-
- /** Inner, recursive, private class for method chaining access.
- * @name StorageRecursionHelper
- * @constructor
- */
- function StorageRecursionHelper( data, parent ){
- //console.debug( 'new StorageRecursionHelper. data:', data );
- data = data || {};
- parent = parent || null;
-
- return /** @lends StorageRecursionHelper.prototype */{
- /** get a value from the storage obj named 'key',
- * if it's an object - return a new StorageRecursionHelper wrapped around it
- * if it's something simpler - return the value
- * if this isn't passed a key - return the data at this level of recursion
- */
- get : function( key ){
- //console.debug( this + '.get', key );
- if( key === undefined ){
- return data;
- } else if( data.hasOwnProperty( key ) ){
- return ( jQuery.type( data[ key ] ) === 'object' )?
- ( new StorageRecursionHelper( data[ key ], this ) )
- :( data[ key ] );
- }
- return undefined;
- },
- /** get the underlying data based on this key */
- // set a value on the current data - then pass up to top to save current entire object in storage
- set : function( key, value ){
- //TODO: add parameterless variation setting the data somehow
- // ??: difficult bc of obj by ref, closure
- //console.debug( this + '.set', key, value );
- data[ key ] = value;
- this._save();
- return this;
- },
- // remove a key at this level - then save entire (as 'set' above)
- deleteKey : function( key ){
- //console.debug( this + '.deleteKey', key );
- delete data[ key ];
- this._save();
- return this;
- },
- // pass up the recursion chain (see below for base case)
- _save : function(){
- //console.debug( this + '.save', parent );
- return parent._save();
- },
- toString : function(){
- return ( 'StorageRecursionHelper(' + data + ')' );
- }
- };
- }
-
- //??: more readable to make another class?
- var returnedStorage = {},
- // attempt to get starting data from engine...
- data = STORAGE_ENGINE_GETTER.call( STORAGE_ENGINE, storageKey );
-
- // ...if that fails, use the defaults (and store them)
- if( data === null || data === undefined ){
- data = jQuery.extend( true, {}, storageDefaults );
- STORAGE_ENGINE_SETTER.call( STORAGE_ENGINE, storageKey, data );
- }
-
- // the object returned by this constructor will be a modified StorageRecursionHelper
- returnedStorage = new StorageRecursionHelper( data );
- jQuery.extend( returnedStorage, /** @lends PersistentStorage.prototype */{
- /** The base case for save()'s upward recursion - save everything to storage.
- * @private
- * @param {Any} newData data object to save to storage
- */
- _save : function( newData ){
- //console.debug( returnedStorage, '._save:', JSON.stringify( returnedStorage.get() ) );
- return STORAGE_ENGINE_SETTER.call( STORAGE_ENGINE, storageKey, returnedStorage.get() );
- },
- /** Delete function to remove the entire base data object from the storageEngine.
- */
- destroy : function(){
- //console.debug( returnedStorage, '.destroy:' );
- return STORAGE_ENGINE_KEY_DELETER.call( STORAGE_ENGINE, storageKey );
- },
- /** String representation.
- */
- toString : function(){ return 'PersistentStorage(' + storageKey + ')'; }
- });
-
- return returnedStorage;
-};
-
-
-//==============================================================================
var HiddenUntilActivatedViewMixin = /** @lends hiddenUntilActivatedMixin# */{
/** */
diff -r 0e1d539dcfcb3246f144258514a43e07a514b52e -r 01b5a1a68ae6901936b6948769aa66b446e52e53 static/scripts/mvc/dataset/hda-base.js
--- a/static/scripts/mvc/dataset/hda-base.js
+++ b/static/scripts/mvc/dataset/hda-base.js
@@ -93,8 +93,8 @@
var $newRender = $( HDABaseView.templates.skeleton( this.model.toJSON() ) );
$newRender.find( '.dataset-primary-actions' ).append( this._render_titleButtons() );
$newRender.children( '.dataset-body' ).replaceWith( this._render_body() );
+ this._setUpBehaviors( $newRender );
//this._renderSelectable( $newRender );
- this._setUpBehaviors( $newRender );
// fade the old render out (if desired)
if( fade ){
diff -r 0e1d539dcfcb3246f144258514a43e07a514b52e -r 01b5a1a68ae6901936b6948769aa66b446e52e53 static/scripts/mvc/history/history-panel.js
--- a/static/scripts/mvc/history/history-panel.js
+++ b/static/scripts/mvc/history/history-panel.js
@@ -3,6 +3,44 @@
"mvc/dataset/hda-base",
"mvc/dataset/hda-edit"
], function( historyModel, hdaBase, hdaEdit ){
+
+
+// ============================================================================
+/** session storage for individual history preferences
+ */
+var HistoryPanelPrefs = SessionStorageModel.extend({
+ defaults : {
+ //TODO:?? expandedHdas to array?
+ expandedHdas : {},
+ //TODO:?? move to user?
+ show_deleted : false,
+ show_hidden : false
+ //TODO: add scroll position?
+ },
+ /** add an hda id to the hash of expanded hdas */
+ addExpandedHda : function( id ){
+ this.save( 'expandedHdas', _.extend( this.get( 'expandedHdas' ), _.object([ id ], [ true ]) ) );
+ },
+ /** remove an hda id from the hash of expanded hdas */
+ removeExpandedHda : function( id ){
+ this.save( 'expandedHdas', _.omit( this.get( 'expandedHdas' ), id ) );
+ },
+ toString : function(){
+ return 'HistoryPanelPrefs(' + this.id + ')';
+ }
+});
+
+/** key string to store each histories settings under */
+HistoryPanelPrefs.historyStorageKey = function historyStorageKey( historyId ){
+ // class lvl for access w/o instantiation
+ if( !historyId ){
+ throw new Error( 'HistoryPanelPrefs.historyStorageKey needs valid id: ' + historyId );
+ }
+ // single point of change
+ return ( 'history:' + historyId );
+};
+
+
/* =============================================================================
Backbone.js implementation of history panel
@@ -216,8 +254,8 @@
// - hdas w/o details will have summary data only (name, hid, deleted, visible, state, etc.))
/** (re-)loads the user's current history & hdas w/ details */
- // implemented as a 'fresh start' or for when there is no model (intial panel render)
loadCurrentHistory : function( attributes ){
+ // implemented as a 'fresh start' or for when there is no model (intial panel render)
var panel = this;
return this.loadHistoryWithHDADetails( 'current', attributes )
.then(function( historyData, hdaData ){
@@ -334,7 +372,7 @@
return this;
},
- // alias to the model. Updates the hda list only (not the history)
+ /** alias to the model. Updates the hda list only (not the history) */
refreshHdas : function( detailIds, options ){
if( this.model ){
return this.model.refresh( detailIds, options );
@@ -344,8 +382,6 @@
},
// ------------------------------------------------------------------------ browser stored prefs
-//TODO: simplify
-
/** Set up client side storage. Currently PersistanStorage keyed under 'HistoryPanel.<id>'
* @param {Object} initiallyExpanded
* @param {Boolean} show_deleted whether to show deleted HDAs (overrides stored)
@@ -353,55 +389,31 @@
* @see PersistentStorage
*/
_setUpWebStorage : function( initiallyExpanded, show_deleted, show_hidden ){
- //this.log( '_setUpWebStorage, initiallyExpanded:', initiallyExpanded,
- // 'show_deleted:', show_deleted, 'show_hidden', show_hidden );
+ //console.debug( '_setUpWebStorage', initiallyExpanded, show_deleted, show_hidden );
+ this.storage = new HistoryPanelPrefs({
+ id: HistoryPanelPrefs.historyStorageKey( this.model.get( 'id' ) )
+ });
- //TODO: add scroll position?
-
- // data that needs to be persistent over page refreshes
- // (note the key function which uses the history id as well)
- this.storage = new PersistentStorage( this._getStorageKey( this.model.get( 'id' ) ), {
- expandedHdas : {},
- show_deleted : false,
- show_hidden : false
- });
- this.log( this + ' (prev) storage:', JSON.stringify( this.storage.get(), null, 2 ) );
-
- // expanded Hdas is a map of hda.ids -> a boolean rep'ing whether this hda's body is expanded
+ // expanded Hdas is a map of hda.ids -> a boolean repr'ing whether this hda's body is already expanded
// store any pre-expanded ids passed in
- if( initiallyExpanded ){
+ if( _.isObject( initiallyExpanded ) ){
this.storage.set( 'exandedHdas', initiallyExpanded );
}
- //TODO: should be global pref? (not specific to each history)
-
- // get the show_deleted/hidden settings giving priority to values passed in,
- // using web storage otherwise
+ // get the show_deleted/hidden settings giving priority to values passed in, using web storage otherwise
// if the page has specifically requested show_deleted/hidden, these will be either true or false
// (as opposed to undefined, null) - and we give priority to that setting
- if( ( show_deleted === true ) || ( show_deleted === false ) ){
- // save them to web storage
+ if( _.isBoolean( show_deleted ) ){
this.storage.set( 'show_deleted', show_deleted );
}
- if( ( show_hidden === true ) || ( show_hidden === false ) ){
+ if( _.isBoolean( show_hidden ) ){
this.storage.set( 'show_hidden', show_hidden );
}
- // if the page hasn't specified whether to show_deleted/hidden, pull show_deleted/hidden from the web storage
- this.show_deleted = this.storage.get( 'show_deleted' );
- this.show_hidden = this.storage.get( 'show_hidden' );
- //this.log( 'this.show_deleted:', this.show_deleted, 'show_hidden', this.show_hidden );
+
this.trigger( 'new-storage', this.storage, this );
this.log( this + ' (init\'d) storage:', this.storage.get() );
},
- /** key string to store each histories settings under */
- _getStorageKey : function( id ){
- if( !id ){
- throw new Error( '_getStorageKey needs valid id: ' + id );
- }
- return ( 'history:' + id );
- },
-
/** clear all stored history panel data */
clearWebStorage : function(){
for( var key in sessionStorage ){
@@ -417,11 +429,11 @@
return ( this.storage )?( this.storage.get() ):( {} );
}
//TODO: make storage engine generic
- var item = sessionStorage.getItem( this._getStorageKey( historyId ) );
+ var item = sessionStorage.getItem( HistoryPanelPrefs.historyStorageKey( historyId ) );
return ( item === null )?( {} ):( JSON.parse( item ) );
},
- /** get all the map of expaneded hda ids for the given history id */
+ /** get an array of expanded hda ids for the given history id */
getExpandedHdaIds : function( historyId ){
var expandedHdas = this.getStoredOptions( historyId ).expandedHdas;
return (( _.isEmpty( expandedHdas ) )?( [] ):( _.keys( expandedHdas ) ));
@@ -509,7 +521,7 @@
*/
createHdaView : function( hda ){
var hdaId = hda.get( 'id' ),
- expanded = this.storage.get( 'expandedHdas' ).get( hdaId ),
+ expanded = this.storage.get( 'expandedHdas' )[ hdaId ],
hdaView = new this.HDAView({
model : hda,
expanded : expanded,
@@ -529,10 +541,10 @@
var historyView = this;
// maintain a list of hdas whose bodies are expanded
hdaView.on( 'body-expanded', function( id ){
- historyView.storage.get( 'expandedHdas' ).set( id, true );
+ historyView.storage.addExpandedHda( id );
});
hdaView.on( 'body-collapsed', function( id ){
- historyView.storage.get( 'expandedHdas' ).deleteKey( id );
+ historyView.storage.removeExpandedHda( id );
});
//TODO: remove?
hdaView.on( 'error', function( model, xhr, options, msg ){
diff -r 0e1d539dcfcb3246f144258514a43e07a514b52e -r 01b5a1a68ae6901936b6948769aa66b446e52e53 static/scripts/packed/mvc/base-mvc.js
--- a/static/scripts/packed/mvc/base-mvc.js
+++ b/static/scripts/packed/mvc/base-mvc.js
@@ -1,1 +1,1 @@
-var BaseModel=Backbone.RelationalModel.extend({defaults:{name:null,hidden:false},show:function(){this.set("hidden",false)},hide:function(){this.set("hidden",true)},is_visible:function(){return !this.attributes.hidden}});var BaseView=Backbone.View.extend({initialize:function(){this.model.on("change:hidden",this.update_visible,this);this.update_visible()},update_visible:function(){if(this.model.attributes.hidden){this.$el.hide()}else{this.$el.show()}}});var LoggableMixin={logger:null,log:function(){if(this.logger){var a=this.logger.log;if(typeof this.logger.log==="object"){a=Function.prototype.bind.call(this.logger.log,this.logger)}return a.apply(this.logger,arguments)}return undefined}};var SessionStorageModel=Backbone.Model.extend({initialize:function(b,a,d,c){if(!b||!b.hasOwnProperty("id")){throw new Error("SessionStorageModel needs an id on init")}this.save();this.on("change",function(){this.save()})},sync:function(d,b,a){b.trigger("request",b,{},a);var c;switch(d){case"create":c=this._create(b);break;case"read":c=this._read(b);break;case"update":c=this._update(b);break;case"delete":c=this._delete(b);break}if(c!==undefined||c!==null){if(a.success){a.success()}}else{if(a.error){a.error()}}return c},_create:function(a){var b=a.toJSON(),c=sessionStorage.setItem(a.id,JSON.stringify(b));return(c===null)?(c):(b)},_read:function(a){return JSON.parse(sessionStorage.getItem(a.id,JSON.stringify(a.toJSON())))},_update:function(a){return a._create(a)},_delete:function(a){return sessionStorage.removeItem(a.id)},isNew:function(){return !sessionStorage.hasOwnProperty(this.id)}});(function(){SessionStorageModel.prototype=_.omit(SessionStorageModel.prototype,"url","urlRoot")}());var PersistentStorage=function(k,g){if(!k){throw ("PersistentStorage needs storageKey argument")}g=g||{};var i=sessionStorage,c=function j(m){var n=this.getItem(m);return(n!==null)?(JSON.parse(this.getItem(m))):(null)},b=function e(m,n){return this.setItem(m,JSON.stringify(n))},d=function f(m){return this.removeItem(m)};function a(n,m){n=n||{};m=m||null;return{get:function(o){if(o===undefined){return n}else{if(n.hasOwnProperty(o)){return(jQuery.type(n[o])==="object")?(new a(n[o],this)):(n[o])}}return undefined},set:function(o,p){n[o]=p;this._save();return this},deleteKey:function(o){delete n[o];this._save();return this},_save:function(){return m._save()},toString:function(){return("StorageRecursionHelper("+n+")")}}}var l={},h=c.call(i,k);if(h===null||h===undefined){h=jQuery.extend(true,{},g);b.call(i,k,h)}l=new a(h);jQuery.extend(l,{_save:function(m){return b.call(i,k,l.get())},destroy:function(){return d.call(i,k)},toString:function(){return"PersistentStorage("+k+")"}});return l};var HiddenUntilActivatedViewMixin={hiddenUntilActivated:function(a,c){c=c||{};this.HUAVOptions={$elementShown:this.$el,showFn:jQuery.prototype.toggle,showSpeed:"fast"};_.extend(this.HUAVOptions,c||{});this.HUAVOptions.hasBeenShown=this.HUAVOptions.$elementShown.is(":visible");if(a){var b=this;a.on("click",function(d){b.toggle(b.HUAVOptions.showSpeed)})}},toggle:function(){if(this.HUAVOptions.$elementShown.is(":hidden")){if(!this.HUAVOptions.hasBeenShown){if(_.isFunction(this.HUAVOptions.onshowFirstTime)){this.HUAVOptions.hasBeenShown=true;this.HUAVOptions.onshowFirstTime.call(this)}}else{if(_.isFunction(this.HUAVOptions.onshow)){this.HUAVOptions.onshow.call(this)}}}return this.HUAVOptions.showFn.apply(this.HUAVOptions.$elementShown,arguments)}};
\ No newline at end of file
+var BaseModel=Backbone.RelationalModel.extend({defaults:{name:null,hidden:false},show:function(){this.set("hidden",false)},hide:function(){this.set("hidden",true)},is_visible:function(){return !this.attributes.hidden}});var BaseView=Backbone.View.extend({initialize:function(){this.model.on("change:hidden",this.update_visible,this);this.update_visible()},update_visible:function(){if(this.model.attributes.hidden){this.$el.hide()}else{this.$el.show()}}});var LoggableMixin={logger:null,log:function(){if(this.logger){var a=this.logger.log;if(typeof this.logger.log==="object"){a=Function.prototype.bind.call(this.logger.log,this.logger)}return a.apply(this.logger,arguments)}return undefined}};var SessionStorageModel=Backbone.Model.extend({initialize:function(b){b.id=(!_.isString(b.id))?(_.uniqueId()):(b.id);this.id=b.id;var a=(!this.isNew())?(this._read(this)):({});this.clear({silent:true});this.save(_.extend({},this.defaults,a,b),{silent:true});this.on("change",function(){this.save()})},sync:function(d,b,a){if(!a.silent){b.trigger("request",b,{},a)}var c;switch(d){case"create":c=this._create(b);break;case"read":c=this._read(b);break;case"update":c=this._update(b);break;case"delete":c=this._delete(b);break}if(c!==undefined||c!==null){if(a.success){a.success()}}else{if(a.error){a.error()}}return c},_create:function(a){var b=a.toJSON(),c=sessionStorage.setItem(a.id,JSON.stringify(b));return(c===null)?(c):(b)},_read:function(a){return JSON.parse(sessionStorage.getItem(a.id))},_update:function(a){return a._create(a)},_delete:function(a){return sessionStorage.removeItem(a.id)},isNew:function(){return !sessionStorage.hasOwnProperty(this.id)},_log:function(){return JSON.stringify(this.toJSON(),null," ")},toString:function(){return"SessionStorageModel("+this.id+")"}});(function(){SessionStorageModel.prototype=_.omit(SessionStorageModel.prototype,"url","urlRoot")}());var HiddenUntilActivatedViewMixin={hiddenUntilActivated:function(a,c){c=c||{};this.HUAVOptions={$elementShown:this.$el,showFn:jQuery.prototype.toggle,showSpeed:"fast"};_.extend(this.HUAVOptions,c||{});this.HUAVOptions.hasBeenShown=this.HUAVOptions.$elementShown.is(":visible");if(a){var b=this;a.on("click",function(d){b.toggle(b.HUAVOptions.showSpeed)})}},toggle:function(){if(this.HUAVOptions.$elementShown.is(":hidden")){if(!this.HUAVOptions.hasBeenShown){if(_.isFunction(this.HUAVOptions.onshowFirstTime)){this.HUAVOptions.hasBeenShown=true;this.HUAVOptions.onshowFirstTime.call(this)}}else{if(_.isFunction(this.HUAVOptions.onshow)){this.HUAVOptions.onshow.call(this)}}}return this.HUAVOptions.showFn.apply(this.HUAVOptions.$elementShown,arguments)}};
\ No newline at end of file
diff -r 0e1d539dcfcb3246f144258514a43e07a514b52e -r 01b5a1a68ae6901936b6948769aa66b446e52e53 static/scripts/packed/mvc/history/history-panel.js
--- a/static/scripts/packed/mvc/history/history-panel.js
+++ b/static/scripts/packed/mvc/history/history-panel.js
@@ -1,1 +1,1 @@
-define(["mvc/history/history-model","mvc/dataset/hda-base","mvc/dataset/hda-edit"],function(d,b,a){var c=Backbone.View.extend(LoggableMixin).extend({HDAView:a.HDAEditView,tagName:"div",className:"history-panel",fxSpeed:"fast",datasetsSelector:".datasets-list",emptyMsgSelector:".empty-history-message",msgsSelector:".message-container",initialize:function(e){e=e||{};if(e.logger){this.logger=e.logger}this.log(this+".initialize:",e);this._setUpListeners();this.hdaViews={};this.indicator=new LoadingIndicator(this.$el);this.filters=[];if(this.model){this._setUpWebStorage(e.initiallyExpanded,e.show_deleted,e.show_hidden);this._setUpModelEventHandlers()}if(e.onready){e.onready.call(this)}},_setUpListeners:function(){this.on("error",function(f,i,e,h,g){this.errorHandler(f,i,e,h,g)});this.on("loading-history",function(){this.showLoadingIndicator("loading history...")});this.on("loading-done",function(){this.hideLoadingIndicator()});this.once("rendered",function(){this.trigger("rendered:initial",this);return false});this.on("switched-history current-history new-history",function(){if(_.isEmpty(this.hdaViews)){this.trigger("empty-history",this)}});if(this.logger){this.on("all",function(e){this.log(this+"",arguments)},this)}},errorHandler:function(g,j,f,i,h){var e=this._parseErrorMessage(g,j,f,i,h);if(j&&j.status===0&&j.readyState===0){}else{if(j&&j.status===502){}else{if(!this.$el.find(this.msgsSelector).is(":visible")){this.once("rendered",function(){this.displayMessage("error",e.message,e.details)})}else{this.displayMessage("error",e.message,e.details)}}}},_parseErrorMessage:function(h,l,g,k,j){var f=Galaxy.currUser,e={message:this._bePolite(k),details:{user:(f instanceof User)?(f.toJSON()):(f+""),source:(h instanceof Backbone.Model)?(h.toJSON()):(h+""),xhr:l,options:(l)?(_.omit(g,"xhr")):(g)}};_.extend(e.details,j||{});if(l&&_.isFunction(l.getAllResponseHeaders)){var i=l.getAllResponseHeaders();i=_.compact(i.split("\n"));i=_.map(i,function(m){return m.split(": ")});e.details.xhr.responseHeaders=_.object(i)}return e},_bePolite:function(e){e=e||_l("An error occurred while getting updates from the server");return e+". "+_l("Please contact a Galaxy administrator if the problem persists.")},loadCurrentHistory:function(f){var e=this;return this.loadHistoryWithHDADetails("current",f).then(function(h,g){e.trigger("current-history",e)})},switchToHistory:function(h,g){var e=this,f=function(){return jQuery.post(galaxy_config.root+"api/histories/"+h+"/set_as_current")};return this.loadHistoryWithHDADetails(h,g,f).then(function(j,i){e.trigger("switched-history",e)})},createNewHistory:function(g){if(!Galaxy||!Galaxy.currUser||Galaxy.currUser.isAnonymous()){this.displayMessage("error",_l("You must be logged in to create histories"));return $.when()}var e=this,f=function(){return jQuery.post(galaxy_config.root+"api/histories",{current:true})};return this.loadHistory(undefined,g,f).then(function(i,h){e.trigger("new-history",e)})},loadHistoryWithHDADetails:function(h,g,f,j){var e=this,i=function(k){return e.getExpandedHdaIds(k.id)};return this.loadHistory(h,g,f,j,i)},loadHistory:function(h,g,f,k,i){this.trigger("loading-history",this);g=g||{};var e=this;var j=d.History.getHistoryData(h,{historyFn:f,hdaFn:k,hdaDetailIds:g.initiallyExpanded||i});return this._loadHistoryFromXHR(j,g).fail(function(n,l,m){e.trigger("error",e,n,g,_l("An error was encountered while "+l),{historyId:h,history:m||{}})}).always(function(){e.trigger("loading-done",e)})},_loadHistoryFromXHR:function(g,f){var e=this;g.then(function(h,i){e.setModel(h,i,f)});g.fail(function(i,h){e.render()});return g},setModel:function(g,e,f){f=f||{};if(this.model){this.model.clearUpdateTimeout();this.stopListening(this.model);this.stopListening(this.model.hdas)}this.hdaViews={};if(Galaxy&&Galaxy.currUser){g.user=Galaxy.currUser.toJSON()}this.model=new d.History(g,e,f);this._setUpWebStorage(f.initiallyExpanded,f.show_deleted,f.show_hidden);this._setUpModelEventHandlers();this.trigger("new-model",this);this.render();return this},refreshHdas:function(f,e){if(this.model){return this.model.refresh(f,e)}return $.when()},_setUpWebStorage:function(f,e,g){this.storage=new PersistentStorage(this._getStorageKey(this.model.get("id")),{expandedHdas:{},show_deleted:false,show_hidden:false});this.log(this+" (prev) storage:",JSON.stringify(this.storage.get(),null,2));if(f){this.storage.set("exandedHdas",f)}if((e===true)||(e===false)){this.storage.set("show_deleted",e)}if((g===true)||(g===false)){this.storage.set("show_hidden",g)}this.show_deleted=this.storage.get("show_deleted");this.show_hidden=this.storage.get("show_hidden");this.trigger("new-storage",this.storage,this);this.log(this+" (init'd) storage:",this.storage.get())},_getStorageKey:function(e){if(!e){throw new Error("_getStorageKey needs valid id: "+e)}return("history:"+e)},clearWebStorage:function(){for(var e in sessionStorage){if(e.indexOf("history:")===0){sessionStorage.removeItem(e)}}},getStoredOptions:function(f){if(!f||f==="current"){return(this.storage)?(this.storage.get()):({})}var e=sessionStorage.getItem(this._getStorageKey(f));return(e===null)?({}):(JSON.parse(e))},getExpandedHdaIds:function(e){var f=this.getStoredOptions(e).expandedHdas;return((_.isEmpty(f))?([]):(_.keys(f)))},_setUpModelEventHandlers:function(){this.model.on("error error:hdas",function(f,h,e,g){this.errorHandler(f,h,e,g)},this);this.model.on("change:nice_size",this.updateHistoryDiskSize,this);if(Galaxy&&Galaxy.quotaMeter){this.listenTo(this.model,"change:nice_size",function(){Galaxy.quotaMeter.update()})}this.model.hdas.on("add",this.addHdaView,this);this.model.hdas.on("change:deleted",this.handleHdaDeletionChange,this);this.model.hdas.on("change:visible",this.handleHdaVisibleChange,this);this.model.hdas.on("change:purged",function(e){this.model.fetch()},this);this.model.hdas.on("state:ready",function(f,g,e){if((!f.get("visible"))&&(!this.storage.get("show_hidden"))){this.removeHdaView(this.hdaViews[f.id])}},this)},addHdaView:function(h){this.log("add."+this,h);var f=this;if(!h.isVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"))){return}$({}).queue([function g(j){var i=f.$el.find(f.emptyMsgSelector);if(i.is(":visible")){i.fadeOut(f.fxSpeed,j)}else{j()}},function e(j){f.scrollToTop();var i=f.$el.find(f.datasetsSelector);f.createHdaView(h).$el.hide().prependTo(i).slideDown(f.fxSpeed)}])},createHdaView:function(g){var f=g.get("id"),e=this.storage.get("expandedHdas").get(f),h=new this.HDAView({model:g,expanded:e,hasUser:this.model.hasUser(),logger:this.logger});this._setUpHdaListeners(h);this.hdaViews[f]=h;return h.render()},_setUpHdaListeners:function(f){var e=this;f.on("body-expanded",function(g){e.storage.get("expandedHdas").set(g,true)});f.on("body-collapsed",function(g){e.storage.get("expandedHdas").deleteKey(g)});f.on("error",function(h,j,g,i){e.errorHandler(h,j,g,i)})},handleHdaDeletionChange:function(e){if(e.get("deleted")&&!this.storage.get("show_deleted")){this.removeHdaView(this.hdaViews[e.id])}},handleHdaVisibleChange:function(e){if(e.hidden()&&!this.storage.get("show_hidden")){this.removeHdaView(this.hdaViews[e.id])}},removeHdaView:function(f){if(!f){return}var e=this;f.$el.fadeOut(e.fxSpeed,function(){f.off();f.remove();delete e.hdaViews[f.model.id];if(_.isEmpty(e.hdaViews)){e.$el.find(e.emptyMsgSelector).fadeIn(e.fxSpeed,function(){e.trigger("empty-history",e)})}})},render:function(g,h){g=(g===undefined)?(this.fxSpeed):(g);var e=this,f;if(this.model){f=this.renderModel()}else{f=this.renderWithoutModel()}$(e).queue("fx",[function(i){if(g&&e.$el.is(":visible")){e.$el.fadeOut(g,i)}else{i()}},function(i){e.$el.empty();if(f){e.$el.append(f.children())}i()},function(i){if(g&&!e.$el.is(":visible")){e.$el.fadeIn(g,i)}else{i()}},function(i){if(h){h.call(this)}e.trigger("rendered",this);i()}]);return this},renderWithoutModel:function(){var e=$("<div/>"),f=$("<div/>").addClass("message-container").css({"margin-left":"4px","margin-right":"4px"});return e.append(f)},renderModel:function(){var e=$("<div/>");if(!Galaxy||!Galaxy.currUser||Galaxy.currUser.isAnonymous()){e.append(c.templates.anonHistoryPanel(this.model.toJSON()))}else{e.append(c.templates.historyPanel(this.model.toJSON()));this._renderTags(e);this._renderAnnotation(e)}this._setUpBehaviours(e);this.renderHdas(e);return e},_renderTags:function(e){this.tagsEditor=new TagsEditor({model:this.model,el:e.find(".history-controls .tags-display"),onshowFirstTime:function(){this.render()},$activator:faIconButton({title:_l("Edit history tags"),classes:"history-tag-btn",faIcon:"fa-tags"}).appendTo(e.find(".history-secondary-actions"))})},_renderAnnotation:function(e){this.annotationEditor=new AnnotationEditor({model:this.model,el:e.find(".history-controls .annotation-display"),onshowFirstTime:function(){this.render()},$activator:faIconButton({title:_l("Edit history tags"),classes:"history-annotate-btn",faIcon:"fa-comment"}).appendTo(e.find(".history-secondary-actions"))})},_setUpBehaviours:function(e){e=e||this.$el;e.find("[title]").tooltip({placement:"bottom"});if(!this.model||!Galaxy.currUser||Galaxy.currUser.isAnonymous()){return}var f=this;e.find(".history-name").make_text_editable({on_finish:function(g){e.find(".history-name").text(g);f.model.save({name:g}).fail(function(){e.find(".history-name").text(f.model.previous("name"))})}})},renderHdas:function(g){g=g||this.$el;this.hdaViews={};var f=this,e=g.find(this.datasetsSelector),h=this.model.hdas.getVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"),this.filters);e.empty();if(h.length){h.each(function(i){e.prepend(f.createHdaView(i).$el)});g.find(this.emptyMsgSelector).hide()}else{g.find(this.emptyMsgSelector).show()}return this.hdaViews},events:{"click .message-container":"clearMessages"},updateHistoryDiskSize:function(){this.$el.find(".history-size").text(this.model.get("nice_size"))},collapseAllHdaBodies:function(){_.each(this.hdaViews,function(e){e.toggleBodyVisibility(null,false)});this.storage.set("expandedHdas",{})},toggleShowDeleted:function(){this.storage.set("show_deleted",!this.storage.get("show_deleted"));this.render();return this.storage.get("show_deleted")},toggleShowHidden:function(){this.storage.set("show_hidden",!this.storage.get("show_hidden"));this.render();return this.storage.get("show_hidden")},renderSearchControls:function(){var e=this;e.model.hdas.fetchAllDetails({silent:true});function g(h){e.searchFor=h;e.filters=[function(i){return i.matchesAll(e.searchFor)}];e.trigger("search:searching",h,e);e.renderHdas()}function f(){e.searchFor="";e.filters=[];e.trigger("search:clear",e);e.renderHdas()}return searchInput({initialVal:e.searchFor,name:"history-search",placeholder:"search datasets",classes:"history-search",onsearch:g,onclear:f}).addClass("history-search-controls").css("padding","0px 0px 8px 0px")},toggleSearchControls:function(){var e=this.$el.find(".history-search-controls");if(!e.size()){e=this.renderSearchControls().hide();this.$el.find(".history-title").before(e)}e.slideToggle(this.fxSpeed)},showSelect:function(e){_.each(this.hdaViews,function(f){f.showSelect(e)})},hideSelect:function(e){_.each(this.hdaViews,function(f){f.hideSelect(e)})},getSelectedHdaViews:function(){return _.filter(this.hdaViews,function(e){return e.selected})},showLoadingIndicator:function(f,e,g){e=(e!==undefined)?(e):(this.fxSpeed);if(!this.indicator){this.indicator=new LoadingIndicator(this.$el,this.$el.parent())}if(!this.$el.is(":visible")){this.indicator.show(0,g)}else{this.$el.fadeOut(e);this.indicator.show(f,e,g)}},hideLoadingIndicator:function(e,f){e=(e!==undefined)?(e):(this.fxSpeed);if(this.indicator){this.indicator.hide(e,f)}},displayMessage:function(j,k,i){var g=this;this.scrollToTop();var h=this.$el.find(this.msgsSelector),e=$("<div/>").addClass(j+"message").html(k);if(!_.isEmpty(i)){var f=$('<a href="javascript:void(0)">Details</a>').click(function(){Galaxy.modal.show(g.messageToModalOptions(j,k,i));return false});e.append(" ",f)}return h.html(e)},messageToModalOptions:function(i,k,h){var e=this,j=$("<div/>"),g={title:"Details"};function f(l){l=_.omit(l,_.functions(l));return["<table>",_.map(l,function(n,m){n=(_.isObject(n))?(f(n)):(n);return'<tr><td style="vertical-align: top; color: grey">'+m+'</td><td style="padding-left: 8px">'+n+"</td></tr>"}).join(""),"</table>"].join("")}if(_.isObject(h)){g.body=j.append(f(h))}else{g.body=j.html(h)}g.buttons={Ok:function(){Galaxy.modal.hide();e.clearMessages()}};return g},clearMessages:function(){var e=this.$el.find(this.msgsSelector);e.empty()},scrollPosition:function(){return this.$el.parent().scrollTop()},scrollTo:function(e){this.$el.parent().scrollTop(e)},scrollToTop:function(){this.$el.parent().scrollTop(0);return this},scrollIntoView:function(f,g){if(!g){this.$el.parent().parent().scrollTop(f);return this}var e=window,h=this.$el.parent().parent(),j=$(e).innerHeight(),i=(j/2)-(g/2);$(h).scrollTop(f-i);return this},scrollToId:function(f){if((!f)||(!this.hdaViews[f])){return this}var e=this.hdaViews[f].$el;this.scrollIntoView(e.offset().top,e.outerHeight());return this},scrollToHid:function(e){var f=this.model.hdas.getByHid(e);if(!f){return this}return this.scrollToId(f.id)},connectToQuotaMeter:function(e){if(!e){return this}this.listenTo(e,"quota:over",this.showQuotaMessage);this.listenTo(e,"quota:under",this.hideQuotaMessage);this.on("rendered rendered:initial",function(){if(e&&e.isOverQuota()){this.showQuotaMessage()}});return this},showQuotaMessage:function(){var e=this.$el.find(".quota-message");if(e.is(":hidden")){e.slideDown(this.fxSpeed)}},hideQuotaMessage:function(){var e=this.$el.find(".quota-message");if(!e.is(":hidden")){e.slideUp(this.fxSpeed)}},connectToOptionsMenu:function(e){if(!e){return this}this.on("new-storage",function(g,f){if(e&&g){e.findItemByHtml(_l("Include Deleted Datasets")).checked=g.get("show_deleted");e.findItemByHtml(_l("Include Hidden Datasets")).checked=g.get("show_hidden")}});return this},toString:function(){return"HistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});c.templates={historyPanel:Handlebars.templates["template-history-historyPanel"],anonHistoryPanel:Handlebars.templates["template-history-historyPanel-anon"]};return{HistoryPanel:c}});
\ No newline at end of file
+define(["mvc/history/history-model","mvc/dataset/hda-base","mvc/dataset/hda-edit"],function(f,b,a){var c=SessionStorageModel.extend({defaults:{expandedHdas:{},show_deleted:false,show_hidden:false},addExpandedHda:function(g){this.save("expandedHdas",_.extend(this.get("expandedHdas"),_.object([g],[true])))},removeExpandedHda:function(g){this.save("expandedHdas",_.omit(this.get("expandedHdas"),g))},toString:function(){return"HistoryPanelPrefs("+this.id+")"}});c.historyStorageKey=function e(g){if(!g){throw new Error("HistoryPanelPrefs.historyStorageKey needs valid id: "+g)}return("history:"+g)};var d=Backbone.View.extend(LoggableMixin).extend({HDAView:a.HDAEditView,tagName:"div",className:"history-panel",fxSpeed:"fast",datasetsSelector:".datasets-list",emptyMsgSelector:".empty-history-message",msgsSelector:".message-container",initialize:function(g){g=g||{};if(g.logger){this.logger=g.logger}this.log(this+".initialize:",g);this._setUpListeners();this.hdaViews={};this.indicator=new LoadingIndicator(this.$el);this.filters=[];if(this.model){this._setUpWebStorage(g.initiallyExpanded,g.show_deleted,g.show_hidden);this._setUpModelEventHandlers()}if(g.onready){g.onready.call(this)}},_setUpListeners:function(){this.on("error",function(h,k,g,j,i){this.errorHandler(h,k,g,j,i)});this.on("loading-history",function(){this.showLoadingIndicator("loading history...")});this.on("loading-done",function(){this.hideLoadingIndicator()});this.once("rendered",function(){this.trigger("rendered:initial",this);return false});this.on("switched-history current-history new-history",function(){if(_.isEmpty(this.hdaViews)){this.trigger("empty-history",this)}});if(this.logger){this.on("all",function(g){this.log(this+"",arguments)},this)}},errorHandler:function(i,l,h,k,j){var g=this._parseErrorMessage(i,l,h,k,j);if(l&&l.status===0&&l.readyState===0){}else{if(l&&l.status===502){}else{if(!this.$el.find(this.msgsSelector).is(":visible")){this.once("rendered",function(){this.displayMessage("error",g.message,g.details)})}else{this.displayMessage("error",g.message,g.details)}}}},_parseErrorMessage:function(j,n,i,m,l){var h=Galaxy.currUser,g={message:this._bePolite(m),details:{user:(h instanceof User)?(h.toJSON()):(h+""),source:(j instanceof Backbone.Model)?(j.toJSON()):(j+""),xhr:n,options:(n)?(_.omit(i,"xhr")):(i)}};_.extend(g.details,l||{});if(n&&_.isFunction(n.getAllResponseHeaders)){var k=n.getAllResponseHeaders();k=_.compact(k.split("\n"));k=_.map(k,function(o){return o.split(": ")});g.details.xhr.responseHeaders=_.object(k)}return g},_bePolite:function(g){g=g||_l("An error occurred while getting updates from the server");return g+". "+_l("Please contact a Galaxy administrator if the problem persists.")},loadCurrentHistory:function(h){var g=this;return this.loadHistoryWithHDADetails("current",h).then(function(j,i){g.trigger("current-history",g)})},switchToHistory:function(j,i){var g=this,h=function(){return jQuery.post(galaxy_config.root+"api/histories/"+j+"/set_as_current")};return this.loadHistoryWithHDADetails(j,i,h).then(function(l,k){g.trigger("switched-history",g)})},createNewHistory:function(i){if(!Galaxy||!Galaxy.currUser||Galaxy.currUser.isAnonymous()){this.displayMessage("error",_l("You must be logged in to create histories"));return $.when()}var g=this,h=function(){return jQuery.post(galaxy_config.root+"api/histories",{current:true})};return this.loadHistory(undefined,i,h).then(function(k,j){g.trigger("new-history",g)})},loadHistoryWithHDADetails:function(j,i,h,l){var g=this,k=function(m){return g.getExpandedHdaIds(m.id)};return this.loadHistory(j,i,h,l,k)},loadHistory:function(j,i,h,m,k){this.trigger("loading-history",this);i=i||{};var g=this;var l=f.History.getHistoryData(j,{historyFn:h,hdaFn:m,hdaDetailIds:i.initiallyExpanded||k});return this._loadHistoryFromXHR(l,i).fail(function(p,n,o){g.trigger("error",g,p,i,_l("An error was encountered while "+n),{historyId:j,history:o||{}})}).always(function(){g.trigger("loading-done",g)})},_loadHistoryFromXHR:function(i,h){var g=this;i.then(function(j,k){g.setModel(j,k,h)});i.fail(function(k,j){g.render()});return i},setModel:function(i,g,h){h=h||{};if(this.model){this.model.clearUpdateTimeout();this.stopListening(this.model);this.stopListening(this.model.hdas)}this.hdaViews={};if(Galaxy&&Galaxy.currUser){i.user=Galaxy.currUser.toJSON()}this.model=new f.History(i,g,h);this._setUpWebStorage(h.initiallyExpanded,h.show_deleted,h.show_hidden);this._setUpModelEventHandlers();this.trigger("new-model",this);this.render();return this},refreshHdas:function(h,g){if(this.model){return this.model.refresh(h,g)}return $.when()},_setUpWebStorage:function(h,g,i){this.storage=new c({id:c.historyStorageKey(this.model.get("id"))});if(_.isObject(h)){this.storage.set("exandedHdas",h)}if(_.isBoolean(g)){this.storage.set("show_deleted",g)}if(_.isBoolean(i)){this.storage.set("show_hidden",i)}this.trigger("new-storage",this.storage,this);this.log(this+" (init'd) storage:",this.storage.get())},clearWebStorage:function(){for(var g in sessionStorage){if(g.indexOf("history:")===0){sessionStorage.removeItem(g)}}},getStoredOptions:function(h){if(!h||h==="current"){return(this.storage)?(this.storage.get()):({})}var g=sessionStorage.getItem(c.historyStorageKey(h));return(g===null)?({}):(JSON.parse(g))},getExpandedHdaIds:function(g){var h=this.getStoredOptions(g).expandedHdas;return((_.isEmpty(h))?([]):(_.keys(h)))},_setUpModelEventHandlers:function(){this.model.on("error error:hdas",function(h,j,g,i){this.errorHandler(h,j,g,i)},this);this.model.on("change:nice_size",this.updateHistoryDiskSize,this);if(Galaxy&&Galaxy.quotaMeter){this.listenTo(this.model,"change:nice_size",function(){Galaxy.quotaMeter.update()})}this.model.hdas.on("add",this.addHdaView,this);this.model.hdas.on("change:deleted",this.handleHdaDeletionChange,this);this.model.hdas.on("change:visible",this.handleHdaVisibleChange,this);this.model.hdas.on("change:purged",function(g){this.model.fetch()},this);this.model.hdas.on("state:ready",function(h,i,g){if((!h.get("visible"))&&(!this.storage.get("show_hidden"))){this.removeHdaView(this.hdaViews[h.id])}},this)},addHdaView:function(j){this.log("add."+this,j);var h=this;if(!j.isVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"))){return}$({}).queue([function i(l){var k=h.$el.find(h.emptyMsgSelector);if(k.is(":visible")){k.fadeOut(h.fxSpeed,l)}else{l()}},function g(l){h.scrollToTop();var k=h.$el.find(h.datasetsSelector);h.createHdaView(j).$el.hide().prependTo(k).slideDown(h.fxSpeed)}])},createHdaView:function(i){var h=i.get("id"),g=this.storage.get("expandedHdas")[h],j=new this.HDAView({model:i,expanded:g,hasUser:this.model.hasUser(),logger:this.logger});this._setUpHdaListeners(j);this.hdaViews[h]=j;return j.render()},_setUpHdaListeners:function(h){var g=this;h.on("body-expanded",function(i){g.storage.addExpandedHda(i)});h.on("body-collapsed",function(i){g.storage.removeExpandedHda(i)});h.on("error",function(j,l,i,k){g.errorHandler(j,l,i,k)})},handleHdaDeletionChange:function(g){if(g.get("deleted")&&!this.storage.get("show_deleted")){this.removeHdaView(this.hdaViews[g.id])}},handleHdaVisibleChange:function(g){if(g.hidden()&&!this.storage.get("show_hidden")){this.removeHdaView(this.hdaViews[g.id])}},removeHdaView:function(h){if(!h){return}var g=this;h.$el.fadeOut(g.fxSpeed,function(){h.off();h.remove();delete g.hdaViews[h.model.id];if(_.isEmpty(g.hdaViews)){g.$el.find(g.emptyMsgSelector).fadeIn(g.fxSpeed,function(){g.trigger("empty-history",g)})}})},render:function(i,j){i=(i===undefined)?(this.fxSpeed):(i);var g=this,h;if(this.model){h=this.renderModel()}else{h=this.renderWithoutModel()}$(g).queue("fx",[function(k){if(i&&g.$el.is(":visible")){g.$el.fadeOut(i,k)}else{k()}},function(k){g.$el.empty();if(h){g.$el.append(h.children())}k()},function(k){if(i&&!g.$el.is(":visible")){g.$el.fadeIn(i,k)}else{k()}},function(k){if(j){j.call(this)}g.trigger("rendered",this);k()}]);return this},renderWithoutModel:function(){var g=$("<div/>"),h=$("<div/>").addClass("message-container").css({"margin-left":"4px","margin-right":"4px"});return g.append(h)},renderModel:function(){var g=$("<div/>");if(!Galaxy||!Galaxy.currUser||Galaxy.currUser.isAnonymous()){g.append(d.templates.anonHistoryPanel(this.model.toJSON()))}else{g.append(d.templates.historyPanel(this.model.toJSON()));this._renderTags(g);this._renderAnnotation(g)}this._setUpBehaviours(g);this.renderHdas(g);return g},_renderTags:function(g){this.tagsEditor=new TagsEditor({model:this.model,el:g.find(".history-controls .tags-display"),onshowFirstTime:function(){this.render()},$activator:faIconButton({title:_l("Edit history tags"),classes:"history-tag-btn",faIcon:"fa-tags"}).appendTo(g.find(".history-secondary-actions"))})},_renderAnnotation:function(g){this.annotationEditor=new AnnotationEditor({model:this.model,el:g.find(".history-controls .annotation-display"),onshowFirstTime:function(){this.render()},$activator:faIconButton({title:_l("Edit history tags"),classes:"history-annotate-btn",faIcon:"fa-comment"}).appendTo(g.find(".history-secondary-actions"))})},_setUpBehaviours:function(g){g=g||this.$el;g.find("[title]").tooltip({placement:"bottom"});if(!this.model||!Galaxy.currUser||Galaxy.currUser.isAnonymous()){return}var h=this;g.find(".history-name").make_text_editable({on_finish:function(i){g.find(".history-name").text(i);h.model.save({name:i}).fail(function(){g.find(".history-name").text(h.model.previous("name"))})}})},renderHdas:function(i){i=i||this.$el;this.hdaViews={};var h=this,g=i.find(this.datasetsSelector),j=this.model.hdas.getVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"),this.filters);g.empty();if(j.length){j.each(function(k){g.prepend(h.createHdaView(k).$el)});i.find(this.emptyMsgSelector).hide()}else{i.find(this.emptyMsgSelector).show()}return this.hdaViews},events:{"click .message-container":"clearMessages"},updateHistoryDiskSize:function(){this.$el.find(".history-size").text(this.model.get("nice_size"))},collapseAllHdaBodies:function(){_.each(this.hdaViews,function(g){g.toggleBodyVisibility(null,false)});this.storage.set("expandedHdas",{})},toggleShowDeleted:function(){this.storage.set("show_deleted",!this.storage.get("show_deleted"));this.render();return this.storage.get("show_deleted")},toggleShowHidden:function(){this.storage.set("show_hidden",!this.storage.get("show_hidden"));this.render();return this.storage.get("show_hidden")},renderSearchControls:function(){var g=this;g.model.hdas.fetchAllDetails({silent:true});function i(j){g.searchFor=j;g.filters=[function(k){return k.matchesAll(g.searchFor)}];g.trigger("search:searching",j,g);g.renderHdas()}function h(){g.searchFor="";g.filters=[];g.trigger("search:clear",g);g.renderHdas()}return searchInput({initialVal:g.searchFor,name:"history-search",placeholder:"search datasets",classes:"history-search",onsearch:i,onclear:h}).addClass("history-search-controls").css("padding","0px 0px 8px 0px")},toggleSearchControls:function(){var g=this.$el.find(".history-search-controls");if(!g.size()){g=this.renderSearchControls().hide();this.$el.find(".history-title").before(g)}g.slideToggle(this.fxSpeed)},showSelect:function(g){_.each(this.hdaViews,function(h){h.showSelect(g)})},hideSelect:function(g){_.each(this.hdaViews,function(h){h.hideSelect(g)})},getSelectedHdaViews:function(){return _.filter(this.hdaViews,function(g){return g.selected})},showLoadingIndicator:function(h,g,i){g=(g!==undefined)?(g):(this.fxSpeed);if(!this.indicator){this.indicator=new LoadingIndicator(this.$el,this.$el.parent())}if(!this.$el.is(":visible")){this.indicator.show(0,i)}else{this.$el.fadeOut(g);this.indicator.show(h,g,i)}},hideLoadingIndicator:function(g,h){g=(g!==undefined)?(g):(this.fxSpeed);if(this.indicator){this.indicator.hide(g,h)}},displayMessage:function(l,m,k){var i=this;this.scrollToTop();var j=this.$el.find(this.msgsSelector),g=$("<div/>").addClass(l+"message").html(m);if(!_.isEmpty(k)){var h=$('<a href="javascript:void(0)">Details</a>').click(function(){Galaxy.modal.show(i.messageToModalOptions(l,m,k));return false});g.append(" ",h)}return j.html(g)},messageToModalOptions:function(k,m,j){var g=this,l=$("<div/>"),i={title:"Details"};function h(n){n=_.omit(n,_.functions(n));return["<table>",_.map(n,function(p,o){p=(_.isObject(p))?(h(p)):(p);return'<tr><td style="vertical-align: top; color: grey">'+o+'</td><td style="padding-left: 8px">'+p+"</td></tr>"}).join(""),"</table>"].join("")}if(_.isObject(j)){i.body=l.append(h(j))}else{i.body=l.html(j)}i.buttons={Ok:function(){Galaxy.modal.hide();g.clearMessages()}};return i},clearMessages:function(){var g=this.$el.find(this.msgsSelector);g.empty()},scrollPosition:function(){return this.$el.parent().scrollTop()},scrollTo:function(g){this.$el.parent().scrollTop(g)},scrollToTop:function(){this.$el.parent().scrollTop(0);return this},scrollIntoView:function(h,i){if(!i){this.$el.parent().parent().scrollTop(h);return this}var g=window,j=this.$el.parent().parent(),l=$(g).innerHeight(),k=(l/2)-(i/2);$(j).scrollTop(h-k);return this},scrollToId:function(h){if((!h)||(!this.hdaViews[h])){return this}var g=this.hdaViews[h].$el;this.scrollIntoView(g.offset().top,g.outerHeight());return this},scrollToHid:function(g){var h=this.model.hdas.getByHid(g);if(!h){return this}return this.scrollToId(h.id)},connectToQuotaMeter:function(g){if(!g){return this}this.listenTo(g,"quota:over",this.showQuotaMessage);this.listenTo(g,"quota:under",this.hideQuotaMessage);this.on("rendered rendered:initial",function(){if(g&&g.isOverQuota()){this.showQuotaMessage()}});return this},showQuotaMessage:function(){var g=this.$el.find(".quota-message");if(g.is(":hidden")){g.slideDown(this.fxSpeed)}},hideQuotaMessage:function(){var g=this.$el.find(".quota-message");if(!g.is(":hidden")){g.slideUp(this.fxSpeed)}},connectToOptionsMenu:function(g){if(!g){return this}this.on("new-storage",function(i,h){if(g&&i){g.findItemByHtml(_l("Include Deleted Datasets")).checked=i.get("show_deleted");g.findItemByHtml(_l("Include Hidden Datasets")).checked=i.get("show_hidden")}});return this},toString:function(){return"HistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});d.templates={historyPanel:Handlebars.templates["template-history-historyPanel"],anonHistoryPanel:Handlebars.templates["template-history-historyPanel-anon"]};return{HistoryPanel:d}});
\ No newline at end of file
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.
1
0
commit/galaxy-central: Dave Bouvier: Fix the update manager functional test.
by commits-noreply@bitbucket.org 25 Nov '13
by commits-noreply@bitbucket.org 25 Nov '13
25 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/0e1d539dcfcb/
Changeset: 0e1d539dcfcb
User: Dave Bouvier
Date: 2013-11-25 19:50:32
Summary: Fix the update manager functional test.
Affected #: 1 file
diff -r d37d6e711d671763d725ffb4931f0acc379964dc -r 0e1d539dcfcb3246f144258514a43e07a514b52e test/tool_shed/functional/test_1410_update_manager.py
--- a/test/tool_shed/functional/test_1410_update_manager.py
+++ b/test/tool_shed/functional/test_1410_update_manager.py
@@ -123,6 +123,12 @@
self.galaxy_login( email=common.admin_email, username=common.admin_username )
repository = test_db_util.get_repository_by_name_and_owner( repository_name, common.test_user_1_name )
self.update_tool_shed_status()
- strings_displayed = [ '"%s"><img src="/static/images/icon_warning_sml.gif"' % self.security.encode_id( repository.id ) ]
+ ok_icon = '/static/june_2007_style/blue/ok_small.png'
+ ok_title = 'This is the latest installable revision of this repository'
+ updates_icon = '/static/images/icon_warning_sml.gif'
+ repository_id = self.security.encode_id( repository.id )
+ html = '<label id="%s" for="%s"><img src="%s" class="icon-button" title="%s"/><img src="%s' % \
+ ( repository_id, repository_id, ok_icon, ok_title, updates_icon )
+ strings_displayed = [ html ]
self.display_galaxy_browse_repositories_page( strings_displayed=strings_displayed )
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.
1
0
3 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/55d684093172/
Changeset: 55d684093172
User: Dave Bouvier
Date: 2013-11-25 19:01:44
Summary: Fix for importing repositories.
Affected #: 1 file
diff -r 8ae8e19ea0762af833558f75b84fe19840c6e783 -r 55d684093172360d6329349337313da202e94108 lib/tool_shed/util/import_util.py
--- a/lib/tool_shed/util/import_util.py
+++ b/lib/tool_shed/util/import_util.py
@@ -164,7 +164,7 @@
# No repository with the specified name and owner currently exists, so make sure the current user can create one.
if trans.user_is_admin():
repository_info_dict[ 'status' ] = None
- elif trans.app.security_agent.user_can_import_repository_archive( trans.user, owner ):
+ elif trans.app.security_agent.user_can_import_repository_archive( trans.user, repository_info_dict[ 'owner' ] ):
repository_info_dict[ 'status' ] = None
else:
repository_info_dict[ 'status' ] = 'Not authorized to import'
https://bitbucket.org/galaxy/galaxy-central/commits/398287552d91/
Changeset: 398287552d91
User: Dave Bouvier
Date: 2013-11-25 19:02:09
Summary: Functional tests for importing and exporting repositories.
Affected #: 3 files
diff -r 55d684093172360d6329349337313da202e94108 -r 398287552d91093721ea0de635ed6b0d7c7cd147 test/tool_shed/test_data/repository_capsules/0490_filtering.tar.gz
Binary file test/tool_shed/test_data/repository_capsules/0490_filtering.tar.gz has changed
diff -r 55d684093172360d6329349337313da202e94108 -r 398287552d91093721ea0de635ed6b0d7c7cd147 test/tool_shed/test_data/repository_capsules/0500_emboss_5.tar.gz
Binary file test/tool_shed/test_data/repository_capsules/0500_emboss_5.tar.gz has changed
diff -r 55d684093172360d6329349337313da202e94108 -r 398287552d91093721ea0de635ed6b0d7c7cd147 test/tool_shed/test_data/repository_capsules/0510_trans_proteomic_pipeline.tar.gz
Binary file test/tool_shed/test_data/repository_capsules/0510_trans_proteomic_pipeline.tar.gz has changed
https://bitbucket.org/galaxy/galaxy-central/commits/d37d6e711d67/
Changeset: d37d6e711d67
User: Dave Bouvier
Date: 2013-11-25 19:02:09
Summary: Functional tests for importing and exporting repositories.
Affected #: 5 files
diff -r 398287552d91093721ea0de635ed6b0d7c7cd147 -r d37d6e711d671763d725ffb4931f0acc379964dc test/tool_shed/base/twilltestcase.py
--- a/test/tool_shed/base/twilltestcase.py
+++ b/test/tool_shed/base/twilltestcase.py
@@ -4,6 +4,7 @@
import re
import test_db_util
import simplejson
+import shutil
import logging
import time
import tempfile
@@ -12,6 +13,7 @@
import galaxy.model as galaxy_model
import galaxy.util as util
from tool_shed.util import shed_util_common as suc
+from tool_shed.util import xml_util
from base.twilltestcase import tc, from_json_string, TwillTestCase, security, urllib
from tool_shed.util.encoding_util import tool_shed_encode, tool_shed_decode
@@ -98,6 +100,16 @@
self.check_repository_changelog( repository )
self.check_string_count_in_page( 'Repository metadata is associated with this change set.', metadata_count )
+ def check_exported_repository_dependency( self, dependency_filename, repository_name, repository_owner ):
+ root, error_message = xml_util.parse_xml( dependency_filename )
+ for elem in root.findall( 'repository' ):
+ if 'changeset_revision' in elem:
+ raise AssertionError( 'Exported repository %s with owner %s has a dependency with a defined changeset revision.' % \
+ ( repository_name, repository_owner ) )
+ if 'toolshed' in elem:
+ raise AssertionError( 'Exported repository %s with owner %s has a dependency with a defined tool shed.' % \
+ ( repository_name, repository_owner ) )
+
def check_for_valid_tools( self, repository, strings_displayed=[], strings_not_displayed=[] ):
strings_displayed.append( 'Valid tools' )
self.display_manage_repository_page( repository, strings_displayed, strings_not_displayed )
@@ -144,6 +156,24 @@
self.visit_galaxy_url( url )
self.check_for_strings( strings_displayed, strings_not_displayed )
+ def check_manifest( self, manifest_filepath, owner=None ):
+ root, error_message = xml_util.parse_xml( manifest_filepath )
+ for elem in root.findall( 'repository' ):
+ repository_name = elem.get( 'name' )
+ manifest_owner = elem.get( 'username' )
+ if owner is not None:
+ assert manifest_owner == owner, 'Expected repository %s to be owned by %s, but found %s' % \
+ ( elem.get( 'name' ), owner, manifest_owner )
+ toolshed = elem.get( 'toolshed' )
+ changeset_revision = elem.get( 'changeset_revision' )
+ assert toolshed is None, 'Repository definition %s has a tool shed attribute %s.' % ( repository_name, toolshed )
+ assert changeset_revision is None, 'Repository definition %s specifies a changeset revision %s.' % \
+ ( repository_name, changeset_revision )
+ repository_archive = elem.find( 'archive' ).text
+ filepath, filename = os.path.split( manifest_filepath )
+ repository_path = os.path.join( filepath, repository_archive )
+ self.verify_repository_in_capsule( repository_path, repository_name, owner )
+
def check_repository_changelog( self, repository, strings_displayed=[], strings_not_displayed=[] ):
url = '/repository/view_changelog?id=%s' % self.security.encode_id( repository.id )
self.visit_url( url )
@@ -1207,6 +1237,15 @@
tc.submit( "upload_button" )
self.check_for_strings( strings_displayed, strings_not_displayed )
+ def verify_capsule_contents( self, capsule_filepath, owner ):
+ tar_object = tarfile.open( capsule_filepath, 'r:*' )
+ extraction_path = tempfile.mkdtemp()
+ tar_object.extractall( extraction_path )
+ for root, dirs, files in os.walk( extraction_path ):
+ if 'manifest.xml' in files:
+ self.check_manifest( os.path.join( root, 'manifest.xml' ), owner=owner )
+ shutil.rmtree( extraction_path )
+
def verify_installed_repositories( self, installed_repositories=[], uninstalled_repositories=[] ):
for repository_name, repository_owner in installed_repositories:
galaxy_repository = test_db_util.get_installed_repository_by_name_owner( repository_name, repository_owner )
@@ -1279,6 +1318,17 @@
# or we know that the repository was not correctly installed!
assert found, 'No entry for %s in %s.' % ( required_data_table_entry, self.shed_tool_data_table_conf )
+ def verify_repository_in_capsule( self, repository_archive, repository_name, repository_owner ):
+ repository_extraction_dir = tempfile.mkdtemp()
+ repository_tar_object = tarfile.open( repository_archive, 'r:*' )
+ repository_tar_object.extractall( repository_extraction_dir )
+ for root, dirs, files in os.walk( repository_extraction_dir ):
+ for filename in files:
+ if filename in [ 'tool_dependencies.xml', 'repository_dependencies.xml' ]:
+ dependency_filepath = os.path.join( root, filename )
+ self.check_exported_repository_dependency( dependency_filepath, repository_name, repository_owner )
+ shutil.rmtree( repository_extraction_dir )
+
def verify_repository_reviews( self, repository, reviewer=None, strings_displayed=[], strings_not_displayed=[] ):
changeset_revision = self.get_repository_tip( repository )
# Verify that the currently logged in user has a repository review for the specified repository, reviewer, and changeset revision.
diff -r 398287552d91093721ea0de635ed6b0d7c7cd147 -r d37d6e711d671763d725ffb4931f0acc379964dc test/tool_shed/functional/test_0490_export_import_repositories.py
--- /dev/null
+++ b/test/tool_shed/functional/test_0490_export_import_repositories.py
@@ -0,0 +1,90 @@
+from tool_shed.base.twilltestcase import ShedTwillTestCase, common, os
+import tool_shed.base.test_db_util as test_db_util
+
+import logging
+log = logging.getLogger( __name__ )
+
+repository_name = 'filtering_0490'
+repository_description = "Galaxy's filtering tool for test 0490"
+repository_long_description = "Long description of Galaxy's filtering tool for test 0490"
+
+category_name = 'Test 0490 Repository Import Export'
+category_description = 'Test script 0490 for importing and exporting single repositories.'
+
+'''
+First test:
+
+1. Import a repository capsule containing a repository with no dependencies, e.g. filter1.
+2. Check that the repository to be imported is not marked as preexisting. The word ' Exists' should not be displayed, but '<b>Exists</b>' will.
+3. Export that repository. Check the capsule's contents, verify that changeset revision and tool shed are not set.
+4. Import the capsule again. Check that the repository to be imported is marked as preexisting. The word ' Exists' should be
+ displayed, as will '<b>Exists</b>'.
+
+'''
+
+class TestExportImportRepository( ShedTwillTestCase ):
+ '''Test exporting and importing repositories.'''
+
+ def test_0000_initiate_users( self ):
+ """Create necessary user accounts and login as an admin user."""
+ self.logout()
+ self.login( email=common.test_user_1_email, username=common.test_user_1_name )
+ test_user_1 = test_db_util.get_user( common.test_user_1_email )
+ assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email
+ test_user_1_private_role = test_db_util.get_private_role( test_user_1 )
+ self.logout()
+ self.login( email=common.admin_email, username=common.admin_username )
+ admin_user = test_db_util.get_user( common.admin_email )
+ assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email
+ admin_user_private_role = test_db_util.get_private_role( admin_user )
+
+ def test_0005_import_repository_capsule( self ):
+ """Import the filter_0490 repository capsule."""
+ '''
+ This is step 1 - Import a repository capsule containing a repository with no dependencies, e.g. filter1.
+ Check that the repository to be imported is not marked as preexisting. The string ' Exists' should not
+ be displayed, but '<b>Exists</b>' should.
+ '''
+ self.logout()
+ self.login( email=common.admin_email, username=common.admin_username )
+ self.create_category( name=category_name, description=category_description )
+ self.logout()
+ self.login( email=common.test_user_1_email, username=common.test_user_1_name )
+ self.import_capsule( self.get_filename( 'repository_capsules/0490_filtering.tar.gz' ),
+ strings_displayed=[ repository_name, '<b>Exists' ],
+ strings_not_displayed=[ ' Exists' ],
+ strings_displayed_after_submit=[ 'Repository <b>filtering_0490</b> has been created.' ],
+ strings_not_displayed_after_submit=[ 'Import not necessary' ] )
+
+ def test_0010_export_repository_capsule( self ):
+ '''Export the repository that was imported in the previous step.'''
+ '''
+ This is step 2 - Export that repository.
+ Export the repository to a temporary location.
+ '''
+ global capsule_filepath
+ repository = test_db_util.get_repository_by_name_and_owner( repository_name, common.test_user_1_name )
+ capsule_filepath = self.export_capsule( repository )
+ log.debug( os.path.exists( capsule_filepath ) )
+
+ def test_0015_verify_exported_capsule( self ):
+ '''Verify the exported capsule contents.'''
+ '''
+ This is step 3 - Check the capsule's contents, verify that changeset revision and tool shed are not set.
+ Extract the exported capsule tarball to a temporary path, and confirm that the manifest does not specify
+ a tool shed or changeset revision.
+ '''
+ global capsule_filepath
+ self.verify_capsule_contents( capsule_filepath, owner=common.test_user_1_name )
+
+ def test_0020_import_repository_capsule( self ):
+ '''Import the exported repository capsule.'''
+ '''
+ This is step 4 - Import the capsule again. Check that the repository to be imported is marked as preexisting.
+ The string ' Exists' should be displayed, as should '<b>Exists</b>'.
+ '''
+ global capsule_filepath
+ self.import_capsule( capsule_filepath,
+ strings_displayed=[ repository_name, ' Exists', self.url ],
+ strings_not_displayed_after_submit=[ 'Repository <b>filtering_0490</b> has been created.' ],
+ strings_displayed_after_submit=[ 'Import not necessary', 'Exists' ] )
diff -r 398287552d91093721ea0de635ed6b0d7c7cd147 -r d37d6e711d671763d725ffb4931f0acc379964dc test/tool_shed/functional/test_0500_export_repository_simple_dependency.py
--- /dev/null
+++ b/test/tool_shed/functional/test_0500_export_repository_simple_dependency.py
@@ -0,0 +1,89 @@
+from tool_shed.base.twilltestcase import ShedTwillTestCase, common, os
+import tool_shed.base.test_db_util as test_db_util
+
+import logging
+log = logging.getLogger( __name__ )
+
+emboss_repository_name = 'emboss_5_0500'
+emboss_repository_description = "Galaxy wrappers for Emboss version 5.0.0 tools"
+emboss_repository_long_description = "Galaxy wrappers for Emboss version 5.0.0 tools"
+datatypes_repository_name = 'emboss_datatypes_0500'
+datatypes_repository_description = 'Galaxy applicable data formats used by Emboss tools.'
+datatypes_repository_long_description = 'Galaxy applicable data formats used by Emboss tools. This repository contains no tools.'
+
+category_name = 'Test 0500 Repository Dependency Import Export'
+category_description = 'Test script 0500 for importing and exporting repositories with simple repository dependencies.'
+
+'''
+1. Export a repository with no dependencies, e.g. filter1.
+2. Temporarily extract the repository capsule.
+2a. For every owner in the manifest, set to a different user.
+3. Import it into the same tool shed.
+4. Check that the repository to be imported has no status in the status column.
+5. Click the import button.
+6. Verify the resulting page is correct.
+'''
+
+class TestExportImportRepository( ShedTwillTestCase ):
+ '''Test exporting and importing repositories.'''
+
+ def test_0000_initiate_users( self ):
+ """Create necessary user accounts and login as an admin user."""
+ self.logout()
+ self.login( email=common.test_user_1_email, username=common.test_user_1_name )
+ test_user_1 = test_db_util.get_user( common.test_user_1_email )
+ assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email
+ test_user_1_private_role = test_db_util.get_private_role( test_user_1 )
+ self.logout()
+ self.login( email=common.admin_email, username=common.admin_username )
+ admin_user = test_db_util.get_user( common.admin_email )
+ assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email
+ admin_user_private_role = test_db_util.get_private_role( admin_user )
+
+ def test_0005_create_category_and_repository( self ):
+ """Create categories for this test suite"""
+ self.logout()
+ self.login( email=common.admin_email, username=common.admin_username )
+ self.create_category( name=category_name, description=category_description )
+ self.logout()
+ self.login( email=common.test_user_1_email, username=common.test_user_1_name )
+ self.import_capsule( self.get_filename( 'repository_capsules/0500_emboss_5.tar.gz' ),
+ strings_displayed=[ emboss_repository_name, datatypes_repository_name, '<b>Exists' ],
+ strings_not_displayed=[ ' Exists' ],
+ strings_displayed_after_submit=[ 'Repository <b>emboss_5_0500</b> has been created.',
+ 'Repository <b>emboss_datatypes_0500</b> has been created.' ],
+ strings_not_displayed_after_submit=[ 'Import not necessary' ] )
+
+ def test_0010_export_repository_capsule( self ):
+ '''Export the repository that was imported in the previous step.'''
+ '''
+ This is step 2 - Export that repository.
+ Export the repository to a temporary location.
+ '''
+ global capsule_filepath
+ repository = test_db_util.get_repository_by_name_and_owner( emboss_repository_name, common.test_user_1_name )
+ capsule_filepath = self.export_capsule( repository )
+ log.debug( os.path.exists( capsule_filepath ) )
+
+ def test_0015_verify_exported_capsule( self ):
+ '''Verify the exported capsule contents.'''
+ '''
+ This is step 3 - Check the capsule's contents, verify that changeset revision and tool shed are not set.
+ Extract the exported capsule tarball to a temporary path, and confirm that the manifest does not specify
+ a tool shed or changeset revision.
+ '''
+ global capsule_filepath
+ self.verify_capsule_contents( capsule_filepath, owner=common.test_user_1_name )
+
+ def test_0020_import_repository_capsule( self ):
+ '''Import the exported repository capsule.'''
+ '''
+ This is step 4 - Import the capsule again. Check that the repository to be imported is marked as preexisting.
+ The string ' Exists' should be displayed, as should '<b>Exists</b>'.
+ '''
+ global capsule_filepath
+ self.import_capsule( capsule_filepath,
+ strings_displayed=[ emboss_repository_name, datatypes_repository_name, ' Exists', self.url ],
+ strings_not_displayed_after_submit=[ 'Repository <b>emboss_5_0500</b> has been created.',
+ 'Repository <b>emboss_datatypes_0500</b> has been created.' ],
+ strings_displayed_after_submit=[ 'Import not necessary', ' Exists' ] )
diff -r 398287552d91093721ea0de635ed6b0d7c7cd147 -r d37d6e711d671763d725ffb4931f0acc379964dc test/tool_shed/functional/test_0510_export_import_repository_complex_dependencies.py
--- /dev/null
+++ b/test/tool_shed/functional/test_0510_export_import_repository_complex_dependencies.py
@@ -0,0 +1,99 @@
+from tool_shed.base.twilltestcase import ShedTwillTestCase, common, os
+import tool_shed.base.test_db_util as test_db_util
+
+import logging
+log = logging.getLogger( __name__ )
+
+category_name = 'Test 0510 Import Export Complex Dependencies'
+category_description = 'Test script 0510 for importing and exporting repositories with complex repository dependencies.'
+
+'''
+Import a repository capsule with a complex repository dependency with trans_proteomic_pipeline and required repositories.
+Check that the repository to be imported is not marked as preexisting. The word ' Exists' should not be displayed, but '<b>Exists</b>' will.
+Click the import button.
+Verify the resulting page is correct.
+Verify the dependency structure that has been created.
+Export the trans_proteomic_pipeline repository with dependencies.
+Check the capsule's contents, verify that changeset revision and tool shed are not set.
+'''
+
+class TestExportImportRepository( ShedTwillTestCase ):
+ '''Test exporting and importing repositories with complex dependencies.'''
+
+ def test_0000_initiate_users( self ):
+ """Create necessary user accounts and login as an admin user."""
+ self.logout()
+ self.login( email=common.test_user_1_email, username=common.test_user_1_name )
+ test_user_1 = test_db_util.get_user( common.test_user_1_email )
+ assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email
+ test_user_1_private_role = test_db_util.get_private_role( test_user_1 )
+ self.logout()
+ self.login( email=common.admin_email, username=common.admin_username )
+ admin_user = test_db_util.get_user( common.admin_email )
+ assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email
+ admin_user_private_role = test_db_util.get_private_role( admin_user )
+
+ def test_0005_create_category_and_repositories( self ):
+ """Create categories for this test suite"""
+ self.logout()
+ self.login( email=common.admin_email, username=common.admin_username )
+ self.create_category( name=category_name, description=category_description )
+ self.logout()
+ self.login( email=common.test_user_1_email, username=common.test_user_1_name )
+ self.import_capsule( self.get_filename( 'repository_capsules/0510_trans_proteomic_pipeline.tar.gz' ),
+ strings_displayed=[ 'package_trans_proteomic_pipeline_4_6_3',
+ 'package_perl_5_18',
+ 'package_libpng_1_2',
+ 'package_libgd_2_1',
+ 'package_expat_2_1',
+ '<b>Exists' ],
+ strings_not_displayed=[ ' Exists' ],
+ strings_displayed_after_submit=[ 'Repository <b>package_trans_proteomic_pipeline_4_6_3</b> has been created.',
+ 'Repository <b>package_perl_5_18</b> has been created.',
+ 'Repository <b>package_libpng_1_2</b> has been created.',
+ 'Repository <b>package_libgd_2_1</b> has been created.',
+ 'Repository <b>package_expat_2_1</b> has been created.' ],
+ strings_not_displayed_after_submit=[ 'Import not necessary' ] )
+
+ def test_0010_export_repository_capsule( self ):
+ '''Export the repository that was imported in the previous step.'''
+ '''
+ This is step 2 - Export that repository.
+ Export the repository to a temporary location.
+ '''
+ global capsule_filepath
+ repository = test_db_util.get_repository_by_name_and_owner( 'package_trans_proteomic_pipeline_4_6_3', common.test_user_1_name )
+ capsule_filepath = self.export_capsule( repository )
+ log.debug( os.path.exists( capsule_filepath ) )
+
+ def test_0015_verify_exported_capsule( self ):
+ '''Verify the exported capsule contents.'''
+ '''
+ This is step 3 - Check the capsule's contents, verify that changeset revision and tool shed are not set.
+ Extract the exported capsule tarball to a temporary path, and confirm that the manifest does not specify
+ a tool shed or changeset revision.
+ '''
+ global capsule_filepath
+ self.verify_capsule_contents( capsule_filepath, owner=common.test_user_1_name )
+
+ def test_0020_import_repository_capsule( self ):
+ '''Import the exported repository capsule.'''
+ '''
+ This is step 4 - Import the capsule again. Check that the repository to be imported is marked as preexisting.
+ The string ' Exists' should be displayed, as should '<b>Exists</b>'.
+ '''
+ global capsule_filepath
+ self.import_capsule( capsule_filepath,
+ strings_displayed=[ 'package_trans_proteomic_pipeline_4_6_3',
+ 'package_perl_5_18',
+ 'package_libpng_1_2',
+ 'package_libgd_2_1',
+ 'package_expat_2_1',
+ ' Exists',
+ self.url ],
+ strings_not_displayed_after_submit=[ 'Repository <b>package_trans_proteomic_pipeline_4_6_3</b> has been created.',
+ 'Repository <b>package_perl_5_18</b> has been created.',
+ 'Repository <b>package_libpng_1_2</b> has been created.',
+ 'Repository <b>package_libgd_2_1</b> has been created.',
+ 'Repository <b>package_expat_2_1</b> has been created.' ],
+ strings_displayed_after_submit=[ 'Import not necessary', ' Exists' ] )
diff -r 398287552d91093721ea0de635ed6b0d7c7cd147 -r d37d6e711d671763d725ffb4931f0acc379964dc test/tool_shed/functional_tests.py
--- a/test/tool_shed/functional_tests.py
+++ b/test/tool_shed/functional_tests.py
@@ -92,8 +92,9 @@
tool_sheds_conf_xml_template = '''<?xml version="1.0"?><tool_sheds>
+ <tool_shed name="Galaxy main tool shed" url="http://toolshed.g2.bx.psu.edu/"/>
+ <tool_shed name="Galaxy test tool shed" url="http://testtoolshed.g2.bx.psu.edu/"/><tool_shed name="Embedded tool shed for functional tests" url="http://${shed_url}:${shed_port}/"/>
- <tool_shed name="Galaxy main tool shed" url="http://toolshed.g2.bx.psu.edu/"/></tool_sheds>
'''
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.
1
0
commit/galaxy-central: Dave Bouvier: Handle cases where installed_repostory_dict has a converter_path or display_path set to None.
by commits-noreply@bitbucket.org 25 Nov '13
by commits-noreply@bitbucket.org 25 Nov '13
25 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/8ae8e19ea076/
Changeset: 8ae8e19ea076
User: Dave Bouvier
Date: 2013-11-25 18:36:34
Summary: Handle cases where installed_repostory_dict has a converter_path or display_path set to None.
Affected #: 2 files
diff -r 6997fa059319b288877cf0728ac20fbb57e80dee -r 8ae8e19ea0762af833558f75b84fe19840c6e783 lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
--- a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
+++ b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
@@ -231,10 +231,13 @@
if tool_shed_repository.includes_datatypes:
# Deactivate proprietary datatypes.
installed_repository_dict = datatype_util.load_installed_datatypes( trans.app, tool_shed_repository, repository_install_dir, deactivate=True )
- if installed_repository_dict and 'converter_path' in installed_repository_dict:
- datatype_util.load_installed_datatype_converters( trans.app, installed_repository_dict, deactivate=True )
- if installed_repository_dict and 'display_path' in installed_repository_dict:
- datatype_util.load_installed_display_applications( trans.app, installed_repository_dict, deactivate=True )
+ if installed_repository_dict:
+ converter_path = installed_repository_dict.get( 'converter_path' )
+ if converter_path is not None:
+ datatype_util.load_installed_datatype_converters( trans.app, installed_repository_dict, deactivate=True )
+ display_path = installed_repository_dict.get( 'display_path' )
+ if display_path is not None:
+ datatype_util.load_installed_display_applications( trans.app, installed_repository_dict, deactivate=True )
if remove_from_disk_checked:
try:
# Remove the repository from disk.
diff -r 6997fa059319b288877cf0728ac20fbb57e80dee -r 8ae8e19ea0762af833558f75b84fe19840c6e783 lib/tool_shed/util/common_install_util.py
--- a/lib/tool_shed/util/common_install_util.py
+++ b/lib/tool_shed/util/common_install_util.py
@@ -61,10 +61,13 @@
repository_install_dir = os.path.abspath( relative_install_dir )
# Activate proprietary datatypes.
installed_repository_dict = datatype_util.load_installed_datatypes( trans.app, repository, repository_install_dir, deactivate=False )
- if installed_repository_dict and 'converter_path' in installed_repository_dict:
- datatype_util.load_installed_datatype_converters( trans.app, installed_repository_dict, deactivate=False )
- if installed_repository_dict and 'display_path' in installed_repository_dict:
- datatype_util.load_installed_display_applications( trans.app, installed_repository_dict, deactivate=False )
+ if installed_repository_dict:
+ converter_path = installed_repository_dict.get( 'converter_path' )
+ if converter_path is not None:
+ datatype_util.load_installed_datatype_converters( trans.app, installed_repository_dict, deactivate=False )
+ display_path = installed_repository_dict.get( 'display_path' )
+ if display_path is not None:
+ datatype_util.load_installed_display_applications( trans.app, installed_repository_dict, deactivate=False )
def get_dependencies_for_repository( trans, tool_shed_url, repo_info_dict, includes_tool_dependencies ):
"""
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.
1
0