galaxy-commits
Threads by month
- ----- 2026 -----
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 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
- 15302 discussions
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
commit/galaxy-central: afgane: Fix tool_panel_section id retrieval (affected installation of tools via the API into an existing tool panel)
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/6997fa059319/
Changeset: 6997fa059319
User: afgane
Date: 2013-11-25 17:56:54
Summary: Fix tool_panel_section id retrieval (affected installation of tools via the API into an existing tool panel)
Affected #: 1 file
diff -r 87086657a2f4dbd44a2377f550fa6573876a8006 -r 6997fa059319b288877cf0728ac20fbb57e80dee lib/tool_shed/util/tool_util.py
--- a/lib/tool_shed/util/tool_util.py
+++ b/lib/tool_shed/util/tool_util.py
@@ -673,7 +673,7 @@
tool_panel_section_id=section_id,
new_tool_panel_section=new_tool_panel_section )
elif tool_panel_section:
- tool_panel_section_key = 'section_%s' % str( tool_panel_section )
+ tool_panel_section_key = 'section_%s' % str( tool_panel_section.id )
tool_section = trans.app.toolbox.tool_panel[ tool_panel_section_key ]
else:
return None, None
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: jmchilton: Update datatypes.data:display_data's doc per Peter Cock's suggestion.
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/87086657a2f4/
Changeset: 87086657a2f4
User: jmchilton
Date: 2013-11-25 16:47:18
Summary: Update datatypes.data:display_data's doc per Peter Cock's suggestion.
Affected #: 1 file
diff -r 35cc1687eb7b348811bf9e4f6e9d4374b00b6f09 -r 87086657a2f4dbd44a2377f550fa6573876a8006 lib/galaxy/datatypes/data.py
--- a/lib/galaxy/datatypes/data.py
+++ b/lib/galaxy/datatypes/data.py
@@ -288,7 +288,14 @@
return open( dataset.file_name )
def display_data(self, trans, data, preview=False, filename=None, to_ext=None, size=None, offset=None, **kwd):
- """ Old display method, for transition """
+ """ Old display method, for transition - though still used by API and
+ test framework. Datatypes should be very careful if overridding this
+ method and this interface between datatypes and Galaxy will likely
+ change.
+
+ TOOD: Document alternatives to overridding this method (data
+ providers?).
+ """
#Relocate all composite datatype display to a common location.
composite_extensions = trans.app.datatypes_registry.get_composite_extensions( )
composite_extensions.append('html') # for archiving composite datatypes
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/583c64d963d4/
Changeset: 583c64d963d4
User: jmchilton
Date: 2013-11-25 16:23:26
Summary: Allow <metabolite>, <metadata>, <metagenome>, etc... in Galaxy XML content.
Affected #: 1 file
diff -r 9165deb8008461d43107c2b1cd99b750bcb0508f -r 583c64d963d41c7e38f76e2be23531b160ec972f lib/galaxy/datatypes/checkers.py
--- a/lib/galaxy/datatypes/checkers.py
+++ b/lib/galaxy/datatypes/checkers.py
@@ -32,7 +32,7 @@
regexp1 = re.compile( "<A\s+[^>]*HREF[^>]+>", re.I )
regexp2 = re.compile( "<IFRAME[^>]*>", re.I )
regexp3 = re.compile( "<FRAMESET[^>]*>", re.I )
- regexp4 = re.compile( "<META[^>]*>", re.I )
+ regexp4 = re.compile( "<META[\W][^>]*>", re.I )
regexp5 = re.compile( "<SCRIPT[^>]*>", re.I )
lineno = 0
for line in temp:
https://bitbucket.org/galaxy/galaxy-central/commits/35cc1687eb7b/
Changeset: 35cc1687eb7b
User: jmchilton
Date: 2013-11-25 16:23:26
Summary: checker.py - define constant for # of lines to check for HTML.
Affected #: 1 file
diff -r 583c64d963d41c7e38f76e2be23531b160ec972f -r 35cc1687eb7b348811bf9e4f6e9d4374b00b6f09 lib/galaxy/datatypes/checkers.py
--- a/lib/galaxy/datatypes/checkers.py
+++ b/lib/galaxy/datatypes/checkers.py
@@ -2,6 +2,8 @@
from galaxy import util
from StringIO import StringIO
+HTML_CHECK_LINES = 100
+
try:
import Image as PIL
except ImportError:
@@ -35,6 +37,8 @@
regexp4 = re.compile( "<META[\W][^>]*>", re.I )
regexp5 = re.compile( "<SCRIPT[^>]*>", re.I )
lineno = 0
+ # TODO: Potentially reading huge lines into string here, this should be
+ # reworked.
for line in temp:
lineno += 1
matches = regexp1.search( line ) or regexp2.search( line ) or regexp3.search( line ) or regexp4.search( line ) or regexp5.search( line )
@@ -42,7 +46,7 @@
if chunk is None:
temp.close()
return True
- if lineno > 100:
+ if HTML_CHECK_LINES and (lineno > HTML_CHECK_LINES):
break
if chunk is None:
temp.close()
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
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/9165deb80084/
Changeset: 9165deb80084
User: guerler
Date: 2013-11-25 15:25:31
Summary: Pack scripts
Affected #: 2 files
diff -r 5dfc0b3bf0351e7274cd3a5bdeab921752215973 -r 9165deb8008461d43107c2b1cd99b750bcb0508f static/scripts/packed/galaxy.grids.js
--- a/static/scripts/packed/galaxy.grids.js
+++ b/static/scripts/packed/galaxy.grids.js
@@ -1,1 +1,1 @@
-jQuery.ajaxSettings.traditional=true;var Grid=Backbone.Model.extend({defaults:{url_base:"",async:false,async_ops:[],categorical_filters:[],filters:{},sort_key:null,show_item_checkboxes:false,cur_page:1,num_pages:1,operation:undefined,item_ids:undefined},can_async_op:function(a){return _.indexOf(this.attributes.async_ops,a)!==-1},add_filter:function(e,f,b){if(b){var c=this.attributes.filters[e],a;if(c===null||c===undefined){a=f}else{if(typeof(c)=="string"){if(c=="All"){a=f}else{var d=[];d[0]=c;d[1]=f;a=d}}else{a=c;a.push(f)}}this.attributes.filters[e]=a}else{this.attributes.filters[e]=f}},remove_filter:function(b,e){var a=this.attributes.filters[b];if(a===null||a===undefined){return false}var d=true;if(typeof(a)==="string"){if(a=="All"){d=false}else{delete this.attributes.filters[b]}}else{var c=_.indexOf(a,e);if(c!==-1){a.splice(c,1)}else{d=false}}return d},get_url_data:function(){var a={async:this.attributes.async,sort:this.attributes.sort_key,page:this.attributes.cur_page,show_item_checkboxes:this.attributes.show_item_checkboxes};if(this.attributes.operation){a.operation=this.attributes.operation}if(this.attributes.item_ids){a.id=this.attributes.item_ids}var b=this;_.each(_.pairs(b.attributes.filters),function(c){a["f-"+c[0]]=c[1]});return a}});var GridView=Backbone.View.extend({grid:null,initialize:function(a){this.grid=a;this.init_grid_elements();this.init_grid_controls();$("input[type=text]").each(function(){$(this).click(function(){$(this).select()}).keyup(function(){$(this).css("font-style","normal")})})},init_grid_controls:function(){$(".submit-image").each(function(){$(this).mousedown(function(){$(this).addClass("gray-background")});$(this).mouseup(function(){$(this).removeClass("gray-background")})});var a=this;$(".sort-link").each(function(){$(this).click(function(){a.set_sort_condition($(this).attr("sort_key"));return false})});$(".page-link > a").each(function(){$(this).click(function(){a.set_page($(this).attr("page_num"));return false})});$(".categorical-filter > a").each(function(){$(this).click(function(){a.set_categorical_filter($(this).attr("filter_key"),$(this).attr("filter_val"));return false})});$(".text-filter-form").each(function(){$(this).submit(function(){var e=$(this).attr("column_key");var d=$("#input-"+e+"-filter");var f=d.val();d.val("");a.add_filter_condition(e,f,true);return false})});var b=$("#input-tags-filter");if(b.length){b.autocomplete(this.grid.history_tag_autocomplete_url,{selectFirst:false,autoFill:false,highlight:false,mustMatch:false})}var c=$("#input-name-filter");if(c.length){c.autocomplete(this.grid.history_name_autocomplete_url,{selectFirst:false,autoFill:false,highlight:false,mustMatch:false})}$(".advanced-search-toggle").each(function(){$(this).click(function(){$("#standard-search").slideToggle("fast");$("#advanced-search").slideToggle("fast");return false})})},init_grid_elements:function(){$(".grid").each(function(){var c=$(this).find("input.grid-row-select-checkbox");var b=$(this).find("span.grid-selected-count");var d=function(){b.text($(c).filter(":checked").length)};$(c).each(function(){$(this).change(d)});d()});var a=this;$(".label").each(function(){var b=$(this).attr("href");if(b!==undefined&&b.indexOf("operation=")!=-1){$(this).click(function(){a.do_operation_from_href($(this).attr("href"));return false})}});if($(".community_rating_star").length!==0){$(".community_rating_star").rating({})}make_popup_menus()},go_page_one:function(){var a=this.grid.get("cur_page");if(a!==null&&a!==undefined&&a!=="all"){this.grid.set("cur_page",1)}},add_filter_condition:function(d,f,a){if(f===""){return false}this.grid.add_filter(d,f,a);var e=$("<span>"+f+"<a href='javascript:void(0);'><span class='delete-search-icon' /></a></span>");e.addClass("text-filter-val");var c=this;e.click(function(){c.grid.remove_filter(d,f);$(this).remove();c.go_page_one();c.update_grid()});var b=$("#"+d+"-filtering-criteria");b.append(e);this.go_page_one();this.update_grid()},set_sort_condition:function(f){var e=this.grid.get("sort_key");var d=f;if(e.indexOf(f)!==-1){if(e.substring(0,1)!=="-"){d="-"+f}else{}}$(".sort-arrow").remove();var c=(d.substring(0,1)=="-")?"↑":"↓";var a=$("<span>"+c+"</span>").addClass("sort-arrow");var b=$("#"+f+"-header");b.append(a);this.grid.set("sort_key",d);this.go_page_one();this.update_grid()},set_categorical_filter:function(c,e){var b=this.grid.get("categorical_filters")[c],d=this.grid.get("filters")[c];var a=this;$("."+c+"-filter").each(function(){var i=$.trim($(this).text());var g=b[i];var h=g[c];if(h==e){$(this).empty();$(this).addClass("current-filter");$(this).append(i)}else{if(h==d){$(this).empty();var f=$("<a href='#'>"+i+"</a>");f.click(function(){a.set_categorical_filter(c,h)});$(this).removeClass("current-filter");$(this).append(f)}}});this.grid.add_filter(c,e);this.go_page_one();this.update_grid()},set_page:function(a){var b=this;$(".page-link").each(function(){var h=$(this).attr("id"),f=parseInt(h.split("-")[2],10),d=b.grid.get("cur_page"),g;if(f===a){g=$(this).children().text();$(this).empty();$(this).addClass("inactive-link");$(this).text(g)}else{if(f===d){g=$(this).text();$(this).empty();$(this).removeClass("inactive-link");var e=$("<a href='#'>"+g+"</a>");e.click(function(){set_page(f)});$(this).append(e)}}});var c=true;if(a==="all"){this.grid.set("cur_page",a);c=false}else{this.grid.set("cur_page",parseInt(a,10))}this.update_grid(c)},do_operation:function(b,a){b=b.toLowerCase();this.grid.set({operation:b,item_ids:a});if(this.grid.can_async_op(b)){this.update_grid(true)}else{this.go_to_URL()}},do_operation_from_href:function(c){var f=c.split("?");if(f.length>1){var a=f[1];var e=a.split("&");var b=null;var g=-1;for(var d=0;d<e.length;d++){if(e[d].indexOf("operation")!=-1){b=e[d].split("=")[1]}else{if(e[d].indexOf("id")!=-1){g=e[d].split("=")[1]}}}this.do_operation(b,g);return false}},go_to_URL:function(){this.grid.set("async",false);window.location=this.grid.get("url_base")+"?"+$.param(this.grid.get_url_data());this.grid.set({operation:undefined,item_ids:undefined})},update_grid:function(b){if(!this.grid.get("async")){this.go_to_URL();return}var c=(this.grid.get("operation")?"POST":"GET");$(".loading-elt-overlay").show();var a=this;$.ajax({type:c,url:a.grid.get("url_base"),data:a.grid.get_url_data(),error:function(){alert("Grid refresh failed")},success:function(e){var d=e.split("*****");$("#grid-table-body").html(d[0]);$("#grid-table-footer").html(d[1]);$("#grid-table-body").trigger("update");a.init_grid_elements();make_popup_menus();$(".loading-elt-overlay").hide();var f=$.trim(d[2]);if(f!==""){$("#grid-message").html(f).show();setTimeout(function(){$("#grid-message").hide()},5000)}},complete:function(){a.grid.set({operation:undefined,item_ids:undefined})}})},check_all_items:function(){var a=document.getElementById("check_all"),b=document.getElementsByTagName("input"),d=0,c;if(a.checked===true){for(c=0;c<b.length;c++){if(b[c].name.indexOf("id")!==-1){b[c].checked=true;d++}}}else{for(c=0;c<b.length;c++){if(b[c].name.indexOf("id")!==-1){b[c].checked=false}}}this.init_grid_elements()},submit_operation:function(d,e){var c=$('input[name="id"]:checked').length;if(!c>0){return false}if(e!="None"&&e!=""){if(!confirm(e)){return false}}var b=$(d).val();var a=[];$("input[name=id]:checked").each(function(){a.push($(this).val())});this.do_operation(b,a);return true}});
\ No newline at end of file
+jQuery.ajaxSettings.traditional=true;define(["mvc/ui"],function(){var a=Backbone.Model.extend({defaults:{url_base:"",async:false,async_ops:[],categorical_filters:[],filters:{},sort_key:null,show_item_checkboxes:false,cur_page:1,num_pages:1,operation:undefined,item_ids:undefined},can_async_op:function(c){return _.indexOf(this.attributes.async_ops,c)!==-1},add_filter:function(g,h,d){if(d){var e=this.attributes.filters[g],c;if(e===null||e===undefined){c=h}else{if(typeof(e)=="string"){if(e=="All"){c=h}else{var f=[];f[0]=e;f[1]=h;c=f}}else{c=e;c.push(h)}}this.attributes.filters[g]=c}else{this.attributes.filters[g]=h}},remove_filter:function(d,g){var c=this.attributes.filters[d];if(c===null||c===undefined){return false}var f=true;if(typeof(c)==="string"){if(c=="All"){f=false}else{delete this.attributes.filters[d]}}else{var e=_.indexOf(c,g);if(e!==-1){c.splice(e,1)}else{f=false}}return f},get_url_data:function(){var c={async:this.attributes.async,sort:this.attributes.sort_key,page:this.attributes.cur_page,show_item_checkboxes:this.attributes.show_item_checkboxes};if(this.attributes.operation){c.operation=this.attributes.operation}if(this.attributes.item_ids){c.id=this.attributes.item_ids}var d=this;_.each(_.pairs(d.attributes.filters),function(e){c["f-"+e[0]]=e[1]});return c}});var b=Backbone.View.extend({grid:null,initialize:function(c){this.init_grid(c);this.init_grid_controls();$("input[type=text]").each(function(){$(this).click(function(){$(this).select()}).keyup(function(){$(this).css("font-style","normal")})})},init_grid:function(c){this.grid=c;this.init_grid_elements()},init_grid_controls:function(){$(".submit-image").each(function(){$(this).mousedown(function(){$(this).addClass("gray-background")});$(this).mouseup(function(){$(this).removeClass("gray-background")})});var c=this;$(".sort-link").each(function(){$(this).click(function(){c.set_sort_condition($(this).attr("sort_key"));return false})});$(".categorical-filter > a").each(function(){$(this).click(function(){c.set_categorical_filter($(this).attr("filter_key"),$(this).attr("filter_val"));return false})});$(".text-filter-form").each(function(){$(this).submit(function(){var g=$(this).attr("column_key");var f=$("#input-"+g+"-filter");var h=f.val();f.val("");c.add_filter_condition(g,h,true);return false})});var d=$("#input-tags-filter");if(d.length){d.autocomplete(this.grid.history_tag_autocomplete_url,{selectFirst:false,autoFill:false,highlight:false,mustMatch:false})}var e=$("#input-name-filter");if(e.length){e.autocomplete(this.grid.history_name_autocomplete_url,{selectFirst:false,autoFill:false,highlight:false,mustMatch:false})}$(".advanced-search-toggle").each(function(){$(this).click(function(){$("#standard-search").slideToggle("fast");$("#advanced-search").slideToggle("fast");return false})})},init_grid_elements:function(){$(".grid").each(function(){var j=$(this).find("input.grid-row-select-checkbox");var i=$(this).find("span.grid-selected-count");var q=function(){i.text($(j).filter(":checked").length)};$(j).each(function(){$(this).change(q)});q()});if($(".community_rating_star").length!==0){$(".community_rating_star").rating({})}var p=this.grid.attributes;var o=this;$(".page-link > a").each(function(){$(this).click(function(){o.set_page($(this).attr("page_num"));return false})});$(".use-inbound").each(function(){$(this).click(function(i){o.execute({href:$(this).attr("href"),inbound:true});return false})});$(".use-outbound").each(function(){$(this).click(function(i){o.execute({href:$(this).attr("href")});return false})});for(var h in p.items){var k=$("#grid-"+h+"-popup");k.off();var d=new PopupMenu(k);var n=p.items[h];for(var g in p.operations){var e=p.operations[g];var l=e.label;var c=n.operation_config[l];var f=n.encode_id;if(c.allowed&&e.allow_popup){var m={html:e.label,href:c.url_args,target:c.target,confirmation_text:e.confirm,inbound:e.inbound};m.func=function(q){q.preventDefault();var j=$(q.target).html();var i=this.findItemByHtml(j);o.execute(i)};d.addItem(m)}}}},add_filter_condition:function(f,h,c){if(h===""){return false}this.grid.add_filter(f,h,c);var g=$("<span>"+h+"<a href='javascript:void(0);'><span class='delete-search-icon' /></a></span>");g.addClass("text-filter-val");var e=this;g.click(function(){e.grid.remove_filter(f,h);$(this).remove();e.go_page_one();e.execute()});var d=$("#"+f+"-filtering-criteria");d.append(g);this.go_page_one();this.execute()},set_sort_condition:function(h){var g=this.grid.get("sort_key");var f=h;if(g.indexOf(h)!==-1){if(g.substring(0,1)!=="-"){f="-"+h}else{}}$(".sort-arrow").remove();var e=(f.substring(0,1)=="-")?"↑":"↓";var c=$("<span>"+e+"</span>").addClass("sort-arrow");var d=$("#"+h+"-header");d.append(c);this.grid.set("sort_key",f);this.go_page_one();this.execute()},set_categorical_filter:function(e,g){var d=this.grid.get("categorical_filters")[e],f=this.grid.get("filters")[e];var c=this;$("."+e+"-filter").each(function(){var k=$.trim($(this).text());var i=d[k];var j=i[e];if(j==g){$(this).empty();$(this).addClass("current-filter");$(this).append(k)}else{if(j==f){$(this).empty();var h=$("<a href='#'>"+k+"</a>");h.click(function(){c.set_categorical_filter(e,j)});$(this).removeClass("current-filter");$(this).append(h)}}});this.grid.add_filter(e,g);this.go_page_one();this.execute()},set_page:function(c){var d=this;$(".page-link").each(function(){var i=$(this).attr("id"),g=parseInt(i.split("-")[2],10),e=d.grid.get("cur_page"),h;if(g===c){h=$(this).children().text();$(this).empty();$(this).addClass("inactive-link");$(this).text(h)}else{if(g===e){h=$(this).text();$(this).empty();$(this).removeClass("inactive-link");var f=$("<a href='#'>"+h+"</a>");f.click(function(){d.set_page(g)});$(this).append(f)}}});if(c==="all"){this.grid.set("cur_page",c)}else{this.grid.set("cur_page",parseInt(c,10))}this.execute()},submit_operation:function(f,g){var e=$('input[name="id"]:checked').length;if(!e>0){return false}var d=$(f).val();var c=[];$("input[name=id]:checked").each(function(){c.push($(this).val())});this.execute({operation:d,id:c,confirmation_text:g});return true},execute:function(l){var f=null;var e=null;var g=null;var c=null;var k=null;if(l){e=l.href;g=l.operation;f=l.id;c=l.confirmation_text;k=l.inbound;if(e!==undefined&&e.indexOf("operation=")!=-1){var j=e.split("?");if(j.length>1){var i=j[1];var d=i.split("&");for(var h=0;h<d.length;h++){if(d[h].indexOf("operation")!=-1){g=d[h].split("=")[1];g=g.replace(/\+/g," ")}else{if(d[h].indexOf("id")!=-1){f=d[h].split("=")[1]}}}}}}if(g&&f){if(c&&c!=""&&c!="None"){if(!confirm(c)){return false}}g=g.toLowerCase();this.grid.set({operation:g,item_ids:f});if(this.grid.can_async_op(g)){this.update_grid()}else{this.go_to(k,"")}return false}if(e){this.go_to(k,e);return false}if(this.grid.get("async")){this.update_grid()}else{this.go_to(k,"")}return false},go_to:function(f,d){var e=this.grid.get("async");this.grid.set("async",false);if(!d){d=this.grid.get("url_base")+"?"+$.param(this.grid.get_url_data())}this.grid.set({operation:undefined,item_ids:undefined,async:e});if(f){var c=$(".grid-header").closest(".inbound");if(c.length!==0){c.load(d);return}}window.location=d},update_grid:function(){var d=(this.grid.get("operation")?"POST":"GET");$(".loading-elt-overlay").show();var c=this;$.ajax({type:d,url:c.grid.get("url_base"),data:c.grid.get_url_data(),error:function(e){alert("Grid refresh failed")},success:function(f){var e=f.split("*****");$("#grid-table-body").html(e[0]);$("#grid-table-footer").html(e[1]);$("#grid-table-body").trigger("update");$(".loading-elt-overlay").hide();var g=$.trim(e[2]);if(g!==""){$("#grid-message").html(g).show();setTimeout(function(){$("#grid-message").hide()},5000)}},complete:function(){c.grid.set({operation:undefined,item_ids:undefined})}})},check_all_items:function(){var c=document.getElementById("check_all"),d=document.getElementsByTagName("input"),f=0,e;if(c.checked===true){for(e=0;e<d.length;e++){if(d[e].name.indexOf("id")!==-1){d[e].checked=true;f++}}}else{for(e=0;e<d.length;e++){if(d[e].name.indexOf("id")!==-1){d[e].checked=false}}}this.init_grid_elements()},go_page_one:function(){var c=this.grid.get("cur_page");if(c!==null&&c!==undefined&&c!=="all"){this.grid.set("cur_page",1)}}});return{Grid:a,GridView:b}});
\ No newline at end of file
diff -r 5dfc0b3bf0351e7274cd3a5bdeab921752215973 -r 9165deb8008461d43107c2b1cd99b750bcb0508f 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").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
+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
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
25 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/5dfc0b3bf035/
Changeset: 5dfc0b3bf035
User: guerler
Date: 2013-11-25 06:16:41
Summary: Fix tagging mako
Affected #: 1 file
diff -r 6d8062a02641e8be1d1df7b9e87519662ac9c2d5 -r 5dfc0b3bf0351e7274cd3a5bdeab921752215973 templates/tagging_common.mako
--- a/templates/tagging_common.mako
+++ b/templates/tagging_common.mako
@@ -135,7 +135,6 @@
## Build script that augments tags using progressive javascript.
<script type="text/javascript">
- $(function() {
//
// Set up autocomplete tagger.
//
@@ -213,8 +212,6 @@
};
$('#${elt_id}').autocomplete_tagging(options);
-
- });
</script>
## Use style to hide/display the tag area.
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
23 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/6d8062a02641/
Changeset: 6d8062a02641
User: guerler
Date: 2013-11-23 23:02:46
Summary: Grids: Fix for toolshed
Affected #: 2 files
diff -r 59c4b30557cd889472ad7162b1f1b5be3e01973a -r 6d8062a02641e8be1d1df7b9e87519662ac9c2d5 templates/webapps/tool_shed/category/grid.mako
--- a/templates/webapps/tool_shed/category/grid.mako
+++ b/templates/webapps/tool_shed/category/grid.mako
@@ -7,6 +7,7 @@
## TODO: This is very similar to this directory's valid_grid.mako, so see if we can re-use this code in a better way.
<%def name="render_grid_header( grid, repo_grid, render_title=True)">
${init()}
+ ${grid_javascripts()}
<div class="grid-header">
%if render_title:
${grid_title()}
diff -r 59c4b30557cd889472ad7162b1f1b5be3e01973a -r 6d8062a02641e8be1d1df7b9e87519662ac9c2d5 templates/webapps/tool_shed/category/valid_grid.mako
--- a/templates/webapps/tool_shed/category/valid_grid.mako
+++ b/templates/webapps/tool_shed/category/valid_grid.mako
@@ -6,6 +6,7 @@
## Render grid header.
<%def name="render_grid_header( grid, repo_grid, render_title=True)">
${init()}
+ ${grid_javascripts()}
<div class="grid-header">
%if render_title:
${grid_title()}
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
23 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/59c4b30557cd/
Changeset: 59c4b30557cd
User: guerler
Date: 2013-11-23 22:49:54
Summary: Grids: Fix for Toolshed
Affected #: 2 files
diff -r 3f630f92f5983c28e1aedff312e7ff7e598fe23c -r 59c4b30557cd889472ad7162b1f1b5be3e01973a templates/webapps/tool_shed/category/grid.mako
--- a/templates/webapps/tool_shed/category/grid.mako
+++ b/templates/webapps/tool_shed/category/grid.mako
@@ -48,7 +48,7 @@
${render_grid_table( grid, show_item_checkboxes )}
</%def>
-<%def name="grid_body( grid )">
+<%def name="grid_body()"><%
from tool_shed.grids.repository_grids import RepositoryGrid
repo_grid = RepositoryGrid()
diff -r 3f630f92f5983c28e1aedff312e7ff7e598fe23c -r 59c4b30557cd889472ad7162b1f1b5be3e01973a templates/webapps/tool_shed/category/valid_grid.mako
--- a/templates/webapps/tool_shed/category/valid_grid.mako
+++ b/templates/webapps/tool_shed/category/valid_grid.mako
@@ -47,7 +47,7 @@
${render_grid_table( grid, show_item_checkboxes )}
</%def>
-<%def name="grid_body( grid )">
+<%def name="grid_body()"><%
from tool_shed.grids.repository_grids import ValidRepositoryGrid
repo_grid = ValidRepositoryGrid()
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: Grids: Unify operation handling, use new popups, refactor, bug fixes
by commits-noreply@bitbucket.org 23 Nov '13
by commits-noreply@bitbucket.org 23 Nov '13
23 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/3f630f92f598/
Changeset: 3f630f92f598
User: guerler
Date: 2013-11-23 22:14:59
Summary: Grids: Unify operation handling, use new popups, refactor, bug fixes
Affected #: 19 files
diff -r 82e91d215acf573d96d3d377620ed8815368c86d -r 3f630f92f5983c28e1aedff312e7ff7e598fe23c lib/galaxy/web/framework/helpers/grids.py
--- a/lib/galaxy/web/framework/helpers/grids.py
+++ b/lib/galaxy/web/framework/helpers/grids.py
@@ -323,7 +323,7 @@
def __init__( self, label, key=None, model_class=None, method=None, format=None, \
link=None, attach_popup=False, visible=True, nowrap=False, \
# Valid values for filterable are ['standard', 'advanced', None]
- filterable=None, sortable=True, label_id_prefix=None ):
+ filterable=None, sortable=True, label_id_prefix=None, inbound=False ):
"""Create a grid column."""
self.label = label
self.key = key
@@ -331,6 +331,7 @@
self.method = method
self.format = format
self.link = link
+ self.inbound = inbound
self.nowrap = nowrap
self.attach_popup = attach_popup
self.visible = visible
@@ -734,7 +735,7 @@
class GridOperation( object ):
def __init__( self, label, key=None, condition=None, allow_multiple=True, allow_popup=True,
target=None, url_args=None, async_compatible=False, confirm=None,
- global_operation=None ):
+ global_operation=None, inbound=False ):
self.label = label
self.key = key
self.allow_multiple = allow_multiple
@@ -743,6 +744,7 @@
self.target = target
self.url_args = url_args
self.async_compatible = async_compatible
+ self.inbound = inbound
# if 'confirm' is set, then ask before completing the operation
self.confirm = confirm
# specify a general operation that acts on the full grid
@@ -772,9 +774,10 @@
return { 'action' : 'display_by_username_and_slug', 'username' : item.user.username, 'slug' : item.slug }
class GridAction( object ):
- def __init__( self, label=None, url_args=None ):
+ def __init__( self, label=None, url_args=None, inbound=False ):
self.label = label
self.url_args = url_args
+ self.inbound = inbound
class GridColumnFilter( object ):
def __init__( self, label, args=None ):
diff -r 82e91d215acf573d96d3d377620ed8815368c86d -r 3f630f92f5983c28e1aedff312e7ff7e598fe23c lib/galaxy/webapps/galaxy/controllers/dataset.py
--- a/lib/galaxy/webapps/galaxy/controllers/dataset.py
+++ b/lib/galaxy/webapps/galaxy/controllers/dataset.py
@@ -99,8 +99,8 @@
columns = [
grids.TextColumn( "Name", key="name",
# Link name to dataset's history.
- link=( lambda item: iff( item.history.deleted, None, dict( operation="switch", id=item.id ) ) ), filterable="advanced", attach_popup=True ),
- HistoryColumn( "History", key="history", sortable=False,
+ link=( lambda item: iff( item.history.deleted, None, dict( operation="switch", id=item.id ) ) ), filterable="advanced", attach_popup=True, inbound=True ),
+ HistoryColumn( "History", key="history", sortable=False, inbound=True,
link=( lambda item: iff( item.history.deleted, None, dict( operation="switch_history", id=item.id ) ) ) ),
grids.IndividualTagsColumn( "Tags", key="tags", model_tag_association_class=model.HistoryDatasetAssociationTagAssociation, filterable="advanced", grid_name="HistoryDatasetAssocationListGrid" ),
StatusColumn( "Status", key="deleted", attach_popup=False ),
diff -r 82e91d215acf573d96d3d377620ed8815368c86d -r 3f630f92f5983c28e1aedff312e7ff7e598fe23c lib/galaxy/webapps/galaxy/controllers/history.py
--- a/lib/galaxy/webapps/galaxy/controllers/history.py
+++ b/lib/galaxy/webapps/galaxy/controllers/history.py
@@ -34,14 +34,14 @@
for state in ( 'ok', 'running', 'queued', 'error' ):
count = state_count_dict.get( state, 0 )
if count:
- rval += '<div class="count-box state-color-%s">%s</div>' % (state, count)
+ rval += '<div class="count-box state-color-%s">%s</div> ' % (state, count)
return rval
class HistoryListNameColumn( NameColumn ):
def get_link( self, trans, grid, history ):
link = None
if not history.deleted:
- link = dict( operation="Switch", id=history.id, use_panels=grid.use_panels )
+ link = dict( operation="Switch", id=history.id, use_panels=grid.use_panels, async_compatible=True )
return link
@@ -85,10 +85,10 @@
key="free-text-search", visible=False, filterable="standard" )
)
operations = [
- grids.GridOperation( "Switch", allow_multiple=False, condition=( lambda item: not item.deleted ), async_compatible=False ),
- grids.GridOperation( "View", allow_multiple=False ),
+ grids.GridOperation( "Switch", allow_multiple=False, condition=( lambda item: not item.deleted ), async_compatible=True ),
+ grids.GridOperation( "View", allow_multiple=False, inbound=True ),
grids.GridOperation( "Share or Publish", allow_multiple=False, condition=( lambda item: not item.deleted ), async_compatible=False ),
- grids.GridOperation( "Rename", condition=( lambda item: not item.deleted ), async_compatible=False ),
+ grids.GridOperation( "Rename", condition=( lambda item: not item.deleted ), async_compatible=False, inbound=True ),
grids.GridOperation( "Delete", condition=( lambda item: not item.deleted ), async_compatible=True ),
grids.GridOperation( "Delete Permanently", condition=( lambda item: not item.purged ), confirm="History contents will be removed from disk, this cannot be undone. Continue?", async_compatible=True ),
grids.GridOperation( "Undelete", condition=( lambda item: item.deleted and not item.purged ), async_compatible=True ),
diff -r 82e91d215acf573d96d3d377620ed8815368c86d -r 3f630f92f5983c28e1aedff312e7ff7e598fe23c lib/galaxy/webapps/galaxy/controllers/page.py
--- a/lib/galaxy/webapps/galaxy/controllers/page.py
+++ b/lib/galaxy/webapps/galaxy/controllers/page.py
@@ -95,7 +95,6 @@
# Grid definition.
show_item_checkboxes = True
template = "/page/select_items_grid.mako"
- async_template = "/page/select_items_grid_async.mako"
default_filter = { "deleted" : "False" , "sharing" : "All" }
default_sort_key = "-update_time"
use_async = True
diff -r 82e91d215acf573d96d3d377620ed8815368c86d -r 3f630f92f5983c28e1aedff312e7ff7e598fe23c lib/galaxy/webapps/galaxy/controllers/visualization.py
--- a/lib/galaxy/webapps/galaxy/controllers/visualization.py
+++ b/lib/galaxy/webapps/galaxy/controllers/visualization.py
@@ -56,7 +56,7 @@
datasets_action = 'list_history_datasets'
datasets_param = "f-history"
columns = [
- NameColumn( "History Name", key="name", filterable="standard" ),
+ NameColumn( "History Name", key="name", filterable="standard", inbound=True ),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago, visible=False ),
DbKeyPlaceholderColumn( "Dbkey", key="dbkey", model_class=model.HistoryDatasetAssociation, visible=False )
]
@@ -77,7 +77,7 @@
datasets_action = 'list_library_datasets'
datasets_param = "f-library"
columns = [
- NameColumn( "Library Name", key="name", filterable="standard" )
+ NameColumn( "Library Name", key="name", filterable="standard", inbound=True )
]
num_rows_per_page = 10
use_async = True
@@ -196,15 +196,15 @@
key="free-text-search", visible=False, filterable="standard" )
)
global_actions = [
- grids.GridAction( "Create new visualization", dict( action='create' ) )
+ grids.GridAction( "Create new visualization", dict( action='create' ), inbound=True )
]
operations = [
grids.GridOperation( "Open", allow_multiple=False, url_args=get_url_args ),
grids.GridOperation( "Open in Circster", allow_multiple=False, condition=( lambda item: item.type == 'trackster' ), url_args=dict( action='circster' ) ),
- grids.GridOperation( "Edit Attributes", allow_multiple=False, url_args=dict( action='edit') ),
- grids.GridOperation( "Copy", allow_multiple=False, condition=( lambda item: not item.deleted ), async_compatible=False, url_args=dict( action='copy') ),
+ grids.GridOperation( "Edit Attributes", allow_multiple=False, url_args=dict( action='edit'), inbound=True),
+ grids.GridOperation( "Copy", allow_multiple=False, condition=( lambda item: not item.deleted )),
grids.GridOperation( "Share or Publish", allow_multiple=False, condition=( lambda item: not item.deleted ), async_compatible=False ),
- grids.GridOperation( "Delete", condition=( lambda item: not item.deleted ), async_compatible=True, confirm="Are you sure you want to delete this visualization?" ),
+ grids.GridOperation( "Delete", condition=( lambda item: not item.deleted ), confirm="Are you sure you want to delete this visualization?" ),
]
def apply_query_filter( self, trans, query, **kwargs ):
return query.filter_by( user=trans.user, deleted=False )
@@ -327,6 +327,7 @@
@web.expose
@web.require_login( "use Galaxy visualizations", use_panels=True )
def list( self, trans, *args, **kwargs ):
+
# Handle operation
if 'operation' in kwargs and 'id' in kwargs:
session = trans.sa_session
@@ -338,6 +339,8 @@
item.deleted = True
if operation == "share or publish":
return self.sharing( trans, **kwargs )
+ if operation == "copy":
+ self.copy( trans, **kwargs )
session.flush()
# Build list of visualizations shared with user.
@@ -350,8 +353,7 @@
.all()
return trans.fill_template( "visualization/list.mako", grid=self._user_list_grid( trans, *args, **kwargs ), shared_by_others=shared_by_others )
-
-
+
#
# -- Functions for operating on visualizations. --
#
@@ -364,7 +366,7 @@
@web.expose
@web.require_login()
- def copy(self, trans, id, *args, **kwargs):
+ def copy(self, trans, id, **kwargs):
visualization = self.get_visualization( trans, id, check_ownership=False )
user = trans.get_user()
owner = ( visualization.user == user )
@@ -381,7 +383,7 @@
# Display the management page
trans.set_message( 'Created new visualization with name "%s"' % copied_viz.title )
- return self.list( trans )
+ return
@web.expose
@web.require_login( "use Galaxy visualizations" )
diff -r 82e91d215acf573d96d3d377620ed8815368c86d -r 3f630f92f5983c28e1aedff312e7ff7e598fe23c static/scripts/galaxy.grids.js
--- a/static/scripts/galaxy.grids.js
+++ b/static/scripts/galaxy.grids.js
@@ -4,6 +4,9 @@
// not appended to the identifier of a nested array.
jQuery.ajaxSettings.traditional = true;
+// dependencies
+define(['mvc/ui'], function() {
+
/**
* A Galaxy grid.
*/
@@ -137,8 +140,7 @@
// Initialize
initialize: function(grid)
{
- this.grid = grid;
- this.init_grid_elements();
+ this.init_grid(grid);
this.init_grid_controls();
// Initialize text filters to select text on click and use normal font when user is typing.
@@ -147,7 +149,14 @@
.keyup(function () { $(this).css("font-style", "normal"); });
});
},
-
+
+ // Initialize
+ init_grid: function(grid)
+ {
+ this.grid = grid;
+ this.init_grid_elements();
+ },
+
// Initialize grid controls
init_grid_controls: function() {
// Initialize submit image elements.
@@ -174,14 +183,6 @@
});
});
- // Initialize page links.
- $('.page-link > a').each( function() {
- $(this).click( function() {
- self.set_page( $(this).attr('page_num') );
- return false;
- });
- });
-
// Initialize categorical filters.
$('.categorical-filter > a').each( function() {
$(this).click( function() {
@@ -227,7 +228,6 @@
// Initialize grid elements.
init_grid_elements : function() {
-
// Initialize grid selection checkboxes.
$(".grid").each( function() {
var checkboxes = $(this).find("input.grid-row-select-checkbox");
@@ -242,34 +242,94 @@
update_checked();
});
- // Initialize item labels.
- var self = this;
- $(".label").each( function() {
- // If href has an operation in it, do operation when clicked. Otherwise do nothing.
- var href = $(this).attr('href');
- if ( href !== undefined && href.indexOf('operation=') != -1 ) {
- $(this).click( function() {
- self.do_operation_from_href( $(this).attr('href') );
- return false;
- });
- }
- });
-
// Initialize ratings.
if ($('.community_rating_star').length !== 0)
$('.community_rating_star').rating({});
+
+ // get options
+ var options = this.grid.attributes;
+ var self = this;
- // Initialize item menu operations.
- make_popup_menus();
- },
-
- // Go back to page one; this is useful when a filter is applied.
- go_page_one: function () {
- // Need to go back to page 1 if not showing all.
- var cur_page = this.grid.get('cur_page');
- if (cur_page !== null && cur_page !== undefined && cur_page !== 'all') {
- this.grid.set('cur_page', 1);
- }
+ //
+ // add page click events
+ //
+ $('.page-link > a').each( function() {
+ $(this).click( function() {
+ self.set_page( $(this).attr('page_num') );
+ return false;
+ });
+ });
+
+ //
+ // add inbound/outbound events
+ //
+ $(".use-inbound").each( function() {
+ $(this).click( function(e) {
+ self.execute({
+ href : $(this).attr('href'),
+ inbound : true
+ });
+ return false;
+
+ });
+ });
+
+ $(".use-outbound").each( function() {
+ $(this).click( function(e) {
+ self.execute({
+ href : $(this).attr('href')
+ });
+ return false;
+ });
+ });
+
+ //
+ // add operation popup menus
+ //
+ for (var i in options['items'])
+ {
+ // get identifiers
+ var button = $('#grid-' + i + '-popup');
+ button.off();
+ var popup = new PopupMenu(button);
+
+ // load details
+ var item = options['items'][i];
+ for (var j in options['operations'])
+ {
+ // get operation details
+ var operation = options['operations'][j];
+ var operation_id = operation['label'];
+ var operation_settings = item['operation_config'][operation_id];
+ var encode_id = item['encode_id'];
+
+ // check
+ if (operation_settings['allowed'] && operation['allow_popup'])
+ {
+ // popup configuration
+ var popupConfig =
+ {
+ html : operation['label'],
+ href : operation_settings['url_args'],
+ target : operation_settings['target'],
+ confirmation_text : operation['confirm'],
+ inbound : operation['inbound']
+ };
+
+ // add popup function
+ popupConfig.func = function(e)
+ {
+ e.preventDefault();
+ var label = $(e.target).html();
+ var options = this.findItemByHtml(label);
+ self.execute(options);
+ };
+
+ // add item
+ popup.addItem(popupConfig);
+ }
+ }
+ }
},
// Add a condition to the grid filter; this adds the condition and refreshes the grid.
@@ -294,14 +354,14 @@
$(this).remove();
self.go_page_one();
- self.update_grid();
+ self.execute();
});
var container = $('#' + name + "-filtering-criteria");
container.append(t);
this.go_page_one();
- this.update_grid();
+ this.execute();
},
// Set sort condition for grid.
@@ -331,7 +391,7 @@
// Update grid.
this.grid.set('sort_key', new_sort);
this.go_page_one();
- this.update_grid();
+ this.execute();
},
// Set new value for categorical filter.
@@ -366,7 +426,7 @@
// Update grid.
this.grid.add_filter(name, new_value);
this.go_page_one();
- this.update_grid();
+ this.execute();
},
// Set page to view.
@@ -394,88 +454,160 @@
$(this).removeClass("inactive-link");
var t = $("<a href='#'>" + text + "</a>");
t.click(function() {
- set_page(page_num);
+ self.set_page(page_num);
});
$(this).append(t);
}
});
- var maintain_page_links = true;
if (new_page === "all") {
this.grid.set('cur_page', new_page);
- maintain_page_links = false;
} else {
this.grid.set('cur_page', parseInt(new_page, 10));
}
- this.update_grid(maintain_page_links);
+ this.execute();
},
- // Perform a grid operation.
- do_operation: function (operation, item_ids) {
- operation = operation.toLowerCase();
-
- // Update grid.
- this.grid.set({
- operation: operation,
- item_ids: item_ids
+ // confirmation/submission of operation request
+ submit_operation: function (selected_button, confirmation_text)
+ {
+ // verify in any item is selected
+ var number_of_checked_ids = $('input[name="id"]:checked').length;
+ if (!number_of_checked_ids > 0)
+ return false;
+
+ // collect ids
+ var operation_name = $(selected_button).val();
+ var item_ids = [];
+ $('input[name=id]:checked').each(function() {
+ item_ids.push( $(this).val() );
+ });
+ this.execute({
+ operation: operation_name,
+ id: item_ids,
+ confirmation_text: confirmation_text
});
- // Do operation. If operation cannot be performed asynchronously, redirect to location.
- if (this.grid.can_async_op(operation)) {
- this.update_grid(true);
+ // return
+ return true;
+ },
+
+ // execute operations and hyperlink requests
+ execute: function (options) {
+ // get url
+ var id = null;
+ var href = null;
+ var operation = null;
+ var confirmation_text = null;
+ var inbound = null;
+
+ // check for options
+ if (options)
+ {
+ // get options
+ href = options.href;
+ operation = options.operation;
+ id = options.id;
+ confirmation_text = options.confirmation_text;
+ inbound = options.inbound;
+
+ // check if input contains the operation tag
+ if (href !== undefined && href.indexOf('operation=') != -1) {
+ // Get operation, id in hyperlink's href.
+ var href_parts = href.split("?");
+ if (href_parts.length > 1) {
+ var href_parms_str = href_parts[1];
+ var href_parms = href_parms_str.split("&");
+ for (var index = 0; index < href_parms.length; index++) {
+ if (href_parms[index].indexOf('operation') != -1) {
+ // Found operation parm; get operation value.
+ operation = href_parms[index].split('=')[1];
+ operation = operation.replace (/\+/g, ' ');
+ } else if (href_parms[index].indexOf('id') != -1) {
+ // Found id parm; get id value.
+ id = href_parms[index].split('=')[1];
+ }
+ }
+ }
+ }
}
- else {
- this.go_to_URL();
+
+ // check for operation details
+ if (operation && id) {
+ // show confirmation box
+ if (confirmation_text && confirmation_text != '' && confirmation_text != 'None')
+ if(!confirm(confirmation_text))
+ return false;
+
+ // use small characters for operation?!
+ operation = operation.toLowerCase();
+
+ // Update grid.
+ this.grid.set({
+ operation: operation,
+ item_ids: id
+ });
+
+ // Do operation. If operation cannot be performed asynchronously, redirect to location.
+ if (this.grid.can_async_op(operation)) {
+ this.update_grid();
+ } else {
+ this.go_to(inbound, '');
+ }
+
+ // done
+ return false;
}
+
+ // check for href details
+ if (href)
+ {
+ this.go_to(inbound, href);
+ return false;
+ }
+
+ // refresh grid
+ if (this.grid.get('async')) {
+ this.update_grid();
+ } else {
+ this.go_to(inbound, '');
+ }
+
+ // done
+ return false;
},
- // Perform a hyperlink click that initiates an operation. If there is no operation, ignore click.
- do_operation_from_href: function (href) {
- // Get operation, id in hyperlink's href.
- var href_parts = href.split("?");
- if (href_parts.length > 1) {
- var href_parms_str = href_parts[1];
- var href_parms = href_parms_str.split("&");
- var operation = null;
- var id = -1;
- for (var index = 0; index < href_parms.length; index++) {
- if (href_parms[index].indexOf('operation') != -1) {
- // Found operation parm; get operation value.
- operation = href_parms[index].split('=')[1];
- } else if (href_parms[index].indexOf('id') != -1) {
- // Found id parm; get id value.
- id = href_parms[index].split('=')[1];
- }
- }
- // Do operation.
- this.do_operation(operation, id);
- return false;
- }
- },
-
- // Navigate window to the URL defined by url_args. This method can be used to short-circuit grid AJAXing.
- go_to_URL: function () {
- // Not async request.
+ // go to url
+ go_to: function (inbound, href) {
+
+ var async = this.grid.get('async');
this.grid.set('async', false);
- // Go.
- window.location = this.grid.get('url_base') + "?" + $.param(this.grid.get_url_data());
-
+ // get default url
+ if(!href)
+ href = this.grid.get('url_base') + "?" + $.param(this.grid.get_url_data());
+
// Clear grid of transient request attributes.
this.grid.set({
operation: undefined,
- item_ids: undefined
+ item_ids: undefined,
+ async: async
});
+
+ if (inbound) {
+ // this currently assumes that there is only a single grid shown at a time
+ var $div = $('.grid-header').closest('.inbound');
+ if ($div.length !== 0) {
+ $div.load(href);
+ return;
+ }
+ }
+
+ window.location = href;
},
// Update grid.
- update_grid: function (maintain_page_links) {
- // If grid is not using async, then go to URL.
- if (!this.grid.get('async')) {
- this.go_to_URL();
- return;
- }
-
+ update_grid: function () {
// If there's an operation, do POST; otherwise, do GET.
var method = (this.grid.get('operation') ? "POST" : "GET" );
$('.loading-elt-overlay').show(); // Show overlay to indicate loading and prevent user actions.
@@ -484,7 +616,7 @@
type: method,
url: self.grid.get('url_base'),
data: self.grid.get_url_data(),
- error: function() { alert( "Grid refresh failed" ); },
+ error: function(response) { alert( "Grid refresh failed" );},
success: function(response_text) {
// HACK: use a simple string to separate the elements in the
// response: (1) table body; (2) number of pages in table; and (3) message.
@@ -498,11 +630,7 @@
// Trigger custom event to indicate grid body has changed.
$('#grid-table-body').trigger('update');
-
- // Init grid.
- self.init_grid_elements();
- make_popup_menus();
-
+
// Hide loading overlay.
$('.loading-elt-overlay').hide();
@@ -546,29 +674,20 @@
}
this.init_grid_elements();
},
-
- // confirmation/submission of operation request
- submit_operation: function (selected_button, confirmation_text)
- {
- // verify in any item is selected
- var number_of_checked_ids = $('input[name="id"]:checked').length;
- if (!number_of_checked_ids > 0)
- return false;
-
- // show confirmation box
- if (confirmation_text != 'None' && confirmation_text != '')
- if(!confirm(confirmation_text))
- return false;
-
- // collect ids
- var operation_name = $(selected_button).val();
- var item_ids = [];
- $('input[name=id]:checked').each(function() {
- item_ids.push( $(this).val() );
- });
- this.do_operation(operation_name, item_ids);
-
- // return
- return true;
+
+ // Go back to page one; this is useful when a filter is applied.
+ go_page_one: function () {
+ // Need to go back to page 1 if not showing all.
+ var cur_page = this.grid.get('cur_page');
+ if (cur_page !== null && cur_page !== undefined && cur_page !== 'all') {
+ this.grid.set('cur_page', 1);
+ }
}
});
+
+return {
+ Grid : Grid,
+ GridView : GridView
+};
+
+});
\ No newline at end of file
diff -r 82e91d215acf573d96d3d377620ed8815368c86d -r 3f630f92f5983c28e1aedff312e7ff7e598fe23c 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' ).click( function( event ){
+ $( this ).children( 'a.popupmenu-option' ).mousedown( 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( "click.close_popup", function(){
+ $elClicked.one( "mousedown.close_popup", function(){
menu.remove();
});
};
diff -r 82e91d215acf573d96d3d377620ed8815368c86d -r 3f630f92f5983c28e1aedff312e7ff7e598fe23c templates/admin/requests/sample_datasets_grid.mako
--- a/templates/admin/requests/sample_datasets_grid.mako
+++ b/templates/admin/requests/sample_datasets_grid.mako
@@ -2,8 +2,8 @@
<%namespace file="/requests/common/common.mako" import="common_javascripts" /><%namespace file="/requests/common/common.mako" import="transfer_status_updater" />
-<%def name="javascripts()">
- ${parent.javascripts()}
- ${common_javascripts()}
- ${transfer_status_updater()}
+<%def name="load()">
+ ${parent.load()}
+ ${common_javascripts()}
+ ${transfer_status_updater()}
</%def>
diff -r 82e91d215acf573d96d3d377620ed8815368c86d -r 3f630f92f5983c28e1aedff312e7ff7e598fe23c templates/base.mako
--- a/templates/base.mako
+++ b/templates/base.mako
@@ -10,7 +10,7 @@
${self.stylesheets()}
${self.javascripts()}
</head>
- <body>
+ <body class="inbound">
${next.body()}
</body></html>
@@ -50,7 +50,8 @@
"libs/backbone/backbone-relational",
"libs/handlebars.runtime",
"galaxy.base",
- "mvc/ui"
+ "mvc/ui",
+ 'libs/require'
)}
<script type="text/javascript">
@@ -69,6 +70,16 @@
error : function(){},
assert : function(){}
};
+
+ ## configure require
+ require.config({
+ baseUrl: "${h.url_for('/static/scripts') }",
+ shim: {
+ "libs/underscore": { exports: "_" },
+ "libs/backbone/backbone": { exports: "Backbone" },
+ "libs/backbone/backbone-relational": ["libs/backbone/backbone"]
+ }
+ });
</script>
%if not form_input_auto_focus is UNDEFINED and form_input_auto_focus:
diff -r 82e91d215acf573d96d3d377620ed8815368c86d -r 3f630f92f5983c28e1aedff312e7ff7e598fe23c templates/base/base_panels.mako
--- a/templates/base/base_panels.mako
+++ b/templates/base/base_panels.mako
@@ -341,7 +341,7 @@
</div></div><!--end left-->
%endif
- <div id="center">
+ <div id="center" class="inbound">
${self.center_panel()}
</div><!--end center-->
%if self.has_right_panel:
diff -r 82e91d215acf573d96d3d377620ed8815368c86d -r 3f630f92f5983c28e1aedff312e7ff7e598fe23c templates/grid_base.mako
--- a/templates/grid_base.mako
+++ b/templates/grid_base.mako
@@ -16,6 +16,20 @@
<%namespace file="/refresh_frames.mako" import="handle_refresh_frames" /><%namespace file="/display_common.mako" import="get_class_plural" />
+<%def name="load(embedded = False)">
+<%
+ self.grid_javascripts()
+ if embedded:
+ self.init()
+ self.stylesheets()
+ self.render_grid_header( grid, False )
+ self.render_grid_table( grid, show_item_checkboxes=show_item_checkboxes )
+ else:
+ self.make_grid( grid )
+ endif
+%>
+</%def>
+
<%def name="init()"><%
self.has_left_panel = False
@@ -47,7 +61,8 @@
'get_class_plural' : get_class_plural( grid.model_class ).lower(),
'use_paging' : grid.use_paging,
'legend' : grid.legend,
- 'current_item_id' : ''
+ 'current_item_id' : False,
+ 'use_panels' : context.get('use_panels')
}
## add current item if exists
@@ -94,6 +109,7 @@
'target' : operation.target,
'label' : operation.label,
'confirm' : operation.confirm,
+ 'inbound' : operation.inbound,
'global_operation' : False
})
if operation.allow_multiple:
@@ -107,7 +123,8 @@
for action in grid.global_actions:
self.grid_config['global_actions'].append({
'url_args' : url(**action.url_args),
- 'label' : action.label
+ 'label' : action.label,
+ 'inbound' : action.inbound
})
endfor
@@ -144,6 +161,9 @@
link = None
endif
+ ## inbound
+ inbound = column.inbound
+
## get value
value = column.get_value( trans, grid, item )
@@ -158,7 +178,8 @@
## Item dictionary
item_dict['column_config'][column.label] = {
'link' : link,
- 'value' : value
+ 'value' : value,
+ 'inbound' : inbound
}
endif
endfor
@@ -181,36 +202,29 @@
##
<%def name="center_panel()">
- ${self.grid_body( grid )}
+ ${self.grid_body()}
</%def>
## Render the grid's basic elements. Each of these elements can be subclassed.
<%def name="body()">
- ${self.grid_body( grid )}
+ ${self.grid_body()}
</%def>
## Because body() is special and always exists even if not explicitly defined,
## it's not possible to override body() in the topmost template in the chain.
## Because of this, override grid_body() instead.
-<%def name="grid_body( grid )">
- ${self.make_grid( grid )}
+<%def name="grid_body()">
+ ${self.load()}
</%def><%def name="title()">${self.grid_config['title']}</%def>
-<%def name="javascripts()">
- ${parent.javascripts()}
- ${self.grid_javascripts()}
-</%def>
-
<%def name="grid_javascripts()">
- ${h.js("libs/jquery/jquery.autocomplete", "galaxy.autocom_tagging", "libs/jquery/jquery.rating", "galaxy.grids" )}
+ ${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)
{
// Put tag name and value together.
@@ -218,23 +232,6 @@
$('#advanced-search').show('fast');
gridView.add_filter_condition("tags", tag, true);
};
-
- $(function() {
- ## get configuration
- var grid_config = ${ h.to_json_string( self.grid_config ) };
-
- // Create grid.
- var grid = new Grid(grid_config);
-
- // strip protocol and domain
- var url = grid.get('url_base');
- url = url.replace(/^.*\/\/[^\/]+/, '');
- grid.set('url_base', url);
-
- // Create view.
- gridView = new GridView(grid);
- });
-
</script></%def>
@@ -290,16 +287,25 @@
%if self.grid_config['global_actions']:
<ul class="manage-table-actions">
- %if len( self.grid_config['global_actions'] ) < 3:
- %for action in self.grid_config['global_actions']:
- <li><a class="action-button" href="${action['url_args']}">${action['label']}</a></li>
- %endfor
- %else:
- <li><a class="action-button" id="action-8675309-popup" class="menubutton">Actions</a></li>
- <div popupmenu="action-8675309-popup">
- %for action in self.grid_config['global_actions']:
- <a class="action-button" href="${action['url_args']}">${action['label']}</a>
- %endfor
+ <%
+ show_popup = len( self.grid_config['global_actions'] ) >= 3
+ %>
+ %if show_popup:
+ <li><a class="action-button" id="popup-global-actions" class="menubutton">Actions</a></li>
+ <div popupmenu="popup-global-actions">
+ %endif
+ %for action in self.grid_config['global_actions']:
+ <%
+ label_cls = ""
+ if action['inbound']:
+ label_cls = "use-inbound"
+ else:
+ label_cls = "use-outbound"
+ endif
+ %>
+ <li><a class="action-button ${label_cls}" href="${action['url_args']}" onclick="return false;">${action['label']}</a></li>
+ %endfor
+ %if show_popup:
</div>
%endif
</ul>
@@ -396,23 +402,21 @@
# load attributes
link = column_settings['link']
value = column_settings['value']
+ inbound = column_settings['inbound']
# check if formatting is defined
value = str(value).replace('//', '/')
# Attach popup menu?
id = ""
+ cls = ""
if column['attach_popup']:
id = 'grid-%d-popup' % i
- endif
-
- # Determine appropriate class
- cls = ""
- if column['attach_popup']:
cls = "menubutton"
if link:
cls += " split"
endif
+ cls += " popup"
endif
%><td ${nowrap}>
@@ -420,7 +424,16 @@
%if len(self.grid_config['operations']) != 0:
<div id="${id}" class="${cls}" style="float: left;">
%endif
- <a class="label" href="${link}">${value}</a>
+
+ <%
+ label_class = ""
+ if inbound:
+ label_class = "use-inbound"
+ else:
+ label_class = "use-outbound"
+ endif
+ %>
+ <a class="label ${label_class}" href="${link}" onclick="return false;">${value}</a>
%if len(self.grid_config['operations']) != 0:
</div>
%endif
@@ -430,32 +443,33 @@
</td>
%endif
%endfor
- ## Actions column
- <td>
- <div popupmenu="${popupmenu_id}">
- %for operation in self.grid_config['operations']:
- <%
- operation_id = operation['label']
- operation_settings = item['operation_config'][operation_id]
- %>
- %if operation_settings['allowed'] and operation['allow_popup']:
- <%
- target = ""
- if operation['target']:
- target = "target='" + operation['target'] + "'"
- %>
- %if operation['confirm']:
- <a class="action-button" ${target} confirm="${operation['confirm']}" href="${operation_settings['url_args']}">${operation_id}</a>
- %else:
- <a class="action-button" ${target} href="${operation_settings['url_args']}">${operation_id}</a>
- %endif
- %endif
- %endfor
- </div>
- </td></tr><% num_rows_rendered += 1 %>
%endfor
+
+ ## update configuration
+ <script type="text/javascript">
+ $(function() {
+ require(['galaxy.grids'], function(mod_grids) {
+ ## get configuration
+ var grid_config = ${ h.to_json_string( self.grid_config ) };
+
+ // Create grid.
+ var grid = new mod_grids.Grid(grid_config);
+
+ // strip protocol and domain
+ var url = grid.get('url_base');
+ url = url.replace(/^.*\/\/[^\/]+/, '');
+ grid.set('url_base', url);
+
+ // Create view.
+ if (!gridView)
+ gridView = new mod_grids.GridView(grid);
+ else
+ gridView.init_grid(grid);
+ });
+ });
+ </script></%def>
## Render grid table footer contents.
@@ -510,24 +524,24 @@
%>
Page:
% if min_page > 1:
- <span class='page-link' id="page-link-1"><a href="${url( page=1 )}" page_num="1">1</a></span> ...
+ <span class='page-link' id="page-link-1"><a href="${url( page=1 )}" page_num="1" onclick="return false;">1</a></span> ...
% endif
%for page_index in range(min_page, max_page + 1):
%if page_index == cur_page_num:
<span class='page-link inactive-link' id="page-link-${page_index}">${page_index}</span>
%else:
<% args = { 'page' : page_index } %>
- <span class='page-link' id="page-link-${page_index}"><a href="${url( args )}" page_num='${page_index}'>${page_index}</a></span>
+ <span class='page-link' id="page-link-${page_index}"><a href="${url( args )}" onclick="return false;" page_num='${page_index}'>${page_index}</a></span>
%endif
%endfor
%if max_page < num_pages:
...
- <span class='page-link' id="page-link-${num_pages}"><a href="${url( page=num_pages )}" page_num="${num_pages}">${num_pages}</a></span>
+ <span class='page-link' id="page-link-${num_pages}"><a href="${url( page=num_pages )}" onclick="return false;" page_num="${num_pages}">${num_pages}</a></span>
%endif
</span>
## Show all link
- <span class='page-link' id='show-all-link-span'> | <a href="${url( page='all' )}" page_num="all">Show All</a></span>
+ <span class='page-link' id='show-all-link-span'> | <a href="${url( page='all' )}" onclick="return false;" page_num="all">Show All</a></span></td></tr>
%endif
diff -r 82e91d215acf573d96d3d377620ed8815368c86d -r 3f630f92f5983c28e1aedff312e7ff7e598fe23c templates/tagging_common.mako
--- a/templates/tagging_common.mako
+++ b/templates/tagging_common.mako
@@ -135,6 +135,7 @@
## Build script that augments tags using progressive javascript.
<script type="text/javascript">
+ $(function() {
//
// Set up autocomplete tagger.
//
@@ -212,6 +213,8 @@
};
$('#${elt_id}').autocomplete_tagging(options);
+
+ });
</script>
## Use style to hide/display the tag area.
diff -r 82e91d215acf573d96d3d377620ed8815368c86d -r 3f630f92f5983c28e1aedff312e7ff7e598fe23c templates/user/openid_manage.mako
--- a/templates/user/openid_manage.mako
+++ b/templates/user/openid_manage.mako
@@ -1,19 +1,10 @@
## Template generates a grid that enables user to select items.
-<%namespace file="../grid_base.mako" import="make_grid" />
+<%inherit file="../grid_base.mako" />
+
<%namespace file="login.mako" import="render_openid_form" />
-<%inherit file="../grid_base.mako" />
-
-<%def name="grid_body( grid )">
- ${make_grid( grid )}
+<%def name="load()">
+ ${parent.load()}
<h2>Associate more OpenIDs</h2>
${render_openid_form( kwargs['redirect'], True, kwargs['openid_providers'] )}
-</%def>
-
-<%def name="center_panel()">
- <div style="overflow: auto; height: 100%">
- <div class="page-container" style="padding: 10px;">
- ${grid_body( grid )}
- </div>
- </div>
-</%def>
+</%def>
\ No newline at end of file
diff -r 82e91d215acf573d96d3d377620ed8815368c86d -r 3f630f92f5983c28e1aedff312e7ff7e598fe23c templates/webapps/galaxy/history/grid.mako
--- a/templates/webapps/galaxy/history/grid.mako
+++ b/templates/webapps/galaxy/history/grid.mako
@@ -1,7 +1,7 @@
<%inherit file="../grid_base.mako"/>
-<%def name="grid_body( grid )">
- ${self.make_grid( grid )}
+<%def name="load()">
+ ${parent.load()}
<br/><div class="toolParamHelp" style="clear: both;">
Histories that have been deleted for more than a time period specified by the Galaxy administrator(s) may be permanently deleted.
diff -r 82e91d215acf573d96d3d377620ed8815368c86d -r 3f630f92f5983c28e1aedff312e7ff7e598fe23c templates/webapps/galaxy/page/select_items_grid.mako
--- a/templates/webapps/galaxy/page/select_items_grid.mako
+++ b/templates/webapps/galaxy/page/select_items_grid.mako
@@ -1,7 +1,3 @@
## Template generates a grid that enables user to select items.
<%namespace file="../grid_base.mako" import="*" />
-${init()}
-${grid_javascripts()}
-${stylesheets()}
-${render_grid_header( grid, False )}
-${render_grid_table( grid, show_item_checkboxes=True )}
+${load(True)}
\ No newline at end of file
diff -r 82e91d215acf573d96d3d377620ed8815368c86d -r 3f630f92f5983c28e1aedff312e7ff7e598fe23c templates/webapps/galaxy/page/select_items_grid_async.mako
--- a/templates/webapps/galaxy/page/select_items_grid_async.mako
+++ /dev/null
@@ -1,9 +0,0 @@
-<%namespace file="../grid_base.mako" import="*" />
-<%namespace file="/display_common.mako" import="render_message" />
-${init()}
-## Always show item checkboxes so that users can select items.
-${render_grid_table_body_contents( grid, show_item_checkboxes=show_item_checkboxes )}
-*****
-${num_pages}
-*****
-${render_message( message, status )}
\ No newline at end of file
diff -r 82e91d215acf573d96d3d377620ed8815368c86d -r 3f630f92f5983c28e1aedff312e7ff7e598fe23c templates/webapps/galaxy/tracks/add_to_viz.mako
--- a/templates/webapps/galaxy/tracks/add_to_viz.mako
+++ b/templates/webapps/galaxy/tracks/add_to_viz.mako
@@ -1,8 +1,3 @@
## Template generates a grid that enables user to add tracks
<%namespace file="../grid_base.mako" import="*" />
-${init()}
-${stylesheets()}
-${grid_javascripts()}
-${render_grid_header( grid, False )}
-${render_grid_table( grid, show_item_checkboxes=True )}
-
+${load(True)}
diff -r 82e91d215acf573d96d3d377620ed8815368c86d -r 3f630f92f5983c28e1aedff312e7ff7e598fe23c templates/webapps/galaxy/tracks/add_tracks.mako
--- a/templates/webapps/galaxy/tracks/add_tracks.mako
+++ b/templates/webapps/galaxy/tracks/add_tracks.mako
@@ -1,7 +1,3 @@
## Template generates a grid that enables user to add tracks
<%namespace file="../grid_base.mako" import="*" />
-${init()}
-${stylesheets()}
-${grid_javascripts()}
-${render_grid_header( grid, False )}
-${render_grid_table( grid, show_item_checkboxes=True )}
\ No newline at end of file
+${load(True)}
\ No newline at end of file
diff -r 82e91d215acf573d96d3d377620ed8815368c86d -r 3f630f92f5983c28e1aedff312e7ff7e598fe23c templates/webapps/galaxy/tracks/history_select_grid.mako
--- a/templates/webapps/galaxy/tracks/history_select_grid.mako
+++ b/templates/webapps/galaxy/tracks/history_select_grid.mako
@@ -3,19 +3,15 @@
## can be easily subclassed. Importing methods like this template does
## not make it possible to easily subclass templates.
##
-<%namespace file="../grid_base.mako" import="*" />
-${init()}
-${stylesheets()}
-${grid_javascripts()}
+<%namespace name="grid_base" file="../grid_base.mako" import="*" /><%def name="select_header()"><script type="text/javascript">
// Load all grid URLs into modal-body element so that
// grid + links stays embedded.
$(document).ready(function() {
- $(".addtracktab, #grid-table a").off();
- $(".addtracktab, #grid-table a").click(function() {
- var modal_body = $(".modal-body");
+ $(".addtracktab").click(function() {
+ var modal_body = $(this).closest('.inbound');
if (modal_body.length !== 0) {
modal_body.load($(this).attr("href"));
return false;
@@ -78,12 +74,11 @@
<div class="divider"></div></%def>
-${select_header()}
## Need to define title so that it can be overridden by child templates.
<%def name="title()"></%def>
-${self.title()}
-
-${render_grid_header( grid, False )}
-${render_grid_table( grid, show_item_checkboxes=show_item_checkboxes )}
-
+<div class='inbound'>
+ ${select_header()}
+ ${self.title()}
+ ${grid_base.load(True)}
+</div>
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: Fix for tool shed install and test framework.
by commits-noreply@bitbucket.org 23 Nov '13
by commits-noreply@bitbucket.org 23 Nov '13
23 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/82e91d215acf/
Changeset: 82e91d215acf
User: greg
Date: 2013-11-23 19:17:30
Summary: Fix for tool shed install and test framework.
Affected #: 1 file
diff -r 13bd960b94141a2974d0c968c26fc046e05e1d14 -r 82e91d215acf573d96d3d377620ed8815368c86d 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
@@ -672,12 +672,12 @@
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' % str( name ) )
+ 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:
- log.exception( 'No installed repository found.' )
- error_message = '%s\n%s' % ( error_message, extract_log_data( result, from_tool_test=False ) )
+ 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,
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: Correct typo in test framework.
by commits-noreply@bitbucket.org 23 Nov '13
by commits-noreply@bitbucket.org 23 Nov '13
23 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/13bd960b9414/
Changeset: 13bd960b9414
User: Dave Bouvier
Date: 2013-11-23 06:37:44
Summary: Correct typo in test framework.
Affected #: 1 file
diff -r a73e13655a942f83d9c475d522a861fb32b0148d -r 13bd960b94141a2974d0c968c26fc046e05e1d14 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
@@ -506,7 +506,7 @@
( str( dependency.name ), str( dependency.type ), str( dependency.version ), unicodify( dependency.error_message ) ) )
test_result = dict( type=dependency.type,
name=dependency.name,
- version=sdependency.version,
+ version=dependency.version,
error_message=dependency.error_message )
repository_status_dict[ 'installation_errors' ][ 'tool_dependencies' ].append( test_result )
for dependency in repository.missing_repository_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
commit/galaxy-central: greg: More fixes for the tool shed's install and test framework.
by commits-noreply@bitbucket.org 22 Nov '13
by commits-noreply@bitbucket.org 22 Nov '13
22 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a73e13655a94/
Changeset: a73e13655a94
User: greg
Date: 2013-11-22 23:27:10
Summary: More fixes for the tool shed's install and test framework.
Affected #: 1 file
diff -r f7a0ac415489fb3d58f46872f4aa5f19712e6cab -r a73e13655a942f83d9c475d522a861fb32b0148d 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
@@ -504,19 +504,19 @@
for dependency in repository.missing_tool_dependencies:
log.debug( 'Missing tool dependency %s of type %s version %s: %s' % \
( str( dependency.name ), str( dependency.type ), str( dependency.version ), unicodify( dependency.error_message ) ) )
- test_result = dict( type=str( dependency.type ),
- name=str( dependency.name ),
- version=str( dependency.version ),
- error_message=unicodify( dependency.error_message ) )
+ test_result = dict( type=dependency.type,
+ name=dependency.name,
+ version=sdependency.version,
+ error_message=dependency.error_message )
repository_status_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 ) ) )
- test_result = dict( tool_shed=str( dependency.tool_shed ),
- name=str( dependency.name ),
- owner=str( dependency.owner ),
- changeset_revision=str( dependency.changeset_revision ),
- error_message=unicodify( dependency.error_message ) )
+ test_result = dict( tool_shed=dependency.tool_shed,
+ name=dependency.name,
+ owner=dependency.owner,
+ changeset_revision=dependency.changeset_revision,
+ error_message=dependency.error_message )
repository_status_dict[ 'installation_errors' ][ 'repository_dependencies' ].append( test_result )
# Record the status of this repository in the tool shed.
params = dict( tools_functionally_correct=False,
@@ -727,7 +727,14 @@
try:
results_dict = test_repository_tools( app, repository, repository_dict, repository_status_dict, results_dict )
except Exception, e:
- log.exception( 'Error executing tests for repository %s: %s' % ( name, str( 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
results_dict[ 'total_repositories_tested' ] = total_repositories_tested
@@ -909,7 +916,7 @@
register_test_result( galaxy_tool_shed_url, repository_status_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' ] = extract_log_data( result, from_tool_test=True )
+ 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
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 code cleanup, fixes and additional exception handling for the tool shed's install and test framework.
by commits-noreply@bitbucket.org 22 Nov '13
by commits-noreply@bitbucket.org 22 Nov '13
22 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f7a0ac415489/
Changeset: f7a0ac415489
User: greg
Date: 2013-11-22 22:19:18
Summary: More code cleanup, fixes and additional exception handling for the tool shed's install and test framework.
Affected #: 2 files
diff -r 14746e61b979fcf17e9fc9039ce2f5bd5621790a -r f7a0ac415489fb3d58f46872f4aa5f19712e6cab 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
@@ -114,6 +114,10 @@
app.model.RepositoryMetadata.table.c.includes_tools == True,
app.model.RepositoryMetadata.table.c.do_not_test == False,
not_( app.model.RepositoryMetadata.table.c.id.in_( skip_metadata_ids ) ) ) ):
+ # Clear any old invalid tests for this metadata revision, since this could lead to duplication of invalid test rows,
+ # or tests incorrectly labeled as invalid.
+ 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.
if repository_metadata.tool_test_results:
@@ -143,12 +147,12 @@
print '# Now checking revision %s of %s, owned by %s.' % ( changeset_revision, name, owner )
# If this changeset revision has no tools, we don't need to do anything here, the install and test script has a filter for returning
# only repositories that contain tools.
- tool_dicts = repository_metadata.get( 'tools', None )
+ tool_dicts = metadata.get( 'tools', None )
if tool_dicts is not None:
has_test_data = False
testable_revision_found = False
# Clone the repository up to the changeset revision we're checking.
- repo_dir = repository_metadata.repository.repo_path( app )
+ repo_dir = repository.repo_path( app )
repo = hg.repository( get_configured_ui(), repo_dir )
work_dir = tempfile.mkdtemp( prefix="tmp-toolshed-cafr" )
cloned_ok, error_message = clone_repository( repo_dir, work_dir, changeset_revision )
diff -r 14746e61b979fcf17e9fc9039ce2f5bd5621790a -r f7a0ac415489fb3d58f46872f4aa5f19712e6cab 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
@@ -267,9 +267,9 @@
remove_generated_tests( app )
sa_session = app.model.context.current
# The dict contains the only repository the app should have installed at this point.
- repository = test_db_util.get_installed_repository_by_name_owner_changeset_revision( repository_dict[ 'name' ],
- repository_dict[ 'owner' ],
- repository_dict[ 'changeset_revision' ] )
+ repository = test_db_util.get_installed_repository_by_name_owner_changeset_revision( str( repository_dict[ 'name' ] ),
+ str( repository_dict[ 'owner' ] ),
+ str( repository_dict[ 'changeset_revision' ] ) )
# We have to do this through Twill, in order to maintain app.toolbox and shed_tool_conf.xml in a state that is valid for future tests.
for required_repository in repository.repository_dependencies:
repository_dict = dict( name=required_repository.name,
@@ -278,13 +278,13 @@
# Generate a test method to uninstall this repository through the embedded Galaxy application's web interface.
test_install_repositories.generate_deactivate_or_uninstall_method( repository_dict, deactivate=True )
log.debug( 'Changeset revision %s of %s repository %s selected for deactivation.' % \
- ( required_repository.changeset_revision, required_repository.status, required_repository.name ) )
+ ( str( required_repository.changeset_revision ), str( required_repository.status ), str( required_repository.name ) ) )
repository_dict = dict( name=repository.name,
owner=repository.owner,
changeset_revision=repository.changeset_revision )
test_install_repositories.generate_deactivate_or_uninstall_method( repository_dict, deactivate=True )
log.debug( 'Changeset revision %s of %s repository %s selected for deactivation.' % \
- ( repository.changeset_revision, repository.status, repository.name ) )
+ ( str( repository.changeset_revision ), str( repository.status ), str( repository.name ) ) )
# Set up nose to run the generated uninstall method as a functional test.
test_config = nose.config.Config( env=os.environ, plugins=nose.plugins.manager.DefaultPluginManager() )
test_config.configure( sys.argv )
@@ -292,7 +292,8 @@
# repository and delete it from disk.
result, _ = run_tests( test_config )
success = result.wasSuccessful()
- return success
+ if not success:
+ log.debug( 'Failed deactivation of repository %s.' % str( repository.name ) )
def extract_log_data( test_result, from_tool_test=True ):
'''Extract any useful data from the test_result.failures and test_result.errors attributes.'''
@@ -411,15 +412,6 @@
error_message = ''
latest_revision_only = '-check_all_revisions' not in sys.argv
repository_dicts = []
- results_dict = {}
- # We are testing deprecated repositories because it is possible that a deprecated repository contains valid tools that
- # someone has previously installed. Deleted repositories have never been installed, so should not be tested. If they are
- # undeleted, this script will then test them the next time it runs. We don't need to check if a repository has been deleted
- # here because our call to the Tool Shed API filters by downloadable='true', in which case deleted will always be False.
- if os.path.exists( exclude_list_file ):
- log.debug( 'Loading the list of repositories excluded from testing from the file %s...', exclude_list_file )
- exclude_list = parse_exclude_list( exclude_list_file )
- results_dict[ 'exclude_list' ] = exclude_list
params = urllib.urlencode( dict( do_not_test='false',
downloadable='true',
malicious='false',
@@ -502,61 +494,53 @@
return {}, error_message
return tool_test_results, error_message
-def handle_missing_dependencies( app, repository, metadata_revision_id, missing_tool_dependencies, repository_dict, repository_status_dict, results_dict ):
+def handle_missing_dependencies( app, repository, missing_tool_dependencies, repository_dict, repository_status_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
# for the test to be considered reliable.
log.debug( 'The following dependencies of this repository are missing, so skipping functional tests.' )
- params = {}
# In keeping with the standard display layout, add the error message to the dict for each tool individually.
for dependency in repository.missing_tool_dependencies:
log.debug( 'Missing tool dependency %s of type %s version %s: %s' % \
( str( dependency.name ), str( dependency.type ), str( dependency.version ), unicodify( dependency.error_message ) ) )
- test_result = dict( type=dependency.type,
- name=dependency.name,
- version=dependency.version,
- error_message=dependency.error_message )
+ test_result = dict( type=str( dependency.type ),
+ name=str( dependency.name ),
+ version=str( dependency.version ),
+ error_message=unicodify( dependency.error_message ) )
repository_status_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 ) ) )
- test_result = dict( tool_shed=dependency.tool_shed,
- name=dependency.name,
- owner=dependency.owner,
- changeset_revision=dependency.changeset_revision,
- error_message=dependency.error_message )
+ test_result = dict( tool_shed=str( dependency.tool_shed ),
+ name=str( dependency.name ),
+ owner=str( dependency.owner ),
+ changeset_revision=str( dependency.changeset_revision ),
+ error_message=unicodify( dependency.error_message ) )
repository_status_dict[ 'installation_errors' ][ 'repository_dependencies' ].append( test_result )
# Record the status of this repository in the tool shed.
- params[ 'tools_functionally_correct' ] = False
- params[ 'do_not_test' ] = False
- params[ 'test_install_error' ] = True
- register_test_result( galaxy_tool_shed_url,
- metadata_revision_id,
- repository_status_dict,
- repository_dict,
- params )
- # Since this repository is missing components, we do not want to test it. Deactivate this repository.
+ 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 )
+ # 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'.
deactivate = asbool( os.environ.get( 'GALAXY_INSTALL_TEST_KEEP_TOOL_DEPENDENCIES', False ) )
if deactivate:
- log.debug( 'Due to the above missing tool dependencies, we are now uninstalling the following tool dependencies but not changing their repositories.' )
for missing_tool_dependency in missing_tool_dependencies:
uninstall_tool_dependency( app, missing_tool_dependency )
# We are deactivating this repository and all of its repository dependencies.
- log.debug( 'Due to the above missing repository dependencies, we are now deactivating the following repositories.' )
deactivate_repository( app, repository_dict )
else:
# We are uninstalling this repository and all of its repository dependencies.
- log.debug( 'Due to the above missing repository dependencies, we are now uninstalling the following repositories.' )
uninstall_repository( app, repository_dict )
results_dict[ 'repositories_failed_install' ].append( dict( name=str( repository.name ),
owner=str( repository.owner ),
changeset_revision=str( repository.changeset_revision ) ) )
# Set the test_toolbox.toolbox module-level variable to the new app.toolbox.
test_toolbox.toolbox = app.toolbox
- return repository_status_dict, results_dict
+ return results_dict
def initialize_results_dict():
# Initialize a dictionary for the summary that will be printed to stdout.
@@ -565,7 +549,6 @@
results_dict[ 'repositories_passed' ] = []
results_dict[ 'repositories_failed' ] = []
results_dict[ 'repositories_failed_install' ] = []
- results_dict[ 'exclude_list' ] = []
return results_dict
def install_repository( app, repository_dict ):
@@ -596,15 +579,32 @@
return repository, error_message
def install_and_test_repositories( app, galaxy_shed_tools_dict, galaxy_shed_tool_conf_file ):
+ results_dict = initialize_results_dict()
error_message = ''
# Allow the option to keep or delete tool dependencies when a repository has been tested.
deactivate = asbool( os.environ.get( 'GALAXY_INSTALL_TEST_KEEP_TOOL_DEPENDENCIES', False ) )
# Initialize a dictionary for the summary that will be printed to stdout.
- results_dict = initialize_results_dict()
total_repositories_tested = results_dict[ 'total_repositories_tested' ]
repositories_to_install, error_message = get_repositories_to_install( galaxy_tool_shed_url )
if error_message:
return None, error_message
+ # Handle repositories not to be tested.
+ if os.path.exists( exclude_list_file ):
+ # Entries in the exclude_list look something like this.
+ # { 'reason': The default reason or the reason specified in this section,
+ # 'repositories':
+ # [( name, owner, changeset revision if changeset revision else None ),
+ # ( name, owner, changeset revision if changeset revision else None )] }
+ # If changeset revision is None, that means the entire repository is excluded from testing, otherwise only the specified
+ # revision should be skipped.
+ # We are testing deprecated repositories because it is possible that a deprecated repository contains valid tools that
+ # someone has previously installed. Deleted repositories have never been installed, so should not be tested. If they are
+ # undeleted, this script will then test them the next time it runs. We don't need to check if a repository has been deleted
+ # here because our call to the Tool Shed API filters by downloadable='true', in which case deleted will always be False.
+ log.debug( 'Loading the list of repositories excluded from testing from the file %s...', exclude_list_file )
+ exclude_list = parse_exclude_list( exclude_list_file )
+ else:
+ exclude_list = []
# Generate a test method that will use Twill to install each repository into the embedded Galaxy application that was
# started up, installing repository and tool dependencies. Upon successful installation, generate a test case for each
# functional test defined for each tool in the repository and execute the test cases. Record the result of the tests.
@@ -629,14 +629,13 @@
# "tool_shed_url": "http://toolshed.local:10001",
# "url": "/api/repository_revisions/529fd61ab1c6cc36",
# "user_id": "529fd61ab1c6cc36" }
- params = {}
- changeset_revision = repository_dict.get( 'changeset_revision', None )
metadata_revision_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:
@@ -651,15 +650,7 @@
repository_status_dict[ 'failed_tests' ] = []
repository_status_dict[ 'skip_reason' ] = None
repository_status_dict[ 'installation_errors' ] = dict( current_repository=[], repository_dependencies=[], tool_dependencies=[] )
- # Handle repositories not to be tested.
- exclude_list = results_dict[ 'exclude_list' ]
- # Entries in the exclude_list look something like this.
- # { 'reason': The default reason or the reason specified in this section,
- # 'repositories':
- # [( name, owner, changeset revision if changeset revision else None ),
- # ( name, owner, changeset revision if changeset revision else None )] }
- # If changeset revision is None, that means the entire repository is excluded from testing, otherwise only the specified
- # revision should be skipped.
+ # See if this repository should be skipped for any reason.
skip_this_repository = False
skip_reason = None
for exclude_dict in exclude_list:
@@ -671,10 +662,10 @@
break
if skip_this_repository:
repository_status_dict[ 'not_tested' ] = dict( reason=skip_reason )
- params[ 'tools_functionally_correct' ] = False
- params[ 'do_not_test' ] = False
- register_test_result( galaxy_tool_shed_url, metadata_revision_id, repository_status_dict, repository_dict, params )
- log.debug( "Not testing revision %s of repository %s owned by %s." % ( str( changeset_revision ), str( name ), str( owner ) ) )
+ params = dict( tools_functionally_correct=False,
+ do_not_test=False )
+ register_test_result( galaxy_tool_shed_url, repository_status_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 )
if error_message:
@@ -693,26 +684,19 @@
changeset_revision=changeset_revision,
error_message=error_message )
repository_status_dict[ 'installation_errors' ][ 'repository_dependencies' ].append( test_result )
- params[ 'tools_functionally_correct' ] = False
- params[ 'test_install_error' ] = True
- params[ 'do_not_test' ] = False
- register_test_result( galaxy_tool_shed_url,
- metadata_revision_id,
- repository_status_dict,
- repository_dict,
- params )
+ 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.
- success = deactivate_repository( app, repository_dict )
+ deactivate_repository( app, repository_dict )
else:
# We are uninstalling this repository and all of its repository dependencies.
- success = uninstall_repository( app, repository_dict )
+ uninstall_repository( app, repository_dict )
except:
- log.exception( 'Encountered error attempting to deactivate or uninstall %s.', repository_dict[ 'name' ] )
- success = False
- if not success:
- log.error( 'Repository %s failed to uninstall.', name )
+ 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:
@@ -729,25 +713,22 @@
repository_status_dict[ 'missing_test_components' ] = []
missing_tool_dependencies = get_missing_tool_dependencies( repository )
if missing_tool_dependencies or repository.missing_repository_dependencies:
- repository_status_dict, results_dict = handle_missing_dependencies( app,
- repository,
- metadata_revision_id,
- missing_tool_dependencies,
- repository_dict,
- repository_status_dict,
- results_dict )
+ 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 ) ) )
- params, repository_status_dict, results_dict = test_repository_tools( app,
- repository,
- params,
- metadata_revision_id,
- repository_dict,
- repository_status_dict,
- results_dict )
+ try:
+ results_dict = test_repository_tools( app, repository, repository_dict, repository_status_dict, results_dict )
+ except Exception, e:
+ log.exception( 'Error executing tests for repository %s: %s' % ( name, str( e ) ) )
+ 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
@@ -805,17 +786,20 @@
log.debug( 'Repository %s owned by %s, all revisions.' % ( str( name ), str( owner ) ) )
return exclude_list
-def register_test_result( url, metadata_id, test_results_dict, repository_dict, params ):
+def register_test_result( url, test_results_dict, repository_dict, params ):
"""Update the repository metadata tool_test_results and appropriate flags using the API."""
- params[ 'tool_test_results' ] = test_results_dict
if '-info_only' in sys.argv or 'GALAXY_INSTALL_TEST_INFO_ONLY' in os.environ:
return {}
else:
- url = '%s' % ( suc.url_join( galaxy_tool_shed_url,'api', 'repository_revisions', metadata_id ) )
- return update( tool_shed_api_key,
- url,
- params,
- return_formatted=False )
+ metadata_revision_id = repository_dict.get( 'id', None )
+ if metadata_revision_id is not None:
+ params[ 'tool_test_results' ] = test_results_dict
+ url = '%s' % ( suc.url_join( galaxy_tool_shed_url,'api', 'repository_revisions', str( metadata_revision_id ) ) )
+ try:
+ return update( tool_shed_api_key, url, params, return_formatted=False )
+ except Exception, e:
+ log.exception( 'Error attempting to register test results: %s' % str( e ) )
+ return {}
def remove_generated_tests( app ):
"""
@@ -885,7 +869,8 @@
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, params, metadata_revision_id, repository_dict, repository_status_dict, results_dict ):
+def test_repository_tools( app, repository, repository_dict, repository_status_dict, results_dict ):
+ """Test tools contained in the received repository."""
name = str( repository.name )
owner = str( repository.owner )
changeset_revision = str( repository.changeset_revision )
@@ -918,14 +903,10 @@
# controller with the status of the test. This also sets the do_not_test and tools_functionally correct flags, and
# updates the time_last_tested field to today's date.
results_dict[ 'repositories_passed' ].append( dict( name=name, owner=owner, changeset_revision=changeset_revision ) )
- params[ 'tools_functionally_correct' ] = True
- params[ 'do_not_test' ] = False
- params[ 'test_install_error' ] = False
- register_test_result( galaxy_tool_shed_url,
- metadata_revision_id,
- repository_status_dict,
- repository_dict,
- params )
+ 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 )
log.debug( 'Revision %s of repository %s installed and passed functional tests.' % ( str( changeset_revision ), str( name ) ) )
else:
repository_status_dict[ 'failed_tests' ] = extract_log_data( result, from_tool_test=True )
@@ -935,14 +916,10 @@
# field to today's date.
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[ 'tools_functionally_correct' ] = False
- params[ 'test_install_error' ] = False
- params[ 'do_not_test' ] = str( set_do_not_test )
- register_test_result( galaxy_tool_shed_url,
- metadata_revision_id,
- repository_status_dict,
- repository_dict,
- params )
+ 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 )
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
@@ -951,25 +928,26 @@
if deactivate:
log.debug( 'Deactivating changeset revision %s of repository %s' % ( str( changeset_revision ), str( name ) ) )
# We are deactivating this repository and all of its repository dependencies.
- success = deactivate_repository( app, repository_dict )
+ deactivate_repository( app, repository_dict )
else:
log.debug( 'Uninstalling changeset revision %s of repository %s' % ( str( changeset_revision ), str( name ) ) )
# We are uninstalling this repository and all of its repository dependencies.
- success = uninstall_repository( app, repository_dict )
- if not success:
- log.debug( 'Repository %s failed to uninstall.' % str( name ) )
+ uninstall_repository( app, repository_dict )
+
# Set the test_toolbox.toolbox module-level variable to the new app.toolbox.
test_toolbox.toolbox = app.toolbox
- return params, repository_status_dict, results_dict
+ return results_dict
def uninstall_repository( app, repository_dict ):
+ """Attempt to uninstall a repository."""
+ sa_session = app.model.context.current
# Clean out any generated tests. This is necessary for Twill.
remove_generated_tests( app )
- sa_session = app.model.context.current
# The dict contains the only repository the app should have installed at this point.
- repository = test_db_util.get_installed_repository_by_name_owner_changeset_revision( repository_dict[ 'name' ],
- repository_dict[ 'owner' ],
- repository_dict[ 'changeset_revision' ] )
+ name = str( repository_dict[ 'name' ] )
+ owner = str( repository_dict[ 'owner' ] )
+ changeset_revision = str( repository_dict[ 'changeset_revision' ] )
+ repository = test_db_util.get_installed_repository_by_name_owner_changeset_revision( name, owner, changeset_revision )
# We have to do this through Twill, in order to maintain app.toolbox and shed_tool_conf.xml in a state that is valid for future tests.
for required_repository in repository.repository_dependencies:
repository_dict = dict( name=str( required_repository.name ),
@@ -979,12 +957,9 @@
test_install_repositories.generate_deactivate_or_uninstall_method( repository_dict, deactivate=False )
log.debug( 'Changeset revision %s of %s repository %s selected for uninstallation.' % \
( str( required_repository.changeset_revision ), str( required_repository.status ), str( required_repository.name ) ) )
- repository_dict = dict( name=str( repository.name ),
- owner=str( repository.owner ),
- changeset_revision=str( repository.changeset_revision ) )
+ repository_dict = dict( name=name, owner=owner, changeset_revision=changeset_revision )
test_install_repositories.generate_deactivate_or_uninstall_method( repository_dict, deactivate=False )
- log.debug( 'Changeset revision %s of %s repository %s selected for uninstallation.' % \
- ( str( repository.changeset_revision ), str( repository.status ), str( repository.name ) ) )
+ log.debug( 'Changeset revision %s of %s repository %s selected for uninstallation.' % ( changeset_revision, str( repository.status ), name ) )
# Set up nose to run the generated uninstall method as a functional test.
test_config = nose.config.Config( env=os.environ, plugins=nose.plugins.manager.DefaultPluginManager() )
test_config.configure( sys.argv )
@@ -992,9 +967,12 @@
# repository and delete it from disk.
result, _ = run_tests( test_config )
success = result.wasSuccessful()
- return success
+ if not success:
+ log.debug( 'Repository %s failed to uninstall.' % str( name ) )
def uninstall_tool_dependency( app, tool_dependency ):
+ """Attempt to uninstall a tool dependency."""
+ sa_session = app.model.context.current
# Clean out any generated tests. This is necessary for Twill.
tool_dependency_install_path = tool_dependency.installation_directory( app )
uninstalled, error_message = tool_dependency_util.remove_tool_dependency( app, tool_dependency )
@@ -1003,7 +981,6 @@
log.debug( error_message )
else:
log.debug( 'Successfully removed tool dependency installation directory: %s' % str( tool_dependency_install_path ) )
- sa_session = app.model.context.current
if not uninstalled or tool_dependency.status != app.model.ToolDependency.installation_status.UNINSTALLED:
tool_dependency.status = app.model.ToolDependency.installation_status.UNINSTALLED
sa_session.add( tool_dependency )
@@ -1213,7 +1190,6 @@
repositories_passed = results_dict[ 'repositories_passed' ]
repositories_failed = results_dict[ 'repositories_failed' ]
repositories_failed_install = results_dict[ 'repositories_failed_install' ]
- exclude_list = results_dict[ 'exclude_list' ]
now = strftime( "%Y-%m-%d %H:%M:%S" )
print "####################################################################################"
print "# %s - repository installation and testing script completed." % now
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 undefined variable.
by commits-noreply@bitbucket.org 22 Nov '13
by commits-noreply@bitbucket.org 22 Nov '13
22 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/14746e61b979/
Changeset: 14746e61b979
User: Dave Bouvier
Date: 2013-11-22 20:52:28
Summary: Fix undefined variable.
Affected #: 1 file
diff -r 31138346d9ecb87887223e7940877b7949059a56 -r 14746e61b979fcf17e9fc9039ce2f5bd5621790a 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
@@ -508,6 +508,7 @@
# and functional tests should be skipped, since the tool dependency needs to be correctly installed
# for the test to be considered reliable.
log.debug( 'The following dependencies of this repository are missing, so skipping functional tests.' )
+ params = {}
# In keeping with the standard display layout, add the error message to the dict for each tool individually.
for dependency in repository.missing_tool_dependencies:
log.debug( 'Missing tool dependency %s of type %s version %s: %s' % \
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: Set the galaxy test host variable for test_toolbox.
by commits-noreply@bitbucket.org 22 Nov '13
by commits-noreply@bitbucket.org 22 Nov '13
22 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/31138346d9ec/
Changeset: 31138346d9ec
User: Dave Bouvier
Date: 2013-11-22 20:41:04
Summary: Set the galaxy test host variable for test_toolbox.
Affected #: 1 file
diff -r 872a34a5760fd4d855c8d2ee8f6dffac6a3d64b9 -r 31138346d9ecb87887223e7940877b7949059a56 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
@@ -1020,6 +1020,9 @@
galaxy_test_host = os.environ.get( 'GALAXY_INSTALL_TEST_HOST', default_galaxy_test_host )
# Set the GALAXY_INSTALL_TEST_HOST variable so that Twill will have the Galaxy url to install repositories into.
os.environ[ 'GALAXY_INSTALL_TEST_HOST' ] = galaxy_test_host
+ # Set the GALAXY_TEST_HOST environment variable so that the toolbox tests will have the Galaxy url to run tool functional
+ # tests on.
+ os.environ[ 'GALAXY_TEST_HOST' ] = galaxy_test_host
galaxy_test_port = os.environ.get( 'GALAXY_INSTALL_TEST_PORT', str( default_galaxy_test_port_max ) )
os.environ[ 'GALAXY_TEST_PORT' ] = galaxy_test_port
tool_path = os.environ.get( 'GALAXY_INSTALL_TEST_TOOL_PATH', 'tools' )
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 undefined name.
by commits-noreply@bitbucket.org 22 Nov '13
by commits-noreply@bitbucket.org 22 Nov '13
22 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/872a34a5760f/
Changeset: 872a34a5760f
User: Dave Bouvier
Date: 2013-11-22 20:21:10
Summary: Fix undefined name.
Affected #: 1 file
diff -r ee214245805dee0e811a93db339ef9ab134de9a3 -r 872a34a5760fd4d855c8d2ee8f6dffac6a3d64b9 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
@@ -411,6 +411,7 @@
error_message = ''
latest_revision_only = '-check_all_revisions' not in sys.argv
repository_dicts = []
+ results_dict = {}
# We are testing deprecated repositories because it is possible that a deprecated repository contains valid tools that
# someone has previously installed. Deleted repositories have never been installed, so should not be tested. If they are
# undeleted, this script will then test them the next time it runs. We don't need to check if a repository has been deleted
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: Refactor the tool shed's install and test framework to enable restriction of bugs introduced into the Galaxy framework that result in server exceptions to specific repository tests rather than the entire framework.
by commits-noreply@bitbucket.org 22 Nov '13
by commits-noreply@bitbucket.org 22 Nov '13
22 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/ee214245805d/
Changeset: ee214245805d
User: greg
Date: 2013-11-22 19:49:30
Summary: Refactor the tool shed's install and test framework to enable restriction of bugs introduced into the Galaxy framework that result in server exceptions to specific repository tests rather than the entire framework.
Affected #: 2 files
diff -r d28d25d66095b84af1aaee1a487ee2b27c5a07ce -r ee214245805dee0e811a93db339ef9ab134de9a3 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
@@ -144,22 +144,6 @@
# If this changeset revision has no tools, we don't need to do anything here, the install and test script has a filter for returning
# only repositories that contain tools.
tool_dicts = repository_metadata.get( 'tools', None )
- """
- "{"tools":
- [{"add_to_tool_panel": true,
- "description": "data on any column using simple expressions",
- "guid": "localhost:9009/repos/iuc/filtering_with_empty_test_tags/Filter1/1.1.0",
- "id": "Filter1",
- "name": "Filter",
- "requirements": [],
- "tests":
- [{"inputs": [], "name": "Test-1", "outputs": [], "required_files": []},
- {"inputs": [], "name": "Test-2", "outputs": [], "required_files": []}],
- "tool_config": "database/community_files/000/repo_6/filtering.xml",
- "tool_type": "default",
- "version": "1.1.0",
- "version_string_cmd": null}]}"
- """
if tool_dicts is not None:
has_test_data = False
testable_revision_found = False
diff -r d28d25d66095b84af1aaee1a487ee2b27c5a07ce -r ee214245805dee0e811a93db339ef9ab134de9a3 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
@@ -91,7 +91,7 @@
default_galaxy_test_port_min = 10000
default_galaxy_test_port_max = 10999
default_galaxy_test_host = '127.0.0.1'
-default_galaxy_master_api_key = "123456"
+default_galaxy_master_api_key = None
# should this serve static resources (scripts, images, styles, etc.)
STATIC_ENABLED = True
@@ -262,14 +262,14 @@
return passed_tests
return []
-def deactivate_repository( app, repository_info_dict ):
+def deactivate_repository( app, repository_dict ):
# Clean out any generated tests. This is necessary for Twill.
remove_generated_tests( app )
sa_session = app.model.context.current
# The dict contains the only repository the app should have installed at this point.
- repository = test_db_util.get_installed_repository_by_name_owner_changeset_revision( repository_info_dict[ 'name' ],
- repository_info_dict[ 'owner' ],
- repository_info_dict[ 'changeset_revision' ] )
+ repository = test_db_util.get_installed_repository_by_name_owner_changeset_revision( repository_dict[ 'name' ],
+ repository_dict[ 'owner' ],
+ repository_dict[ 'changeset_revision' ] )
# We have to do this through Twill, in order to maintain app.toolbox and shed_tool_conf.xml in a state that is valid for future tests.
for required_repository in repository.repository_dependencies:
repository_dict = dict( name=required_repository.name,
@@ -355,14 +355,17 @@
return url
def get_latest_downloadable_changeset_revision( url, name, owner ):
+ error_message = ''
api_url_parts = [ 'api', 'repositories', 'get_ordered_installable_revisions' ]
params = urllib.urlencode( dict( name=name, owner=owner ) )
api_url = get_api_url( url, api_url_parts, params )
- changeset_revisions = json_from_url( api_url )
+ changeset_revisions, error_message = json_from_url( api_url )
+ if error_message:
+ return None, error_message
if changeset_revisions:
- return changeset_revisions[ -1 ]
+ return changeset_revisions[ -1 ], error_message
else:
- return '000000000000'
+ return suc.INITIAL_CHANGELOG_HASH, error_message
def get_missing_tool_dependencies( repository ):
log.debug( 'Checking %s repository %s for missing tool dependencies.' % ( repository.status, repository.name ) )
@@ -370,18 +373,24 @@
for tool_dependency in repository.tool_dependencies:
log.debug( 'Tool dependency %s version %s has status %s.' % ( tool_dependency.name, tool_dependency.version, tool_dependency.status ) )
for repository_dependency in repository.repository_dependencies:
- if not repository_dependency.includes_tool_dependencies:
- continue
- missing_tool_dependencies.extend( get_missing_tool_dependencies( repository_dependency ) )
+ if repository_dependency.includes_tool_dependencies:
+ missing_tool_dependencies.extend( get_missing_tool_dependencies( repository_dependency ) )
return missing_tool_dependencies
-def get_repository_info_from_api( url, repository_info_dict ):
- parts = [ 'api', 'repositories', repository_info_dict[ 'repository_id' ] ]
+def get_repository_info_from_api( url, repository_dict ):
+ error_message = ''
+ parts = [ 'api', 'repositories', repository_dict[ 'repository_id' ] ]
api_url = get_api_url( base=url, parts=parts )
- extended_dict = json_from_url( api_url )
- latest_changeset_revision = get_latest_downloadable_changeset_revision( url, extended_dict[ 'name' ], extended_dict[ 'owner' ] )
+ extended_dict, error_message = json_from_url( api_url )
+ if error_message:
+ return None, error_message
+ latest_changeset_revision, error_message = get_latest_downloadable_changeset_revision( url,
+ extended_dict[ 'name' ],
+ extended_dict[ 'owner' ] )
+ if error_message:
+ return None, error_message
extended_dict[ 'latest_revision' ] = str( latest_changeset_revision )
- return extended_dict
+ return extended_dict, error_message
def get_repository_tuple_from_elem( elem ):
attributes = elem.attrib
@@ -390,78 +399,84 @@
changeset_revision = attributes.get( 'changeset_revision', None )
return ( name, owner, changeset_revision )
-def get_repositories_to_install( tool_shed_url, latest_revision_only=True ):
- '''
+def get_repositories_to_install( tool_shed_url ):
+ """
Get a list of repository info dicts to install. This method expects a json list of dicts with the following structure:
- [
- {
- "changeset_revision": <revision>,
- "encoded_repository_id": <encoded repository id from the tool shed>,
- "name": <name>,
- "owner": <owner>,
- "tool_shed_url": <url>
- },
- ...
- ]
- NOTE: If the tool shed URL specified in any dict is not present in the tool_sheds_conf.xml, the installation will fail.
- '''
- assert tool_shed_api_key is not None, 'Cannot proceed without tool shed API key.'
+ [{ "changeset_revision": <revision>,
+ "encoded_repository_id": <encoded repository id from the tool shed>,
+ "name": <name>,
+ "owner": <owner>,
+ "tool_shed_url": <url> }]
+ """
+ error_message = ''
+ latest_revision_only = '-check_all_revisions' not in sys.argv
+ repository_dicts = []
+ # We are testing deprecated repositories because it is possible that a deprecated repository contains valid tools that
+ # someone has previously installed. Deleted repositories have never been installed, so should not be tested. If they are
+ # undeleted, this script will then test them the next time it runs. We don't need to check if a repository has been deleted
+ # here because our call to the Tool Shed API filters by downloadable='true', in which case deleted will always be False.
+ if os.path.exists( exclude_list_file ):
+ log.debug( 'Loading the list of repositories excluded from testing from the file %s...', exclude_list_file )
+ exclude_list = parse_exclude_list( exclude_list_file )
+ results_dict[ 'exclude_list' ] = exclude_list
params = urllib.urlencode( dict( do_not_test='false',
downloadable='true',
malicious='false',
includes_tools='true',
skip_tool_test='false' ) )
api_url = get_api_url( base=tool_shed_url, parts=[ 'repository_revisions' ], params=params )
- base_repository_list = json_from_url( api_url )
- log.info( 'The api returned %d metadata revisions.', len( base_repository_list ) )
- known_repository_ids = {}
- detailed_repository_list = []
- for repository_to_install_dict in base_repository_list:
+ baseline_repository_dicts, error_message = json_from_url( api_url )
+ if error_message:
+ return None, error_message
+ log.debug( 'The Tool Shed API returned %d metadata revisions for installation and testing.' % len( baseline_repository_dicts ) )
+ for baseline_repository_dict in baseline_repository_dicts:
# We need to get some details from the tool shed API, such as repository name and owner, to pass on to the
# module that will generate the install methods.
- repository_info_dict = get_repository_info_from_api( galaxy_tool_shed_url, repository_to_install_dict )
- if repository_info_dict[ 'latest_revision' ] == '000000000000':
- continue
- owner = repository_info_dict[ 'owner' ]
- name = repository_info_dict[ 'name' ]
- changeset_revision = repository_to_install_dict[ 'changeset_revision' ]
- repository_id = repository_to_install_dict[ 'repository_id' ]
- # We are testing deprecated repositories, because it is possible that a deprecated repository contains valid
- # and functionally correct tools that someone has previously installed. Deleted repositories have never been installed,
- # and therefore do not need to be checked. If they are undeleted, this script will then test them the next time it runs.
- if repository_info_dict[ 'deleted' ]:
- log.info( "Skipping revision %s of repository id %s (%s/%s) since the repository is deleted...",
- changeset_revision,
- repository_id,
- name,
- owner )
- continue
- # Now merge the dict returned from /api/repository_revisions with the detailed dict we just retrieved.
- if latest_revision_only:
- if changeset_revision == repository_info_dict[ 'latest_revision' ]:
- detailed_repository_list.append( dict( repository_info_dict.items() + repository_to_install_dict.items() ) )
+ repository_dict, error_message = get_repository_info_from_api( galaxy_tool_shed_url, baseline_repository_dict )
+ if error_message:
+ log.debug( 'Error getting additional details about repository %s from the API: %s' % ( str( name ), error_message ) )
else:
- detailed_repository_list.append( dict( repository_info_dict.items() + repository_to_install_dict.items() ) )
- repositories_tested = len( detailed_repository_list )
+ # Don't test empty repositories.
+ changeset_revision = baseline_repository_dict[ 'changeset_revision' ]
+ if changeset_revision != suc.INITIAL_CHANGELOG_HASH:
+ # Merge the dictionary returned from /api/repository_revisions with the detailed repository_dict and
+ # append it to the list of repository_dicts to install and test.
+ if latest_revision_only:
+ latest_revision = repository_dict[ 'latest_revision' ]
+ if changeset_revision == latest_revision:
+ repository_dicts.append( dict( repository_dict.items() + baseline_repository_dict.items() ) )
+ else:
+ repository_dicts.append( dict( repository_dict.items() + baseline_repository_dict.items() ) )
if latest_revision_only:
skipped_previous = ' and metadata revisions that are not the most recent'
else:
skipped_previous = ''
if testing_single_repository:
- log.info( 'Testing single repository with name %s and owner %s.',
- testing_single_repository[ 'name' ],
- testing_single_repository[ 'owner' ])
- for repository_to_install in detailed_repository_list:
- if repository_to_install[ 'name' ] == testing_single_repository[ 'name' ] \
- and repository_to_install[ 'owner' ] == testing_single_repository[ 'owner' ]:
- if testing_single_repository[ 'changeset_revision' ] is None:
- return [ repository_to_install ]
+ tsr_name = testing_single_repository[ 'name' ]
+ tsr_owner = testing_single_repository[ 'owner' ]
+ tsr_changeset_revision = testing_single_repository[ 'changeset_revision' ]
+ log.debug( 'Testing single repository with name %s and owner %s.' % ( str( tsr_name ), str( tsr_owner ) ) )
+ for repository_to_install in repository_dicts:
+ rti_name = repository_to_install[ 'name' ]
+ rti_owner = repository_to_install[ 'owner' ]
+ rti_changeset_revision = repository_to_install[ 'changeset_revision' ]
+ if rti_name == tsr_name and rti_owner == tsr_owner:
+ if tsr_changeset_revision is None:
+ return [ repository_to_install ], error_message
else:
- if testing_single_repository[ 'changeset_revision' ] == repository_to_install[ 'changeset_revision' ]:
- return [ repository_to_install ]
- return []
- log.info( 'After removing deleted repositories%s from the list, %d remain to be tested.', skipped_previous, repositories_tested )
- return detailed_repository_list
+ if tsr_changeset_revision == rti_changeset_revision:
+ return repository_dicts, error_message
+ return repository_dicts, error_message
+ # Get a list of repositories to test from the tool shed specified in the GALAXY_INSTALL_TEST_TOOL_SHED_URL environment variable.
+ log.debug( "Retrieved %d repositories from the API url: %s." % ( len( repository_dicts ), str( galaxy_tool_shed_url ) ) )
+ if '-list_repositories' in sys.argv:
+ log.debug( "Repositories for testing:" )
+ for repository_dict in repository_dicts:
+ log.debug( "Revision %s of repository %s owned by %s" % \
+ ( str( repository_dict.get( 'changeset_revision', None ) ), \
+ str( repository_dict.get( 'name', None ) ), \
+ str( repository_dict.get( 'owner', None ) ) ) )
+ return repository_dicts, error_message
def get_tool_info_from_test_id( test_id ):
'''
@@ -474,82 +489,289 @@
return tool_id, tool_version
def get_tool_test_results_from_api( tool_shed_url, metadata_revision_id ):
+ error_message = ''
api_path = [ 'api', 'repository_revisions', metadata_revision_id ]
api_url = get_api_url( base=tool_shed_url, parts=api_path )
- repository_metadata = json_from_url( api_url )
+ 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 {}
- return tool_test_results
+ return {}, error_message
+ return tool_test_results, error_message
-def install_repository( repository_info_dict ):
- """
- The repository_info_dict looks something like:
- {
- "changeset_revision": "13fa22a258b5",
- "contents_url": "/api/repositories/529fd61ab1c6cc36/contents",
- "deleted": false,
- "deprecated": false,
- "description": "Convert column case.",
- "downloadable": true,
- "id": "529fd61ab1c6cc36",
- "long_description": "This tool takes the specified columns and converts them to uppercase or lowercase.",
- "malicious": false,
- "name": "change_case",
- "owner": "test",
- "private": false,
- "repository_id": "529fd61ab1c6cc36",
- "times_downloaded": 0,
- "tool_shed_url": "http://toolshed.local:10001",
- "url": "/api/repository_revisions/529fd61ab1c6cc36",
- "user_id": "529fd61ab1c6cc36"
- }
- """
- data[ 'tool_shed_url' ] = repository_info_dict[ 'tool_shed_url' ]
- data[ 'name' ] = repository_info_dict[ 'name' ]
- data[ 'owner' ] = repository_info_dict[ 'owner' ]
- data[ 'changeset_revision' ] = repository_info_dict[ 'changeset_revision' ]
- data[ 'install_repository_dependencies' ] = True
- data[ 'install_tool_dependencies' ] = True
- submit( options.api, '%s%s' % ( galaxy_url.strip( '/' ), '/api/tool_shed_repositories/new/install_repository_revision' ), data )
+def handle_missing_dependencies( app, repository, metadata_revision_id, missing_tool_dependencies, repository_dict, repository_status_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
+ # for the test to be considered reliable.
+ log.debug( 'The following dependencies of this repository are missing, so skipping functional tests.' )
+ # In keeping with the standard display layout, add the error message to the dict for each tool individually.
+ for dependency in repository.missing_tool_dependencies:
+ log.debug( 'Missing tool dependency %s of type %s version %s: %s' % \
+ ( str( dependency.name ), str( dependency.type ), str( dependency.version ), unicodify( dependency.error_message ) ) )
+ test_result = dict( type=dependency.type,
+ name=dependency.name,
+ version=dependency.version,
+ error_message=dependency.error_message )
+ repository_status_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 ) ) )
+ test_result = dict( tool_shed=dependency.tool_shed,
+ name=dependency.name,
+ owner=dependency.owner,
+ changeset_revision=dependency.changeset_revision,
+ error_message=dependency.error_message )
+ repository_status_dict[ 'installation_errors' ][ 'repository_dependencies' ].append( test_result )
+ # Record the status of this repository in the tool shed.
+ params[ 'tools_functionally_correct' ] = False
+ params[ 'do_not_test' ] = False
+ params[ 'test_install_error' ] = True
+ register_test_result( galaxy_tool_shed_url,
+ metadata_revision_id,
+ repository_status_dict,
+ repository_dict,
+ params )
+ # Since this repository is missing components, we do not want to test it. Deactivate this repository.
+ # The deactivate flag is set to True if the environment variable GALAXY_INSTALL_TEST_KEEP_TOOL_DEPENDENCIES
+ # is set to 'true'.
+ deactivate = asbool( os.environ.get( 'GALAXY_INSTALL_TEST_KEEP_TOOL_DEPENDENCIES', False ) )
+ if deactivate:
+ log.debug( 'Due to the above missing tool dependencies, we are now uninstalling the following tool dependencies but not changing their repositories.' )
+ for missing_tool_dependency in missing_tool_dependencies:
+ uninstall_tool_dependency( app, missing_tool_dependency )
+ # We are deactivating this repository and all of its repository dependencies.
+ log.debug( 'Due to the above missing repository dependencies, we are now deactivating the following repositories.' )
+ deactivate_repository( app, repository_dict )
+ else:
+ # We are uninstalling this repository and all of its repository dependencies.
+ log.debug( 'Due to the above missing repository dependencies, we are now uninstalling the following repositories.' )
+ uninstall_repository( app, repository_dict )
+ results_dict[ 'repositories_failed_install' ].append( dict( name=str( repository.name ),
+ owner=str( repository.owner ),
+ changeset_revision=str( repository.changeset_revision ) ) )
+ # Set the test_toolbox.toolbox module-level variable to the new app.toolbox.
+ test_toolbox.toolbox = app.toolbox
+ return repository_status_dict, results_dict
-def is_latest_downloadable_revision( url, repository_info_dict ):
- latest_revision = get_latest_downloadable_changeset_revision( url, name=repository_info_dict[ 'name' ], owner=repository_info_dict[ 'owner' ] )
- return str( repository_info_dict[ 'changeset_revision' ] ) == str( latest_revision )
+def initialize_results_dict():
+ # Initialize a dictionary for the summary that will be printed to stdout.
+ results_dict = {}
+ results_dict[ 'total_repositories_tested' ] = 0
+ results_dict[ 'repositories_passed' ] = []
+ results_dict[ 'repositories_failed' ] = []
+ results_dict[ 'repositories_failed_install' ] = []
+ results_dict[ 'exclude_list' ] = []
+ return results_dict
+
+def install_repository( app, repository_dict ):
+ """Attempt to install a repository defined by the received repository_dict from the tool shed into Galaxy."""
+ name = str( repository_dict[ 'name' ] )
+ owner = str( repository_dict[ 'owner' ] )
+ changeset_revision = str( repository_dict[ 'changeset_revision' ] )
+ error_message = ''
+ repository = None
+ log.debug( "Installing revision %s of repository %s owned by %s..." % ( str( changeset_revision ), str( name ), str( owner ) ) )
+ # Explicitly clear tests from twill's test environment.
+ remove_generated_tests( app )
+ # Use the repository information dictionary to generate an install method that will install the repository into the
+ # embedded Galaxy application, with tool dependencies and repository dependencies, if any.
+ test_install_repositories.generate_install_method( repository_dict )
+ # Configure nose to run the install method as a test.
+ test_config = nose.config.Config( env=os.environ, plugins=nose.plugins.manager.DefaultPluginManager() )
+ test_config.configure( sys.argv )
+ # Run the configured install method as a test. This method uses the embedded Galaxy application's web interface to
+ # install the specified repository with tool and repository dependencies also selected for installation.
+ result, _ = run_tests( test_config )
+ try:
+ repository = test_db_util.get_installed_repository_by_name_owner_changeset_revision( name, owner, changeset_revision )
+ except Exception, e:
+ error_message = 'Error getting revision %s of installed repository %s owned by %s: %s' % \
+ ( str( changeset_revision ), str( name ), str( owner ), str( e ) )
+ log.exception( error_message )
+ return repository, error_message
+
+def install_and_test_repositories( app, galaxy_shed_tools_dict, galaxy_shed_tool_conf_file ):
+ error_message = ''
+ # Allow the option to keep or delete tool dependencies when a repository has been tested.
+ deactivate = asbool( os.environ.get( 'GALAXY_INSTALL_TEST_KEEP_TOOL_DEPENDENCIES', False ) )
+ # Initialize a dictionary for the summary that will be printed to stdout.
+ results_dict = initialize_results_dict()
+ total_repositories_tested = results_dict[ 'total_repositories_tested' ]
+ repositories_to_install, error_message = get_repositories_to_install( galaxy_tool_shed_url )
+ if error_message:
+ return None, error_message
+ # Generate a test method that will use Twill to install each repository into the embedded Galaxy application that was
+ # started up, installing repository and tool dependencies. Upon successful installation, generate a test case for each
+ # functional test defined for each tool in the repository and execute the test cases. Record the result of the tests.
+ # The traceback and captured output of the tool that was run will be recored for test failures. After all tests have
+ # completed, the repository is uninstalled, so test cases don't interfere with the next repository's functional tests.
+ for repository_dict in repositories_to_install:
+ # Each repository_dict looks something like:
+ # { "changeset_revision": "13fa22a258b5",
+ # "contents_url": "/api/repositories/529fd61ab1c6cc36/contents",
+ # "deleted": false,
+ # "deprecated": false,
+ # "description": "Convert column case.",
+ # "downloadable": true,
+ # "id": "529fd61ab1c6cc36",
+ # "long_description": "This tool takes the specified columns and converts them to uppercase or lowercase.",
+ # "malicious": false,
+ # "name": "change_case",
+ # "owner": "test",
+ # "private": false,
+ # "repository_id": "529fd61ab1c6cc36",
+ # "times_downloaded": 0,
+ # "tool_shed_url": "http://toolshed.local:10001",
+ # "url": "/api/repository_revisions/529fd61ab1c6cc36",
+ # "user_id": "529fd61ab1c6cc36" }
+ params = {}
+ changeset_revision = repository_dict.get( 'changeset_revision', None )
+ metadata_revision_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' ] )
+ # 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=[] )
+ # Handle repositories not to be tested.
+ exclude_list = results_dict[ 'exclude_list' ]
+ # Entries in the exclude_list look something like this.
+ # { 'reason': The default reason or the reason specified in this section,
+ # 'repositories':
+ # [( name, owner, changeset revision if changeset revision else None ),
+ # ( name, owner, changeset revision if changeset revision else None )] }
+ # If changeset revision is None, that means the entire repository is excluded from testing, otherwise only the specified
+ # revision should be skipped.
+ skip_this_repository = False
+ skip_reason = None
+ for exclude_dict in exclude_list:
+ reason = exclude_dict[ 'reason' ]
+ exclude_repositories = exclude_dict[ 'repositories' ]
+ if ( name, owner, changeset_revision ) in exclude_repositories or ( name, owner, None ) in exclude_repositories:
+ skip_this_repository = True
+ skip_reason = reason
+ break
+ if skip_this_repository:
+ repository_status_dict[ 'not_tested' ] = dict( reason=skip_reason )
+ params[ 'tools_functionally_correct' ] = False
+ params[ 'do_not_test' ] = False
+ register_test_result( galaxy_tool_shed_url, metadata_revision_id, repository_status_dict, repository_dict, params )
+ log.debug( "Not testing revision %s of repository %s owned by %s." % ( str( changeset_revision ), str( name ), str( owner ) ) )
+ else:
+ repository, error_message = install_repository( app, repository_dict )
+ 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' % str( name ) )
+ try:
+ repository = test_db_util.get_installed_repository_by_name_owner_changeset_revision( name, owner, changeset_revision )
+ except:
+ log.exception( 'No installed repository found.' )
+ error_message = '%s\n%s' % ( error_message, extract_log_data( result, from_tool_test=False ) )
+ 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[ 'tools_functionally_correct' ] = False
+ params[ 'test_install_error' ] = True
+ params[ 'do_not_test' ] = False
+ register_test_result( galaxy_tool_shed_url,
+ metadata_revision_id,
+ repository_status_dict,
+ repository_dict,
+ params )
+ try:
+ if deactivate:
+ # We are deactivating this repository and all of its repository dependencies.
+ success = deactivate_repository( app, repository_dict )
+ else:
+ # We are uninstalling this repository and all of its repository dependencies.
+ success = uninstall_repository( app, repository_dict )
+ except:
+ log.exception( 'Encountered error attempting to deactivate or uninstall %s.', repository_dict[ 'name' ] )
+ success = False
+ if not success:
+ log.error( 'Repository %s failed to uninstall.', 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:
+ repository_status_dict, results_dict = handle_missing_dependencies( app,
+ repository,
+ metadata_revision_id,
+ 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 ) ) )
+ params, repository_status_dict, results_dict = test_repository_tools( app,
+ repository,
+ params,
+ metadata_revision_id,
+ repository_dict,
+ repository_status_dict,
+ results_dict )
+ total_repositories_tested += 1
+ results_dict[ 'total_repositories_tested' ] = total_repositories_tested
+ return results_dict, error_message
+
+def is_latest_downloadable_revision( url, repository_dict ):
+ latest_revision = get_latest_downloadable_changeset_revision( url, name=repository_dict[ 'name' ], owner=repository_dict[ 'owner' ] )
+ return str( repository_dict[ 'changeset_revision' ] ) == str( latest_revision )
def json_from_url( url ):
+ error_message = ''
url_handle = urllib.urlopen( url )
url_contents = url_handle.read()
try:
parsed_json = from_json_string( url_contents )
- except:
- log.exception( 'Error parsing JSON data.' )
- raise
- return parsed_json
+ except Exception, e:
+ error_message = str( url_contents )
+ log.exception( 'Error parsing JSON data in json_from_url(): %s.' % str( e ) )
+ return None, error_message
+ return parsed_json, error_message
def parse_exclude_list( xml_filename ):
- '''
- This method should return a list with the following structure:
- [
- {
- 'reason': The default reason or the reason specified in this section,
- 'repositories':
- [
- ( name, owner, changeset revision if changeset revision else None ),
- ( name, owner, changeset revision if changeset revision else None )
- ]
- },
- {
- 'reason': The default reason or the reason specified in this section,
- 'repositories':
- [
- ( name, owner, changeset revision if changeset revision else None ),
- ( name, owner, changeset revision if changeset revision else None )
- ]
- },
- ]
- '''
+ """Return a list of repositories to exclude from testing."""
+ # This method should return a list with the following structure:
+ # [{ 'reason': The default reason or the reason specified in this section,
+ # 'repositories': [( name, owner, changeset revision if changeset revision else None ),
+ # ( name, owner, changeset revision if changeset revision else None )]}]
exclude_list = []
exclude_verbose = []
xml_tree = parse_xml( xml_filename )
@@ -572,17 +794,17 @@
exclude_count += 1
exclude_dict[ 'repositories' ].append( repository_tuple )
exclude_list.append( exclude_dict )
- log.debug( '%d repositories excluded from testing...', exclude_count )
+ log.debug( '%s repositories excluded from testing...' % str( exclude_count ) )
if '-list_repositories' in sys.argv:
for name, owner, changeset_revision in exclude_verbose:
if changeset_revision:
- log.debug( 'Repository %s owned by %s, changeset revision %s.', name, owner, changeset_revision )
+ log.debug( 'Repository %s owned by %s, changeset revision %s.' % ( str( name ), str( owner ), str( changeset_revision ) ) )
else:
- log.debug( 'Repository %s owned by %s, all revisions.', name, owner )
+ log.debug( 'Repository %s owned by %s, all revisions.' % ( str( name ), str( owner ) ) )
return exclude_list
-def register_test_result( url, metadata_id, test_results_dict, repository_info_dict, params ):
- '''Update the repository metadata tool_test_results and appropriate flags using the API.'''
+def register_test_result( url, metadata_id, test_results_dict, repository_dict, params ):
+ """Update the repository metadata tool_test_results and appropriate flags using the API."""
params[ 'tool_test_results' ] = test_results_dict
if '-info_only' in sys.argv or 'GALAXY_INSTALL_TEST_INFO_ONLY' in os.environ:
return {}
@@ -594,15 +816,17 @@
return_formatted=False )
def remove_generated_tests( app ):
- # Delete any configured tool functional tests from the test_toolbox.__dict__, otherwise nose will find them
- # and try to re-run the tests after uninstalling the repository, which will cause false failure reports,
- # since the test data has been deleted from disk by now.
+ """
+ Delete any configured tool functional tests from the test_toolbox.__dict__, otherwise nose will find them
+ and try to re-run the tests after uninstalling the repository, which will cause false failure reports,
+ since the test data has been deleted from disk by now.
+ """
tests_to_delete = []
tools_to_delete = []
global test_toolbox
for key in test_toolbox.__dict__:
if key.startswith( 'TestForTool_' ):
- log.info( 'Tool test found in test_toolbox, deleting: %s', key )
+ log.debug( 'Tool test found in test_toolbox, deleting: %s' % str( key ) )
# We can't delete this test just yet, we're still iterating over __dict__.
tests_to_delete.append( key )
tool_id = key.replace( 'TestForTool_', '' )
@@ -615,15 +839,17 @@
for tool in tools_to_delete:
del app.toolbox.tools_by_id[ tool ]
-def remove_install_tests( app ):
- # Delete any configured repository installation tests from the test_toolbox.__dict__, otherwise nose will find them
- # and try to install the repository again while running tool functional tests.
+def remove_install_tests():
+ """
+ Delete any configured repository installation tests from the test_toolbox.__dict__, otherwise nose will find them
+ and try to install the repository again while running tool functional tests.
+ """
tests_to_delete = []
global test_toolbox
# Push all the toolbox tests to module level
for key in test_install_repositories.__dict__:
if key.startswith( 'TestInstallRepository_' ):
- log.info( 'Repository installation process found, deleting: %s', key )
+ log.debug( 'Repository installation process found, deleting: %s' % str( key ) )
# We can't delete this test just yet, we're still iterating over __dict__.
tests_to_delete.append( key )
for key in tests_to_delete:
@@ -646,9 +872,9 @@
result = test_runner.run( tests )
return result, test_config.plugins._plugins
-def show_summary_output( repository_info_dicts ):
+def show_summary_output( repository_dicts ):
repositories_by_owner = {}
- for repository in repository_info_dicts:
+ for repository in repository_dicts:
if repository[ 'owner' ] not in repositories_by_owner:
repositories_by_owner[ repository[ 'owner' ] ] = []
repositories_by_owner[ repository[ 'owner' ] ].append( repository )
@@ -657,29 +883,106 @@
for repository in repositories_by_owner[ owner ]:
print "# %s owned by %s, changeset revision %s" % ( repository[ 'name' ], repository[ 'owner' ], repository[ 'changeset_revision' ] )
-def uninstall_repository( app, repository_info_dict ):
+def test_repository_tools( app, repository, params, metadata_revision_id, repository_dict, repository_status_dict, results_dict ):
+ name = str( repository.name )
+ owner = str( repository.owner )
+ changeset_revision = str( repository.changeset_revision )
+ # Set the module-level variable 'toolbox', so that test.functional.test_toolbox will generate the appropriate test methods.
+ test_toolbox.toolbox = app.toolbox
+ # Generate the test methods for this installed repository. We need to pass in True here, or it will look
+ # in $GALAXY_HOME/test-data for test data, which may result in missing or invalid test files.
+ test_toolbox.build_tests( testing_shed_tools=True, master_api_key=default_galaxy_master_api_key )
+ # Set up nose to run the generated functional tests.
+ test_config = nose.config.Config( env=os.environ, plugins=nose.plugins.manager.DefaultPluginManager() )
+ test_config.configure( sys.argv )
+ # Run the configured tests.
+ result, test_plugins = run_tests( test_config )
+ success = result.wasSuccessful()
+ # Use the ReportResults nose plugin to get a list of tests that passed.
+ for plugin in test_plugins:
+ if hasattr( plugin, 'getTestStatus' ):
+ test_identifier = '%s/%s' % ( owner, name )
+ passed_tests = plugin.getTestStatus( test_identifier )
+ break
+ repository_status_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 )
+ 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
+ # controller with the status of the test. This also sets the do_not_test and tools_functionally correct flags, and
+ # updates the time_last_tested field to today's date.
+ results_dict[ 'repositories_passed' ].append( dict( name=name, owner=owner, changeset_revision=changeset_revision ) )
+ params[ 'tools_functionally_correct' ] = True
+ params[ 'do_not_test' ] = False
+ params[ 'test_install_error' ] = False
+ register_test_result( galaxy_tool_shed_url,
+ metadata_revision_id,
+ repository_status_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' ] = 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.
+ 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[ 'tools_functionally_correct' ] = False
+ params[ 'test_install_error' ] = False
+ params[ 'do_not_test' ] = str( set_do_not_test )
+ register_test_result( galaxy_tool_shed_url,
+ metadata_revision_id,
+ repository_status_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
+ # repository using Twill.
+ deactivate = asbool( os.environ.get( 'GALAXY_INSTALL_TEST_KEEP_TOOL_DEPENDENCIES', False ) )
+ if deactivate:
+ log.debug( 'Deactivating changeset revision %s of repository %s' % ( str( changeset_revision ), str( name ) ) )
+ # We are deactivating this repository and all of its repository dependencies.
+ success = deactivate_repository( app, repository_dict )
+ else:
+ log.debug( 'Uninstalling changeset revision %s of repository %s' % ( str( changeset_revision ), str( name ) ) )
+ # We are uninstalling this repository and all of its repository dependencies.
+ success = uninstall_repository( app, repository_dict )
+ if not success:
+ log.debug( 'Repository %s failed to uninstall.' % str( name ) )
+ # Set the test_toolbox.toolbox module-level variable to the new app.toolbox.
+ test_toolbox.toolbox = app.toolbox
+ return params, repository_status_dict, results_dict
+
+def uninstall_repository( app, repository_dict ):
# Clean out any generated tests. This is necessary for Twill.
remove_generated_tests( app )
sa_session = app.model.context.current
# The dict contains the only repository the app should have installed at this point.
- repository = test_db_util.get_installed_repository_by_name_owner_changeset_revision( repository_info_dict[ 'name' ],
- repository_info_dict[ 'owner' ],
- repository_info_dict[ 'changeset_revision' ] )
+ repository = test_db_util.get_installed_repository_by_name_owner_changeset_revision( repository_dict[ 'name' ],
+ repository_dict[ 'owner' ],
+ repository_dict[ 'changeset_revision' ] )
# We have to do this through Twill, in order to maintain app.toolbox and shed_tool_conf.xml in a state that is valid for future tests.
for required_repository in repository.repository_dependencies:
- repository_dict = dict( name=required_repository.name,
- owner=required_repository.owner,
- changeset_revision=required_repository.changeset_revision )
+ repository_dict = dict( name=str( required_repository.name ),
+ owner=str( required_repository.owner ),
+ changeset_revision=str( required_repository.changeset_revision ) )
# Generate a test method to uninstall this repository through the embedded Galaxy application's web interface.
test_install_repositories.generate_deactivate_or_uninstall_method( repository_dict, deactivate=False )
log.debug( 'Changeset revision %s of %s repository %s selected for uninstallation.' % \
- ( required_repository.changeset_revision, required_repository.status, required_repository.name ) )
- repository_dict = dict( name=repository.name,
- owner=repository.owner,
- changeset_revision=repository.changeset_revision )
+ ( str( required_repository.changeset_revision ), str( required_repository.status ), str( required_repository.name ) ) )
+ repository_dict = dict( name=str( repository.name ),
+ owner=str( repository.owner ),
+ changeset_revision=str( repository.changeset_revision ) )
test_install_repositories.generate_deactivate_or_uninstall_method( repository_dict, deactivate=False )
log.debug( 'Changeset revision %s of %s repository %s selected for uninstallation.' % \
- ( repository.changeset_revision, repository.status, repository.name ) )
+ ( str( repository.changeset_revision ), str( repository.status ), str( repository.name ) ) )
# Set up nose to run the generated uninstall method as a functional test.
test_config = nose.config.Config( env=os.environ, plugins=nose.plugins.manager.DefaultPluginManager() )
test_config.configure( sys.argv )
@@ -708,11 +1011,16 @@
suc.remove_dir( tool_dependency_install_path )
def main():
+ if tool_shed_api_key is None:
+ # If the tool shed URL specified in any dict is not present in the tool_sheds_conf.xml, the installation will fail.
+ log.debug( 'Cannot proceed without a valid tool shed API key set in the enviroment variable GALAXY_INSTALL_TEST_TOOL_SHED_API_KEY.' )
+ return 1
# ---- Configuration ------------------------------------------------------
- # TODO: refactor this very large main method into smaller, more maintainable components.
galaxy_test_host = os.environ.get( 'GALAXY_INSTALL_TEST_HOST', default_galaxy_test_host )
+ # Set the GALAXY_INSTALL_TEST_HOST variable so that Twill will have the Galaxy url to install repositories into.
+ os.environ[ 'GALAXY_INSTALL_TEST_HOST' ] = galaxy_test_host
galaxy_test_port = os.environ.get( 'GALAXY_INSTALL_TEST_PORT', str( default_galaxy_test_port_max ) )
-
+ os.environ[ 'GALAXY_TEST_PORT' ] = galaxy_test_port
tool_path = os.environ.get( 'GALAXY_INSTALL_TEST_TOOL_PATH', 'tools' )
if 'HTTP_ACCEPT_LANGUAGE' not in os.environ:
os.environ[ 'HTTP_ACCEPT_LANGUAGE' ] = default_galaxy_locales
@@ -722,9 +1030,6 @@
use_distributed_object_store = os.environ.get( 'GALAXY_INSTALL_TEST_USE_DISTRIBUTED_OBJECT_STORE', False )
if not os.path.isdir( galaxy_test_tmp_dir ):
os.mkdir( galaxy_test_tmp_dir )
- galaxy_test_proxy_port = None
- # Allow the option to keep or delete tool dependencies when a repository has been tested.
- deactivate = asbool( os.environ.get( 'GALAXY_INSTALL_TEST_KEEP_TOOL_DEPENDENCIES', False ) )
# Set up the configuration files for the Galaxy instance.
shed_tool_data_table_conf_file = os.environ.get( 'GALAXY_INSTALL_TEST_SHED_TOOL_DATA_TABLE_CONF', os.path.join( galaxy_test_tmp_dir, 'test_shed_tool_data_table_conf.xml' ) )
galaxy_tool_data_table_conf_file = os.environ.get( 'GALAXY_INSTALL_TEST_TOOL_DATA_TABLE_CONF', tool_data_table_conf )
@@ -735,6 +1040,9 @@
galaxy_tool_sheds_conf_file = os.environ.get( 'GALAXY_INSTALL_TEST_TOOL_SHEDS_CONF', os.path.join( galaxy_test_tmp_dir, 'test_tool_sheds_conf.xml' ) )
galaxy_shed_tools_dict = os.environ.get( 'GALAXY_INSTALL_TEST_SHED_TOOL_DICT_FILE', os.path.join( galaxy_test_tmp_dir, 'shed_tool_dict' ) )
file( galaxy_shed_tools_dict, 'w' ).write( to_json_string( {} ) )
+ # Set the GALAXY_TOOL_SHED_TEST_FILE environment variable to the path of the shed_tools_dict file, so that test.base.twilltestcase.setUp
+ # will find and parse it properly.
+ os.environ[ 'GALAXY_TOOL_SHED_TEST_FILE' ] = galaxy_shed_tools_dict
if 'GALAXY_INSTALL_TEST_TOOL_DATA_PATH' in os.environ:
tool_data_path = os.environ.get( 'GALAXY_INSTALL_TEST_TOOL_DATA_PATH' )
else:
@@ -768,9 +1076,7 @@
os.makedirs( dir )
except OSError:
pass
-
print "Database connection: ", database_connection
-
# Generate the shed_tool_data_table_conf.xml file.
file( shed_tool_data_table_conf_file, 'w' ).write( tool_data_table_conf_xml_template )
os.environ[ 'GALAXY_INSTALL_TEST_SHED_TOOL_DATA_TABLE_CONF' ] = shed_tool_data_table_conf_file
@@ -839,9 +1145,7 @@
kwargs[ 'database_engine_option_pool_size' ] = '10'
kwargs[ 'config_file' ] = galaxy_config_file
app = UniverseApplication( **kwargs )
-
- log.info( "Embedded Galaxy application started" )
-
+ log.debug( "Embedded Galaxy application started..." )
# ---- Run galaxy webserver ------------------------------------------------------
server = None
global_conf = get_webapp_global_conf()
@@ -850,7 +1154,6 @@
use_translogger=False,
static_enabled=STATIC_ENABLED,
app=app )
-
# Serve the app on a specified or random port.
if galaxy_test_port is not None:
server = httpserver.serve( webapp, host=galaxy_test_host, port=galaxy_test_port, start_loop=False )
@@ -869,10 +1172,7 @@
else:
raise Exception( "Unable to open a port between %s and %s to start Galaxy server" % \
( default_galaxy_test_port_min, default_galaxy_test_port_max ) )
- if galaxy_test_proxy_port:
- os.environ[ 'GALAXY_INSTALL_TEST_PORT' ] = galaxy_test_proxy_port
- else:
- os.environ[ 'GALAXY_INSTALL_TEST_PORT' ] = galaxy_test_port
+ os.environ[ 'GALAXY_INSTALL_TEST_PORT' ] = galaxy_test_port
# Start the server.
t = threading.Thread( target=server.serve_forever )
t.start()
@@ -886,9 +1186,9 @@
time.sleep( 0.1 )
else:
raise Exception( "Test HTTP server did not return '200 OK' after 10 tries" )
- log.info( "Embedded galaxy web server started" )
- log.info( "The embedded Galaxy application is running on %s:%s", galaxy_test_host, galaxy_test_port )
- log.info( "Repositories will be installed from the tool shed at %s", galaxy_tool_shed_url )
+ log.debug( "Embedded galaxy web server started..." )
+ log.debug( "The embedded Galaxy application is running on %s:%s" % ( str( galaxy_test_host ), str( galaxy_test_port ) ) )
+ log.debug( "Repositories will be installed from the tool shed at %s" % str( galaxy_tool_shed_url ) )
success = False
# If a tool_data_table_conf.test.xml file was found, add the entries from it into the app's tool data tables.
if additional_tool_data_tables:
@@ -896,452 +1196,68 @@
tool_data_path=additional_tool_data_path,
shed_tool_data_table_config=None,
persist=False )
- # Initialize some variables for the summary that will be printed to stdout.
- repositories_passed = []
- repositories_failed = []
- repositories_failed_install = []
- exclude_list = []
- if os.path.exists( exclude_list_file ):
- log.info( 'Loading the list of repositories excluded from testing from the file %s...', exclude_list_file )
- exclude_list = parse_exclude_list( exclude_list_file )
- try:
- # Get a list of repositories to test from the tool shed specified in the GALAXY_INSTALL_TEST_TOOL_SHED_URL environment variable.
- log.info( "Retrieving repositories to install from the URL:\n%s\n", str( galaxy_tool_shed_url ) )
- if '-check_all_revisions' not in sys.argv:
- repositories_to_install = get_repositories_to_install( galaxy_tool_shed_url, latest_revision_only=True )
+ now = strftime( "%Y-%m-%d %H:%M:%S" )
+ print "####################################################################################"
+ print "# %s - running repository installation and testing script." % now
+ print "####################################################################################"
+ results_dict, error_message = install_and_test_repositories( app, galaxy_shed_tools_dict, galaxy_shed_tool_conf_file )
+ if error_message:
+ log.debug( error_message )
+ else:
+ total_repositories_tested = results_dict[ 'total_repositories_tested' ]
+ repositories_passed = results_dict[ 'repositories_passed' ]
+ repositories_failed = results_dict[ 'repositories_failed' ]
+ repositories_failed_install = results_dict[ 'repositories_failed_install' ]
+ exclude_list = results_dict[ 'exclude_list' ]
+ now = strftime( "%Y-%m-%d %H:%M:%S" )
+ print "####################################################################################"
+ print "# %s - repository installation and testing script completed." % now
+ print "# Repository revisions tested: %s" % str( total_repositories_tested )
+ if '-info_only' in sys.argv:
+ print "# -info_only set, not updating the tool shed."
+ if total_repositories_tested > 0:
+ if repositories_passed:
+ print '# ----------------------------------------------------------------------------------'
+ print "# %d repositories passed all tests:" % len( repositories_passed )
+ show_summary_output( repositories_passed )
+ if repositories_failed:
+ print '# ----------------------------------------------------------------------------------'
+ print "# %d repositories failed one or more tests:" % len( repositories_failed )
+ show_summary_output( repositories_failed )
+ if repositories_failed_install:
+ # Set success to False so that the return code will not be 0.
+ success = False
+ print '# ----------------------------------------------------------------------------------'
+ print "# %d repositories with installation errors:" % len( repositories_failed_install )
+ show_summary_output( repositories_failed_install )
+ else:
+ success = True
else:
- repositories_to_install = get_repositories_to_install( galaxy_tool_shed_url, latest_revision_only=False )
- log.info( "Retrieved %d repositories from the API.", len( repositories_to_install ) )
- if '-list_repositories' in sys.argv:
- log.info( "The API returned the following repositories, not counting deleted:" )
- for repository_info_dict in repositories_to_install:
- log.info( "%s owned by %s changeset revision %s",
- repository_info_dict.get( 'name', None ),
- repository_info_dict.get( 'owner', None ),
- repository_info_dict.get( 'changeset_revision', None ) )
- repositories_tested = len( repositories_to_install )
- # This loop will iterate through the list of repositories generated by the above code, having already filtered out any
- # that were marked as deleted. For each repository, it will generate a test method that will use Twill to install that
- # repository into the embedded Galaxy application that was started up, selecting to install repository and tool
- # dependencies if they are defined. If the installation completes successfully, it will then generate a test case for
- # each functional test defined for each tool in the repository, and execute the generated test cases. When this completes,
- # it will record the result of the tests, and if any failed, the traceback and captured output of the tool that was run.
- # After all tests have completed, the repository is uninstalled, so that the previous test cases don't interfere with
- # the next repository's functional tests.
- for repository_info_dict in repositories_to_install:
- """
- Each repository_info_dict looks something like:
- {
- "changeset_revision": "13fa22a258b5",
- "contents_url": "/api/repositories/529fd61ab1c6cc36/contents",
- "deleted": false,
- "deprecated": false,
- "description": "Convert column case.",
- "downloadable": true,
- "id": "529fd61ab1c6cc36",
- "long_description": "This tool takes the specified columns and converts them to uppercase or lowercase.",
- "malicious": false,
- "name": "change_case",
- "owner": "test",
- "private": false,
- "repository_id": "529fd61ab1c6cc36",
- "times_downloaded": 0,
- "tool_shed_url": "http://toolshed.local:10001",
- "url": "/api/repository_revisions/529fd61ab1c6cc36",
- "user_id": "529fd61ab1c6cc36"
- }
- """
- repository_status = {}
- params = {}
- repository_id = str( repository_info_dict.get( 'repository_id', None ) )
- changeset_revision = str( repository_info_dict.get( 'changeset_revision', None ) )
- metadata_revision_id = repository_info_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_info_dict[ 'tool_shed_url' ] = galaxy_tool_shed_url
- # Get the name and owner out of the repository info dict.
- name = str( repository_info_dict[ 'name' ] )
- owner = str( repository_info_dict[ 'owner' ] )
- # Populate the repository_status dict now.
- repository_status = get_tool_test_results_from_api( galaxy_tool_shed_url, metadata_revision_id )
- if 'test_environment' not in repository_status:
- repository_status[ 'test_environment' ] = {}
- test_environment = get_test_environment( repository_status[ 'test_environment' ] )
- test_environment[ 'galaxy_database_version' ] = get_database_version( app )
- test_environment[ 'galaxy_revision'] = get_repository_current_revision( os.getcwd() )
- repository_status[ 'test_environment' ] = test_environment
- repository_status[ 'passed_tests' ] = []
- repository_status[ 'failed_tests' ] = []
- repository_status[ 'skip_reason' ] = None
- # Iterate through the list of repositories defined not to be installed. This should be a list of dicts in the following format:
- # {
- # 'reason': The default reason or the reason specified in this section,
- # 'repositories':
- # [
- # ( name, owner, changeset revision if changeset revision else None ),
- # ( name, owner, changeset revision if changeset revision else None )
- # ]
- # },
- # If changeset revision is None, that means the entire repository is excluded from testing, otherwise only the specified
- # revision should be skipped.
- # TODO: When a repository is selected to be skipped, use the API to update the tool shed with the defined skip reason.
- skip_this_repository = False
- skip_because = None
- for exclude_by_reason in exclude_list:
- reason = exclude_by_reason[ 'reason' ]
- exclude_repositories = exclude_by_reason[ 'repositories' ]
- if ( name, owner, changeset_revision ) in exclude_repositories or ( name, owner, None ) in exclude_repositories:
- skip_this_repository = True
- skip_because = reason
- break
- if skip_this_repository:
- repository_status[ 'not_tested' ] = dict( reason=skip_because )
- params[ 'tools_functionally_correct' ] = False
- params[ 'do_not_test' ] = False
- register_test_result( galaxy_tool_shed_url, metadata_revision_id, repository_status, repository_info_dict, params )
- log.info( "Not testing revision %s of repository %s owned by %s.", changeset_revision, name, owner )
- continue
- else:
- log.info( "Installing and testing revision %s of repository %s owned by %s...", changeset_revision, name, owner )
- # Explicitly clear tests from twill's test environment.
- remove_generated_tests( app )
- # Use the repository information dict to generate an install method that will install the repository into the embedded
- # Galaxy application, with tool dependencies and repository dependencies, if any.
- test_install_repositories.generate_install_method( repository_info_dict )
- # Set the GALAXY_INSTALL_TEST_HOST variable so that Twill will have the Galaxy url to install repositories into.
- os.environ[ 'GALAXY_INSTALL_TEST_HOST' ] = galaxy_test_host
- # Configure nose to run the install method as a test.
- test_config = nose.config.Config( env=os.environ, plugins=nose.plugins.manager.DefaultPluginManager() )
- test_config.configure( sys.argv )
- # Run the configured install method as a test. This method uses the embedded Galaxy application's web interface to install the specified
- # repository, with tool and repository dependencies also selected for installation.
- result, _ = run_tests( test_config )
- success = result.wasSuccessful()
- repository_status[ 'installation_errors' ] = dict( current_repository=[], repository_dependencies=[], tool_dependencies=[] )
- try:
- repository = test_db_util.get_installed_repository_by_name_owner_changeset_revision( name, owner, changeset_revision )
- except:
- log.exception( 'Error getting installed repository.' )
- success = False
- pass
- # If the installation succeeds, configure and run functional tests for this repository. This is equivalent to
- # sh run_functional_tests.sh -installed
- if success:
- # Clean out repository installation methods.
- remove_install_tests( app )
- log.debug( 'Installation of %s succeeded, running all defined functional tests.', 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() ) )
- # The repository_status dict should always have the following structure:
- # {
- # "test_environment":
- # {
- # "galaxy_revision": "9001:abcd1234",
- # "galaxy_database_version": "114",
- # "tool_shed_revision": "9001:abcd1234",
- # "tool_shed_mercurial_version": "2.3.1",
- # "tool_shed_database_version": "17",
- # "python_version": "2.7.2",
- # "architecture": "x86_64",
- # "system": "Darwin 12.2.0"
- # },
- # "passed_tests":
- # [
- # {
- # "test_id": "The test ID, generated by twill",
- # "tool_id": "The tool ID that was tested",
- # "tool_version": "The tool version that was tested",
- # },
- # ]
- # "failed_tests":
- # [
- # {
- # "test_id": "The test ID, generated by twill",
- # "tool_id": "The tool ID that was tested",
- # "tool_version": "The tool version that was tested",
- # "stderr": "The output of the test, or a more detailed description of what was tested and what the outcome was."
- # "traceback": "The captured traceback."
- # },
- # ]
- # "installation_errors":
- # {
- # 'tool_dependencies':
- # [
- # {
- # 'type': 'Type of tool dependency, e.g. package, set_environment, etc.',
- # 'name': 'Name of the tool dependency.',
- # 'version': 'Version if this is a package, otherwise blank.',
- # 'error_message': 'The error message returned when installation was attempted.',
- # },
- # ],
- # 'repository_dependencies':
- # [
- # {
- # 'tool_shed': 'The tool shed that this repository was installed from.',
- # 'name': 'The name of the repository that failed to install.',
- # 'owner': 'Owner of the failed repository.',
- # 'changeset_revision': 'Changeset revision of the failed repository.',
- # 'error_message': 'The error message that was returned when the repository failed to install.',
- # },
- # ],
- # 'current_repository':
- # [
- # {
- # 'tool_shed': 'The tool shed that this repository was installed from.',
- # 'name': 'The name of the repository that failed to install.',
- # 'owner': 'Owner of the failed repository.',
- # 'changeset_revision': 'Changeset revision of the failed repository.',
- # 'error_message': 'The error message that was returned when the repository failed to install.',
- # },
- # ],
- # {
- # "name": "The name of the repository.",
- # "owner": "The owner of the repository.",
- # "changeset_revision": "The changeset revision of the repository.",
- # "error_message": "The message stored in tool_dependency.error_message."
- # },
- # }
- # "missing_test_components":
- # [
- # {
- # "tool_id": "The tool ID that missing components.",
- # "tool_version": "The version of the tool."
- # "tool_guid": "The guid of the tool."
- # "missing_components": "Which components are missing, e.g. the test data filename, or the test-data directory."
- # },
- # ]
- # "not_tested":
- # {
- # "reason": "The Galaxy development team has determined that this repository should not be installed and tested by the automated framework."
- # }
- # }
- if 'missing_test_components' not in repository_status:
- repository_status[ 'missing_test_components' ] = []
- missing_tool_dependencies = get_missing_tool_dependencies( repository )
- if missing_tool_dependencies or repository.missing_repository_dependencies:
- # If a tool dependency fails to install correctly, this should be considered an installation error,
- # and functional tests should be skipped, since the tool dependency needs to be correctly installed
- # for the test to be considered reliable.
- log.error( 'The following dependencies of this repository are missing, skipping functional tests.' )
- # In keeping with the standard display layout, add the error message to the dict for each tool individually.
- for dependency in repository.missing_tool_dependencies:
- log.error( 'Missing tool dependency %s of type %s version %s: %s' % \
- ( str( dependency.name ), str( dependency.type ), str( dependency.version ), unicodify( dependency.error_message ) ) )
- test_result = dict( type=dependency.type,
- name=dependency.name,
- version=dependency.version,
- error_message=dependency.error_message )
- repository_status[ 'installation_errors' ][ 'tool_dependencies' ].append( test_result )
- for dependency in repository.missing_repository_dependencies:
- log.error( '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 ) ) )
- test_result = dict( tool_shed=dependency.tool_shed,
- name=dependency.name,
- owner=dependency.owner,
- changeset_revision=dependency.changeset_revision,
- error_message=dependency.error_message )
- repository_status[ 'installation_errors' ][ 'repository_dependencies' ].append( test_result )
- # Record the status of this repository in the tool shed.
- params[ 'tools_functionally_correct' ] = False
- params[ 'do_not_test' ] = False
- params[ 'test_install_error' ] = True
- register_test_result( galaxy_tool_shed_url,
- metadata_revision_id,
- repository_status,
- repository_info_dict,
- params )
- # Since this repository is missing components, we do not want to test it. Deactivate this repository.
- # The deactivate flag is set to True if the environment variable GALAXY_INSTALL_TEST_KEEP_TOOL_DEPENDENCIES
- # is set to 'true'.
- if deactivate:
- log.debug( 'Due to the above missing tool dependencies, we are now uninstalling the following tool dependencies, but not changing their repositories.' )
- for missing_tool_dependency in missing_tool_dependencies:
- uninstall_tool_dependency( app, missing_tool_dependency )
- # We are deactivating this repository and all of its repository dependencies.
- log.debug( 'Due to the above missing repository dependencies, we are now deactivating the following repositories.' )
- deactivate_repository( app, repository_info_dict )
- else:
- # We are uninstalling this repository and all of its repository dependencies.
- log.debug( 'Due to the above missing repository dependencies, we are now uninstalling the following repositories.' )
- uninstall_repository( app, repository_info_dict )
- # Set the test_toolbox.toolbox module-level variable to the new app.toolbox.
- test_toolbox.toolbox = app.toolbox
- repositories_failed_install.append( dict( name=name, owner=owner, changeset_revision=changeset_revision ) )
- else:
- # If the repository does have 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.info( 'Saved generated shed_tools_dict to %s\nContents: %s', galaxy_shed_tools_dict, str( shed_tools_dict ) )
- # Set the GALAXY_TOOL_SHED_TEST_FILE environment variable to the path of the shed_tools_dict file, so that test.base.twilltestcase.setUp
- # will find and parse it properly.
- os.environ[ 'GALAXY_TOOL_SHED_TEST_FILE' ] = galaxy_shed_tools_dict
- os.environ[ 'GALAXY_TEST_HOST' ] = galaxy_test_host
- os.environ[ 'GALAXY_TEST_PORT' ] = galaxy_test_port
- # Set the module-level variable 'toolbox', so that test.functional.test_toolbox will generate the appropriate test methods.
- test_toolbox.toolbox = app.toolbox
- # Generate the test methods for this installed repository. We need to pass in True here, or it will look
- # in $GALAXY_HOME/test-data for test data, which may result in missing or invalid test files.
- test_toolbox.build_tests( testing_shed_tools=True, master_api_key=default_galaxy_master_api_key )
- # Set up nose to run the generated functional tests.
- test_config = nose.config.Config( env=os.environ, plugins=nose.plugins.manager.DefaultPluginManager() )
- test_config.configure( sys.argv )
- # Run the configured tests.
- result, test_plugins = run_tests( test_config )
- success = result.wasSuccessful()
- # Use the ReportResults nose plugin to get a list of tests that passed.
- for plugin in test_plugins:
- if hasattr( plugin, 'getTestStatus' ):
- test_identifier = '%s/%s' % ( owner, name )
- passed_tests = plugin.getTestStatus( test_identifier )
- break
- repository_status[ '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[ '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
- # controller with the status of the test. This also sets the do_not_test and tools_functionally correct flags, and
- # updates the time_last_tested field to today's date.
- repositories_passed.append( dict( name=name, owner=owner, changeset_revision=changeset_revision ) )
- params[ 'tools_functionally_correct' ] = True
- params[ 'do_not_test' ] = False
- params[ 'test_install_error' ] = False
- register_test_result( galaxy_tool_shed_url,
- metadata_revision_id,
- repository_status,
- repository_info_dict,
- params )
- log.debug( 'Revision %s of repository %s installed and passed functional tests.', changeset_revision, name )
- else:
- repository_status[ 'failed_tests' ] = 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.
- 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_info_dict )
- params[ 'tools_functionally_correct' ] = False
- params[ 'test_install_error' ] = False
- params[ 'do_not_test' ] = str( set_do_not_test )
- register_test_result( galaxy_tool_shed_url,
- metadata_revision_id,
- repository_status,
- repository_info_dict,
- params )
- log.debug( 'Revision %s of repository %s installed successfully, but did not pass functional tests.',
- changeset_revision, name )
- # Run the uninstall method. This removes tool functional test methods from the test_toolbox module and uninstalls the
- # repository using Twill.
- if deactivate:
- log.debug( 'Deactivating changeset revision %s of repository %s',
- repository_info_dict[ 'changeset_revision' ],
- repository_info_dict[ 'name' ] )
- # We are deactivating this repository and all of its repository dependencies.
- success = deactivate_repository( app, repository_info_dict )
- else:
- log.debug( 'Uninstalling changeset revision %s of repository %s',
- repository_info_dict[ 'changeset_revision' ],
- repository_info_dict[ 'name' ] )
- # We are uninstalling this repository and all of its repository dependencies.
- success = uninstall_repository( app, repository_info_dict )
- if not success:
- log.error( 'Repository %s failed to uninstall.', repository_info_dict[ 'name' ] )
- # Set the test_toolbox.toolbox module-level variable to the new app.toolbox.
- test_toolbox.toolbox = app.toolbox
- else:
- # Even if the repository failed to install, execute the uninstall method, in case a dependency did succeed.
- log.debug( 'Uninstalling repository %s', repository_info_dict[ 'name' ] )
- try:
- repository = test_db_util.get_installed_repository_by_name_owner_changeset_revision( name, owner, changeset_revision )
- except:
- log.exception( 'Unable to uninstall, no installed repository found.' )
- test_result = dict( tool_shed=galaxy_tool_shed_url,
- name=repository_info_dict[ 'name' ],
- owner=repository_info_dict[ 'owner' ],
- changeset_revision=repository_info_dict[ 'changeset_revision' ],
- error_message=extract_log_data( result, from_tool_test=False ) )
- repository_status[ 'installation_errors' ][ 'repository_dependencies' ].append( test_result )
- params[ 'tools_functionally_correct' ] = False
- params[ 'test_install_error' ] = True
- params[ 'do_not_test' ] = False
- register_test_result( galaxy_tool_shed_url,
- metadata_revision_id,
- repository_status,
- repository_info_dict,
- params )
- try:
- if deactivate:
- # We are deactivating this repository and all of its repository dependencies.
- success = deactivate_repository( app, repository_info_dict )
- else:
- # We are uninstalling this repository and all of its repository dependencies.
- success = uninstall_repository( app, repository_info_dict )
- except:
- log.exception( 'Encountered error attempting to deactivate or uninstall %s.', repository_info_dict[ 'name' ] )
- success = False
- if not success:
- log.error( 'Repository %s failed to uninstall.', repository_info_dict[ 'name' ] )
- repositories_failed_install.append( dict( name=name, owner=owner, changeset_revision=changeset_revision ) )
- log.debug( 'Repository %s failed to install correctly.', repository_info_dict[ 'name' ] )
- except:
- log.exception( "Failure running tests" )
-
- log.info( "Shutting down" )
- # ---- Tear down -----------------------------------------------------------
+ success = True
+ print "####################################################################################"
+ log.debug( "Shutting down..." )
# Gracefully shut down the embedded web server and UniverseApplication.
if server:
- log.info( "Shutting down embedded galaxy web server" )
+ log.debug( "Shutting down embedded galaxy web server..." )
server.server_close()
server = None
- log.info( "Embedded galaxy server stopped" )
+ log.debug( "Embedded galaxy server stopped..." )
if app:
- log.info( "Shutting down galaxy application" )
+ log.debug( "Shutting down galaxy application..." )
app.shutdown()
app = None
- log.info( "Embedded galaxy application stopped" )
+ log.debug( "Embedded galaxy application stopped..." )
# Clean up test files unless otherwise specified.
if 'GALAXY_INSTALL_TEST_NO_CLEANUP' not in os.environ:
- try:
- for dir in [ galaxy_test_tmp_dir ]:
- if os.path.exists( dir ):
- log.info( "Cleaning up temporary files in %s", dir )
+ for dir in [ galaxy_test_tmp_dir ]:
+ if os.path.exists( dir ):
+ try:
shutil.rmtree( dir )
- except:
- pass
+ log.debug( "Cleaned up temporary files in %s", dir )
+ except:
+ pass
else:
log.debug( 'GALAXY_INSTALL_TEST_NO_CLEANUP set, not cleaning up.' )
-
- now = strftime( "%Y-%m-%d %H:%M:%S" )
- print "####################################################################################"
- print "# %s - repository installation and testing script completed." % now
- print "# Repository revisions tested: %d" % repositories_tested
- if '-info_only' in sys.argv:
- print "# -info_only set, not updating the tool shed."
- if repositories_tested > 0:
- if repositories_passed:
- print '# ----------------------------------------------------------------------------------'
- print "# %d repositories passed all tests:" % len( repositories_passed )
- show_summary_output( repositories_passed )
- if repositories_failed:
- print '# ----------------------------------------------------------------------------------'
- print "# %d repositories failed one or more tests:" % len( repositories_failed )
- show_summary_output( repositories_failed )
- if repositories_failed_install:
- # Set success to False so that the return code will not be 0.
- success = False
- print '# ----------------------------------------------------------------------------------'
- print "# %d repositories with installation errors:" % len( repositories_failed_install )
- show_summary_output( repositories_failed_install )
- else:
- success = True
- else:
- success = True
- print "####################################################################################"
# Normally, the value of 'success' would determine whether this test suite is marked as passed or failed
# in the automated buildbot framework. However, due to the procedure used here, we only want to report
# failure if a repository fails to install correctly. Therefore, we have overriden the value of 'success'
@@ -1352,8 +1268,87 @@
return 1
if __name__ == "__main__":
- now = strftime( "%Y-%m-%d %H:%M:%S" )
- print "####################################################################################"
- print "# %s - running repository installation and testing script." % now
- print "####################################################################################"
+ # The repository_status_dict should always have the following structure:
+ # {
+ # "test_environment":
+ # {
+ # "galaxy_revision": "9001:abcd1234",
+ # "galaxy_database_version": "114",
+ # "tool_shed_revision": "9001:abcd1234",
+ # "tool_shed_mercurial_version": "2.3.1",
+ # "tool_shed_database_version": "17",
+ # "python_version": "2.7.2",
+ # "architecture": "x86_64",
+ # "system": "Darwin 12.2.0"
+ # },
+ # "passed_tests":
+ # [
+ # {
+ # "test_id": "The test ID, generated by twill",
+ # "tool_id": "The tool ID that was tested",
+ # "tool_version": "The tool version that was tested",
+ # },
+ # ]
+ # "failed_tests":
+ # [
+ # {
+ # "test_id": "The test ID, generated by twill",
+ # "tool_id": "The tool ID that was tested",
+ # "tool_version": "The tool version that was tested",
+ # "stderr": "The output of the test, or a more detailed description of what was tested and what the outcome was."
+ # "traceback": "The captured traceback."
+ # },
+ # ]
+ # "installation_errors":
+ # {
+ # 'tool_dependencies':
+ # [
+ # {
+ # 'type': 'Type of tool dependency, e.g. package, set_environment, etc.',
+ # 'name': 'Name of the tool dependency.',
+ # 'version': 'Version if this is a package, otherwise blank.',
+ # 'error_message': 'The error message returned when installation was attempted.',
+ # },
+ # ],
+ # 'repository_dependencies':
+ # [
+ # {
+ # 'tool_shed': 'The tool shed that this repository was installed from.',
+ # 'name': 'The name of the repository that failed to install.',
+ # 'owner': 'Owner of the failed repository.',
+ # 'changeset_revision': 'Changeset revision of the failed repository.',
+ # 'error_message': 'The error message that was returned when the repository failed to install.',
+ # },
+ # ],
+ # 'current_repository':
+ # [
+ # {
+ # 'tool_shed': 'The tool shed that this repository was installed from.',
+ # 'name': 'The name of the repository that failed to install.',
+ # 'owner': 'Owner of the failed repository.',
+ # 'changeset_revision': 'Changeset revision of the failed repository.',
+ # 'error_message': 'The error message that was returned when the repository failed to install.',
+ # },
+ # ],
+ # {
+ # "name": "The name of the repository.",
+ # "owner": "The owner of the repository.",
+ # "changeset_revision": "The changeset revision of the repository.",
+ # "error_message": "The message stored in tool_dependency.error_message."
+ # },
+ # }
+ # "missing_test_components":
+ # [
+ # {
+ # "tool_id": "The tool ID that missing components.",
+ # "tool_version": "The version of the tool."
+ # "tool_guid": "The guid of the tool."
+ # "missing_components": "Which components are missing, e.g. the test data filename, or the test-data directory."
+ # },
+ # ]
+ # "not_tested":
+ # {
+ # "reason": "The Galaxy development team has determined that this repository should not be installed and tested by the automated framework."
+ # }
+ # }
sys.exit( main() )
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, History panel: fix assembly of popupmenus when rendering only body of hdas
by commits-noreply@bitbucket.org 22 Nov '13
by commits-noreply@bitbucket.org 22 Nov '13
22 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d28d25d66095/
Changeset: d28d25d66095
User: carlfeberhard
Date: 2013-11-22 18:53:30
Summary: UI, History panel: fix assembly of popupmenus when rendering only body of hdas
Affected #: 2 files
diff -r 54377b1aff65eb892d8e4067574c0cde552a2a57 -r d28d25d66095b84af1aaee1a487ee2b27c5a07ce static/scripts/mvc/dataset/hda-base.js
--- a/static/scripts/mvc/dataset/hda-base.js
+++ b/static/scripts/mvc/dataset/hda-base.js
@@ -263,6 +263,8 @@
if( _.isFunction( renderFn ) ){
$body = renderFn.call( this );
}
+ this._setUpBehaviors( $body );
+
// only render the body html if it's being shown
if( this.expanded ){
$body.show();
diff -r 54377b1aff65eb892d8e4067574c0cde552a2a57 -r d28d25d66095b84af1aaee1a487ee2b27c5a07ce static/scripts/packed/mvc/dataset/hda-base.js
--- a/static/scripts/packed/mvc/dataset/hda-base.js
+++ b/static/scripts/packed/mvc/dataset/hda-base.js
@@ -1,1 +1,1 @@
-define(["mvc/dataset/hda-model"],function(b){var a=Backbone.View.extend(LoggableMixin).extend({tagName:"div",className:"dataset hda history-panel-hda",id:function(){return"hda-"+this.model.get("id")},fxSpeed:"fast",initialize:function(c){if(c.logger){this.logger=this.model.logger=c.logger}this.log(this+".initialize:",c);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton];this.selectable=false;this.selected=false;this.expanded=c.expanded||false;this._setUpListeners()},_setUpListeners:function(){this.model.on("change",function(d,c){if(this.model.changedAttributes().state&&this.model.inReadyState()&&this.expanded&&!this.model.hasDetails()){this.model.fetch()}else{this.render()}},this)},render:function(e){e=(e===undefined)?(true):(e);var c=this;this.$el.find("[title]").tooltip("destroy");this.urls=this.model.urls();var d=$(a.templates.skeleton(this.model.toJSON()));d.find(".dataset-primary-actions").append(this._render_titleButtons());d.children(".dataset-body").replaceWith(this._render_body());this._setUpBehaviors(d);if(e){$(c).queue(function(f){this.$el.fadeOut(c.fxSpeed,f)})}$(c).queue(function(f){this.$el.empty().attr("class",c.className).addClass("state-"+c.model.get("state")).append(d.children());f()});if(e){$(c).queue(function(f){this.$el.fadeIn(c.fxSpeed,f)})}$(c).queue(function(f){this.trigger("rendered",c);if(this.model.inReadyState()){this.trigger("rendered:ready",c)}if(this.selectable){this.showSelect()}f()});return this},_setUpBehaviors:function(c){c=c||this.$el;make_popup_menus(c);c.find("[title]").tooltip({placement:"bottom"})},_render_titleButtons:function(){return[this._render_displayButton()]},_render_displayButton:function(){if((this.model.get("state")===b.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(this.model.get("state")===b.HistoryDatasetAssociation.STATES.DISCARDED)||(this.model.get("state")===b.HistoryDatasetAssociation.STATES.NEW)||(!this.model.get("accessible"))){return null}var d={target:"galaxy_main",classes:"dataset-display"};if(this.model.get("purged")){d.disabled=true;d.title=_l("Cannot display datasets removed from disk")}else{if(this.model.get("state")===b.HistoryDatasetAssociation.STATES.UPLOAD){d.disabled=true;d.title=_l("This dataset must finish uploading before it can be viewed")}else{d.title=_l("View data");d.href=this.urls.display;var c=this;d.onclick=function(){Galaxy.frame.add({title:"Data Viewer: "+c.model.get("name"),type:"url",target:"galaxy_main",content:c.urls.display})}}}d.faIcon="fa-eye";return faIconButton(d)},_render_downloadButton:function(){if(this.model.get("purged")||!this.model.hasData()){return null}var d=this.urls,e=this.model.get("meta_files");if(_.isEmpty(e)){return $(['<a href="'+d.download+'" title="'+_l("Download")+'" class="icon-btn">','<span class="fa fa-floppy-o"></span>',"</a>"].join(""))}var f="dataset-"+this.model.get("id")+"-popup",c=['<div popupmenu="'+f+'">','<a href="'+d.download+'">',_l("Download Dataset"),"</a>","<a>"+_l("Additional Files")+"</a>",_.map(e,function(g){return['<a class="action-button" href="',d.meta_download+g.file_type,'">',_l("Download")," ",g.file_type,"</a>"].join("")}).join("\n"),"</div>",'<div class="icon-btn-group">','<a href="'+d.download+'" title="'+_l("Download")+'" class="icon-btn">','<span class="fa fa-floppy-o"></span>','</a><a class="icon-btn popup" id="'+f+'">','<span class="fa fa-caret-down"></span>',"</a>","</div>"].join("\n");return $(c)},_render_showParamsButton:function(){return faIconButton({title:_l("View details"),href:this.urls.show_params,target:"galaxy_main",faIcon:"fa-info-circle"})},_render_body:function(){var d=$('<div>Error: unknown dataset state "'+this.model.get("state")+'".</div>'),c=this["_render_body_"+this.model.get("state")];if(_.isFunction(c)){d=c.call(this)}if(this.expanded){d.show()}return d},_render_stateBodyHelper:function(c,f){f=f||[];var d=this,e=$(a.templates.body(_.extend(this.model.toJSON(),{body:c})));e.find(".dataset-actions .left").append(_.map(f,function(g){return g.call(d)}));return e},_render_body_new:function(){return this._render_stateBodyHelper("<div>"+_l("This is a new dataset and not all of its data are available yet")+"</div>")},_render_body_noPermission:function(){return this._render_stateBodyHelper("<div>"+_l("You do not have permission to view this dataset")+"</div>")},_render_body_discarded:function(){return this._render_stateBodyHelper("<div>"+_l("The job creating this dataset was cancelled before completion")+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_queued:function(){return this._render_stateBodyHelper("<div>"+_l("This job is waiting to run")+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_upload:function(){return this._render_stateBodyHelper("<div>"+_l("This dataset is currently uploading")+"</div>")},_render_body_setting_metadata:function(){return this._render_stateBodyHelper("<div>"+_l("Metadata is being auto-detected")+"</div>")},_render_body_running:function(){return this._render_stateBodyHelper("<div>"+_l("This job is currently running")+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_paused:function(){return this._render_stateBodyHelper("<div>"+_l('This job is paused. Use the "Resume Paused Jobs" in the history menu to resume')+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_error:function(){var c=['<span class="help-text">',_l("An error occurred with this dataset"),":</span>",'<div class="job-error-text">',$.trim(this.model.get("misc_info")),"</div>"].join("");if(!this.model.get("purged")){c="<div>"+this.model.get("misc_blurb")+"</div>"+c}return this._render_stateBodyHelper(c,this.defaultPrimaryActionButtonRenderers.concat([this._render_downloadButton]))},_render_body_empty:function(){return this._render_stateBodyHelper("<div>"+_l("No data")+": <i>"+this.model.get("misc_blurb")+"</i></div>",this.defaultPrimaryActionButtonRenderers)},_render_body_failed_metadata:function(){var c=$('<div class="warningmessagesmall"></div>').append($("<strong/>").text(_l("An error occurred setting the metadata for this dataset"))),d=this._render_body_ok();d.prepend(c);return d},_render_body_ok:function(){var c=this,e=$(a.templates.body(this.model.toJSON())),d=[this._render_downloadButton].concat(this.defaultPrimaryActionButtonRenderers);e.find(".dataset-actions .left").append(_.map(d,function(f){return f.call(c)}));if(this.model.isDeletedOrPurged()){return e}return e},events:{"click .dataset-title-bar":"toggleBodyVisibility","click .dataset-selector":"select"},toggleBodyVisibility:function(d,c){var e=this.$el.find(".dataset-body");c=(c===undefined)?(!e.is(":visible")):(c);if(c){this.expandBody()}else{this.collapseBody()}return false},expandBody:function(){var c=this;function d(){c.$el.children(".dataset-body").replaceWith(c._render_body());c.$el.children(".dataset-body").slideDown(c.fxSpeed,function(){c.expanded=true;c.trigger("body-expanded",c.model.get("id"))})}if(this.model.inReadyState()&&!this.model.hasDetails()){this.model.fetch({silent:true}).always(function(e){d()})}else{d()}},collapseBody:function(){var c=this;this.$el.children(".dataset-body").slideUp(c.fxSpeed,function(){c.expanded=false;c.trigger("body-collapsed",c.model.get("id"))})},showSelect:function(e){if(this.$el.find(".dataset-selector").css("display")!=="none"){return}e=(e!==undefined)?(e):(this.fxSpeed);var d=this,c=32;this.$el.queue("fx",function(f){$(this).find(".dataset-primary-actions").fadeOut(e,f)});this.$el.queue("fx",function(f){$(this).find(".dataset-selector").show().css({height:$(this).find(".dataset-title-bar").innerHeight()}).animate({width:c},e,f);d.selectable=true;d.trigger("selectable",true,d)})},hideSelect:function(c){c=(c!==undefined)?(c):(this.fxSpeed);this.selectable=false;this.trigger("selectable",false,this);this.$el.queue("fx",function(d){$(this).find(".dataset-selector").animate({width:"0px"},c,function(){$(this).hide();d()})});this.$el.queue("fx",function(d){$(this).find(".dataset-primary-actions").fadeIn(c,d)})},select:function(d,c){if(c!==undefined&&c===this.selected){return false}this.$el.find(".dataset-selector span").toggleClass("fa-square-o fa-check-square-o");this.selected=!this.selected;this.trigger((this.selected)?("selected"):("de-selected"),this);return false},remove:function(d){var c=this;this.$el.fadeOut(c.fxSpeed,function(){c.$el.remove();c.off();if(d){d()}})},toString:function(){var c=(this.model)?(this.model+""):("(no model)");return"HDABaseView("+c+")"}});a.templates={skeleton:Handlebars.templates["template-hda-skeleton"],body:Handlebars.templates["template-hda-body"]};return{HDABaseView:a}});
\ No newline at end of file
+define(["mvc/dataset/hda-model"],function(b){var a=Backbone.View.extend(LoggableMixin).extend({tagName:"div",className:"dataset hda history-panel-hda",id:function(){return"hda-"+this.model.get("id")},fxSpeed:"fast",initialize:function(c){if(c.logger){this.logger=this.model.logger=c.logger}this.log(this+".initialize:",c);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton];this.selectable=false;this.selected=false;this.expanded=c.expanded||false;this._setUpListeners()},_setUpListeners:function(){this.model.on("change",function(d,c){if(this.model.changedAttributes().state&&this.model.inReadyState()&&this.expanded&&!this.model.hasDetails()){this.model.fetch()}else{this.render()}},this)},render:function(e){e=(e===undefined)?(true):(e);var c=this;this.$el.find("[title]").tooltip("destroy");this.urls=this.model.urls();var d=$(a.templates.skeleton(this.model.toJSON()));d.find(".dataset-primary-actions").append(this._render_titleButtons());d.children(".dataset-body").replaceWith(this._render_body());this._setUpBehaviors(d);if(e){$(c).queue(function(f){this.$el.fadeOut(c.fxSpeed,f)})}$(c).queue(function(f){this.$el.empty().attr("class",c.className).addClass("state-"+c.model.get("state")).append(d.children());f()});if(e){$(c).queue(function(f){this.$el.fadeIn(c.fxSpeed,f)})}$(c).queue(function(f){this.trigger("rendered",c);if(this.model.inReadyState()){this.trigger("rendered:ready",c)}if(this.selectable){this.showSelect()}f()});return this},_setUpBehaviors:function(c){c=c||this.$el;make_popup_menus(c);c.find("[title]").tooltip({placement:"bottom"})},_render_titleButtons:function(){return[this._render_displayButton()]},_render_displayButton:function(){if((this.model.get("state")===b.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(this.model.get("state")===b.HistoryDatasetAssociation.STATES.DISCARDED)||(this.model.get("state")===b.HistoryDatasetAssociation.STATES.NEW)||(!this.model.get("accessible"))){return null}var d={target:"galaxy_main",classes:"dataset-display"};if(this.model.get("purged")){d.disabled=true;d.title=_l("Cannot display datasets removed from disk")}else{if(this.model.get("state")===b.HistoryDatasetAssociation.STATES.UPLOAD){d.disabled=true;d.title=_l("This dataset must finish uploading before it can be viewed")}else{d.title=_l("View data");d.href=this.urls.display;var c=this;d.onclick=function(){Galaxy.frame.add({title:"Data Viewer: "+c.model.get("name"),type:"url",target:"galaxy_main",content:c.urls.display})}}}d.faIcon="fa-eye";return faIconButton(d)},_render_downloadButton:function(){if(this.model.get("purged")||!this.model.hasData()){return null}var d=this.urls,e=this.model.get("meta_files");if(_.isEmpty(e)){return $(['<a href="'+d.download+'" title="'+_l("Download")+'" class="icon-btn">','<span class="fa fa-floppy-o"></span>',"</a>"].join(""))}var f="dataset-"+this.model.get("id")+"-popup",c=['<div popupmenu="'+f+'">','<a href="'+d.download+'">',_l("Download Dataset"),"</a>","<a>"+_l("Additional Files")+"</a>",_.map(e,function(g){return['<a class="action-button" href="',d.meta_download+g.file_type,'">',_l("Download")," ",g.file_type,"</a>"].join("")}).join("\n"),"</div>",'<div class="icon-btn-group">','<a href="'+d.download+'" title="'+_l("Download")+'" class="icon-btn">','<span class="fa fa-floppy-o"></span>','</a><a class="icon-btn popup" id="'+f+'">','<span class="fa fa-caret-down"></span>',"</a>","</div>"].join("\n");return $(c)},_render_showParamsButton:function(){return faIconButton({title:_l("View details"),href:this.urls.show_params,target:"galaxy_main",faIcon:"fa-info-circle"})},_render_body:function(){var d=$('<div>Error: unknown dataset state "'+this.model.get("state")+'".</div>'),c=this["_render_body_"+this.model.get("state")];if(_.isFunction(c)){d=c.call(this)}this._setUpBehaviors(d);if(this.expanded){d.show()}return d},_render_stateBodyHelper:function(c,f){f=f||[];var d=this,e=$(a.templates.body(_.extend(this.model.toJSON(),{body:c})));e.find(".dataset-actions .left").append(_.map(f,function(g){return g.call(d)}));return e},_render_body_new:function(){return this._render_stateBodyHelper("<div>"+_l("This is a new dataset and not all of its data are available yet")+"</div>")},_render_body_noPermission:function(){return this._render_stateBodyHelper("<div>"+_l("You do not have permission to view this dataset")+"</div>")},_render_body_discarded:function(){return this._render_stateBodyHelper("<div>"+_l("The job creating this dataset was cancelled before completion")+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_queued:function(){return this._render_stateBodyHelper("<div>"+_l("This job is waiting to run")+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_upload:function(){return this._render_stateBodyHelper("<div>"+_l("This dataset is currently uploading")+"</div>")},_render_body_setting_metadata:function(){return this._render_stateBodyHelper("<div>"+_l("Metadata is being auto-detected")+"</div>")},_render_body_running:function(){return this._render_stateBodyHelper("<div>"+_l("This job is currently running")+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_paused:function(){return this._render_stateBodyHelper("<div>"+_l('This job is paused. Use the "Resume Paused Jobs" in the history menu to resume')+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_error:function(){var c=['<span class="help-text">',_l("An error occurred with this dataset"),":</span>",'<div class="job-error-text">',$.trim(this.model.get("misc_info")),"</div>"].join("");if(!this.model.get("purged")){c="<div>"+this.model.get("misc_blurb")+"</div>"+c}return this._render_stateBodyHelper(c,this.defaultPrimaryActionButtonRenderers.concat([this._render_downloadButton]))},_render_body_empty:function(){return this._render_stateBodyHelper("<div>"+_l("No data")+": <i>"+this.model.get("misc_blurb")+"</i></div>",this.defaultPrimaryActionButtonRenderers)},_render_body_failed_metadata:function(){var c=$('<div class="warningmessagesmall"></div>').append($("<strong/>").text(_l("An error occurred setting the metadata for this dataset"))),d=this._render_body_ok();d.prepend(c);return d},_render_body_ok:function(){var c=this,e=$(a.templates.body(this.model.toJSON())),d=[this._render_downloadButton].concat(this.defaultPrimaryActionButtonRenderers);e.find(".dataset-actions .left").append(_.map(d,function(f){return f.call(c)}));if(this.model.isDeletedOrPurged()){return e}return e},events:{"click .dataset-title-bar":"toggleBodyVisibility","click .dataset-selector":"select"},toggleBodyVisibility:function(d,c){var e=this.$el.find(".dataset-body");c=(c===undefined)?(!e.is(":visible")):(c);if(c){this.expandBody()}else{this.collapseBody()}return false},expandBody:function(){var c=this;function d(){c.$el.children(".dataset-body").replaceWith(c._render_body());c.$el.children(".dataset-body").slideDown(c.fxSpeed,function(){c.expanded=true;c.trigger("body-expanded",c.model.get("id"))})}if(this.model.inReadyState()&&!this.model.hasDetails()){this.model.fetch({silent:true}).always(function(e){d()})}else{d()}},collapseBody:function(){var c=this;this.$el.children(".dataset-body").slideUp(c.fxSpeed,function(){c.expanded=false;c.trigger("body-collapsed",c.model.get("id"))})},showSelect:function(e){if(this.$el.find(".dataset-selector").css("display")!=="none"){return}e=(e!==undefined)?(e):(this.fxSpeed);var d=this,c=32;this.$el.queue("fx",function(f){$(this).find(".dataset-primary-actions").fadeOut(e,f)});this.$el.queue("fx",function(f){$(this).find(".dataset-selector").show().css({height:$(this).find(".dataset-title-bar").innerHeight()}).animate({width:c},e,f);d.selectable=true;d.trigger("selectable",true,d)})},hideSelect:function(c){c=(c!==undefined)?(c):(this.fxSpeed);this.selectable=false;this.trigger("selectable",false,this);this.$el.queue("fx",function(d){$(this).find(".dataset-selector").animate({width:"0px"},c,function(){$(this).hide();d()})});this.$el.queue("fx",function(d){$(this).find(".dataset-primary-actions").fadeIn(c,d)})},select:function(d,c){if(c!==undefined&&c===this.selected){return false}this.$el.find(".dataset-selector span").toggleClass("fa-square-o fa-check-square-o");this.selected=!this.selected;this.trigger((this.selected)?("selected"):("de-selected"),this);return false},remove:function(d){var c=this;this.$el.fadeOut(c.fxSpeed,function(){c.$el.remove();c.off();if(d){d()}})},toString:function(){var c=(this.model)?(this.model+""):("(no model)");return"HDABaseView("+c+")"}});a.templates={skeleton:Handlebars.templates["template-hda-skeleton"],body:Handlebars.templates["template-hda-body"]};return{HDABaseView:a}});
\ 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: jmchilton: Fix metadata_util.py for recent changes to representation of ToolTestBuilder.inputs.
by commits-noreply@bitbucket.org 22 Nov '13
by commits-noreply@bitbucket.org 22 Nov '13
22 Nov '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/54377b1aff65/
Changeset: 54377b1aff65
User: jmchilton
Date: 2013-11-22 17:36:01
Summary: Fix metadata_util.py for recent changes to representation of ToolTestBuilder.inputs.
Thanks to Greg for catching the error. Inputs display to the user will now be fully qualified - we should do some extra work I guess and display a prettified tree structure to match the new expressiveness of test inputs allowed.
Affected #: 1 file
diff -r 211f30207d48101a1250983d4f0f55c937f00a2e -r 54377b1aff65eb892d8e4067574c0cde552a2a57 lib/tool_shed/util/metadata_util.py
--- a/lib/tool_shed/util/metadata_util.py
+++ b/lib/tool_shed/util/metadata_util.py
@@ -940,10 +940,7 @@
for required_file in ttb.required_files:
value, extra = required_file
required_files.append( ( value ) )
- inputs = []
- for input in ttb.inputs:
- name, value, extra = input
- inputs.append( ( name, value ) )
+ inputs = [ input for input in ttb.inputs ]
outputs = []
for output in ttb.outputs:
name, file_name, extra = output
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