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
6 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/50062f6e9b47/
Changeset: 50062f6e9b47
User: jmchilton
Date: 2014-12-28 16:23:44+00:00
Summary: PEP-8 fixes for a few Tool Shed install components.
- lib/tool_shed/galaxy_install/install_manager.py
- lib/tool_shed/galaxy_install/repository_dependencies/repository_dependency_manager.py
- lib/tool_shed/galaxy_install/repair_repository_manager.py
Affected #: 3 files
diff -r 97f46da40bb3767c6cf0d440b1d2d58e06edf5e6 -r 50062f6e9b47a36dad57393292611632908fe79a lib/tool_shed/galaxy_install/install_manager.py
--- a/lib/tool_shed/galaxy_install/install_manager.py
+++ b/lib/tool_shed/galaxy_install/install_manager.py
@@ -42,11 +42,11 @@
class InstallToolDependencyManager( object ):
-
+
def __init__( self, app ):
self.app = app
self.install_model = self.app.install_model
- self.INSTALL_ACTIONS = [ 'download_binary', 'download_by_url', 'download_file',
+ self.INSTALL_ACTIONS = [ 'download_binary', 'download_by_url', 'download_file',
'setup_perl_environment', 'setup_python_environment',
'setup_r_environment', 'setup_ruby_environment', 'shell_command' ]
@@ -142,9 +142,9 @@
# Since there was an installation error, update the tool dependency status to Error. The remove_installation_path option must
# be left False here.
error_message = '%s\n%s' % ( self.format_traceback(), str( e ) )
- tool_dependency = tool_dependency_util.handle_tool_dependency_installation_error( self.app,
- tool_dependency,
- error_message,
+ tool_dependency = tool_dependency_util.handle_tool_dependency_installation_error( self.app,
+ tool_dependency,
+ error_message,
remove_installation_path=False )
tool_dependency = self.mark_tool_dependency_installed( tool_dependency )
return tool_dependency
@@ -208,9 +208,9 @@
tool_dependency_db_records=tool_dependencies )
if ( tool_dependency.type == 'package' and proceed_with_install ):
try:
- tool_dependency = self.install_package( elem,
- tool_shed_repository,
- tool_dependencies=tool_dependencies,
+ tool_dependency = self.install_package( elem,
+ tool_shed_repository,
+ tool_dependencies=tool_dependencies,
from_tool_migration_manager=from_tool_migration_manager )
except Exception, e:
error_message = "Error installing tool dependency %s version %s: %s" % \
@@ -220,9 +220,9 @@
# Since there was an installation error, update the tool dependency status to Error. The
# remove_installation_path option must be left False here.
tool_dependency = \
- tool_dependency_util.handle_tool_dependency_installation_error( self.app,
- tool_dependency,
- error_message,
+ tool_dependency_util.handle_tool_dependency_installation_error( self.app,
+ tool_dependency,
+ error_message,
remove_installation_path=False )
if tool_dependency and tool_dependency.status in [ self.install_model.ToolDependency.installation_status.INSTALLED,
self.install_model.ToolDependency.installation_status.ERROR ]:
@@ -236,7 +236,7 @@
def install_via_fabric( self, tool_shed_repository, tool_dependency, install_dir, package_name=None, custom_fabfile_path=None,
actions_elem=None, action_elem=None, **kwd ):
"""
- Parse a tool_dependency.xml file's <actions> tag set to gather information for installation using
+ Parse a tool_dependency.xml file's <actions> tag set to gather information for installation using
self.install_and_build_package(). The use of fabric is being eliminated, so some of these functions
may need to be renamed at some point.
"""
@@ -363,8 +363,8 @@
else:
# Process the next matching <actions> tag, or any defined <actions> tags that do not
# contain platform dependent recipes.
- log.debug( 'Error downloading binary for tool dependency %s version %s: %s' % \
- ( str( package_name ), str( package_version ), str( tool_dependency.error_message ) ) )
+ log.debug( 'Error downloading binary for tool dependency %s version %s: %s' %
+ ( str( package_name ), str( package_version ), str( tool_dependency.error_message ) ) )
else:
if actions_elem.tag == 'actions':
# We've reached an <actions> tag that defines the recipe for installing and compiling from
@@ -380,7 +380,7 @@
if removed:
can_install_from_source = True
else:
- log.debug( 'Error removing old files from installation directory %s: %s' % \
+ log.debug( 'Error removing old files from installation directory %s: %s' %
( str( installation_directory, str( error_message ) ) ) )
else:
can_install_from_source = True
@@ -389,7 +389,7 @@
if can_install_from_source:
# We now know that binary installation was not successful, so proceed with the <actions>
# tag set that defines the recipe to install and compile from source.
- log.debug( 'Proceeding with install and compile recipe for tool dependency %s.' % \
+ log.debug( 'Proceeding with install and compile recipe for tool dependency %s.' %
str( tool_dependency.name ) )
tool_dependency = self.install_via_fabric( tool_shed_repository,
tool_dependency,
@@ -398,7 +398,7 @@
actions_elem=actions_elem,
action_elem=None )
if actions_elem.tag == 'action' and \
- tool_dependency.status != self.install_model.ToolDependency.installation_status.ERROR:
+ tool_dependency.status != self.install_model.ToolDependency.installation_status.ERROR:
# If the tool dependency is not in an error state, perform any final actions that have been
# defined within the actions_group tag set, but outside of an <actions> tag, which defines
# the recipe for installing and compiling from source.
@@ -419,17 +419,17 @@
actions_elem=actions_elems,
action_elem=None )
if tool_dependency.status != self.install_model.ToolDependency.installation_status.ERROR:
- log.debug( 'Tool dependency %s version %s has been installed in %s.' % \
- ( str( package_name ), str( package_version ), str( install_dir ) ) )
+ log.debug( 'Tool dependency %s version %s has been installed in %s.' %
+ ( str( package_name ), str( package_version ), str( install_dir ) ) )
return tool_dependency
def mark_tool_dependency_installed( self, tool_dependency ):
if tool_dependency.status not in [ self.install_model.ToolDependency.installation_status.ERROR,
self.install_model.ToolDependency.installation_status.INSTALLED ]:
- log.debug( 'Changing status for tool dependency %s from %s to %s.' % \
- ( str( tool_dependency.name ),
- str( tool_dependency.status ),
- str( self.install_model.ToolDependency.installation_status.INSTALLED ) ) )
+ log.debug( 'Changing status for tool dependency %s from %s to %s.' %
+ ( str( tool_dependency.name ),
+ str( tool_dependency.status ),
+ str( self.install_model.ToolDependency.installation_status.INSTALLED ) ) )
status = self.install_model.ToolDependency.installation_status.INSTALLED
tool_dependency = tool_dependency_util.set_tool_dependency_attributes( self.app,
tool_dependency=tool_dependency,
@@ -531,10 +531,10 @@
self.install_model.context.add( tool_shed_repository )
self.install_model.context.flush()
if 'tool_dependencies' in irmm_metadata_dict and not reinstalling:
- tool_dependencies = tool_dependency_util.create_tool_dependency_objects( self.app,
- tool_shed_repository,
- relative_install_dir,
- set_status=True )
+ tool_dependency_util.create_tool_dependency_objects( self.app,
+ tool_shed_repository,
+ relative_install_dir,
+ set_status=True )
if 'sample_files' in irmm_metadata_dict:
sample_files = irmm_metadata_dict.get( 'sample_files', [] )
tool_index_sample_files = tdtm.get_tool_index_sample_files( sample_files )
@@ -579,12 +579,12 @@
new_install=True )
if 'data_manager' in irmm_metadata_dict:
dmh = data_manager.DataManagerHandler( self.app )
- new_data_managers = dmh.install_data_managers( self.app.config.shed_data_manager_config_file,
- irmm_metadata_dict,
- shed_config_dict,
- relative_install_dir,
- tool_shed_repository,
- repository_tools_tups )
+ dmh.install_data_managers( self.app.config.shed_data_manager_config_file,
+ irmm_metadata_dict,
+ shed_config_dict,
+ relative_install_dir,
+ tool_shed_repository,
+ repository_tools_tups )
if 'datatypes' in irmm_metadata_dict:
tool_shed_repository.status = self.install_model.ToolShedRepository.installation_status.LOADING_PROPRIETARY_DATATYPES
if not tool_shed_repository.includes_datatypes:
@@ -656,13 +656,9 @@
tool_shed_url = installation_dict[ 'tool_shed_url' ]
# Handle contained tools.
if includes_tools_for_display_in_tool_panel and ( new_tool_panel_section_label or tool_panel_section_id ):
- tool_panel_section_key, tool_section = \
- self.tpm.handle_tool_panel_section( self.app.toolbox,
- tool_panel_section_id=tool_panel_section_id,
- new_tool_panel_section_label=new_tool_panel_section_label )
- else:
- tool_panel_section_key = None
- tool_section = None
+ self.tpm.handle_tool_panel_section( self.app.toolbox,
+ tool_panel_section_id=tool_panel_section_id,
+ new_tool_panel_section_label=new_tool_panel_section_label )
encoded_repository_ids = [ self.app.security.encode_id( tsr.id ) for tsr in created_or_updated_tool_shed_repositories ]
new_kwd = dict( includes_tools=includes_tools,
includes_tools_for_display_in_tool_panel=includes_tools_for_display_in_tool_panel,
@@ -679,7 +675,7 @@
tool_shed_repository_ids=encoded_repository_ids,
tool_shed_url=tool_shed_url )
encoded_kwd = encoding_util.tool_shed_encode( new_kwd )
- tsr_ids = [ r.id for r in created_or_updated_tool_shed_repositories ]
+ tsr_ids = [ r.id for r in created_or_updated_tool_shed_repositories ]
tool_shed_repositories = []
for tsr_id in tsr_ids:
tsr = self.install_model.context.query( self.install_model.ToolShedRepository ).get( tsr_id )
@@ -895,10 +891,10 @@
# Get the tool_dependencies.xml file from the repository.
tool_dependencies_config = hg_util.get_config_from_disk( 'tool_dependencies.xml', install_dir )
itdm = InstallToolDependencyManager( self.app )
- installed_tool_dependencies = itdm.install_specified_tool_dependencies( tool_shed_repository=tool_shed_repository,
- tool_dependencies_config=tool_dependencies_config,
- tool_dependencies=tool_shed_repository.tool_dependencies,
- from_tool_migration_manager=False )
+ itdm.install_specified_tool_dependencies( tool_shed_repository=tool_shed_repository,
+ tool_dependencies_config=tool_dependencies_config,
+ tool_dependencies=tool_shed_repository.tool_dependencies,
+ from_tool_migration_manager=False )
basic_util.remove_dir( work_dir )
self.update_tool_shed_repository_status( tool_shed_repository,
self.install_model.ToolShedRepository.installation_status.INSTALLED )
diff -r 97f46da40bb3767c6cf0d440b1d2d58e06edf5e6 -r 50062f6e9b47a36dad57393292611632908fe79a lib/tool_shed/galaxy_install/repair_repository_manager.py
--- a/lib/tool_shed/galaxy_install/repair_repository_manager.py
+++ b/lib/tool_shed/galaxy_install/repair_repository_manager.py
@@ -65,7 +65,7 @@
repair_dict = {}
irm = install_manager.InstallRepositoryManager( self.app )
# Get a dictionary of all repositories upon which the contents of the current repository_metadata
- #record depend.
+ # record depend.
repository_dependencies_dict = rdim.get_repository_dependencies_for_installed_tool_shed_repository( self.app,
repository )
if repository_dependencies_dict:
@@ -142,14 +142,14 @@
return repo_info_dict, tool_panel_section_key
def repair_tool_shed_repository( self, repository, repo_info_dict ):
-
+
def add_repair_dict_entry( repository_name, error_message ):
if repository_name in repair_dict:
repair_dict[ repository_name ].append( error_message )
else:
repair_dict[ repository_name ] = [ error_message ]
return repair_dict
-
+
metadata = repository.metadata
repair_dict = {}
tpm = tool_panel_manager.ToolPanelManager( self.app )
diff -r 97f46da40bb3767c6cf0d440b1d2d58e06edf5e6 -r 50062f6e9b47a36dad57393292611632908fe79a lib/tool_shed/galaxy_install/repository_dependencies/repository_dependency_manager.py
--- a/lib/tool_shed/galaxy_install/repository_dependencies/repository_dependency_manager.py
+++ b/lib/tool_shed/galaxy_install/repository_dependencies/repository_dependency_manager.py
@@ -38,13 +38,13 @@
for repo_info_dict in repo_info_dicts:
for name, repo_info_tuple in repo_info_dict.items():
description, \
- repository_clone_url, \
- changeset_revision, \
- ctx_rev, \
- repository_owner, \
- repository_dependencies, \
- tool_dependencies = \
- suc.get_repo_info_tuple_contents( repo_info_tuple )
+ repository_clone_url, \
+ changeset_revision, \
+ ctx_rev, \
+ repository_owner, \
+ repository_dependencies, \
+ tool_dependencies = \
+ suc.get_repo_info_tuple_contents( repo_info_tuple )
if repository_dependencies:
for key, val in repository_dependencies.items():
if key in [ 'root_key', 'description' ]:
@@ -71,12 +71,12 @@
for repository_dependency_components_list in val:
required_repository = None
rd_toolshed, \
- rd_name, \
- rd_owner, \
- rd_changeset_revision, \
- rd_prior_installation_required, \
- rd_only_if_compiling_contained_td = \
- common_util.parse_repository_dependency_tuple( repository_dependency_components_list )
+ rd_name, \
+ rd_owner, \
+ rd_changeset_revision, \
+ rd_prior_installation_required, \
+ rd_only_if_compiling_contained_td = \
+ common_util.parse_repository_dependency_tuple( repository_dependency_components_list )
# Get the the tool_shed_repository defined by rd_name, rd_owner and rd_changeset_revision. This
# is the repository that will be required by the current d_repository.
# TODO: Check tool_shed_repository.tool_shed as well when repository dependencies across tool sheds is supported.
@@ -101,10 +101,10 @@
repository_dependency = self.get_repository_dependency_by_repository_id( install_model,
required_repository.id )
if not repository_dependency:
- log.debug( 'Creating new repository_dependency record for installed revision %s of repository: %s owned by %s.' % \
- ( str( required_repository.installed_changeset_revision ),
- str( required_repository.name ),
- str( required_repository.owner ) ) )
+ log.debug( 'Creating new repository_dependency record for installed revision %s of repository: %s owned by %s.' %
+ ( str( required_repository.installed_changeset_revision ),
+ str( required_repository.name ),
+ str( required_repository.owner ) ) )
repository_dependency = install_model.RepositoryDependency( tool_shed_repository_id=required_repository.id )
install_model.context.add( repository_dependency )
install_model.context.flush()
@@ -159,13 +159,13 @@
for name, repo_info_tuple in repo_info_dict.items():
can_update_db_record = False
description, \
- repository_clone_url, \
- changeset_revision, \
- ctx_rev, \
- repository_owner, \
- repository_dependencies, \
- tool_dependencies = \
- suc.get_repo_info_tuple_contents( repo_info_tuple )
+ repository_clone_url, \
+ changeset_revision, \
+ ctx_rev, \
+ repository_owner, \
+ repository_dependencies, \
+ tool_dependencies = \
+ suc.get_repo_info_tuple_contents( repo_info_tuple )
# See if the repository has an existing record in the database.
repository_db_record, installed_changeset_revision = \
suc.repository_was_previously_installed( self.app, tool_shed_url, name, repo_info_tuple, from_tip=False )
@@ -190,8 +190,6 @@
# record in the database.
name = repository_db_record.name
installed_changeset_revision = repository_db_record.installed_changeset_revision
- metadata_dict = repository_db_record.metadata
- dist_to_shed = repository_db_record.dist_to_shed
can_update_db_record = True
elif repository_db_record.status in [ install_model.ToolShedRepository.installation_status.DEACTIVATED ]:
# The current tool shed repository is deactivated, so updating its database record
@@ -209,8 +207,6 @@
else:
# No record exists in the database for the repository currently being processed.
installed_changeset_revision = changeset_revision
- metadata_dict = {}
- dist_to_shed = False
can_update_db_record = True
if can_update_db_record:
# The database record for the tool shed repository currently being processed can be updated.
@@ -348,13 +344,10 @@
# a dependency of the dependent repository's contained tool dependency, and only if that
# tool dependency requires compilation.
# For backward compatibility to the 12/20/12 Galaxy release.
- prior_installation_required = 'False'
only_if_compiling_contained_td = 'False'
if len( components_list ) == 4:
- prior_installation_required = 'False'
only_if_compiling_contained_td = 'False'
elif len( components_list ) == 5:
- prior_installation_required = components_list[ 4 ]
only_if_compiling_contained_td = 'False'
if not asbool( only_if_compiling_contained_td ):
if components_list not in required_repository_tups:
https://bitbucket.org/galaxy/galaxy-central/commits/032eefd299cb/
Changeset: 032eefd299cb
User: jmchilton
Date: 2014-12-28 16:23:44+00:00
Summary: Tweak two ToolShed modules to clarify they don't use ToolSection...
... objects (directly anyway). I would like to refactor all the tool shed components to not deal directly with ToolSection objects but instead just pass around IDs.
Affected #: 2 files
diff -r 50062f6e9b47a36dad57393292611632908fe79a -r 032eefd299cbfd103ea85103e64147d436068fb5 lib/tool_shed/galaxy_install/repair_repository_manager.py
--- a/lib/tool_shed/galaxy_install/repair_repository_manager.py
+++ b/lib/tool_shed/galaxy_install/repair_repository_manager.py
@@ -123,7 +123,7 @@
tool_panel_section_name = section_dict[ 'name' ]
if tool_panel_section_id:
tpm = tool_panel_manager.ToolPanelManager( self.app )
- tool_panel_section_key, tool_panel_section = \
+ tool_panel_section_key, _ = \
tpm.get_or_create_tool_section( self.app.toolbox,
tool_panel_section_id=tool_panel_section_id,
new_tool_panel_section_label=tool_panel_section_name )
@@ -165,7 +165,7 @@
suc.get_tool_panel_config_tool_path_install_dir( self.app, repository )
# Reset the repository attributes to the New state for installation.
if metadata:
- tool_section, tool_panel_section_key = \
+ _, tool_panel_section_key = \
tpm.handle_tool_panel_selection( self.app.toolbox,
metadata,
no_changes_checked=True,
diff -r 50062f6e9b47a36dad57393292611632908fe79a -r 032eefd299cbfd103ea85103e64147d436068fb5 lib/tool_shed/galaxy_install/repository_dependencies/repository_dependency_manager.py
--- a/lib/tool_shed/galaxy_install/repository_dependencies/repository_dependency_manager.py
+++ b/lib/tool_shed/galaxy_install/repository_dependencies/repository_dependency_manager.py
@@ -213,7 +213,7 @@
# Get the repository metadata to see where it was previously located in the tool panel.
tpm = tool_panel_manager.ToolPanelManager( self.app )
if repository_db_record and repository_db_record.metadata:
- tool_section, tool_panel_section_key = \
+ _, tool_panel_section_key = \
tpm.handle_tool_panel_selection( toolbox=self.app.toolbox,
metadata=repository_db_record.metadata,
no_changes_checked=no_changes_checked,
@@ -221,7 +221,7 @@
new_tool_panel_section_label=new_tool_panel_section_label )
else:
# We're installing a new tool shed repository that does not yet have a database record.
- tool_panel_section_key, tool_section = \
+ tool_panel_section_key, _ = \
tpm.handle_tool_panel_section( self.app.toolbox,
tool_panel_section_id=tool_panel_section_id,
new_tool_panel_section_label=new_tool_panel_section_label )
https://bitbucket.org/galaxy/galaxy-central/commits/6d4909f34123/
Changeset: 6d4909f34123
User: jmchilton
Date: 2014-12-28 16:23:44+00:00
Summary: More centralization of code for registering tools in ToolBox.
Affected #: 1 file
diff -r 032eefd299cbfd103ea85103e64147d436068fb5 -r 6d4909f34123fe53f1497dd2ea27a611039ae5c0 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -679,7 +679,7 @@
# changed, so the tool should always be reloaded here. We used to
# only load the tool if it was not found in self.tools_by_id, but
# performing that check did not enable this scenario.
- self.tools_by_id[ tool.id ] = tool
+ self.register_tool( tool )
if load_panel_dict:
self.__add_tool_to_tool_panel( tool, panel_dict, section=isinstance( panel_dict, ToolSection ) )
https://bitbucket.org/galaxy/galaxy-central/commits/b499a560826b/
Changeset: b499a560826b
User: jmchilton
Date: 2014-12-28 16:23:44+00:00
Summary: Eliminate one reference to ToolBox.tool_panel in install_manager.py.
Affected #: 2 files
diff -r 6d4909f34123fe53f1497dd2ea27a611039ae5c0 -r b499a560826b2d3a3cfc16dc44b99dafa7c3802e lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -1021,6 +1021,24 @@
status = 'done'
return message, status
+ def find_section_id( self, tool_panel_section_id ):
+ """
+ Find the section ID referenced by the key or return '' indicating
+ no such section id.
+ """
+ if not tool_panel_section_id:
+ tool_panel_section_id = ''
+ else:
+ if tool_panel_section_id not in self.tool_panel:
+ # Hack introduced without comment in a29d54619813d5da992b897557162a360b8d610c-
+ # not sure why it is needed.
+ fixed_tool_panel_section_id = 'section_%s' % tool_panel_section_id
+ if fixed_tool_panel_section_id in self.tool_panel:
+ tool_panel_section_id = fixed_tool_panel_section_id
+ else:
+ tool_panel_section_id = ''
+ return tool_panel_section_id
+
def load_workflow( self, workflow_id ):
"""
Return an instance of 'Workflow' identified by `id`,
diff -r 6d4909f34123fe53f1497dd2ea27a611039ae5c0 -r b499a560826b2d3a3cfc16dc44b99dafa7c3802e lib/tool_shed/galaxy_install/install_manager.py
--- a/lib/tool_shed/galaxy_install/install_manager.py
+++ b/lib/tool_shed/galaxy_install/install_manager.py
@@ -742,16 +742,7 @@
tool_path = shed_config_dict[ 'tool_path' ]
if not shed_tool_conf:
raise exceptions.RequestParameterMissingException( "Missing required parameter 'shed_tool_conf'." )
- tool_panel_section_id = install_options.get( 'tool_panel_section_id', '' )
- if tool_panel_section_id not in [ None, '' ]:
- if tool_panel_section_id not in self.app.toolbox.tool_panel:
- fixed_tool_panel_section_id = 'section_%s' % tool_panel_section_id
- if fixed_tool_panel_section_id in self.app.toolbox.tool_panel:
- tool_panel_section_id = fixed_tool_panel_section_id
- else:
- tool_panel_section_id = ''
- else:
- tool_panel_section_id = ''
+ tool_panel_section_id = self.app.toolbox.find_section_id( install_options.get( 'tool_panel_section_id', '' ) )
# Build the dictionary of information necessary for creating tool_shed_repository database records
# for each repository being installed.
installation_dict = dict( install_repository_dependencies=install_repository_dependencies,
https://bitbucket.org/galaxy/galaxy-central/commits/54b778976b7b/
Changeset: 54b778976b7b
User: jmchilton
Date: 2014-12-28 16:23:44+00:00
Summary: Simplify shed-y logic in load_tool_tag_set.
Drops cycolomatic complexity from 14 to 10 for that method.
Affected #: 2 files
diff -r b499a560826b2d3a3cfc16dc44b99dafa7c3802e -r 54b778976b7bb297160955170fda6ff1efd2d62a lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -559,6 +559,23 @@
def tools( self ):
return self.tools_by_id.iteritems()
+ def __elem_to_tool_shed_repository( self, elem ):
+ # The tool is contained in an installed tool shed repository, so load
+ # the tool only if the repository has not been marked deleted.
+ tool_shed = elem.find( "tool_shed" ).text
+ repository_name = elem.find( "repository_name" ).text
+ repository_owner = elem.find( "repository_owner" ).text
+ installed_changeset_revision_elem = elem.find( "installed_changeset_revision" )
+ if installed_changeset_revision_elem is None:
+ # Backward compatibility issue - the tag used to be named 'changeset_revision'.
+ installed_changeset_revision_elem = elem.find( "changeset_revision" )
+ installed_changeset_revision = installed_changeset_revision_elem.text
+ tool_shed_repository = self.__get_tool_shed_repository( tool_shed,
+ repository_name,
+ repository_owner,
+ installed_changeset_revision )
+ return tool_shed_repository
+
def __get_tool_shed_repository( self, tool_shed, name, owner, installed_changeset_revision ):
# We store only the port, if one exists, in the database.
tool_shed = common_util.remove_protocol_from_tool_shed_url( tool_shed )
@@ -613,42 +630,29 @@
try:
path = elem.get( "file" )
repository_id = None
- if guid is None:
- tool_shed_repository = None
- can_load_into_panel_dict = True
- else:
+
+ tool_shed_repository = None
+ can_load_into_panel_dict = True
+ if guid is not None:
# The tool is contained in an installed tool shed repository, so load
# the tool only if the repository has not been marked deleted.
- tool_shed = elem.find( "tool_shed" ).text
- repository_name = elem.find( "repository_name" ).text
- repository_owner = elem.find( "repository_owner" ).text
- installed_changeset_revision_elem = elem.find( "installed_changeset_revision" )
- if installed_changeset_revision_elem is None:
- # Backward compatibility issue - the tag used to be named 'changeset_revision'.
- installed_changeset_revision_elem = elem.find( "changeset_revision" )
- installed_changeset_revision = installed_changeset_revision_elem.text
- tool_shed_repository = self.__get_tool_shed_repository( tool_shed,
- repository_name,
- repository_owner,
- installed_changeset_revision )
+ tool_shed_repository = self.__elem_to_tool_shed_repository( elem )
if tool_shed_repository:
# Only load tools if the repository is not deactivated or uninstalled.
can_load_into_panel_dict = not tool_shed_repository.deleted
repository_id = self.app.security.encode_id( tool_shed_repository.id )
- else:
- # If there is not yet a tool_shed_repository record, we're in the process of installing
- # a new repository, so any included tools can be loaded into the tool panel.
- can_load_into_panel_dict = True
+ # Else there is not yet a tool_shed_repository record, we're in the process of installing
+ # a new repository, so any included tools can be loaded into the tool panel.
tool = self.load_tool( os.path.join( tool_path, path ), guid=guid, repository_id=repository_id )
if string_as_bool(elem.get( 'hidden', False )):
tool.hidden = True
key = 'tool_%s' % str( tool.id )
if can_load_into_panel_dict:
if guid is not None:
- tool.tool_shed = tool_shed
- tool.repository_name = repository_name
- tool.repository_owner = repository_owner
- tool.installed_changeset_revision = installed_changeset_revision
+ tool.tool_shed = tool_shed_repository.tool_shed
+ tool.repository_name = tool_shed_repository.name
+ tool.repository_owner = tool_shed_repository.owner
+ tool.installed_changeset_revision = tool_shed_repository.installed_changeset_revision
tool.guid = guid
tool.version = elem.find( "version" ).text
# Make sure the tool has a tool_version.
diff -r b499a560826b2d3a3cfc16dc44b99dafa7c3802e -r 54b778976b7bb297160955170fda6ff1efd2d62a test/unit/tools/test_toolbox.py
--- a/test/unit/tools/test_toolbox.py
+++ b/test/unit/tools/test_toolbox.py
@@ -136,6 +136,27 @@
assert toolbox.get_tool( "test_tool" ) is not None
assert toolbox.get_tool( "not_a_test_tool" ) is None
+ def test_tool_shed_properties( self ):
+ self._init_tool()
+ self._setup_two_versions_in_config( section=False )
+ self._setup_two_versions()
+
+ test_tool = self.toolbox.get_tool( "test_tool" )
+ assert test_tool.tool_shed == "github.com"
+ assert test_tool.repository_owner == "galaxyproject"
+ assert test_tool.repository_name == "example"
+ assert test_tool.installed_changeset_revision == "1"
+
+ def test_tool_shed_properties_only_on_installed_tools( self ):
+ self._init_tool()
+ self._add_config( """<toolbox><tool file="tool.xml" /></toolbox>""" )
+ toolbox = self.toolbox
+ test_tool = toolbox.get_tool( "test_tool" )
+ assert test_tool.tool_shed is None
+ assert test_tool.repository_name is None
+ assert test_tool.repository_owner is None
+ assert test_tool.installed_changeset_revision is None
+
def test_load_file_in_section( self ):
self._init_tool()
self._add_config( """<toolbox><section id="t" name="test"><tool file="tool.xml" /></section></toolbox>""" )
https://bitbucket.org/galaxy/galaxy-central/commits/1912dec92b72/
Changeset: 1912dec92b72
User: jmchilton
Date: 2014-12-28 16:23:44+00:00
Summary: De-duplication for loading elements into the tool panel.
Create one public method load_item on ToolBox that should be used externally instead of load_tool_tag_set, load_section_tag_set, etc.... This reduces the duplication within the toolbox and between the toolbox and the Tool Shed's ToolPanelManager. Probably more importantly it also is another step down the road toward hiding implementation details such as toolbox.tool_panel and toolbox.intergrated_tool_panel from the ToolPanelManager.
Already had unit test coverage for ToolPanelManager stuff here - but added test coverage for loading labels, workflows, and tool directories.
Affected #: 3 files
diff -r 54b778976b7bb297160955170fda6ff1efd2d62a -r 1912dec92b728b974094456be8eb6d84d34a7ca6 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -222,16 +222,14 @@
self.index += 1
if parsing_shed_tool_conf:
config_elems.append( elem )
- if elem.tag == 'tool':
- self.load_tool_tag_set( elem, self.tool_panel, self.integrated_tool_panel, tool_path, load_panel_dict, guid=elem.get( 'guid' ), index=index )
- elif elem.tag == 'workflow':
- self.load_workflow_tag_set( elem, self.tool_panel, self.integrated_tool_panel, load_panel_dict, index=index )
- elif elem.tag == 'section':
- self.load_section_tag_set( elem, tool_path, load_panel_dict, index=index )
- elif elem.tag == 'label':
- self.load_label_tag_set( elem, self.tool_panel, self.integrated_tool_panel, load_panel_dict, index=index )
- elif elem.tag == 'tool_dir':
- self.load_tooldir_tag_set( elem, self.tool_panel, self.integrated_tool_panel, tool_path, load_panel_dict )
+ self.load_item(
+ elem,
+ tool_path=tool_path,
+ load_panel_dict=load_panel_dict,
+ guid=elem.get( 'guid' ),
+ index=index,
+ internal=True
+ )
if parsing_shed_tool_conf:
shed_tool_conf_dict = dict( config_filename=config_filename,
@@ -239,6 +237,28 @@
config_elems=config_elems )
self.shed_tool_confs.append( shed_tool_conf_dict )
+ def load_item( self, elem, tool_path, panel_dict=None, integrated_panel_dict=None, load_panel_dict=True, guid=None, index=None, internal=False ):
+ item_type = elem.tag
+ if item_type not in ['tool', 'section'] and not internal:
+ # External calls from tool shed code cannot load labels or tool
+ # directories.
+ return
+
+ if panel_dict is None:
+ panel_dict = self.tool_panel
+ if integrated_panel_dict is None:
+ integrated_panel_dict = self.integrated_tool_panel
+ if item_type == 'tool':
+ self.load_tool_tag_set( elem, panel_dict=panel_dict, integrated_panel_dict=integrated_panel_dict, tool_path=tool_path, load_panel_dict=load_panel_dict, guid=guid, index=index )
+ elif item_type == 'workflow':
+ self.load_workflow_tag_set( elem, panel_dict=panel_dict, integrated_panel_dict=integrated_panel_dict, load_panel_dict=load_panel_dict, index=index )
+ elif item_type == 'section':
+ self.load_section_tag_set( elem, tool_path=tool_path, load_panel_dict=load_panel_dict, index=index )
+ elif item_type == 'label':
+ self.load_label_tag_set( elem, panel_dict=panel_dict, integrated_panel_dict=integrated_panel_dict, load_panel_dict=load_panel_dict, index=index )
+ elif item_type == 'tool_dir':
+ self.load_tooldir_tag_set( elem, panel_dict, tool_path, integrated_panel_dict, load_panel_dict=load_panel_dict )
+
def get_shed_config_dict_by_filename( self, filename, default=None ):
for shed_config_dict in self.shed_tool_confs:
if shed_config_dict[ 'config_filename' ] == filename:
@@ -729,14 +749,16 @@
integrated_section = ToolSection( elem )
integrated_elems = integrated_section.elems
for sub_index, sub_elem in enumerate( elem ):
- if sub_elem.tag == 'tool':
- self.load_tool_tag_set( sub_elem, elems, integrated_elems, tool_path, load_panel_dict, guid=sub_elem.get( 'guid' ), index=sub_index )
- elif sub_elem.tag == 'workflow':
- self.load_workflow_tag_set( sub_elem, elems, integrated_elems, load_panel_dict, index=sub_index )
- elif sub_elem.tag == 'label':
- self.load_label_tag_set( sub_elem, elems, integrated_elems, load_panel_dict, index=sub_index )
- elif sub_elem.tag == 'tool_dir':
- self.load_tooldir_tag_set( sub_elem, elems, tool_path, integrated_elems, load_panel_dict )
+ self.load_item(
+ sub_elem,
+ tool_path=tool_path,
+ panel_dict=elems,
+ integrated_panel_dict=integrated_elems,
+ load_panel_dict=load_panel_dict,
+ guid=sub_elem.get( 'guid' ),
+ index=sub_index,
+ internal=True,
+ )
if load_panel_dict:
self.tool_panel[ key ] = section
# Always load sections into the integrated_tool_panel.
diff -r 54b778976b7bb297160955170fda6ff1efd2d62a -r 1912dec92b728b974094456be8eb6d84d34a7ca6 lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
--- a/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
+++ b/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
@@ -58,22 +58,12 @@
# Add the new elements to the in-memory list of config_elems.
config_elems.append( config_elem )
# Load the tools into the in-memory tool panel.
- if config_elem.tag == 'section':
- self.app.toolbox.load_section_tag_set( config_elem, tool_path, load_panel_dict=True )
- elif config_elem.tag == 'workflow':
- self.app.toolbox.load_workflow_tag_set( config_elem,
- self.app.toolbox.tool_panel,
- self.app.toolbox.integrated_tool_panel,
- load_panel_dict=True )
- elif config_elem.tag == 'tool':
- self.app.toolbox.load_tool_tag_set(
- config_elem,
- self.app.toolbox.tool_panel,
- self.app.toolbox.integrated_tool_panel,
- tool_path,
- load_panel_dict=True,
- guid=config_elem.get( 'guid' )
- )
+ self.app.toolbox.load_item(
+ config_elem,
+ tool_path=tool_path,
+ load_panel_dict=True,
+ guid=config_elem.get( 'guid' ),
+ )
# Replace the old list of in-memory config_elems with the new list for this shed_tool_conf_dict.
shed_tool_conf_dict[ 'config_elems' ] = config_elems
self.app.toolbox.update_shed_config( index, shed_tool_conf_dict )
diff -r 54b778976b7bb297160955170fda6ff1efd2d62a -r 1912dec92b728b974094456be8eb6d84d34a7ca6 test/unit/tools/test_toolbox.py
--- a/test/unit/tools/test_toolbox.py
+++ b/test/unit/tools/test_toolbox.py
@@ -3,6 +3,7 @@
import unittest
from galaxy.tools import ToolBox
+from galaxy import model
from galaxy.model import tool_shed_install
from galaxy.model.tool_shed_install import mapping
import tools_support
@@ -216,6 +217,67 @@
assert self.toolbox.get_tool_id( "github.com/galaxyproect/example/test_tool/0.2" ) == "github.com/galaxyproect/example/test_tool/0.2"
assert self.toolbox.get_tool_id( "github.com/galaxyproect/example/test_tool/0.3" ) is None
+ def test_tool_dir( self ):
+ self._init_tool()
+ self._add_config( """<toolbox><tool_dir dir="%s" /></toolbox>""" % self.test_directory )
+
+ toolbox = self.toolbox
+ assert toolbox.get_tool( "test_tool" ) is not None
+
+ def test_workflow_in_panel( self ):
+ stored_workflow = self.__test_workflow()
+ encoded_id = self.app.security.encode_id( stored_workflow.id )
+ self._add_config( """<toolbox><workflow id="%s" /></toolbox>""" % encoded_id )
+ assert len( self.toolbox.tool_panel ) == 1
+ panel_workflow = self.toolbox.tool_panel.values()[ 0 ]
+ assert panel_workflow == stored_workflow.latest_workflow
+ # TODO: test to_dict with workflows
+
+ def test_workflow_in_section( self ):
+ stored_workflow = self.__test_workflow()
+ encoded_id = self.app.security.encode_id( stored_workflow.id )
+ self._add_config( """<toolbox><section id="tid" name="TID"><workflow id="%s" /></section></toolbox>""" % encoded_id )
+ assert len( self.toolbox.tool_panel ) == 1
+ section = self.toolbox.tool_panel[ 'tid' ]
+ assert len( section.elems ) == 1
+ panel_workflow = section.elems.values()[ 0 ]
+ assert panel_workflow == stored_workflow.latest_workflow
+
+ def test_label_in_panel( self ):
+ self._add_config( """<toolbox><label id="lab1" text="Label 1" /><label id="lab2" text="Label 2" /></toolbox>""" )
+ assert len( self.toolbox.tool_panel ) == 2
+ self.__check_test_labels( self.toolbox.tool_panel )
+
+ def test_label_in_section( self ):
+ self._add_config( """<toolbox><section id="tid" name="TID"><label id="lab1" text="Label 1" /><label id="lab2" text="Label 2" /></section></toolbox>""" )
+ assert len( self.toolbox.tool_panel ) == 1
+ section = self.toolbox.tool_panel[ 'tid' ]
+ self.__check_test_labels( section.elems )
+
+ def __check_test_labels( self, panel_dict ):
+ assert panel_dict.keys() == ["label_lab1", "label_lab2"]
+ label1 = panel_dict.values()[ 0 ]
+ assert label1.id == "lab1"
+ assert label1.text == "Label 1"
+
+ label2 = panel_dict[ "label_lab2" ]
+ assert label2.id == "lab2"
+ assert label2.text == "Label 2"
+
+ def __test_workflow( self ):
+ stored_workflow = model.StoredWorkflow()
+ workflow = model.Workflow()
+ workflow.stored_workflow = stored_workflow
+ stored_workflow.latest_workflow = workflow
+ user = model.User()
+ user.email = "test(a)example.com"
+ user.password = "passw0rD1"
+ stored_workflow.user = user
+ self.app.model.context.add( workflow )
+ self.app.model.context.add( stored_workflow )
+ self.app.model.context.flush()
+ return stored_workflow
+
def __verify_two_test_tools( self ):
# Assert tool versions of the tool with simple id 'test_tool'
all_versions = self.toolbox.get_tool( "test_tool", get_all_versions=True )
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 remaining tool shed test cases for new escaped values.
by commits-noreply@bitbucket.org 27 Dec '14
by commits-noreply@bitbucket.org 27 Dec '14
27 Dec '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/97f46da40bb3/
Changeset: 97f46da40bb3
User: jmchilton
Date: 2014-12-28 04:46:22+00:00
Summary: Fix remaining tool shed test cases for new escaped values.
I think in this case the values on the page are correct now - but the test framework needs to be updated to handle the escaped value.
Affected #: 1 file
diff -r 461a6a9379001959b5b3259f90a2b9471ce391ed -r 97f46da40bb3767c6cf0d440b1d2d58e06edf5e6 test/tool_shed/base/twilltestcase.py
--- a/test/tool_shed/base/twilltestcase.py
+++ b/test/tool_shed/base/twilltestcase.py
@@ -430,6 +430,8 @@
url = '/admin_toolshed/manage_repository?id=%s' % self.security.encode_id( installed_repository.id )
self.visit_galaxy_url( url )
strings_displayed.append( str( installed_repository.installed_changeset_revision ) )
+ # Every place Galaxy's XXXX tool appears in attribute - need to quote.
+ strings_displayed = map( lambda x: x.replace("'", "'"), strings_displayed )
self.check_for_strings( strings_displayed, strings_not_displayed )
def display_installed_workflow_image( self, repository, workflow_name, strings_displayed=[], strings_not_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
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/86241a27f4d8/
Changeset: 86241a27f4d8
User: jmchilton
Date: 2014-12-27 22:49:16+00:00
Summary: Add --no_cleanup option to tests.
Affected #: 1 file
diff -r 1ed5a63aae0a5c8091483658c579d9d762a4c3fb -r 86241a27f4d8d7065fb7908a0e687d6b11a062eb run_tests.sh
--- a/run_tests.sh
+++ b/run_tests.sh
@@ -21,6 +21,12 @@
'${0##*/} -unit testscriptath' running particular tests scripts
'${0##*/} -qunit' for running qunit JavaScript tests
'${0##*/} -qunit testname' for running single JavaScript test with given name
+
+Extra options:
+
+ --no_cleanup Do not delete temp files for Python functional tests (-toolshed, -framework, etc...)
+ --report_file Path of HTML report to produce (for Python Galaxy functional tests).
+ --xunit_report_file Path of XUnit report to produce (for Python Galaxy functional tests).
EOF
}
@@ -196,6 +202,16 @@
shift 1
fi
;;
+ --no_cleanup)
+ GALAXY_TEST_NO_CLEANUP=1
+ export GALAXY_TEST_NO_CLEANUP
+ TOOL_SHED_TEST_NO_CLEANUP=1
+ export TOOL_SHED_TEST_NO_CLEANUP
+ GALAXY_INSTALL_TEST_NO_CLEANUP=1
+ export GALAXY_INSTALL_TEST_NO_CLEANUP
+ echo "Skipping Python test clean up."
+ shift
+ ;;
-watch|--watch)
# Have grunt watch test or directory for changes, only
# valid for javascript testing.
https://bitbucket.org/galaxy/galaxy-central/commits/461a6a937900/
Changeset: 461a6a937900
User: jmchilton
Date: 2014-12-27 22:49:16+00:00
Summary: Skip checking tool migrations for Galaxy in tool shed tests.
Affected #: 1 file
diff -r 86241a27f4d8d7065fb7908a0e687d6b11a062eb -r 461a6a9379001959b5b3259f90a2b9471ce391ed test/tool_shed/functional_tests.py
--- a/test/tool_shed/functional_tests.py
+++ b/test/tool_shed/functional_tests.py
@@ -359,6 +359,7 @@
database_connection = galaxy_database_connection,
database_auto_migrate = galaxy_database_auto_migrate,
datatype_converters_config_file = "datatype_converters_conf.xml.sample",
+ check_migrate_tools = False,
enable_tool_shed_check = True,
file_path = galaxy_file_path,
global_conf = galaxy_global_conf,
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
27 Dec '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/1ed5a63aae0a/
Changeset: 1ed5a63aae0a
User: jmchilton
Date: 2014-12-27 22:35:51+00:00
Summary: Merge next-stable.
Affected #: 9 files
diff -r 63ec80be64bb00414be0f7122a51907114ffb714 -r 1ed5a63aae0a5c8091483658c579d9d762a4c3fb lib/galaxy/web/base/controllers/admin.py
--- a/lib/galaxy/web/base/controllers/admin.py
+++ b/lib/galaxy/web/base/controllers/admin.py
@@ -7,7 +7,7 @@
from galaxy.web.form_builder import CheckboxField
from string import punctuation as PUNCTUATION
import galaxy.queue_worker
-from markupsafe import escape
+from tool_shed.util.web_util import escape
from tool_shed.util import shed_util_common as suc
diff -r 63ec80be64bb00414be0f7122a51907114ffb714 -r 1ed5a63aae0a5c8091483658c579d9d762a4c3fb lib/galaxy/webapps/galaxy/controllers/admin.py
--- a/lib/galaxy/webapps/galaxy/controllers/admin.py
+++ b/lib/galaxy/webapps/galaxy/controllers/admin.py
@@ -17,7 +17,7 @@
from galaxy.web.params import QuotaParamParser
from tool_shed.util import common_util
from tool_shed.util import encoding_util
-from markupsafe import escape
+from tool_shed.util.web_util import escape
log = logging.getLogger( __name__ )
diff -r 63ec80be64bb00414be0f7122a51907114ffb714 -r 1ed5a63aae0a5c8091483658c579d9d762a4c3fb 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
@@ -8,9 +8,9 @@
from galaxy.web.form_builder import CheckboxField
from galaxy.util import json
from galaxy.model.orm import or_
-from markupsafe import escape
import tool_shed.repository_types.util as rt_util
+from tool_shed.util.web_util import escape
from tool_shed.util import common_util
from tool_shed.util import encoding_util
diff -r 63ec80be64bb00414be0f7122a51907114ffb714 -r 1ed5a63aae0a5c8091483658c579d9d762a4c3fb lib/galaxy/webapps/tool_shed/controllers/admin.py
--- a/lib/galaxy/webapps/tool_shed/controllers/admin.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/admin.py
@@ -3,7 +3,7 @@
from galaxy import util
from galaxy.util import inflector
from galaxy import web
-from markupsafe import escape
+from tool_shed.util.web_util import escape
from galaxy.web.base.controller import BaseUIController
from galaxy.web.base.controllers.admin import Admin
diff -r 63ec80be64bb00414be0f7122a51907114ffb714 -r 1ed5a63aae0a5c8091483658c579d9d762a4c3fb lib/galaxy/webapps/tool_shed/controllers/repository.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py
@@ -6,7 +6,6 @@
from time import strftime
from datetime import date
from datetime import datetime
-from markupsafe import escape
from galaxy import util
from galaxy import web
@@ -19,6 +18,7 @@
from tool_shed.capsule import capsule_manager
from tool_shed.dependencies.repository import relation_builder
+from tool_shed.util.web_util import escape
from tool_shed.galaxy_install import dependency_display
from tool_shed.metadata import repository_metadata_manager
from tool_shed.utility_containers import ToolShedUtilityContainerManager
diff -r 63ec80be64bb00414be0f7122a51907114ffb714 -r 1ed5a63aae0a5c8091483658c579d9d762a4c3fb lib/galaxy/webapps/tool_shed/controllers/repository_review.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository_review.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository_review.py
@@ -2,7 +2,7 @@
import os
from sqlalchemy.sql.expression import func
-from markupsafe import escape
+from tool_shed.util.web_util import escape
from galaxy import util
from galaxy import web
diff -r 63ec80be64bb00414be0f7122a51907114ffb714 -r 1ed5a63aae0a5c8091483658c579d9d762a4c3fb lib/galaxy/webapps/tool_shed/controllers/upload.py
--- a/lib/galaxy/webapps/tool_shed/controllers/upload.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/upload.py
@@ -9,7 +9,7 @@
from galaxy import web
from galaxy.datatypes import checkers
from galaxy.web.base.controller import BaseUIController
-from markupsafe import escape
+from tool_shed.util.web_util import escape
from tool_shed.dependencies import attribute_handlers
from tool_shed.galaxy_install import dependency_display
diff -r 63ec80be64bb00414be0f7122a51907114ffb714 -r 1ed5a63aae0a5c8091483658c579d9d762a4c3fb lib/tool_shed/util/repository_util.py
--- a/lib/tool_shed/util/repository_util.py
+++ b/lib/tool_shed/util/repository_util.py
@@ -7,7 +7,7 @@
from galaxy import web
from galaxy.web.form_builder import build_select_field
from galaxy.webapps.tool_shed.model import directory_hash_id
-from markupsafe import escape
+from tool_shed.util.web_util import escape
from tool_shed.dependencies.repository import relation_builder
diff -r 63ec80be64bb00414be0f7122a51907114ffb714 -r 1ed5a63aae0a5c8091483658c579d9d762a4c3fb lib/tool_shed/util/web_util.py
--- /dev/null
+++ b/lib/tool_shed/util/web_util.py
@@ -0,0 +1,21 @@
+from markupsafe import escape as raw_escape
+
+ALLOWED_ELEMENTS = ["<b>", "</b>", "<br/>"]
+ALLOWED_MAP = dict(map(lambda x: (x, raw_escape(x)), ALLOWED_ELEMENTS))
+
+
+def escape( value ):
+ """ A tool shed variant of markupsafe.escape that allows a select few
+ HTML elements that are repeatedly used in messages created deep
+ in the toolshed components. Ideally abstract things would be produced
+ in these components and messages in the views or client side - this is
+ what should be worked toward - but for now - we have this hack.
+
+ >>> escape("A <b>repo</b>")
+ u'A <b>repo</b>'
+ """
+ escaped = str( raw_escape( value ) )
+ # Unescape few selected tags.
+ for key, value in ALLOWED_MAP.iteritems():
+ escaped = escaped.replace(value, key)
+ return escaped
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: Fixes for over escaping in c2bed0a.
by commits-noreply@bitbucket.org 27 Dec '14
by commits-noreply@bitbucket.org 27 Dec '14
27 Dec '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/93a868eb314d/
Changeset: 93a868eb314d
Branch: next-stable
User: jmchilton
Date: 2014-12-27 22:30:59+00:00
Summary: Fixes for over escaping in c2bed0a.
Fixes dozens of tool functional tests.
Affected #: 9 files
diff -r 501f510ff101849c45d9b0925bb55fe59319088b -r 93a868eb314d257c21bb19380b360bcf0d8dd82c lib/galaxy/web/base/controllers/admin.py
--- a/lib/galaxy/web/base/controllers/admin.py
+++ b/lib/galaxy/web/base/controllers/admin.py
@@ -7,7 +7,7 @@
from galaxy.web.form_builder import CheckboxField
from string import punctuation as PUNCTUATION
import galaxy.queue_worker
-from markupsafe import escape
+from tool_shed.util.web_util import escape
from tool_shed.util import shed_util_common as suc
diff -r 501f510ff101849c45d9b0925bb55fe59319088b -r 93a868eb314d257c21bb19380b360bcf0d8dd82c lib/galaxy/webapps/galaxy/controllers/admin.py
--- a/lib/galaxy/webapps/galaxy/controllers/admin.py
+++ b/lib/galaxy/webapps/galaxy/controllers/admin.py
@@ -17,7 +17,7 @@
from galaxy.web.params import QuotaParamParser
from tool_shed.util import common_util
from tool_shed.util import encoding_util
-from markupsafe import escape
+from tool_shed.util.web_util import escape
log = logging.getLogger( __name__ )
diff -r 501f510ff101849c45d9b0925bb55fe59319088b -r 93a868eb314d257c21bb19380b360bcf0d8dd82c 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
@@ -8,9 +8,9 @@
from galaxy.web.form_builder import CheckboxField
from galaxy.util import json
from galaxy.model.orm import or_
-from markupsafe import escape
import tool_shed.repository_types.util as rt_util
+from tool_shed.util.web_util import escape
from tool_shed.util import common_util
from tool_shed.util import encoding_util
diff -r 501f510ff101849c45d9b0925bb55fe59319088b -r 93a868eb314d257c21bb19380b360bcf0d8dd82c lib/galaxy/webapps/tool_shed/controllers/admin.py
--- a/lib/galaxy/webapps/tool_shed/controllers/admin.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/admin.py
@@ -3,7 +3,7 @@
from galaxy import util
from galaxy.util import inflector
from galaxy import web
-from markupsafe import escape
+from tool_shed.util.web_util import escape
from galaxy.web.base.controller import BaseUIController
from galaxy.web.base.controllers.admin import Admin
diff -r 501f510ff101849c45d9b0925bb55fe59319088b -r 93a868eb314d257c21bb19380b360bcf0d8dd82c lib/galaxy/webapps/tool_shed/controllers/repository.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py
@@ -6,7 +6,6 @@
from time import strftime
from datetime import date
from datetime import datetime
-from markupsafe import escape
from galaxy import util
from galaxy import web
@@ -19,6 +18,7 @@
from tool_shed.capsule import capsule_manager
from tool_shed.dependencies.repository import relation_builder
+from tool_shed.util.web_util import escape
from tool_shed.galaxy_install import dependency_display
from tool_shed.metadata import repository_metadata_manager
from tool_shed.utility_containers import ToolShedUtilityContainerManager
diff -r 501f510ff101849c45d9b0925bb55fe59319088b -r 93a868eb314d257c21bb19380b360bcf0d8dd82c lib/galaxy/webapps/tool_shed/controllers/repository_review.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository_review.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository_review.py
@@ -2,7 +2,7 @@
import os
from sqlalchemy.sql.expression import func
-from markupsafe import escape
+from tool_shed.util.web_util import escape
from galaxy import util
from galaxy import web
diff -r 501f510ff101849c45d9b0925bb55fe59319088b -r 93a868eb314d257c21bb19380b360bcf0d8dd82c lib/galaxy/webapps/tool_shed/controllers/upload.py
--- a/lib/galaxy/webapps/tool_shed/controllers/upload.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/upload.py
@@ -9,7 +9,7 @@
from galaxy import web
from galaxy.datatypes import checkers
from galaxy.web.base.controller import BaseUIController
-from markupsafe import escape
+from tool_shed.util.web_util import escape
from tool_shed.dependencies import attribute_handlers
from tool_shed.galaxy_install import dependency_display
diff -r 501f510ff101849c45d9b0925bb55fe59319088b -r 93a868eb314d257c21bb19380b360bcf0d8dd82c lib/tool_shed/util/repository_util.py
--- a/lib/tool_shed/util/repository_util.py
+++ b/lib/tool_shed/util/repository_util.py
@@ -7,7 +7,7 @@
from galaxy import web
from galaxy.web.form_builder import build_select_field
from galaxy.webapps.tool_shed.model import directory_hash_id
-from markupsafe import escape
+from tool_shed.util.web_util import escape
from tool_shed.dependencies.repository import relation_builder
diff -r 501f510ff101849c45d9b0925bb55fe59319088b -r 93a868eb314d257c21bb19380b360bcf0d8dd82c lib/tool_shed/util/web_util.py
--- /dev/null
+++ b/lib/tool_shed/util/web_util.py
@@ -0,0 +1,21 @@
+from markupsafe import escape as raw_escape
+
+ALLOWED_ELEMENTS = ["<b>", "</b>", "<br/>"]
+ALLOWED_MAP = dict(map(lambda x: (x, raw_escape(x)), ALLOWED_ELEMENTS))
+
+
+def escape( value ):
+ """ A tool shed variant of markupsafe.escape that allows a select few
+ HTML elements that are repeatedly used in messages created deep
+ in the toolshed components. Ideally abstract things would be produced
+ in these components and messages in the views or client side - this is
+ what should be worked toward - but for now - we have this hack.
+
+ >>> escape("A <b>repo</b>")
+ u'A <b>repo</b>'
+ """
+ escaped = str( raw_escape( value ) )
+ # Unescape few selected tags.
+ for key, value in ALLOWED_MAP.iteritems():
+ escaped = escaped.replace(value, key)
+ return escaped
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
[galaxyproject/usegalaxy-playbook] b8c80f: Disable Stampede for now, it's being unstable.
by GitHub 26 Dec '14
by GitHub 26 Dec '14
26 Dec '14
Branch: refs/heads/master
Home: https://github.com/galaxyproject/usegalaxy-playbook
Commit: b8c80fd82c9cd8c602d09bcb97e7a4d567ba84e3
https://github.com/galaxyproject/usegalaxy-playbook/commit/b8c80fd82c9cd8c6…
Author: Nate Coraor <nate(a)bx.psu.edu>
Date: 2014-12-26 (Fri, 26 Dec 2014)
Changed paths:
M templates/galaxy/usegalaxy.org/config/job_conf.xml.j2
Log Message:
-----------
Disable Stampede for now, it's being unstable.
1
0
6 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/919dd242fd62/
Changeset: 919dd242fd62
Branch: arff_datatype
User: BjoernGruening
Date: 2014-12-16 11:40:29+00:00
Summary: Created new branch arff_datatype
Affected #: 0 files
https://bitbucket.org/galaxy/galaxy-central/commits/807b1e8a7815/
Changeset: 807b1e8a7815
Branch: arff_datatype
User: BjoernGruening
Date: 2014-12-16 12:08:50+00:00
Summary: Add Arff datatype class with sniffer and metadata.
Affected #: 1 file
diff -r 919dd242fd625a71d26b3935cabfbdb9b48c97b4 -r 807b1e8a7815f1514712146e909a508acc31a93d lib/galaxy/datatypes/text.py
--- a/lib/galaxy/datatypes/text.py
+++ b/lib/galaxy/datatypes/text.py
@@ -6,6 +6,7 @@
from galaxy.datatypes.data import Text
from galaxy.datatypes.data import get_file_peek
from galaxy.datatypes.data import nice_size
+from galaxy.datatypes.metadata import MetadataElement
from galaxy import util
import tempfile
@@ -155,3 +156,106 @@
return True
return False
+
+class Arff( Text ):
+ """
+ An ARFF (Attribute-Relation File Format) file is an ASCII text file that describes a list of instances sharing a set of attributes.
+ http://weka.wikispaces.com/ARFF
+ """
+ file_ext = "arff"
+
+
+ """Add metadata elements"""
+ MetadataElement( name="comment_lines", default=0, desc="Number of comment lines", readonly=True, optional=True, no_value=0 )
+ MetadataElement( name="columns", default=0, desc="Number of columns", readonly=True, visible=True, no_value=0 )
+
+ def set_peek( self, dataset, is_multi_byte=False ):
+ if not dataset.dataset.purged:
+ dataset.peek = get_file_peek( dataset.file_name, is_multi_byte=is_multi_byte )
+ dataset.blurb = "Attribute-Relation File Format (ARFF)"
+ dataset.blurb += ", %s comments, %s attributes" % ( dataset.metadata.comment_lines, dataset.metadata.columns )
+ else:
+ dataset.peek = 'file does not exist'
+ dataset.blurb = 'file purged from disc'
+
+ def sniff( self, filename ):
+ """
+ Try to guess the Arff filetype.
+ It usually starts with a "format-version:" string and has several stanzas which starts with "id:".
+ """
+ with open( filename ) as handle:
+ relation_found = False
+ attribute_found = False
+ prefix = ""
+ for line_count, line in enumerate( handle ):
+ if line_count > 1000:
+ # only investigate the first 1000 lines
+ return False
+ line = line.strip()
+ if not line:
+ continue
+
+ start_string = line[:20].upper()
+ if start_string.startswith("@RELATION"):
+ relation_found = True
+ elif start_string.startswith("@ATTRIBUTE"):
+ attribute_found = True
+ elif start_string.startswith("@DATA"):
+ # @DATA should be the last data block
+ if relation_found and attribute_found:
+ return True
+ return False
+
+ def set_meta( self, dataset, **kwd ):
+ """
+ Trying to count the comment lines and the number of columns included.
+ A typical ARFF data block looks like this:
+ @DATA
+ 5.1,3.5,1.4,0.2,Iris-setosa
+ 4.9,3.0,1.4,0.2,Iris-setosa
+ """
+ if dataset.has_data():
+ comment_lines = 0
+ first_real_line = False
+ data_block = False
+ with open( dataset.file_name ) as handle:
+ for line in handle:
+ line = line.strip()
+ if not line:
+ continue
+ if line.startswith('%') and not first_real_line:
+ comment_lines += 1
+ else:
+ first_real_line = True
+ if data_block:
+ if line.startswith('{'):
+ # Sparse representation
+ """
+ @data
+ 0, X, 0, Y, "class A", {5}
+ or
+ @data
+ {1 X, 3 Y, 4 "class A"}, {5}
+ """
+ token = line.split('}',1)
+ first_part = token[0]
+ last_column = first_part.split(',')[-1].strip()
+ numeric_value = last_column.split()[0]
+ column_count = int(numeric_value)
+ if len(token) > 1:
+ # we have an additional weight
+ column_count -= 1
+ else:
+ columns = line.strip().split(',')
+ column_count = len(columns)
+ if columns[-1].strip().startswith('{'):
+ # we have an additional weight at the end
+ column_count -= 1
+
+ # We have now the column_count and we know the initial comment lines. So we can terminate here.
+ break
+ if line[:5].upper() == "@DATA":
+ data_block = True
+ dataset.metadata.comment_lines = comment_lines
+ dataset.metadata.columns = column_count
+
https://bitbucket.org/galaxy/galaxy-central/commits/a876fb01dba3/
Changeset: a876fb01dba3
Branch: arff_datatype
User: BjoernGruening
Date: 2014-12-16 12:16:00+00:00
Summary: Add Arff datatype and sniffer to datatypes_conf.xml.
Affected #: 1 file
diff -r 807b1e8a7815f1514712146e909a508acc31a93d -r a876fb01dba3595d68ae99fea8e2070fa3ffad55 config/datatypes_conf.xml.sample
--- a/config/datatypes_conf.xml.sample
+++ b/config/datatypes_conf.xml.sample
@@ -3,6 +3,7 @@
<registration converters_path="lib/galaxy/datatypes/converters" display_path="display_applications"><datatype extension="ab1" type="galaxy.datatypes.binary:Ab1" mimetype="application/octet-stream" display_in_upload="true" description="A binary sequence file in 'ab1' format with a '.ab1' file extension. You must manually select this 'File Format' when uploading the file." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#Ab1"/><datatype extension="afg" type="galaxy.datatypes.assembly:Amos" display_in_upload="false" />
+ <!--datatype extension="arff" type="galaxy.datatypes.text:Arff" mimetype="text/plain" display_in_upload="True"/--><datatype extension="asn1" type="galaxy.datatypes.data:GenericAsn1" mimetype="text/plain" display_in_upload="true" /><datatype extension="asn1-binary" type="galaxy.datatypes.binary:GenericAsn1Binary" mimetype="application/octet-stream" display_in_upload="true" /><datatype extension="axt" type="galaxy.datatypes.sequence:Axt" display_in_upload="true" description="blastz pairwise alignment format. Each alignment block in an axt file contains three lines: a summary line and 2 sequence lines. Blocks are separated from one another by blank lines. The summary line contains chromosomal position and size information about the alignment. It consists of 9 required fields." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#Axt"/>
@@ -298,6 +299,7 @@
<sniffer type="galaxy.datatypes.data:Newick"/><sniffer type="galaxy.datatypes.data:Nexus"/><sniffer type="galaxy.datatypes.text:Obo"/>
+ <!--sniffer type="galaxy.datatypes.text.Arff"/--><sniffer type="galaxy.datatypes.text:Ipynb"/><sniffer type="galaxy.datatypes.text:Json"/><sniffer type="galaxy.datatypes.images:Jpg"/>
https://bitbucket.org/galaxy/galaxy-central/commits/d91d8e8beada/
Changeset: d91d8e8beada
Branch: arff_datatype
User: BjoernGruening
Date: 2014-12-23 00:27:36+00:00
Summary: Activate arff datatype by default
Affected #: 1 file
diff -r a876fb01dba3595d68ae99fea8e2070fa3ffad55 -r d91d8e8beadac2a187645f86c199119064a5ccb0 config/datatypes_conf.xml.sample
--- a/config/datatypes_conf.xml.sample
+++ b/config/datatypes_conf.xml.sample
@@ -3,7 +3,7 @@
<registration converters_path="lib/galaxy/datatypes/converters" display_path="display_applications"><datatype extension="ab1" type="galaxy.datatypes.binary:Ab1" mimetype="application/octet-stream" display_in_upload="true" description="A binary sequence file in 'ab1' format with a '.ab1' file extension. You must manually select this 'File Format' when uploading the file." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#Ab1"/><datatype extension="afg" type="galaxy.datatypes.assembly:Amos" display_in_upload="false" />
- <!--datatype extension="arff" type="galaxy.datatypes.text:Arff" mimetype="text/plain" display_in_upload="True"/-->
+ <datatype extension="arff" type="galaxy.datatypes.text:Arff" mimetype="text/plain" display_in_upload="True" /><datatype extension="asn1" type="galaxy.datatypes.data:GenericAsn1" mimetype="text/plain" display_in_upload="true" /><datatype extension="asn1-binary" type="galaxy.datatypes.binary:GenericAsn1Binary" mimetype="application/octet-stream" display_in_upload="true" /><datatype extension="axt" type="galaxy.datatypes.sequence:Axt" display_in_upload="true" description="blastz pairwise alignment format. Each alignment block in an axt file contains three lines: a summary line and 2 sequence lines. Blocks are separated from one another by blank lines. The summary line contains chromosomal position and size information about the alignment. It consists of 9 required fields." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#Axt"/>
@@ -299,7 +299,7 @@
<sniffer type="galaxy.datatypes.data:Newick"/><sniffer type="galaxy.datatypes.data:Nexus"/><sniffer type="galaxy.datatypes.text:Obo"/>
- <!--sniffer type="galaxy.datatypes.text.Arff"/-->
+ <sniffer type="galaxy.datatypes.text.Arff"/><sniffer type="galaxy.datatypes.text:Ipynb"/><sniffer type="galaxy.datatypes.text:Json"/><sniffer type="galaxy.datatypes.images:Jpg"/>
https://bitbucket.org/galaxy/galaxy-central/commits/63ec80be64bb/
Changeset: 63ec80be64bb
User: jmchilton
Date: 2014-12-26 22:33:02+00:00
Summary: Merge pull request #614.
Affected #: 2 files
diff -r 338a32cc6067d92055324e4b827697051ec99254 -r 63ec80be64bb00414be0f7122a51907114ffb714 config/datatypes_conf.xml.sample
--- a/config/datatypes_conf.xml.sample
+++ b/config/datatypes_conf.xml.sample
@@ -3,6 +3,7 @@
<registration converters_path="lib/galaxy/datatypes/converters" display_path="display_applications"><datatype extension="ab1" type="galaxy.datatypes.binary:Ab1" mimetype="application/octet-stream" display_in_upload="true" description="A binary sequence file in 'ab1' format with a '.ab1' file extension. You must manually select this 'File Format' when uploading the file." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#Ab1"/><datatype extension="afg" type="galaxy.datatypes.assembly:Amos" display_in_upload="false" />
+ <datatype extension="arff" type="galaxy.datatypes.text:Arff" mimetype="text/plain" display_in_upload="True" /><datatype extension="asn1" type="galaxy.datatypes.data:GenericAsn1" mimetype="text/plain" display_in_upload="true" /><datatype extension="asn1-binary" type="galaxy.datatypes.binary:GenericAsn1Binary" mimetype="application/octet-stream" display_in_upload="true" /><datatype extension="axt" type="galaxy.datatypes.sequence:Axt" display_in_upload="true" description="blastz pairwise alignment format. Each alignment block in an axt file contains three lines: a summary line and 2 sequence lines. Blocks are separated from one another by blank lines. The summary line contains chromosomal position and size information about the alignment. It consists of 9 required fields." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#Axt"/>
@@ -298,6 +299,7 @@
<sniffer type="galaxy.datatypes.data:Newick"/><sniffer type="galaxy.datatypes.data:Nexus"/><sniffer type="galaxy.datatypes.text:Obo"/>
+ <sniffer type="galaxy.datatypes.text.Arff"/><sniffer type="galaxy.datatypes.text:Ipynb"/><sniffer type="galaxy.datatypes.text:Json"/><sniffer type="galaxy.datatypes.images:Jpg"/>
diff -r 338a32cc6067d92055324e4b827697051ec99254 -r 63ec80be64bb00414be0f7122a51907114ffb714 lib/galaxy/datatypes/text.py
--- a/lib/galaxy/datatypes/text.py
+++ b/lib/galaxy/datatypes/text.py
@@ -6,6 +6,7 @@
from galaxy.datatypes.data import Text
from galaxy.datatypes.data import get_file_peek
from galaxy.datatypes.data import nice_size
+from galaxy.datatypes.metadata import MetadataElement
from galaxy import util
import tempfile
@@ -155,3 +156,106 @@
return True
return False
+
+class Arff( Text ):
+ """
+ An ARFF (Attribute-Relation File Format) file is an ASCII text file that describes a list of instances sharing a set of attributes.
+ http://weka.wikispaces.com/ARFF
+ """
+ file_ext = "arff"
+
+
+ """Add metadata elements"""
+ MetadataElement( name="comment_lines", default=0, desc="Number of comment lines", readonly=True, optional=True, no_value=0 )
+ MetadataElement( name="columns", default=0, desc="Number of columns", readonly=True, visible=True, no_value=0 )
+
+ def set_peek( self, dataset, is_multi_byte=False ):
+ if not dataset.dataset.purged:
+ dataset.peek = get_file_peek( dataset.file_name, is_multi_byte=is_multi_byte )
+ dataset.blurb = "Attribute-Relation File Format (ARFF)"
+ dataset.blurb += ", %s comments, %s attributes" % ( dataset.metadata.comment_lines, dataset.metadata.columns )
+ else:
+ dataset.peek = 'file does not exist'
+ dataset.blurb = 'file purged from disc'
+
+ def sniff( self, filename ):
+ """
+ Try to guess the Arff filetype.
+ It usually starts with a "format-version:" string and has several stanzas which starts with "id:".
+ """
+ with open( filename ) as handle:
+ relation_found = False
+ attribute_found = False
+ prefix = ""
+ for line_count, line in enumerate( handle ):
+ if line_count > 1000:
+ # only investigate the first 1000 lines
+ return False
+ line = line.strip()
+ if not line:
+ continue
+
+ start_string = line[:20].upper()
+ if start_string.startswith("@RELATION"):
+ relation_found = True
+ elif start_string.startswith("@ATTRIBUTE"):
+ attribute_found = True
+ elif start_string.startswith("@DATA"):
+ # @DATA should be the last data block
+ if relation_found and attribute_found:
+ return True
+ return False
+
+ def set_meta( self, dataset, **kwd ):
+ """
+ Trying to count the comment lines and the number of columns included.
+ A typical ARFF data block looks like this:
+ @DATA
+ 5.1,3.5,1.4,0.2,Iris-setosa
+ 4.9,3.0,1.4,0.2,Iris-setosa
+ """
+ if dataset.has_data():
+ comment_lines = 0
+ first_real_line = False
+ data_block = False
+ with open( dataset.file_name ) as handle:
+ for line in handle:
+ line = line.strip()
+ if not line:
+ continue
+ if line.startswith('%') and not first_real_line:
+ comment_lines += 1
+ else:
+ first_real_line = True
+ if data_block:
+ if line.startswith('{'):
+ # Sparse representation
+ """
+ @data
+ 0, X, 0, Y, "class A", {5}
+ or
+ @data
+ {1 X, 3 Y, 4 "class A"}, {5}
+ """
+ token = line.split('}',1)
+ first_part = token[0]
+ last_column = first_part.split(',')[-1].strip()
+ numeric_value = last_column.split()[0]
+ column_count = int(numeric_value)
+ if len(token) > 1:
+ # we have an additional weight
+ column_count -= 1
+ else:
+ columns = line.strip().split(',')
+ column_count = len(columns)
+ if columns[-1].strip().startswith('{'):
+ # we have an additional weight at the end
+ column_count -= 1
+
+ # We have now the column_count and we know the initial comment lines. So we can terminate here.
+ break
+ if line[:5].upper() == "@DATA":
+ data_block = True
+ dataset.metadata.comment_lines = comment_lines
+ dataset.metadata.columns = column_count
+
https://bitbucket.org/galaxy/galaxy-central/commits/3ce3ebfdd734/
Changeset: 3ce3ebfdd734
Branch: arff_datatype
User: jmchilton
Date: 2014-12-26 22:34:57+00:00
Summary: Close arff_datatype.
Affected #: 0 files
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/f7b777f46f9b/
Changeset: f7b777f46f9b
User: jmchilton
Date: 2014-12-26 14:55:27+00:00
Summary: Remove unused method lib/galaxy/workflow/modules.py.
Affected #: 1 file
diff -r 4844fa1099447fb8397159be710c99a82726821a -r f7b777f46f9b69b3cd2ca2d90a30988d9f4fa0ab lib/galaxy/workflow/modules.py
--- a/lib/galaxy/workflow/modules.py
+++ b/lib/galaxy/workflow/modules.py
@@ -557,13 +557,6 @@
def normalize_runtime_state( self, runtime_state ):
return runtime_state.encode( self.tool, self.trans.app, secure=False )
- @classmethod
- def __get_tool_version( cls, trans, tool_id ):
- # Return a ToolVersion if one exists for tool_id.
- return trans.install_model.context.query( trans.install_model.ToolVersion ) \
- .filter( trans.install_model.ToolVersion.table.c.tool_id == tool_id ) \
- .first()
-
def save_to_step( self, step ):
step.type = self.type
step.tool_id = self.tool_id
https://bitbucket.org/galaxy/galaxy-central/commits/8a2b4ebdf492/
Changeset: 8a2b4ebdf492
User: jmchilton
Date: 2014-12-26 14:55:27+00:00
Summary: Eliminate direct in/get checks against toolbox.tools_by_id - use get_tool or has_tool.
Affected #: 6 files
diff -r f7b777f46f9b69b3cd2ca2d90a30988d9f4fa0ab -r 8a2b4ebdf4927fccbe44eda80eaba17b8033802c lib/galaxy/jobs/__init__.py
--- a/lib/galaxy/jobs/__init__.py
+++ b/lib/galaxy/jobs/__init__.py
@@ -711,7 +711,7 @@
self.job_id = job.id
self.session_id = job.session_id
self.user_id = job.user_id
- self.tool = queue.app.toolbox.tools_by_id.get( job.tool_id, None )
+ self.tool = queue.app.toolbox.get_tool( job.tool_id, exact=True )
self.queue = queue
self.app = queue.app
self.sa_session = self.app.model.context
diff -r f7b777f46f9b69b3cd2ca2d90a30988d9f4fa0ab -r 8a2b4ebdf4927fccbe44eda80eaba17b8033802c lib/galaxy/jobs/handler.py
--- a/lib/galaxy/jobs/handler.py
+++ b/lib/galaxy/jobs/handler.py
@@ -119,7 +119,7 @@
& ( model.Job.handler == self.app.config.server_name ) ).all()
for job in jobs_at_startup:
- if job.tool_id not in self.app.toolbox.tools_by_id:
+ if not self.app.toolbox.has_tool( job.tool_id, exact=True ):
log.warning( "(%s) Tool '%s' removed from tool config, unable to recover job" % ( job.id, job.tool_id ) )
self.job_wrapper( job ).fail( 'This tool was disabled before the job completed. Please contact your Galaxy administrator.' )
elif job.job_runner_name is not None and job.job_runner_external_id is None:
diff -r f7b777f46f9b69b3cd2ca2d90a30988d9f4fa0ab -r 8a2b4ebdf4927fccbe44eda80eaba17b8033802c lib/galaxy/managers/workflows.py
--- a/lib/galaxy/managers/workflows.py
+++ b/lib/galaxy/managers/workflows.py
@@ -224,7 +224,7 @@
errors = []
for key, step_dict in data['steps'].iteritems():
is_tool = is_tool_module_type( step_dict[ 'type' ] )
- if is_tool and step_dict['tool_id'] not in trans.app.toolbox.tools_by_id:
+ if is_tool and not trans.app.toolbox.has_tool( step_dict['tool_id'], exact=True ):
errors.append("Step %s requires tool '%s'." % (step_dict['id'], step_dict['tool_id']))
if errors:
raise MissingToolsException(workflow, errors)
diff -r f7b777f46f9b69b3cd2ca2d90a30988d9f4fa0ab -r 8a2b4ebdf4927fccbe44eda80eaba17b8033802c lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -478,8 +478,11 @@
shutil.move( filename, os.path.abspath( self.integrated_tool_panel_config ) )
os.chmod( self.integrated_tool_panel_config, 0644 )
- def get_tool( self, tool_id, tool_version=None, get_all_versions=False ):
+ def get_tool( self, tool_id, tool_version=None, get_all_versions=False, exact=False ):
"""Attempt to locate a tool in the tool box."""
+ if get_all_versions and exact:
+ raise AssertionError("Cannot specify get_tool with both get_all_versions and exact as True")
+
if tool_id in self.tools_by_id and not get_all_versions:
#tool_id exactly matches an available tool by id (which is 'old' tool_id or guid)
return self.tools_by_id[ tool_id ]
@@ -513,6 +516,9 @@
return[ self.tools_by_id[ tool_id ] ]
return None
+ def has_tool( self, tool_id, exact=False ):
+ return self.get_tool( tool_id, exact=exact ) is not None
+
def get_loaded_tools_by_lineage( self, tool_id ):
"""Get all loaded tools associated by lineage to the tool whose id is tool_id."""
tv = self.__get_tool_version( tool_id )
diff -r f7b777f46f9b69b3cd2ca2d90a30988d9f4fa0ab -r 8a2b4ebdf4927fccbe44eda80eaba17b8033802c lib/galaxy/webapps/galaxy/controllers/admin.py
--- a/lib/galaxy/webapps/galaxy/controllers/admin.py
+++ b/lib/galaxy/webapps/galaxy/controllers/admin.py
@@ -486,7 +486,8 @@
class ToolIdColumn( grids.TextColumn ):
def get_value( self, trans, grid, tool_version ):
- if tool_version.tool_id in trans.app.toolbox.tools_by_id:
+ toolbox = trans.app.toolbox
+ if toolbox.has_tool( tool_version.tool_id, exact=True ):
link = url_for( controller='tool_runner', tool_id=tool_version.tool_id )
link_str = '<a href="%s">' % link
return '<div class="count-box state-color-ok">%s%s</a></div>' % ( link_str, tool_version.tool_id )
@@ -497,8 +498,9 @@
def get_value( self, trans, grid, tool_version ):
tool_ids_str = ''
+ toolbox = trans.app.toolbox
for tool_id in tool_version.get_version_ids( trans.app ):
- if tool_id in trans.app.toolbox.tools_by_id:
+ if toolbox.has_tool( tool_id, exact=True ):
link = url_for( controller='tool_runner', tool_id=tool_version.tool_id )
link_str = '<a href="%s">' % link
tool_ids_str += '<div class="count-box state-color-ok">%s%s</a></div><br/>' % ( link_str, tool_id )
diff -r f7b777f46f9b69b3cd2ca2d90a30988d9f4fa0ab -r 8a2b4ebdf4927fccbe44eda80eaba17b8033802c test/unit/jobs/test_job_wrapper.py
--- a/test/unit/jobs/test_job_wrapper.py
+++ b/test/unit/jobs/test_job_wrapper.py
@@ -190,14 +190,14 @@
def __init__(self, test_tool):
self.test_tool = test_tool
- @property
- def tools_by_id(self):
- return self
-
def get(self, tool_id, default=None):
assert tool_id == TEST_TOOL_ID
return self.test_tool
+ def get_tool( self, tool_id, exact=False ):
+ tool = self.get(tool_id)
+ return tool
+
class MockObjectStore(object):
https://bitbucket.org/galaxy/galaxy-central/commits/338a32cc6067/
Changeset: 338a32cc6067
User: jmchilton
Date: 2014-12-26 14:55:27+00:00
Summary: Introduce abstraction shielding toolbox.tools_by_id from galaxy.workflow.modules.
That was the last module outside of ToolBox itself that was accessing tools_by_id directly.
Affected #: 5 files
diff -r 8a2b4ebdf4927fccbe44eda80eaba17b8033802c -r 338a32cc6067d92055324e4b827697051ec99254 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -519,6 +519,21 @@
def has_tool( self, tool_id, exact=False ):
return self.get_tool( tool_id, exact=exact ) is not None
+ def get_tool_id( self, tool_id ):
+ """ Take a tool id (potentially from a different Galaxy instance or that
+ is no longer loaded - and find the closest match to the currently loaded
+ tools (using get_tool for inexact matches which currently returns the oldest
+ tool shed installed tool with the same short id).
+ """
+ if tool_id not in self.tools_by_id:
+ tool = self.get_tool( tool_id )
+ if tool:
+ tool_id = tool.id
+ else:
+ tool_id = None
+ # else exact match - leave unmodified.
+ return tool_id
+
def get_loaded_tools_by_lineage( self, tool_id ):
"""Get all loaded tools associated by lineage to the tool whose id is tool_id."""
tv = self.__get_tool_version( tool_id )
diff -r 8a2b4ebdf4927fccbe44eda80eaba17b8033802c -r 338a32cc6067d92055324e4b827697051ec99254 lib/galaxy/workflow/modules.py
--- a/lib/galaxy/workflow/modules.py
+++ b/lib/galaxy/workflow/modules.py
@@ -508,15 +508,13 @@
def from_workflow_step( Class, trans, step ):
toolbox = trans.app.toolbox
tool_id = step.tool_id
- if toolbox and tool_id not in toolbox.tools_by_id:
+ if toolbox:
# See if we have access to a different version of the tool.
# TODO: If workflows are ever enhanced to use tool version
# in addition to tool id, enhance the selection process here
# to retrieve the correct version of the tool.
- tool = toolbox.get_tool( tool_id )
- if tool:
- tool_id = tool.id
- if ( toolbox and tool_id in toolbox.tools_by_id ):
+ tool_id = toolbox.get_tool_id( tool_id )
+ if ( toolbox and tool_id ):
if step.config:
# This step has its state saved in the config field due to the
# tool being previously unavailable.
diff -r 8a2b4ebdf4927fccbe44eda80eaba17b8033802c -r 338a32cc6067d92055324e4b827697051ec99254 test/unit/tools/test_toolbox.py
--- a/test/unit/tools/test_toolbox.py
+++ b/test/unit/tools/test_toolbox.py
@@ -186,6 +186,15 @@
# No changes, should be regenerated
self.assert_integerated_tool_panel(exists=False)
+ def test_get_tool_id( self ):
+ self._init_tool()
+ self._setup_two_versions_in_config( )
+ self._setup_two_versions()
+ assert self.toolbox.get_tool_id( "test_tool" ) == "github.com/galaxyproect/example/test_tool/0.1"
+ assert self.toolbox.get_tool_id( "github.com/galaxyproect/example/test_tool/0.1" ) == "github.com/galaxyproect/example/test_tool/0.1"
+ assert self.toolbox.get_tool_id( "github.com/galaxyproect/example/test_tool/0.2" ) == "github.com/galaxyproect/example/test_tool/0.2"
+ assert self.toolbox.get_tool_id( "github.com/galaxyproect/example/test_tool/0.3" ) is None
+
def __verify_two_test_tools( self ):
# Assert tool versions of the tool with simple id 'test_tool'
all_versions = self.toolbox.get_tool( "test_tool", get_all_versions=True )
diff -r 8a2b4ebdf4927fccbe44eda80eaba17b8033802c -r 338a32cc6067d92055324e4b827697051ec99254 test/unit/workflows/test_modules.py
--- a/test/unit/workflows/test_modules.py
+++ b/test/unit/workflows/test_modules.py
@@ -5,6 +5,7 @@
import mock
from galaxy import model
+from galaxy.util import bunch
from galaxy.workflow import modules
from .workflow_support import MockTrans
@@ -201,6 +202,37 @@
assert exception
+def test_updated_tool_version():
+ trans = MockTrans()
+ mock_tool = __mock_tool(id="cat1", version="0.9")
+ trans.app.toolbox.tools[ "cat1" ] = mock_tool
+ module = __from_step(
+ trans=trans,
+ type="tool",
+ tool_id="cat1",
+ tool_version="0.7",
+ config=None,
+ )
+ # Make sure there is a warnin with tool id, old version,
+ # and new version.
+ for val in "cat1", "0.7", "0.9":
+ assert val in module.version_changes[0]
+
+
+def test_tool_version_same():
+ trans = MockTrans()
+ mock_tool = __mock_tool(id="cat1", version="1.0")
+ trans.app.toolbox.tools[ "cat1" ] = mock_tool
+ module = __from_step(
+ trans=trans,
+ type="tool",
+ tool_id="cat1",
+ tool_version="1.0",
+ config=None,
+ )
+ assert not module.version_changes
+
+
def __assert_has_runtime_input( module, label=None, collection_type=None ):
inputs = module.get_runtime_inputs()
assert len( inputs ) == 1
@@ -221,7 +253,11 @@
def __from_step( **kwds ):
- trans = MockTrans()
+ if "trans" in kwds:
+ trans = kwds["trans"]
+ del kwds["trans"]
+ else:
+ trans = MockTrans()
step = __step(
**kwds
)
@@ -238,3 +274,20 @@
setattr( step, key, value )
return step
+
+
+def __mock_tool(
+ id="cat1",
+ version="1.0",
+):
+ # For now ignoring inputs, params_from_strings, and
+ # check_and_update_param_values since only have unit tests for version
+ # handling - but need to write tests for all of this longer term.
+ tool = bunch.Bunch(
+ id=id,
+ version=version,
+ inputs={},
+ params_from_strings=mock.Mock(),
+ check_and_update_param_values=mock.Mock(),
+ )
+ return tool
diff -r 8a2b4ebdf4927fccbe44eda80eaba17b8033802c -r 338a32cc6067d92055324e4b827697051ec99254 test/unit/workflows/workflow_support.py
--- a/test/unit/workflows/workflow_support.py
+++ b/test/unit/workflows/workflow_support.py
@@ -40,3 +40,7 @@
def get_tool( self, tool_id ):
# Real tool box returns None of missing tool also
return self.tools.get( tool_id, None )
+
+ def get_tool_id( self, tool_id ):
+ tool = self.get_tool( tool_id )
+ return tool and tool.id
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
7 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/2b6e21823ea7/
Changeset: 2b6e21823ea7
User: jmchilton
Date: 2014-12-25 18:35:13+00:00
Summary: More ToolPanelManager unit testing.
Affected #: 1 file
diff -r 0587bc5413d66e85673d7b429bc04d34e47ad4c4 -r 2b6e21823ea70429b7913b913010f6501f10a601 test/unit/tool_shed_unit_tests/test_tool_panel_manager.py
--- a/test/unit/tool_shed_unit_tests/test_tool_panel_manager.py
+++ b/test/unit/tool_shed_unit_tests/test_tool_panel_manager.py
@@ -101,6 +101,16 @@
assert "github.com/galaxyproect/example/test_tool/0.2" not in open(os.path.join(self.test_directory, "tool_conf.xml"), "r").read()
self._verify_tool_confs()
+ self._remove_guids( ["github.com/galaxyproect/example/test_tool/0.1"], uninstall=True )
+
+ # Now no versions of this tool are returned by toolbox.
+ all_versions = self.toolbox.get_tool( "test_tool", get_all_versions=True )
+ assert not all_versions
+
+ # Check that tool panel has reverted to old value...
+ section = self.toolbox.tool_panel["tid"]
+ assert len(section.elems) == 0
+
def _setup_two_versions_remove_one( self, section, uninstall ):
self._init_tool()
self._setup_two_versions_in_config( section=True )
https://bitbucket.org/galaxy/galaxy-central/commits/8ffb20fd4300/
Changeset: 8ffb20fd4300
User: jmchilton
Date: 2014-12-25 18:35:13+00:00
Summary: Eliminate repeated nested object access in ToolPanelManager.remove_guids.
Affected #: 1 file
diff -r 2b6e21823ea70429b7913b913010f6501f10a601 -r 8ffb20fd4300fbf3b4cc5ac21022e55cd2c1da68 lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
--- a/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
+++ b/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
@@ -445,10 +445,11 @@
self.remove_guids( guids_to_remove, shed_tool_conf, uninstall )
def remove_guids( self, guids_to_remove, shed_tool_conf, uninstall ):
+ toolbox = self.app.toolbox
# Remove the tools from the toolbox's tools_by_id dictionary.
for guid_to_remove in guids_to_remove:
- if guid_to_remove in self.app.toolbox.tools_by_id:
- del self.app.toolbox.tools_by_id[ guid_to_remove ]
+ if guid_to_remove in toolbox.tools_by_id:
+ del toolbox.tools_by_id[ guid_to_remove ]
index, shed_tool_conf_dict = self.get_shed_tool_conf_dict( shed_tool_conf )
if uninstall:
# Remove from the shed_tool_conf file on disk.
@@ -469,12 +470,12 @@
# Remove the tool sub-element from the section element.
config_elem.remove( tool_elem )
# Remove the tool from the section in the in-memory tool panel.
- if section_key in self.app.toolbox.tool_panel:
- tool_section = self.app.toolbox.tool_panel[ section_key ]
+ if section_key in toolbox.tool_panel:
+ tool_section = toolbox.tool_panel[ section_key ]
guid = tool_elem.get( 'guid' )
tool_key = 'tool_%s' % str( guid )
# Get the list of versions of this tool that are currently available in the toolbox.
- available_tool_versions = self.app.toolbox.get_loaded_tools_by_lineage( guid )
+ available_tool_versions = toolbox.get_loaded_tools_by_lineage( guid )
if tool_key in tool_section.elems:
if available_tool_versions:
available_tool_versions.reverse()
@@ -505,8 +506,8 @@
del tool_section.elems[ tool_key ]
if uninstall:
# Remove the tool from the section in the in-memory integrated tool panel.
- if section_key in self.app.toolbox.integrated_tool_panel:
- tool_section = self.app.toolbox.integrated_tool_panel[ section_key ]
+ if section_key in toolbox.integrated_tool_panel:
+ tool_section = toolbox.integrated_tool_panel[ section_key ]
tool_key = 'tool_%s' % str( tool_elem.get( 'guid' ) )
if tool_key in tool_section.elems:
del tool_section.elems[ tool_key ]
@@ -518,8 +519,8 @@
if guid in guids_to_remove:
tool_key = 'tool_%s' % str( config_elem.get( 'guid' ) )
# Get the list of versions of this tool that are currently available in the toolbox.
- available_tool_versions = self.app.toolbox.get_loaded_tools_by_lineage( guid )
- if tool_key in self.app.toolbox.tool_panel:
+ available_tool_versions = toolbox.get_loaded_tools_by_lineage( guid )
+ if tool_key in toolbox.tool_panel:
if available_tool_versions:
available_tool_versions.reverse()
replacement_tool_key = None
@@ -528,32 +529,32 @@
# the newest loaded version of the tool.
for available_tool_version in available_tool_versions:
available_tool_section_id, available_tool_section_name = available_tool_version.get_panel_section()
- if available_tool_version.id in self.app.toolbox.tool_panel.keys() or not available_tool_section_id:
+ if available_tool_version.id in toolbox.tool_panel.keys() or not available_tool_section_id:
replacement_tool_key = 'tool_%s' % str( available_tool_version.id )
replacement_tool_version = available_tool_version
break
if replacement_tool_key and replacement_tool_version:
# Get the index of the tool_key in the tool_section.
- for tool_panel_index, key in enumerate( self.app.toolbox.tool_panel.keys() ):
+ for tool_panel_index, key in enumerate( toolbox.tool_panel.keys() ):
if key == tool_key:
break
# Remove the tool from the tool panel.
- del self.app.toolbox.tool_panel[ tool_key ]
+ del toolbox.tool_panel[ tool_key ]
# Add the replacement tool at the same location in the tool panel.
- self.app.toolbox.tool_panel.insert( tool_panel_index,
- replacement_tool_key,
- replacement_tool_version )
+ toolbox.tool_panel.insert( tool_panel_index,
+ replacement_tool_key,
+ replacement_tool_version )
else:
- del self.app.toolbox.tool_panel[ tool_key ]
+ del toolbox.tool_panel[ tool_key ]
else:
- del self.app.toolbox.tool_panel[ tool_key ]
+ del toolbox.tool_panel[ tool_key ]
if uninstall:
- if tool_key in self.app.toolbox.integrated_tool_panel:
- del self.app.toolbox.integrated_tool_panel[ tool_key ]
+ if tool_key in toolbox.integrated_tool_panel:
+ del toolbox.integrated_tool_panel[ tool_key ]
config_elems_to_remove.append( config_elem )
for config_elem in config_elems_to_remove:
# Remove the element from the in-memory list of elements.
config_elems.remove( config_elem )
# Update the config_elems of the in-memory shed_tool_conf_dict.
shed_tool_conf_dict[ 'config_elems' ] = config_elems
- self.app.toolbox.update_shed_config( index, shed_tool_conf_dict, integrated_panel_changes=uninstall )
+ toolbox.update_shed_config( index, shed_tool_conf_dict, integrated_panel_changes=uninstall )
https://bitbucket.org/galaxy/galaxy-central/commits/44dfa6fc2701/
Changeset: 44dfa6fc2701
User: jmchilton
Date: 2014-12-25 18:35:13+00:00
Summary: Reduce duplication/complexity in tool_panel_manager.py.
Big conditional in remove_guids switched on sectioned versus un-sectioned with very little difference in what was actually being done. This reduces the cyclomatic complexity of that method from 35 down to 26 (though it is still the most 'complex' method in that file by a wide margin).
Affected #: 1 file
diff -r 8ffb20fd4300fbf3b4cc5ac21022e55cd2c1da68 -r 44dfa6fc270161fb12a3f152d5f24f53d757cd29 lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
--- a/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
+++ b/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
@@ -446,6 +446,48 @@
def remove_guids( self, guids_to_remove, shed_tool_conf, uninstall ):
toolbox = self.app.toolbox
+
+ def remove_from_panel( tool_elem, has_elems, integrated_has_elems, section_key='' ):
+ # Hide tool from panel and promote next oldest version if
+ # available.
+ guid = tool_elem.get( 'guid' )
+ tool_key = 'tool_%s' % str( guid )
+ available_tool_versions = toolbox.get_loaded_tools_by_lineage( guid )
+ if tool_key in has_elems:
+ if available_tool_versions:
+ available_tool_versions.reverse()
+ replacement_tool_key = None
+ replacement_tool_version = None
+ # Since we are going to remove the tool from the section, replace it with
+ # the newest loaded version of the tool.
+ for available_tool_version in available_tool_versions:
+ available_tool_section_id, available_tool_section_name = available_tool_version.get_panel_section()
+ # I suspect "available_tool_version.id in has_elems.keys()" doesn't
+ # belong in the following line or at least I don't understand what
+ # purpose it might serve. -John
+ if available_tool_version.id in has_elems.keys() or (available_tool_section_id == section_key):
+ replacement_tool_key = 'tool_%s' % str( available_tool_version.id )
+ replacement_tool_version = available_tool_version
+ break
+ if replacement_tool_key and replacement_tool_version:
+ # Get the index of the tool_key in the tool_section.
+ for tool_panel_index, key in enumerate( has_elems.keys() ):
+ if key == tool_key:
+ break
+ # Remove the tool from the tool panel.
+ del has_elems[ tool_key ]
+ # Add the replacement tool at the same location in the tool panel.
+ has_elems.insert( tool_panel_index,
+ replacement_tool_key,
+ replacement_tool_version )
+ else:
+ del has_elems[ tool_key ]
+ else:
+ del has_elems[ tool_key ]
+ if uninstall:
+ if tool_key in toolbox.integrated_tool_panel:
+ del toolbox.integrated_tool_panel[ tool_key ]
+
# Remove the tools from the toolbox's tools_by_id dictionary.
for guid_to_remove in guids_to_remove:
if guid_to_remove in toolbox.tools_by_id:
@@ -472,85 +514,15 @@
# Remove the tool from the section in the in-memory tool panel.
if section_key in toolbox.tool_panel:
tool_section = toolbox.tool_panel[ section_key ]
- guid = tool_elem.get( 'guid' )
- tool_key = 'tool_%s' % str( guid )
- # Get the list of versions of this tool that are currently available in the toolbox.
- available_tool_versions = toolbox.get_loaded_tools_by_lineage( guid )
- if tool_key in tool_section.elems:
- if available_tool_versions:
- available_tool_versions.reverse()
- replacement_tool_key = None
- replacement_tool_version = None
- # Since we are going to remove the tool from the section, replace it with the
- # newest loaded version of the tool.
- for available_tool_version in available_tool_versions:
- available_tool_section_id, available_tool_section_name = available_tool_version.get_panel_section()
- if available_tool_version.id in tool_section.elems.keys() or section_key == available_tool_section_id:
- replacement_tool_key = 'tool_%s' % str( available_tool_version.id )
- replacement_tool_version = available_tool_version
- break
- if replacement_tool_key and replacement_tool_version:
- # Get the index of the tool_key in the tool_section.
- for tool_section_elems_index, key in enumerate( tool_section.elems.keys() ):
- if key == tool_key:
- break
- # Remove the tool from the tool section.
- del tool_section.elems[ tool_key ]
- # Add the replacement tool at the same location in the tool section.
- tool_section.elems.insert( tool_section_elems_index,
- replacement_tool_key,
- replacement_tool_version )
- else:
- del tool_section.elems[ tool_key ]
- else:
- del tool_section.elems[ tool_key ]
- if uninstall:
- # Remove the tool from the section in the in-memory integrated tool panel.
- if section_key in toolbox.integrated_tool_panel:
- tool_section = toolbox.integrated_tool_panel[ section_key ]
- tool_key = 'tool_%s' % str( tool_elem.get( 'guid' ) )
- if tool_key in tool_section.elems:
- del tool_section.elems[ tool_key ]
+ remove_from_panel( tool_elem, tool_section.elems, toolbox.integrated_tool_panel.get( section_key, {} ), section_key=section_key )
if len( config_elem ) < 1:
# Keep a list of all empty section elements so they can be removed.
config_elems_to_remove.append( config_elem )
elif config_elem.tag == 'tool':
guid = config_elem.get( 'guid' )
if guid in guids_to_remove:
- tool_key = 'tool_%s' % str( config_elem.get( 'guid' ) )
- # Get the list of versions of this tool that are currently available in the toolbox.
- available_tool_versions = toolbox.get_loaded_tools_by_lineage( guid )
- if tool_key in toolbox.tool_panel:
- if available_tool_versions:
- available_tool_versions.reverse()
- replacement_tool_key = None
- replacement_tool_version = None
- # Since we are going to remove the tool from the section, replace it with
- # the newest loaded version of the tool.
- for available_tool_version in available_tool_versions:
- available_tool_section_id, available_tool_section_name = available_tool_version.get_panel_section()
- if available_tool_version.id in toolbox.tool_panel.keys() or not available_tool_section_id:
- replacement_tool_key = 'tool_%s' % str( available_tool_version.id )
- replacement_tool_version = available_tool_version
- break
- if replacement_tool_key and replacement_tool_version:
- # Get the index of the tool_key in the tool_section.
- for tool_panel_index, key in enumerate( toolbox.tool_panel.keys() ):
- if key == tool_key:
- break
- # Remove the tool from the tool panel.
- del toolbox.tool_panel[ tool_key ]
- # Add the replacement tool at the same location in the tool panel.
- toolbox.tool_panel.insert( tool_panel_index,
- replacement_tool_key,
- replacement_tool_version )
- else:
- del toolbox.tool_panel[ tool_key ]
- else:
- del toolbox.tool_panel[ tool_key ]
- if uninstall:
- if tool_key in toolbox.integrated_tool_panel:
- del toolbox.integrated_tool_panel[ tool_key ]
+ # get_panel_section return '' for un-sectioned tools.
+ remove_from_panel( config_elem, toolbox.tool_panel, toolbox.integrated_tool_panel, section_key='' )
config_elems_to_remove.append( config_elem )
for config_elem in config_elems_to_remove:
# Remove the element from the in-memory list of elements.
https://bitbucket.org/galaxy/galaxy-central/commits/01293fc1f167/
Changeset: 01293fc1f167
User: jmchilton
Date: 2014-12-25 18:35:13+00:00
Summary: Abstract out ToolBox internals from tool_shed.util.tool_util.
Instead of reloading upload actions at this level and exposing tools_by_id - move this logic into the ToolBox in a new method called handle_datatypes_changed().
Affected #: 2 files
diff -r 44dfa6fc270161fb12a3f152d5f24f53d757cd29 -r 01293fc1f16715121524b987fcab031f3e149a02 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -34,6 +34,7 @@
from galaxy import exceptions
from galaxy.tools import watcher
from galaxy.tools.actions import DefaultToolAction
+from galaxy.tools.actions.upload import UploadToolAction
from galaxy.tools.actions.data_source import DataSourceToolAction
from galaxy.tools.actions.data_manager import DataManagerToolAction
from galaxy.tools.deps import build_dependency_manager
@@ -992,6 +993,13 @@
def init_dependency_manager( self ):
self.dependency_manager = build_dependency_manager( self.app.config )
+ def handle_datatypes_changed( self ):
+ """ Refresh upload tools when new datatypes are added. """
+ for tool_id in self.tools_by_id:
+ tool = self.tools_by_id[ tool_id ]
+ if isinstance( tool.tool_action, UploadToolAction ):
+ self.reload_tool_by_id( tool_id )
+
@property
def sa_session( self ):
"""
diff -r 44dfa6fc270161fb12a3f152d5f24f53d757cd29 -r 01293fc1f16715121524b987fcab031f3e149a02 lib/tool_shed/util/tool_util.py
--- a/lib/tool_shed/util/tool_util.py
+++ b/lib/tool_shed/util/tool_util.py
@@ -260,7 +260,4 @@
def reload_upload_tools( app ):
if hasattr( app, 'toolbox' ):
- for tool_id in app.toolbox.tools_by_id:
- tool = app.toolbox.tools_by_id[ tool_id ]
- if isinstance( tool.tool_action, UploadToolAction ):
- app.toolbox.reload_tool_by_id( tool_id )
+ app.toolbox.handle_datatypes_changed()
https://bitbucket.org/galaxy/galaxy-central/commits/7716c8fbb891/
Changeset: 7716c8fbb891
User: jmchilton
Date: 2014-12-25 18:35:13+00:00
Summary: Centralize abstraction for removing tools from toolbox.
Shield's toolbox.tools_by_id from lib/tool_shed/galaxy_install/tools/tool_panel_manager.py.
Affected #: 3 files
diff -r 01293fc1f16715121524b987fcab031f3e149a02 -r 7716c8fbb891eb18f81bc80fc5f85f735d025357 lib/galaxy/datatypes/registry.py
--- a/lib/galaxy/datatypes/registry.py
+++ b/lib/galaxy/datatypes/registry.py
@@ -529,8 +529,7 @@
converter.id = tool_dict[ 'guid' ]
break
if deactivate:
- if converter.id in toolbox.tools_by_id:
- del toolbox.tools_by_id[ converter.id ]
+ toolbox.remove_tool_by_id( converter.id, remove_from_panel=False )
if source_datatype in self.datatype_converters:
if target_datatype in self.datatype_converters[ source_datatype ]:
del self.datatype_converters[ source_datatype ][ target_datatype ]
diff -r 01293fc1f16715121524b987fcab031f3e149a02 -r 7716c8fbb891eb18f81bc80fc5f85f735d025357 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -952,9 +952,13 @@
status = 'done'
return message, status
- def remove_tool_by_id( self, tool_id ):
+ def remove_tool_by_id( self, tool_id, remove_from_panel=True ):
"""
- Attempt to remove the tool identified by 'tool_id'.
+ Attempt to remove the tool identified by 'tool_id'. Ignores
+ tool lineage - so to remove a tool with potentially multiple
+ versions send remove_from_panel=False and handle the logic of
+ promoting the next newest version of the tool into the panel
+ if needed.
"""
if tool_id not in self.tools_by_id:
message = "No tool with id %s" % escape( tool_id )
@@ -962,17 +966,18 @@
else:
tool = self.tools_by_id[ tool_id ]
del self.tools_by_id[ tool_id ]
- tool_key = 'tool_' + tool_id
- for key, val in self.tool_panel.items():
- if key == tool_key:
- del self.tool_panel[ key ]
- break
- elif key.startswith( 'section' ):
- if tool_key in val.elems:
- del self.tool_panel[ key ].elems[ tool_key ]
+ if remove_from_panel:
+ tool_key = 'tool_' + tool_id
+ for key, val in self.tool_panel.items():
+ if key == tool_key:
+ del self.tool_panel[ key ]
break
- if tool_id in self.data_manager_tools:
- del self.data_manager_tools[ tool_id ]
+ elif key.startswith( 'section' ):
+ if tool_key in val.elems:
+ del self.tool_panel[ key ].elems[ tool_key ]
+ break
+ if tool_id in self.data_manager_tools:
+ del self.data_manager_tools[ tool_id ]
#TODO: do we need to manually remove from the integrated panel here?
message = "Removed the tool:<br/>"
message += "<b>name:</b> %s<br/>" % tool.name
diff -r 01293fc1f16715121524b987fcab031f3e149a02 -r 7716c8fbb891eb18f81bc80fc5f85f735d025357 lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
--- a/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
+++ b/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
@@ -490,8 +490,8 @@
# Remove the tools from the toolbox's tools_by_id dictionary.
for guid_to_remove in guids_to_remove:
- if guid_to_remove in toolbox.tools_by_id:
- del toolbox.tools_by_id[ guid_to_remove ]
+ # remove_from_tool_panel to false, will handling that logic below.
+ toolbox.remove_tool_by_id( guid_to_remove, remove_from_panel=False )
index, shed_tool_conf_dict = self.get_shed_tool_conf_dict( shed_tool_conf )
if uninstall:
# Remove from the shed_tool_conf file on disk.
https://bitbucket.org/galaxy/galaxy-central/commits/75e5db40bd2e/
Changeset: 75e5db40bd2e
User: jmchilton
Date: 2014-12-25 18:35:13+00:00
Summary: Eliminate walking over tools_by_id externally from toolbox.
Affected #: 2 files
diff -r 7716c8fbb891eb18f81bc80fc5f85f735d025357 -r 75e5db40bd2e6bfb481b500081a3d8b066063541 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -535,6 +535,9 @@
.filter( self.app.install_model.ToolVersion.table.c.tool_id == tool_id ) \
.first()
+ def tools( self ):
+ return self.tools_by_id.iteritems()
+
def __get_tool_shed_repository( self, tool_shed, name, owner, installed_changeset_revision ):
# We store only the port, if one exists, in the database.
tool_shed = common_util.remove_protocol_from_tool_shed_url( tool_shed )
diff -r 7716c8fbb891eb18f81bc80fc5f85f735d025357 -r 75e5db40bd2e6bfb481b500081a3d8b066063541 lib/galaxy/tools/search/__init__.py
--- a/lib/galaxy/tools/search/__init__.py
+++ b/lib/galaxy/tools/search/__init__.py
@@ -27,7 +27,7 @@
self.index = self.storage.create_index( schema )
writer = self.index.writer()
## TODO: would also be nice to search section headers.
- for id, tool in self.toolbox.tools_by_id.iteritems():
+ for id, tool in self.toolbox.tools():
add_doc_kwds = {
"id": id,
"title": to_unicode(tool.name),
https://bitbucket.org/galaxy/galaxy-central/commits/4844fa109944/
Changeset: 4844fa109944
User: jmchilton
Date: 2014-12-25 18:35:13+00:00
Summary: Abstractions for registering tools from outside toolbox.
Part of effort to further limit exposing tools_by_id directly outside Toolbox.
Affected #: 4 files
diff -r 75e5db40bd2e6bfb481b500081a3d8b066063541 -r 4844fa1099447fb8397159be710c99a82726821a lib/galaxy/datatypes/registry.py
--- a/lib/galaxy/datatypes/registry.py
+++ b/lib/galaxy/datatypes/registry.py
@@ -535,7 +535,7 @@
del self.datatype_converters[ source_datatype ][ target_datatype ]
self.log.debug( "Deactivated converter: %s", converter.id )
else:
- toolbox.tools_by_id[ converter.id ] = converter
+ toolbox.register_tool( converter )
if source_datatype not in self.datatype_converters:
self.datatype_converters[ source_datatype ] = odict()
self.datatype_converters[ source_datatype ][ target_datatype ] = converter
@@ -644,8 +644,7 @@
tmp_name = tempfile.NamedTemporaryFile()
tmp_name.write( tool_xml_text )
tmp_name.flush()
- set_meta_tool = toolbox.load_tool( tmp_name.name )
- toolbox.tools_by_id[ set_meta_tool.id ] = set_meta_tool
+ set_meta_tool = toolbox.load_hidden_tool( tmp_name.name )
self.set_external_metadata_tool = set_meta_tool
self.log.debug( "Loaded external metadata tool: %s", self.set_external_metadata_tool.id )
diff -r 75e5db40bd2e6bfb481b500081a3d8b066063541 -r 4844fa1099447fb8397159be710c99a82726821a lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -804,6 +804,17 @@
self.tool_watcher.watch_file( config_file, tool.id )
return tool
+ def load_hidden_tool( self, config_file, **kwds ):
+ """ Load a hidden tool (in this context meaning one that does not
+ appear in the tool panel) and register it in tools_by_id.
+ """
+ tool = self.load_tool( config_file, **kwds )
+ self.register_tool( tool )
+ return tool
+
+ def register_tool( self, tool ):
+ self.tools_by_id[ tool.id ] = tool
+
def package_tool( self, trans, tool_id ):
"""
Create a tarball with the tool's xml, help images, and test data.
diff -r 75e5db40bd2e6bfb481b500081a3d8b066063541 -r 4844fa1099447fb8397159be710c99a82726821a lib/galaxy/tools/data_manager/manager.py
--- a/lib/galaxy/tools/data_manager/manager.py
+++ b/lib/galaxy/tools/data_manager/manager.py
@@ -244,12 +244,12 @@
return self.guid or self.declared_id #if we have a guid, we will use that as the data_manager id
def load_tool( self, tool_filename, guid=None, data_manager_id=None, tool_shed_repository_id=None ):
- tool = self.data_managers.app.toolbox.load_tool( tool_filename,
- guid=guid,
- data_manager_id=data_manager_id,
- repository_id=tool_shed_repository_id )
+ toolbox = self.data_managers.app.toolbox
+ tool = toolbox.load_hidden_tool( tool_filename,
+ guid=guid,
+ data_manager_id=data_manager_id,
+ repository_id=tool_shed_repository_id )
self.data_managers.app.toolbox.data_manager_tools[ tool.id ] = tool
- self.data_managers.app.toolbox.tools_by_id[ tool.id ] = tool
self.tool = tool
return tool
diff -r 75e5db40bd2e6bfb481b500081a3d8b066063541 -r 4844fa1099447fb8397159be710c99a82726821a lib/galaxy/tools/imp_exp/__init__.py
--- a/lib/galaxy/tools/imp_exp/__init__.py
+++ b/lib/galaxy/tools/imp_exp/__init__.py
@@ -40,14 +40,12 @@
tmp_name = tempfile.NamedTemporaryFile()
tmp_name.write( tool_xml_text )
tmp_name.flush()
- history_exp_tool = toolbox.load_tool( tmp_name.name )
- toolbox.tools_by_id[ history_exp_tool.id ] = history_exp_tool
+ history_exp_tool = toolbox.load_hidden_tool( tmp_name.name )
log.debug( "Loaded history export tool: %s", history_exp_tool.id )
# Load import tool.
tool_xml = os.path.join( os.getcwd(), "lib/galaxy/tools/imp_exp/imp_history_from_archive.xml" )
- history_imp_tool = toolbox.load_tool( tool_xml )
- toolbox.tools_by_id[ history_imp_tool.id ] = history_imp_tool
+ history_imp_tool = toolbox.load_hidden_tool( tool_xml )
log.debug( "Loaded history import tool: %s", history_imp_tool.id )
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
5 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/38c8222d9e79/
Changeset: 38c8222d9e79
User: jmchilton
Date: 2014-12-25 17:24:23+00:00
Summary: Bugfix: Allow passing key to GET /api/datatypes/mapping.
All anonymous API endpoints should also allow authenticated access and just ignore the key.
Affected #: 1 file
diff -r 179199007ec93cdfa45b200e9a27486035ff2477 -r 38c8222d9e79a237dea9179a63b486447aeb9999 lib/galaxy/webapps/galaxy/api/datatypes.py
--- a/lib/galaxy/webapps/galaxy/api/datatypes.py
+++ b/lib/galaxy/webapps/galaxy/api/datatypes.py
@@ -44,7 +44,7 @@
return { 'error': str( exception ) }
@web.expose_api_anonymous
- def mapping( self, trans ):
+ def mapping( self, trans, **kwd ):
'''
GET /api/datatypes/mapping
Return a dictionary of class to class mappings.
https://bitbucket.org/galaxy/galaxy-central/commits/cd529da77278/
Changeset: cd529da77278
User: jmchilton
Date: 2014-12-25 17:24:23+00:00
Summary: Suite of API tests for exist datatypes endpoint.
Affected #: 1 file
diff -r 38c8222d9e79a237dea9179a63b486447aeb9999 -r cd529da7727870e472d18a4ba9037aa554bb9e81 test/api/test_datatypes.py
--- /dev/null
+++ b/test/api/test_datatypes.py
@@ -0,0 +1,51 @@
+from base import api
+
+
+HIDDEN_DURING_UPLOAD_DATATYPE = "fli"
+
+
+class DatatypesApiTestCase( api.ApiTestCase ):
+
+ def test_index( self ):
+ datatypes = self._index_datatypes()
+ for common_type in ["tabular", "fasta"]:
+ assert common_type in datatypes, "%s not in %s" % (common_type, datatypes)
+
+ def test_index_upload_only( self ):
+ # fli is not displayed in upload - so only show it if upload_only
+ # is explicitly false.
+ datatypes = self._index_datatypes( data={ "upload_only": False } )
+ assert HIDDEN_DURING_UPLOAD_DATATYPE in datatypes
+
+ datatypes = self._index_datatypes( data={ "upload_only": True } )
+ assert HIDDEN_DURING_UPLOAD_DATATYPE not in datatypes
+
+ datatypes = self._index_datatypes( )
+ assert HIDDEN_DURING_UPLOAD_DATATYPE not in datatypes
+
+ def test_full_index( self ):
+ datatypes = self._index_datatypes( data={ "extension_only": False } )
+ for datatype in datatypes:
+ self._assert_has_keys( datatype, "extension", "description", "description_url" )
+ assert datatype["extension"] != HIDDEN_DURING_UPLOAD_DATATYPE
+
+ def test_mapping( self ):
+ response = self._get( "datatypes/mapping" )
+ self._assert_status_code_is( response, 200 )
+ mapping_dict = response.json()
+ self._assert_has_keys( mapping_dict, "ext_to_class_name", "class_to_classes" )
+
+ def test_sniffers( self ):
+ response = self._get( "datatypes/sniffers" )
+ self._assert_status_code_is( response, 200 )
+ sniffer_list = response.json()
+ owl_index = sniffer_list.index( "galaxy.datatypes.xml:Owl" )
+ xml_index = sniffer_list.index( "galaxy.datatypes.xml:GenericXml" )
+ assert owl_index < xml_index
+
+ def _index_datatypes( self, data={} ):
+ response = self._get( "datatypes", data=data )
+ self._assert_status_code_is( response, 200 )
+ datatypes = response.json()
+ assert isinstance( datatypes, list )
+ return datatypes
https://bitbucket.org/galaxy/galaxy-central/commits/afc01429c885/
Changeset: afc01429c885
User: jmchilton
Date: 2014-12-25 17:24:23+00:00
Summary: Update datatypes API to newer API decoarator/exception handling.
Affected #: 1 file
diff -r cd529da7727870e472d18a4ba9037aa554bb9e81 -r afc01429c88520099bbbb1715f8412d995d4b92c lib/galaxy/webapps/galaxy/api/datatypes.py
--- a/lib/galaxy/webapps/galaxy/api/datatypes.py
+++ b/lib/galaxy/webapps/galaxy/api/datatypes.py
@@ -2,7 +2,8 @@
API operations allowing clients to determine datatype supported by Galaxy.
"""
-from galaxy import web
+from galaxy.web import _future_expose_api_anonymous as expose_api_anonymous
+from galaxy import exceptions
from galaxy.web.base.controller import BaseAPIController
from galaxy.util import asbool
from galaxy.datatypes.data import Data
@@ -13,7 +14,7 @@
class DatatypesController( BaseAPIController ):
- @web.expose_api_anonymous
+ @expose_api_anonymous
def index( self, trans, **kwd ):
"""
GET /api/datatypes
@@ -38,12 +39,14 @@
dictionary[key] = elem.get(key)
rval.append(dictionary)
return rval
- except Exception, exception:
+ except Exception as exception:
log.error( 'could not get datatypes: %s', str( exception ), exc_info=True )
- trans.response.status = 500
- return { 'error': str( exception ) }
+ if not isinstance( exception, exceptions.MessageException ):
+ raise exceptions.InternalServerError( str( exception ) )
+ else:
+ raise
- @web.expose_api_anonymous
+ @expose_api_anonymous
def mapping( self, trans, **kwd ):
'''
GET /api/datatypes/mapping
@@ -69,12 +72,15 @@
visit_bases( types, c )
class_to_classes[ n ] = dict( ( t, True ) for t in types )
return dict( ext_to_class_name=ext_to_class_name, class_to_classes=class_to_classes )
- except Exception, exception:
+
+ except Exception as exception:
log.error( 'could not get datatype mapping: %s', str( exception ), exc_info=True )
- trans.response.status = 500
- return { 'error': str( exception ) }
+ if not isinstance( exception, exceptions.MessageException ):
+ raise exceptions.InternalServerError( str( exception ) )
+ else:
+ raise
- @web.expose_api_anonymous
+ @expose_api_anonymous
def sniffers( self, trans, **kwd ):
'''
GET /api/datatypes/sniffers
@@ -87,7 +93,9 @@
if datatype is not None:
rval.append( datatype )
return rval
- except Exception, exception:
+ except Exception as exception:
log.error( 'could not get datatypes: %s', str( exception ), exc_info=True )
- trans.response.status = 500
- return { 'error': str( exception ) }
+ if not isinstance( exception, exceptions.MessageException ):
+ raise exceptions.InternalServerError( str( exception ) )
+ else:
+ raise
https://bitbucket.org/galaxy/galaxy-central/commits/750775b64cb7/
Changeset: 750775b64cb7
User: jmchilton
Date: 2014-12-25 17:24:23+00:00
Summary: Reduce repeated nested object access in galaxy.api.datatypes.
Affected #: 1 file
diff -r afc01429c88520099bbbb1715f8412d995d4b92c -r 750775b64cb758876745af058550b97ae1c47105 lib/galaxy/webapps/galaxy/api/datatypes.py
--- a/lib/galaxy/webapps/galaxy/api/datatypes.py
+++ b/lib/galaxy/webapps/galaxy/api/datatypes.py
@@ -20,17 +20,18 @@
GET /api/datatypes
Return an object containing upload datatypes.
"""
+ datatypes_registry = self._datatypes_registry
extension_only = asbool( kwd.get( 'extension_only', True ) )
upload_only = asbool( kwd.get( 'upload_only', True ) )
try:
if extension_only:
if upload_only:
- return trans.app.datatypes_registry.upload_file_formats
+ return datatypes_registry.upload_file_formats
else:
- return [ ext for ext in trans.app.datatypes_registry.datatypes_by_extension ]
+ return [ ext for ext in datatypes_registry.datatypes_by_extension ]
else:
rval = []
- for elem in trans.app.datatypes_registry.datatype_elems:
+ for elem in datatypes_registry.datatype_elems:
if not asbool(elem.get('display_in_upload')) and upload_only:
continue
keys = ['extension', 'description', 'description_url']
@@ -55,7 +56,7 @@
try:
ext_to_class_name = dict()
classes = []
- for k, v in trans.app.datatypes_registry.datatypes_by_extension.iteritems():
+ for k, v in self._datatypes_registry.datatypes_by_extension.iteritems():
c = v.__class__
ext_to_class_name[k] = c.__module__ + "." + c.__name__
classes.append( c )
@@ -88,7 +89,7 @@
'''
try:
rval = []
- for sniffer_elem in trans.app.datatypes_registry.sniffer_elems:
+ for sniffer_elem in self._datatypes_registry.sniffer_elems:
datatype = sniffer_elem.get( 'type' )
if datatype is not None:
rval.append( datatype )
@@ -99,3 +100,7 @@
raise exceptions.InternalServerError( str( exception ) )
else:
raise
+
+ @property
+ def _datatypes_registry( self ):
+ return self.app.datatypes_registry
https://bitbucket.org/galaxy/galaxy-central/commits/0587bc5413d6/
Changeset: 0587bc5413d6
User: jmchilton
Date: 2014-12-25 17:24:23+00:00
Summary: Expose datatype converter information via datatype API.
With test case.
Affected #: 3 files
diff -r 750775b64cb758876745af058550b97ae1c47105 -r 0587bc5413d66e85673d7b429bc04d34e47ad4c4 lib/galaxy/webapps/galaxy/api/datatypes.py
--- a/lib/galaxy/webapps/galaxy/api/datatypes.py
+++ b/lib/galaxy/webapps/galaxy/api/datatypes.py
@@ -101,6 +101,19 @@
else:
raise
+ @expose_api_anonymous
+ def converters( self, trans, **kwd ):
+ converters = []
+ for (source_type, targets) in self._datatypes_registry.datatype_converters.iteritems():
+ for target_type in targets:
+ converters.append( {
+ 'source': source_type,
+ 'target': target_type,
+ 'tool_id': targets[ target_type ].id,
+ } )
+
+ return converters
+
@property
def _datatypes_registry( self ):
return self.app.datatypes_registry
diff -r 750775b64cb758876745af058550b97ae1c47105 -r 0587bc5413d66e85673d7b429bc04d34e47ad4c4 lib/galaxy/webapps/galaxy/buildapp.py
--- a/lib/galaxy/webapps/galaxy/buildapp.py
+++ b/lib/galaxy/webapps/galaxy/buildapp.py
@@ -198,7 +198,7 @@
webapp.mapper.resource( 'datatype',
'datatypes',
path_prefix='/api',
- collection={ 'sniffers': 'GET', 'mapping' : 'GET' },
+ collection={ 'sniffers': 'GET', 'mapping' : 'GET', 'converters': 'GET' },
parent_resources=dict( member_name='datatype', collection_name='datatypes' ) )
#webapp.mapper.connect( 'run_workflow', '/api/workflow/{workflow_id}/library/{library_id}', controller='workflows', action='run', workflow_id=None, library_id=None, conditions=dict(method=["GET"]) )
webapp.mapper.resource( 'search', 'search', path_prefix='/api' )
diff -r 750775b64cb758876745af058550b97ae1c47105 -r 0587bc5413d66e85673d7b429bc04d34e47ad4c4 test/api/test_datatypes.py
--- a/test/api/test_datatypes.py
+++ b/test/api/test_datatypes.py
@@ -43,6 +43,19 @@
xml_index = sniffer_list.index( "galaxy.datatypes.xml:GenericXml" )
assert owl_index < xml_index
+ def test_converters( self ):
+ response = self._get( "datatypes/converters" )
+ self._assert_status_code_is( response, 200 )
+ converters_list = response.json()
+ found_fasta_to_tabular = False
+
+ for converter in converters_list:
+ self._assert_has_key( converter, "source", "target", "tool_id" )
+ if converter["source"] == "fasta" and converter["target"] == "tabular":
+ found_fasta_to_tabular = True
+
+ assert found_fasta_to_tabular
+
def _index_datatypes( self, data={} ):
response = self._get( "datatypes", data=data )
self._assert_status_code_is( response, 200 )
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/29ed5db57e42/
Changeset: 29ed5db57e42
User: jmchilton
Date: 2014-12-24 05:42:54+00:00
Summary: Breakup big remove method in tool_panel_manager.py to ease testing.
Separate out logic for dealing with toolbox from logic for dealing repository metadata in the database.
Affected #: 2 files
diff -r 17f4ab6dc1ff388f1e58e72b886cfa792e3b131c -r 29ed5db57e4247653a9530540180025de8e93f5d 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
@@ -249,9 +249,9 @@
if tool_shed_repository.includes_tools_for_display_in_tool_panel:
# Handle tool panel alterations.
tpm = tool_panel_manager.ToolPanelManager( trans.app )
- tpm.remove_from_tool_panel( tool_shed_repository,
- shed_tool_conf,
- uninstall=remove_from_disk_checked )
+ tpm.remove_repository_contents( tool_shed_repository,
+ shed_tool_conf,
+ uninstall=remove_from_disk_checked )
if tool_shed_repository.includes_data_managers:
dmh = data_manager.DataManagerHandler( trans.app )
dmh.remove_from_data_manager( tool_shed_repository )
diff -r 17f4ab6dc1ff388f1e58e72b886cfa792e3b131c -r 29ed5db57e4247653a9530540180025de8e93f5d lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
--- a/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
+++ b/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
@@ -427,7 +427,7 @@
# Persist the altered in-memory version of the tool config.
self.config_elems_to_xml_file( config_elems, shed_tool_conf, tool_path )
- def remove_from_tool_panel( self, repository, shed_tool_conf, uninstall ):
+ def remove_repository_contents( self, repository, shed_tool_conf, uninstall ):
"""
A tool shed repository is being deactivated or uninstalled, so handle
tool panel alterations accordingly.
@@ -442,6 +442,9 @@
# Create a list of guids for all tools that will be removed from the in-memory tool panel
# and config file on disk.
guids_to_remove = [ k for k in tool_panel_dict.keys() ]
+ self.remove_guids( guids_to_remove, shed_tool_conf, uninstall )
+
+ def remove_guids( self, guids_to_remove, shed_tool_conf, uninstall ):
# Remove the tools from the toolbox's tools_by_id dictionary.
for guid_to_remove in guids_to_remove:
if guid_to_remove in self.app.toolbox.tools_by_id:
https://bitbucket.org/galaxy/galaxy-central/commits/179199007ec9/
Changeset: 179199007ec9
User: jmchilton
Date: 2014-12-24 05:42:54+00:00
Summary: Unit test coverage for removing stuff from the toolbox.
Covers cases for tools inside and outside of sections and both deactivation versus uninstallation.
Affected #: 2 files
diff -r 29ed5db57e4247653a9530540180025de8e93f5d -r 179199007ec93cdfa45b200e9a27486035ff2477 test/unit/tool_shed_unit_tests/test_tool_panel_manager.py
--- a/test/unit/tool_shed_unit_tests/test_tool_panel_manager.py
+++ b/test/unit/tool_shed_unit_tests/test_tool_panel_manager.py
@@ -12,7 +12,7 @@
self._init_tool()
self._add_config( """<toolbox><section id="tid" name="test"><tool file="tool.xml" /></section></toolbox>""" )
toolbox = self.toolbox
- tpm = tool_panel_manager.ToolPanelManager( self.app )
+ tpm = self.tpm
# Test fetch existing section by id.
section_id, section = tpm.handle_tool_panel_section( toolbox, tool_panel_section_id="tid" )
assert section_id == "tid"
@@ -47,7 +47,7 @@
)
]
_, section = self.toolbox.get_or_create_section("tid1")
- tpm = tool_panel_manager.ToolPanelManager( self.app )
+ tpm = self.tpm
tool_panel_dict = tpm.generate_tool_panel_dict_for_new_install(
tool_dicts=new_tools,
tool_section=section,
@@ -61,6 +61,77 @@
shed_tool_conf="tool_conf.xml",
tool_panel_dict=tool_panel_dict,
)
+ self._verify_tool_confs()
+
+ def test_deactivate_in_section( self ):
+ self._setup_two_versions_remove_one( section=True, uninstall=False )
+ self._verify_version_2_removed_from_panel( )
+ # Still in tool conf since not uninstalled only deactivated...
+ assert "github.com/galaxyproect/example/test_tool/0.2" in open(os.path.join(self.test_directory, "tool_conf.xml"), "r").read()
+ self._verify_tool_confs()
+
+ self._remove_guids( ["github.com/galaxyproect/example/test_tool/0.1"], uninstall=False )
+
+ # Now no versions of this tool are returned by toolbox.
+ all_versions = self.toolbox.get_tool( "test_tool", get_all_versions=True )
+ assert not all_versions
+
+ # Check that tool panel has reverted to old value...
+ section = self.toolbox.tool_panel["tid"]
+ assert len(section.elems) == 0
+
+ def test_uninstall_in_section( self ):
+ self._setup_two_versions_remove_one( section=True, uninstall=True )
+ self._verify_version_2_removed_from_panel( )
+ # Not in tool conf because it was uninstalled.
+ assert "github.com/galaxyproect/example/test_tool/0.2" not in open(os.path.join(self.test_directory, "tool_conf.xml"), "r").read()
+ self._verify_tool_confs()
+
+ def test_deactivate_outside_section( self ):
+ self._setup_two_versions_remove_one( section=False, uninstall=False )
+ self._verify_version_2_removed_from_panel( section=False )
+ # Still in tool conf since not uninstalled only deactivated...
+ assert "github.com/galaxyproect/example/test_tool/0.2" in open(os.path.join(self.test_directory, "tool_conf.xml"), "r").read()
+ self._verify_tool_confs()
+
+ def test_uninstall_outside_section( self ):
+ self._setup_two_versions_remove_one( section=False, uninstall=True )
+ self._verify_version_2_removed_from_panel( section=False )
+ # Still in tool conf since not uninstalled only deactivated...
+ assert "github.com/galaxyproect/example/test_tool/0.2" not in open(os.path.join(self.test_directory, "tool_conf.xml"), "r").read()
+ self._verify_tool_confs()
+
+ def _setup_two_versions_remove_one( self, section, uninstall ):
+ self._init_tool()
+ self._setup_two_versions_in_config( section=True )
+ self._setup_two_versions()
+ self.toolbox
+ self._remove_guids( ["github.com/galaxyproect/example/test_tool/0.2"], uninstall=uninstall )
+
+ def _verify_version_2_removed_from_panel( self, section=True ):
+ # Check that test_tool now only has one version...
+ all_versions = self.toolbox.get_tool( "test_tool", get_all_versions=True )
+ assert len( all_versions ) == 1
+
+ # Check that tool panel has reverted to old value...
+ if section:
+ section = self.toolbox.tool_panel["tid"]
+ assert len(section.elems) == 1
+ assert section.elems.values()[0].id == "github.com/galaxyproect/example/test_tool/0.1"
+
+ assert "github.com/galaxyproect/example/test_tool/0.2" not in self.toolbox.integrated_tool_panel["tid"].elems
+ else:
+ self.toolbox.tool_panel.values()[0].id == "github.com/galaxyproect/example/test_tool/0.1"
+ assert "github.com/galaxyproect/example/test_tool/0.2" not in self.toolbox.integrated_tool_panel
+
+ def _remove_guids( self, guids, uninstall, shed_tool_conf="tool_conf.xml" ):
+ self.tpm.remove_guids(
+ guids_to_remove=guids,
+ shed_tool_conf=shed_tool_conf,
+ uninstall=uninstall,
+ )
+
+ def _verify_tool_confs( self ):
self._assert_valid_xml( self.integerated_tool_panel_path )
self._assert_valid_xml( os.path.join( self.test_directory, "tool_conf.xml" ) )
@@ -71,3 +142,7 @@
message_template = "file %s does not contain valid XML, content %s"
message = message_template % ( filename, open( filename, "r" ).read() )
raise AssertionError( message )
+
+ @property
+ def tpm( self ):
+ return tool_panel_manager.ToolPanelManager( self.app )
diff -r 29ed5db57e4247653a9530540180025de8e93f5d -r 179199007ec93cdfa45b200e9a27486035ff2477 test/unit/tools/test_toolbox.py
--- a/test/unit/tools/test_toolbox.py
+++ b/test/unit/tools/test_toolbox.py
@@ -91,6 +91,27 @@
self.app.install_model.context.add( version_association )
self.app.install_model.context.flush( )
+ def _setup_two_versions_in_config( self, section=False ):
+ if section:
+ template = """<toolbox tool_path="%s">
+<section id="tid" name="TID" version="">
+ %s
+</section>
+<section id="tid" name="TID" version="">
+ %s
+</section>
+</toolbox>"""
+ else:
+ template = """<toolbox tool_path="%s">
+<section id="tid" name="TID" version="">
+ %s
+</section>
+<section id="tid" name="TID" version="">
+ %s
+</section>
+</toolbox>"""
+ self._add_config( template % (self.test_directory, CONFIG_TEST_TOOL_VERSION_1, CONFIG_TEST_TOOL_VERSION_2 ) )
+
def _add_config( self, xml, name="tool_conf.xml" ):
path = self._tool_conf_path( name=name )
with open( path, "w" ) as f:
@@ -133,14 +154,7 @@
def test_groups_tools_in_section( self ):
self._init_tool()
- self._add_config( """<toolbox tool_path="%s">
-<section id="tid" name="TID" version="">
- %s
-</section>
-<section id="tid" name="TID" version="">
- %s
-</section>
-</toolbox>""" % (self.test_directory, CONFIG_TEST_TOOL_VERSION_1, CONFIG_TEST_TOOL_VERSION_2 ) )
+ self._setup_two_versions_in_config( section=True )
self._setup_two_versions()
self.toolbox
self.__verify_two_test_tools( )
@@ -152,11 +166,7 @@
def test_group_tools_out_of_section( self ):
self._init_tool()
- self._add_config( """<toolbox tool_path="%s">
-%s
-%s
-</toolbox>""" % (self.test_directory, CONFIG_TEST_TOOL_VERSION_1, CONFIG_TEST_TOOL_VERSION_2 ) )
-
+ self._setup_two_versions_in_config( section=False )
self._setup_two_versions()
self.__verify_two_test_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: jmchilton: Add tool lineage test for tools outside of sections.
by commits-noreply@bitbucket.org 23 Dec '14
by commits-noreply@bitbucket.org 23 Dec '14
23 Dec '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/17f4ab6dc1ff/
Changeset: 17f4ab6dc1ff
User: jmchilton
Date: 2014-12-24 03:17:55+00:00
Summary: Add tool lineage test for tools outside of sections.
Affected #: 1 file
diff -r 39e6037047070a5014c4250dc7f47775e78452b4 -r 17f4ab6dc1ff388f1e58e72b886cfa792e3b131c test/unit/tools/test_toolbox.py
--- a/test/unit/tools/test_toolbox.py
+++ b/test/unit/tools/test_toolbox.py
@@ -1,4 +1,5 @@
import os
+import string
import unittest
from galaxy.tools import ToolBox
@@ -7,6 +8,21 @@
import tools_support
+CONFIG_TEST_TOOL_VERSION_TEMPLATE = string.Template(
+ """ <tool file="tool.xml" guid="github.com/galaxyproect/example/test_tool/0.${version}">
+ <tool_shed>github.com</tool_shed>
+ <repository_name>example</repository_name>
+ <repository_owner>galaxyproject</repository_owner>
+ <installed_changeset_revision>${version}</installed_changeset_revision>
+ <id>github.com/galaxyproect/example/test_tool/0.${version}</id>
+ <version>0.${version}</version>
+ </tool>
+ """
+)
+CONFIG_TEST_TOOL_VERSION_1 = CONFIG_TEST_TOOL_VERSION_TEMPLATE.safe_substitute( dict( version="1" ) )
+CONFIG_TEST_TOOL_VERSION_2 = CONFIG_TEST_TOOL_VERSION_TEMPLATE.safe_substitute( dict( version="2" ) )
+
+
class BaseToolBoxTestCase( unittest.TestCase, tools_support.UsesApp, tools_support.UsesTools ):
@property
@@ -115,32 +131,52 @@
self.toolbox
self.assert_integerated_tool_panel(exists=True)
- def test_groups_tools( self ):
+ def test_groups_tools_in_section( self ):
self._init_tool()
self._add_config( """<toolbox tool_path="%s"><section id="tid" name="TID" version="">
- <tool file="tool.xml" guid="github.com/galaxyproect/example/test_tool/0.1">
- <tool_shed>github.com</tool_shed>
- <repository_name>example</repository_name>
- <repository_owner>galaxyproject</repository_owner>
- <installed_changeset_revision>2</installed_changeset_revision>
- <id>github.com/galaxyproect/example/test_tool/0.1</id>
- <version>0.1</version>
- </tool>
+ %s
</section><section id="tid" name="TID" version="">
- <tool file="tool.xml" guid="github.com/galaxyproect/example/test_tool/0.2">
- <tool_shed>github.com</tool_shed>
- <repository_name>example</repository_name>
- <repository_owner>galaxyproject</repository_owner>
- <installed_changeset_revision>2</installed_changeset_revision>
- <id>github.com/galaxyproect/example/test_tool/0.2</id>
- <version>0.2</version>
- </tool>
+ %s
</section>
-</toolbox>""" % self.test_directory )
+</toolbox>""" % (self.test_directory, CONFIG_TEST_TOOL_VERSION_1, CONFIG_TEST_TOOL_VERSION_2 ) )
self._setup_two_versions()
+ self.toolbox
+ self.__verify_two_test_tools( )
+ # Assert only newer version of the tool loaded into the panel.
+ section = self.toolbox.tool_panel["tid"]
+ assert len(section.elems) == 1
+ assert section.elems.values()[0].id == "github.com/galaxyproect/example/test_tool/0.2"
+
+ def test_group_tools_out_of_section( self ):
+ self._init_tool()
+ self._add_config( """<toolbox tool_path="%s">
+%s
+%s
+</toolbox>""" % (self.test_directory, CONFIG_TEST_TOOL_VERSION_1, CONFIG_TEST_TOOL_VERSION_2 ) )
+
+ self._setup_two_versions()
+ self.__verify_two_test_tools( )
+
+ # Assert tools merged in tool panel.
+ assert len( self.toolbox.tool_panel ) == 1
+
+ def test_update_shed_conf(self):
+ self.__setup_shed_tool_conf()
+ self.toolbox.update_shed_config( 0, {} )
+ assert self.reindexed
+ self.assert_integerated_tool_panel(exists=True)
+
+ def test_update_shed_conf_deactivate_only(self):
+ self.__setup_shed_tool_conf()
+ self.toolbox.update_shed_config( 0, {}, integrated_panel_changes=False )
+ assert self.reindexed
+ # No changes, should be regenerated
+ self.assert_integerated_tool_panel(exists=False)
+
+ def __verify_two_test_tools( self ):
# Assert tool versions of the tool with simple id 'test_tool'
all_versions = self.toolbox.get_tool( "test_tool", get_all_versions=True )
assert len( all_versions ) == 2
@@ -156,24 +192,6 @@
assert self.toolbox.get_tool( "test_tool", tool_version="0.1" ).guid == "github.com/galaxyproect/example/test_tool/0.1"
assert self.toolbox.get_tool( "test_tool", tool_version="0.2" ).guid == "github.com/galaxyproect/example/test_tool/0.2"
- # Assert only newer version of the tool loaded into the panel.
- section = self.toolbox.tool_panel["tid"]
- assert len(section.elems) == 1
- assert section.elems.values()[0].id == "github.com/galaxyproect/example/test_tool/0.2"
-
- def test_update_shed_conf(self):
- self.__setup_shed_tool_conf()
- self.toolbox.update_shed_config( 0, {} )
- assert self.reindexed
- self.assert_integerated_tool_panel(exists=True)
-
- def test_update_shed_conf_deactivate_only(self):
- self.__setup_shed_tool_conf()
- self.toolbox.update_shed_config( 0, {}, integrated_panel_changes=False )
- assert self.reindexed
- # No changes, should be regenerated
- self.assert_integerated_tool_panel(exists=False)
-
def __remove_itp( self ):
os.remove( os.path)
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/97b801cca67e/
Changeset: 97b801cca67e
User: jmchilton
Date: 2014-12-24 02:42:37+00:00
Summary: More tool panel manager unit tests.
(Including adding file missing with previous commit 697b58f0.)
Affected #: 3 files
diff -r 697b58fa885a215bbcd33aa6e09c8f98e2c8b7fe -r 97b801cca67e566839e9c7fdaf5c558ff1eebab4 lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
--- a/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
+++ b/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
@@ -105,6 +105,8 @@
else:
tool_elem = XmlET.Element( 'tool' )
tool_elem.attrib[ 'file' ] = tool_file_path
+ if not tool.guid:
+ raise ValueError("tool has no guid")
tool_elem.attrib[ 'guid' ] = tool.guid
tool_shed_elem = XmlET.SubElement( tool_elem, 'tool_shed' )
tool_shed_elem.text = tool_shed
diff -r 697b58fa885a215bbcd33aa6e09c8f98e2c8b7fe -r 97b801cca67e566839e9c7fdaf5c558ff1eebab4 test/unit/tool_shed_unit_tests/test_tool_panel_manager.py
--- /dev/null
+++ b/test/unit/tool_shed_unit_tests/test_tool_panel_manager.py
@@ -0,0 +1,73 @@
+import os
+
+from galaxy.util import parse_xml
+
+from tools.test_toolbox import BaseToolBoxTestCase
+from tool_shed.galaxy_install.tools import tool_panel_manager
+
+
+class ToolPanelManagerTestCase( BaseToolBoxTestCase ):
+
+ def test_handle_tool_panel_section( self ):
+ self._init_tool()
+ self._add_config( """<toolbox><section id="tid" name="test"><tool file="tool.xml" /></section></toolbox>""" )
+ toolbox = self.toolbox
+ tpm = tool_panel_manager.ToolPanelManager( self.app )
+ # Test fetch existing section by id.
+ section_id, section = tpm.handle_tool_panel_section( toolbox, tool_panel_section_id="tid" )
+ assert section_id == "tid"
+ assert len( section.elems ) == 1 # tool.xml
+ assert section.id == "tid"
+ assert len( toolbox.tool_panel ) == 1
+
+ section_id, section = tpm.handle_tool_panel_section( toolbox, new_tool_panel_section_label="tid2" )
+ assert section_id == "tid2"
+ assert len( section.elems ) == 0 # new section
+ assert section.id == "tid2"
+ assert len( toolbox.tool_panel ) == 2
+
+ # Test re-fetch new section by same id.
+ section_id, section = tpm.handle_tool_panel_section( toolbox, new_tool_panel_section_label="tid2" )
+ assert section_id == "tid2"
+ assert len( section.elems ) == 0 # new section
+ assert section.id == "tid2"
+ assert len( toolbox.tool_panel ) == 2
+
+ def test_add_tool_to_panel( self ):
+ self._init_tool()
+ self._add_config( """<toolbox tool_path="%s"></toolbox>""" % self.test_directory )
+ tool_path = os.path.join(self.test_directory, "tool.xml")
+ self.tool.guid = "123456"
+ new_tools = [{"guid": "123456", "tool_config": tool_path}]
+ repository_tools_tups = [
+ (
+ tool_path,
+ "123456",
+ self.tool,
+ )
+ ]
+ _, section = self.toolbox.get_or_create_section("tid1")
+ tpm = tool_panel_manager.ToolPanelManager( self.app )
+ tool_panel_dict = tpm.generate_tool_panel_dict_for_new_install(
+ tool_dicts=new_tools,
+ tool_section=section,
+ )
+ tpm.add_to_tool_panel(
+ repository_name="test_repo",
+ repository_clone_url="http://github.com/galaxyproject/example.git",
+ changeset_revision="0123456789abcde",
+ repository_tools_tups=repository_tools_tups,
+ owner="devteam",
+ shed_tool_conf="tool_conf.xml",
+ tool_panel_dict=tool_panel_dict,
+ )
+ self._assert_valid_xml( self.integerated_tool_panel_path )
+ self._assert_valid_xml( os.path.join( self.test_directory, "tool_conf.xml" ) )
+
+ def _assert_valid_xml( self, filename ):
+ try:
+ parse_xml( filename )
+ except Exception:
+ message_template = "file %s does not contain valid XML, content %s"
+ message = message_template % ( filename, open( filename, "r" ).read() )
+ raise AssertionError( message )
diff -r 697b58fa885a215bbcd33aa6e09c8f98e2c8b7fe -r 97b801cca67e566839e9c7fdaf5c558ff1eebab4 test/unit/tools/test_toolbox.py
--- a/test/unit/tools/test_toolbox.py
+++ b/test/unit/tools/test_toolbox.py
@@ -23,6 +23,8 @@
def toolbox( self ):
if self.__toolbox is None:
self.__toolbox = SimplifiedToolBox( self )
+ # wire app with this new toolbox
+ self.app.toolbox = self.__toolbox
return self.__toolbox
def setUp( self ):
@@ -35,11 +37,15 @@
self.config_files = []
def _add_config( self, xml, name="tool_conf.xml" ):
- path = os.path.join( self.test_directory, "tool_conf.xml" )
+ path = self._tool_conf_path( name=name )
with open( path, "w" ) as f:
f.write( xml )
self.config_files.append( path )
+ def _tool_conf_path( self, name="tool_conf.xml" ):
+ path = os.path.join( self.test_directory, name )
+ return path
+
def __reindex( self ):
self.reindexed = True
https://bitbucket.org/galaxy/galaxy-central/commits/f1d8ecfadb85/
Changeset: f1d8ecfadb85
User: jmchilton
Date: 2014-12-24 02:42:37+00:00
Summary: PEP-8 and style tweaks to tool_panel_manager.py.
Affected #: 1 file
diff -r 97b801cca67e566839e9c7fdaf5c558ff1eebab4 -r f1d8ecfadb85df376846b5e4df0c0f30be569fc5 lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
--- a/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
+++ b/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
@@ -1,7 +1,6 @@
import logging
import threading
-import galaxy.tools
from xml.etree import ElementTree as XmlET
from tool_shed.util import basic_util
@@ -67,13 +66,14 @@
self.app.toolbox.integrated_tool_panel,
load_panel_dict=True )
elif config_elem.tag == 'tool':
- guid = config_elem.get( 'guid' )
- self.app.toolbox.load_tool_tag_set( config_elem,
- self.app.toolbox.tool_panel,
- self.app.toolbox.integrated_tool_panel,
- tool_path,
- load_panel_dict=True,
- guid=guid )
+ self.app.toolbox.load_tool_tag_set(
+ config_elem,
+ self.app.toolbox.tool_panel,
+ self.app.toolbox.integrated_tool_panel,
+ tool_path,
+ load_panel_dict=True,
+ guid=config_elem.get( 'guid' )
+ )
# Replace the old list of in-memory config_elems with the new list for this shed_tool_conf_dict.
shed_tool_conf_dict[ 'config_elems' ] = config_elems
self.app.toolbox.update_shed_config( index, shed_tool_conf_dict )
@@ -124,8 +124,9 @@
def generate_tool_panel_dict_for_new_install( self, tool_dicts, tool_section=None ):
"""
- When installing a repository that contains tools, all tools must currently be defined
- within the same tool section in the tool panel or outside of any sections.
+ When installing a repository that contains tools, all tools must
+ currently be defined within the same tool section in the tool panel or
+ outside of any sections.
"""
tool_panel_dict = {}
if tool_section:
@@ -168,11 +169,12 @@
def generate_tool_panel_dict_from_shed_tool_conf_entries( self, repository ):
"""
- Keep track of the section in the tool panel in which this repository's tools
- will be contained by parsing the shed_tool_conf in which the repository's tools
- are defined and storing the tool panel definition of each tool in the repository.
- This method is called only when the repository is being deactivated or un-installed
- and allows for activation or re-installation using the original layout.
+ Keep track of the section in the tool panel in which this repository's
+ tools will be contained by parsing the shed_tool_conf in which the
+ repository's tools are defined and storing the tool panel definition
+ of each tool in the repository. This method is called only when the
+ repository is being deactivated or un-installed and allows for
+ activation or re-installation using the original layout.
"""
tool_panel_dict = {}
shed_tool_conf, tool_path, relative_install_dir = \
@@ -351,8 +353,8 @@
def handle_tool_panel_selection( self, toolbox, metadata, no_changes_checked, tool_panel_section_id,
new_tool_panel_section_label ):
"""
- Handle the selected tool panel location for loading tools included in tool shed
- repositories when installing or reinstalling them.
+ Handle the selected tool panel location for loading tools included in
+ tool shed repositories when installing or reinstalling them.
"""
# Get the location in the tool panel in which each tool was originally loaded.
tool_section = None
@@ -390,10 +392,11 @@
def remove_from_shed_tool_config( self, shed_tool_conf_dict, guids_to_remove ):
"""
- A tool shed repository is being uninstalled so change the shed_tool_conf file.
- Parse the config file to generate the entire list of config_elems instead of
- using the in-memory list since it will be a subset of the entire list if one
- or more repositories have been deactivated.
+ A tool shed repository is being uninstalled so change the
+ shed_tool_conf file. Parse the config file to generate the entire list
+ of config_elems instead of using the in-memory list since it will be a
+ subset of the entire list if one or more repositories have been
+ deactivated.
"""
shed_tool_conf = shed_tool_conf_dict[ 'config_filename' ]
tool_path = shed_tool_conf_dict[ 'tool_path' ]
@@ -426,8 +429,8 @@
def remove_from_tool_panel( self, repository, shed_tool_conf, uninstall ):
"""
- A tool shed repository is being deactivated or uninstalled, so handle tool panel
- alterations accordingly.
+ A tool shed repository is being deactivated or uninstalled, so handle
+ tool panel alterations accordingly.
"""
# Determine where the tools are currently defined in the tool panel and store this
# information so the tools can be displayed in the same way when the repository is
https://bitbucket.org/galaxy/galaxy-central/commits/39e603704707/
Changeset: 39e603704707
User: jmchilton
Date: 2014-12-24 02:42:37+00:00
Summary: Unit test for tool panel merging tools by tool shed lineage.
Affected #: 1 file
diff -r f1d8ecfadb85df376846b5e4df0c0f30be569fc5 -r 39e6037047070a5014c4250dc7f47775e78452b4 test/unit/tools/test_toolbox.py
--- a/test/unit/tools/test_toolbox.py
+++ b/test/unit/tools/test_toolbox.py
@@ -2,6 +2,7 @@
import unittest
from galaxy.tools import ToolBox
+from galaxy.model import tool_shed_install
from galaxy.model.tool_shed_install import mapping
import tools_support
@@ -30,12 +31,50 @@
def setUp( self ):
self.reindexed = False
self.setup_app( mock_model=False )
+ install_model = mapping.init( "sqlite:///:memory:", create_tables=True )
+ self.app.install_model = install_model
self.app.reindex_tool_search = self.__reindex
itp_config = os.path.join(self.test_directory, "integrated_tool_panel.xml")
self.app.config.integrated_tool_panel_config = itp_config
self.__toolbox = None
self.config_files = []
+ def _repo_install( self, changeset ):
+ repository = tool_shed_install.ToolShedRepository()
+ repository.tool_shed = "github.com"
+ repository.owner = "galaxyproject"
+ repository.name = "example"
+ repository.changeset_revision = changeset
+ repository.installed_changeset_revision = changeset
+ repository.deleted = False
+ repository.uninstalled = False
+ self.app.install_model.context.add( repository )
+ self.app.install_model.context.flush( )
+ return repository
+
+ def _setup_two_versions( self ):
+ repository1 = self._repo_install( changeset="1" )
+ version1 = tool_shed_install.ToolVersion()
+ version1.tool_id = "github.com/galaxyproect/example/test_tool/0.1"
+ version1.repository = repository1
+ self.app.install_model.context.add( version1 )
+ self.app.install_model.context.flush( )
+
+ repository2 = self._repo_install( changeset="2" )
+ version2 = tool_shed_install.ToolVersion()
+ version2.tool_id = "github.com/galaxyproect/example/test_tool/0.2"
+ version2.repository = repository2
+
+ self.app.install_model.context.add( version2 )
+ self.app.install_model.context.flush( )
+
+ version_association = tool_shed_install.ToolVersionAssociation()
+ version_association.parent_id = version1.id
+ version_association.tool_id = version2.id
+
+ self.app.install_model.context.add( version_association )
+ self.app.install_model.context.flush( )
+
def _add_config( self, xml, name="tool_conf.xml" ):
path = self._tool_conf_path( name=name )
with open( path, "w" ) as f:
@@ -78,7 +117,49 @@
def test_groups_tools( self ):
self._init_tool()
- self._add_config( """<toolbox><tool file="tool.xml" /></toolbox>""" )
+ self._add_config( """<toolbox tool_path="%s">
+<section id="tid" name="TID" version="">
+ <tool file="tool.xml" guid="github.com/galaxyproect/example/test_tool/0.1">
+ <tool_shed>github.com</tool_shed>
+ <repository_name>example</repository_name>
+ <repository_owner>galaxyproject</repository_owner>
+ <installed_changeset_revision>2</installed_changeset_revision>
+ <id>github.com/galaxyproect/example/test_tool/0.1</id>
+ <version>0.1</version>
+ </tool>
+</section>
+<section id="tid" name="TID" version="">
+ <tool file="tool.xml" guid="github.com/galaxyproect/example/test_tool/0.2">
+ <tool_shed>github.com</tool_shed>
+ <repository_name>example</repository_name>
+ <repository_owner>galaxyproject</repository_owner>
+ <installed_changeset_revision>2</installed_changeset_revision>
+ <id>github.com/galaxyproect/example/test_tool/0.2</id>
+ <version>0.2</version>
+ </tool>
+</section>
+</toolbox>""" % self.test_directory )
+ self._setup_two_versions()
+
+ # Assert tool versions of the tool with simple id 'test_tool'
+ all_versions = self.toolbox.get_tool( "test_tool", get_all_versions=True )
+ assert len( all_versions ) == 2
+
+ # Verify lineage_ids on both tools is correctly ordered.
+ for version in ["0.1", "0.2"]:
+ guid = "github.com/galaxyproect/example/test_tool/" + version
+ lineage_ids = self.toolbox.get_tool( guid ).lineage_ids
+ assert lineage_ids[ 0 ] == "github.com/galaxyproect/example/test_tool/0.1"
+ assert lineage_ids[ 1 ] == "github.com/galaxyproect/example/test_tool/0.2"
+
+ # Test tool_version attribute.
+ assert self.toolbox.get_tool( "test_tool", tool_version="0.1" ).guid == "github.com/galaxyproect/example/test_tool/0.1"
+ assert self.toolbox.get_tool( "test_tool", tool_version="0.2" ).guid == "github.com/galaxyproect/example/test_tool/0.2"
+
+ # Assert only newer version of the tool loaded into the panel.
+ section = self.toolbox.tool_panel["tid"]
+ assert len(section.elems) == 1
+ assert section.elems.values()[0].id == "github.com/galaxyproect/example/test_tool/0.2"
def test_update_shed_conf(self):
self.__setup_shed_tool_conf()
@@ -110,7 +191,6 @@
def __init__( self, test_case ):
app = test_case.app
# Handle app/config stuff needed by toolbox but not by tools.
- app.install_model = mapping.init( "sqlite:///:memory:", create_tables=True )
app.job_config.get_tool_resource_parameters = lambda tool_id: None
app.config.update_integrated_tool_panel = True
config_files = test_case.config_files
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: Move ToolPanelManager operation to create or get section into ToolBox.
by commits-noreply@bitbucket.org 23 Dec '14
by commits-noreply@bitbucket.org 23 Dec '14
23 Dec '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/697b58fa885a/
Changeset: 697b58fa885a
User: jmchilton
Date: 2014-12-23 19:22:08+00:00
Summary: Move ToolPanelManager operation to create or get section into ToolBox.
Now with unit test. Part of broader effort to make ToolBox interface more explicit, tested, and hide implementation details from other parts of code (such as ToolPanelManager).
Also reworked the code to now build up and re-parse XML structures - just use a dictionary - thanks to 34b3e1c.
Affected #: 3 files
diff -r 5328806e31ac52e01f89b89d4d7873c38d9ae07b -r 697b58fa885a215bbcd33aa6e09c8f98e2c8b7fe lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -256,6 +256,27 @@
self.write_integrated_tool_panel_config_file()
app.reindex_tool_search()
+ def get_or_create_section( self, section_id, new_label=None ):
+ tool_panel_section_key = str( section_id )
+ if tool_panel_section_key in self.tool_panel:
+ # Appending a tool to an existing section in toolbox.tool_panel
+ tool_section = self.tool_panel[ tool_panel_section_key ]
+ log.debug( "Appending to tool panel section: %s" % str( tool_section.name ) )
+ else:
+ # Appending a new section to toolbox.tool_panel
+ if new_label is None:
+ # This might add an ugly section label to the tool panel, but, oh well...
+ new_label = section_id
+ section_dict = {
+ 'name': new_label,
+ 'id': section_id,
+ 'version': '',
+ }
+ tool_section = ToolSection( section_dict )
+ self.tool_panel[ tool_panel_section_key ] = tool_section
+ log.debug( "Loading new tool panel section: %s" % str( tool_section.name ) )
+ return tool_panel_section_key, tool_section
+
def __resolve_tool_path(self, tool_path, config_filename):
if not tool_path:
# Default to backward compatible config setting.
diff -r 5328806e31ac52e01f89b89d4d7873c38d9ae07b -r 697b58fa885a215bbcd33aa6e09c8f98e2c8b7fe lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
--- a/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
+++ b/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
@@ -312,24 +312,7 @@
return tool_section
def get_or_create_tool_section( self, toolbox, tool_panel_section_id, new_tool_panel_section_label=None ):
- tool_panel_section_key = str( tool_panel_section_id )
- if tool_panel_section_key in toolbox.tool_panel:
- # Appending a tool to an existing section in toolbox.tool_panel
- tool_section = toolbox.tool_panel[ tool_panel_section_key ]
- log.debug( "Appending to tool panel section: %s" % str( tool_section.name ) )
- else:
- # Appending a new section to toolbox.tool_panel
- if new_tool_panel_section_label is None:
- # This might add an ugly section label to the tool panel, but, oh well...
- new_tool_panel_section_label = tool_panel_section_id
- elem = XmlET.Element( 'section' )
- elem.attrib[ 'name' ] = new_tool_panel_section_label
- elem.attrib[ 'id' ] = tool_panel_section_id
- elem.attrib[ 'version' ] = ''
- tool_section = galaxy.tools.ToolSection( elem )
- toolbox.tool_panel[ tool_panel_section_key ] = tool_section
- log.debug( "Loading new tool panel section: %s" % str( tool_section.name ) )
- return tool_panel_section_key, tool_section
+ return toolbox.get_or_create_section( section_id=tool_panel_section_id, new_label=new_tool_panel_section_label )
def get_shed_tool_conf_dict( self, shed_tool_conf ):
"""
diff -r 5328806e31ac52e01f89b89d4d7873c38d9ae07b -r 697b58fa885a215bbcd33aa6e09c8f98e2c8b7fe test/unit/tools/test_toolbox.py
--- a/test/unit/tools/test_toolbox.py
+++ b/test/unit/tools/test_toolbox.py
@@ -6,63 +6,7 @@
import tools_support
-class ToolBoxTestCase( unittest.TestCase, tools_support.UsesApp, tools_support.UsesTools ):
-
- def test_load_file( self ):
- self._init_tool()
- self.__add_config( """<toolbox><tool file="tool.xml" /></toolbox>""" )
-
- toolbox = self.toolbox
- assert toolbox.get_tool( "test_tool" ) is not None
- assert toolbox.get_tool( "not_a_test_tool" ) is None
-
- def test_load_file_in_section( self ):
- self._init_tool()
- self.__add_config( """<toolbox><section id="t" name="test"><tool file="tool.xml" /></section></toolbox>""" )
-
- toolbox = self.toolbox
- assert toolbox.get_tool( "test_tool" ) is not None
- assert toolbox.get_tool( "not_a_test_tool" ) is None
-
- def test_writes_integrate_tool_panel( self ):
- self._init_tool()
- self.__add_config( """<toolbox><tool file="tool.xml" /></toolbox>""" )
-
- self.assert_integerated_tool_panel(exists=False)
- self.toolbox
- self.assert_integerated_tool_panel(exists=True)
-
- def test_groups_tools( self ):
- self._init_tool()
- self.__add_config( """<toolbox><tool file="tool.xml" /></toolbox>""" )
-
- def test_update_shed_conf(self):
- self.__setup_shed_tool_conf()
- self.toolbox.update_shed_config( 0, {} )
- assert self.reindexed
- self.assert_integerated_tool_panel(exists=True)
-
- def test_update_shed_conf_deactivate_only(self):
- self.__setup_shed_tool_conf()
- self.toolbox.update_shed_config( 0, {}, integrated_panel_changes=False )
- assert self.reindexed
- # No changes, should be regenerated
- self.assert_integerated_tool_panel(exists=False)
-
- def setUp( self ):
- self.reindexed = False
- self.setup_app( mock_model=False )
- self.app.reindex_tool_search = self.__reindex
- itp_config = os.path.join(self.test_directory, "integrated_tool_panel.xml")
- self.app.config.integrated_tool_panel_config = itp_config
- self.__toolbox = None
- self.config_files = []
-
- def __reindex( self ):
- self.reindexed = True
-
- def __remove_itp( self ):
- os.remove( os.path)
+class BaseToolBoxTestCase( unittest.TestCase, tools_support.UsesApp, tools_support.UsesTools ):
@property
def integerated_tool_panel_path( self ):
@@ -81,14 +25,73 @@
self.__toolbox = SimplifiedToolBox( self )
return self.__toolbox
- def __add_config( self, xml, name="tool_conf.xml" ):
+ def setUp( self ):
+ self.reindexed = False
+ self.setup_app( mock_model=False )
+ self.app.reindex_tool_search = self.__reindex
+ itp_config = os.path.join(self.test_directory, "integrated_tool_panel.xml")
+ self.app.config.integrated_tool_panel_config = itp_config
+ self.__toolbox = None
+ self.config_files = []
+
+ def _add_config( self, xml, name="tool_conf.xml" ):
path = os.path.join( self.test_directory, "tool_conf.xml" )
with open( path, "w" ) as f:
f.write( xml )
self.config_files.append( path )
+ def __reindex( self ):
+ self.reindexed = True
+
+
+class ToolBoxTestCase( BaseToolBoxTestCase ):
+
+ def test_load_file( self ):
+ self._init_tool()
+ self._add_config( """<toolbox><tool file="tool.xml" /></toolbox>""" )
+
+ toolbox = self.toolbox
+ assert toolbox.get_tool( "test_tool" ) is not None
+ assert toolbox.get_tool( "not_a_test_tool" ) is None
+
+ def test_load_file_in_section( self ):
+ self._init_tool()
+ self._add_config( """<toolbox><section id="t" name="test"><tool file="tool.xml" /></section></toolbox>""" )
+
+ toolbox = self.toolbox
+ assert toolbox.get_tool( "test_tool" ) is not None
+ assert toolbox.get_tool( "not_a_test_tool" ) is None
+
+ def test_writes_integrate_tool_panel( self ):
+ self._init_tool()
+ self._add_config( """<toolbox><tool file="tool.xml" /></toolbox>""" )
+
+ self.assert_integerated_tool_panel(exists=False)
+ self.toolbox
+ self.assert_integerated_tool_panel(exists=True)
+
+ def test_groups_tools( self ):
+ self._init_tool()
+ self._add_config( """<toolbox><tool file="tool.xml" /></toolbox>""" )
+
+ def test_update_shed_conf(self):
+ self.__setup_shed_tool_conf()
+ self.toolbox.update_shed_config( 0, {} )
+ assert self.reindexed
+ self.assert_integerated_tool_panel(exists=True)
+
+ def test_update_shed_conf_deactivate_only(self):
+ self.__setup_shed_tool_conf()
+ self.toolbox.update_shed_config( 0, {}, integrated_panel_changes=False )
+ assert self.reindexed
+ # No changes, should be regenerated
+ self.assert_integerated_tool_panel(exists=False)
+
+ def __remove_itp( self ):
+ os.remove( os.path)
+
def __setup_shed_tool_conf( self ):
- self.__add_config( """<toolbox tool_path="."></toolbox>""" )
+ self._add_config( """<toolbox tool_path="."></toolbox>""" )
self.toolbox # create toolbox
assert not self.reindexed
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
7 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d3298df33143/
Changeset: d3298df33143
User: jmchilton
Date: 2014-12-23 18:52:39+00:00
Summary: Make tool filters properties optional attributes of config.
This way the tool shed doesn't need to pointlessly add them to its config object.
Affected #: 2 files
diff -r 3131a76ddd932911a80838d83aaf71baf26a3d6f -r d3298df33143d829bc9e9ed5d1cae0e1c39b60b1 lib/galaxy/tools/filters/__init__.py
--- a/lib/galaxy/tools/filters/__init__.py
+++ b/lib/galaxy/tools/filters/__init__.py
@@ -20,9 +20,9 @@
self.default_filters = dict( tool=[ _not_hidden, _handle_requires_login ], section=[], label=[] )
# Add dynamic filters to these default filters.
config = toolbox.app.config
- self.__init_filters( "tool", config.tool_filters, self.default_filters )
- self.__init_filters( "section", config.tool_section_filters, self.default_filters )
- self.__init_filters( "label", config.tool_label_filters, self.default_filters )
+ self.__init_filters( "tool", getattr( config, "tool_filters", "" ), self.default_filters )
+ self.__init_filters( "section", getattr( config, "tool_section_filters", "" ), self.default_filters )
+ self.__init_filters( "label", getattr( config, "tool_label_filters", "" ), self.default_filters )
def build_filters( self, trans, **kwds ):
"""
diff -r 3131a76ddd932911a80838d83aaf71baf26a3d6f -r d3298df33143d829bc9e9ed5d1cae0e1c39b60b1 lib/galaxy/webapps/tool_shed/config.py
--- a/lib/galaxy/webapps/tool_shed/config.py
+++ b/lib/galaxy/webapps/tool_shed/config.py
@@ -50,9 +50,6 @@
self.test_conf = resolve_path( kwargs.get( "test_conf", "" ), self.root )
self.id_secret = kwargs.get( "id_secret", "USING THE DEFAULT IS NOT SECURE!" )
# Tool stuff
- self.tool_filters = listify( kwargs.get( "tool_filters", [] ) )
- self.tool_label_filters = listify( kwargs.get( "tool_label_filters", [] ) )
- self.tool_section_filters = listify( kwargs.get( "tool_section_filters", [] ) )
self.tool_path = resolve_path( kwargs.get( "tool_path", "tools" ), self.root )
self.tool_secret = kwargs.get( "tool_secret", "" )
self.tool_data_path = resolve_path( kwargs.get( "tool_data_path", "shed-tool-data" ), os.getcwd() )
https://bitbucket.org/galaxy/galaxy-central/commits/175345aa482e/
Changeset: 175345aa482e
User: jmchilton
Date: 2014-12-23 18:52:39+00:00
Summary: Make use_tool_dependencies an optional attribute of config.
This way the tool shed doesn't need to pointlessly configure this property to create a toolbox.
Affected #: 2 files
diff -r d3298df33143d829bc9e9ed5d1cae0e1c39b60b1 -r 175345aa482e4ef394e639b1a3688ee38ac84fc4 lib/galaxy/tools/deps/__init__.py
--- a/lib/galaxy/tools/deps/__init__.py
+++ b/lib/galaxy/tools/deps/__init__.py
@@ -14,7 +14,7 @@
def build_dependency_manager( config ):
- if config.use_tool_dependencies:
+ if getattr( config, "use_tool_dependencies", False ):
dependency_manager_kwds = {
'default_base_path': config.tool_dependency_dir,
'conf_file': config.dependency_resolvers_config_file,
diff -r d3298df33143d829bc9e9ed5d1cae0e1c39b60b1 -r 175345aa482e4ef394e639b1a3688ee38ac84fc4 lib/galaxy/webapps/tool_shed/config.py
--- a/lib/galaxy/webapps/tool_shed/config.py
+++ b/lib/galaxy/webapps/tool_shed/config.py
@@ -59,13 +59,6 @@
self.ftp_upload_dir = kwargs.get( 'ftp_upload_dir', None )
# Install and test framework for testing tools contained in repositories.
self.num_tool_test_results_saved = kwargs.get( 'num_tool_test_results_saved', 5 )
- # Location for dependencies
- if 'tool_dependency_dir' in kwargs:
- self.tool_dependency_dir = resolve_path( kwargs.get( "tool_dependency_dir" ), self.root )
- self.use_tool_dependencies = True
- else:
- self.tool_dependency_dir = None
- self.use_tool_dependencies = False
self.update_integrated_tool_panel = False
# Galaxy flavor Docker Image
self.enable_galaxy_flavor_docker_image = string_as_bool( kwargs.get( "enable_galaxy_flavor_docker_image", "False" ) )
https://bitbucket.org/galaxy/galaxy-central/commits/50150dc1e84a/
Changeset: 50150dc1e84a
User: jmchilton
Date: 2014-12-23 18:52:39+00:00
Summary: Update XML library use during tool parsing to elimiante FutureWarnings.
Affected #: 5 files
diff -r 175345aa482e4ef394e639b1a3688ee38ac84fc4 -r 50150dc1e84a33a2a5c9d73dd7e66c5b8fdc6eb8 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -742,13 +742,13 @@
root = getattr( tool_source, "root", None )
# TODO: mucking with the XML directly like this is terrible,
# modify inputs directly post load if possible.
- if root and hasattr( self.app, "job_config" ): # toolshed may not have job_config?
- tool_id = root.get( 'id' ) if root else None
+ if root is not None and hasattr( self.app, "job_config" ): # toolshed may not have job_config?
+ tool_id = root.get( 'id' )
parameters = self.app.job_config.get_tool_resource_parameters( tool_id )
if parameters:
inputs = root.find('inputs')
# If tool has not inputs, create some so we can insert conditional
- if not inputs:
+ if inputs is None:
inputs = ElementTree.fromstring( "<inputs></inputs>")
root.append( inputs )
# Insert a conditional allowing user to specify resource parameters.
@@ -1563,7 +1563,7 @@
root = tool_source.root
conf_parent_elem = root.find("configfiles")
- if conf_parent_elem:
+ if conf_parent_elem is not None:
for conf_elem in conf_parent_elem.findall( "configfile" ):
name = conf_elem.get( "name" )
filename = conf_elem.get( "filename", None )
@@ -1697,7 +1697,7 @@
root = tool_source.root
citations = []
citations_elem = root.find("citations")
- if not citations_elem:
+ if citations_elem is None:
return citations
for citation_elem in citations_elem:
diff -r 175345aa482e4ef394e639b1a3688ee38ac84fc4 -r 50150dc1e84a33a2a5c9d73dd7e66c5b8fdc6eb8 lib/galaxy/tools/parameters/basic.py
--- a/lib/galaxy/tools/parameters/basic.py
+++ b/lib/galaxy/tools/parameters/basic.py
@@ -49,7 +49,7 @@
self.label = input_source.parse_label()
self.help = input_source.parse_help()
sanitizer_elem = input_source.parse_sanitizer_elem()
- if sanitizer_elem:
+ if sanitizer_elem is not None:
self.sanitizer = ToolParameterSanitizer.from_element( sanitizer_elem )
else:
self.sanitizer = None
diff -r 175345aa482e4ef394e639b1a3688ee38ac84fc4 -r 50150dc1e84a33a2a5c9d73dd7e66c5b8fdc6eb8 lib/galaxy/tools/parameters/input_translation.py
--- a/lib/galaxy/tools/parameters/input_translation.py
+++ b/lib/galaxy/tools/parameters/input_translation.py
@@ -59,7 +59,7 @@
append_param = None
value_trans_elem = req_param.find( 'value_translation' )
- if value_trans_elem:
+ if value_trans_elem is not None:
for value_elem in value_trans_elem.findall( 'value' ):
remote_value = value_elem.get( "remote_value" )
galaxy_value = value_elem.get( "galaxy_value" )
@@ -67,7 +67,7 @@
value_trans[ remote_value ] = galaxy_value
append_param_elem = req_param.find( "append_param" )
- if append_param_elem:
+ if append_param_elem is not None:
separator = append_param_elem.get( 'separator', ',' )
first_separator = append_param_elem.get( 'first_separator', None )
join_str = append_param_elem.get( 'join', '=' )
diff -r 175345aa482e4ef394e639b1a3688ee38ac84fc4 -r 50150dc1e84a33a2a5c9d73dd7e66c5b8fdc6eb8 lib/galaxy/tools/parameters/output.py
--- a/lib/galaxy/tools/parameters/output.py
+++ b/lib/galaxy/tools/parameters/output.py
@@ -15,7 +15,7 @@
def __init__( self, parent, config_elem ):
self.parent = parent
self.actions = []
- if config_elem:
+ if config_elem is not None:
for elem in config_elem:
if elem.tag == "conditional":
self.actions.append( ToolOutputActionConditional( self, elem ) )
diff -r 175345aa482e4ef394e639b1a3688ee38ac84fc4 -r 50150dc1e84a33a2a5c9d73dd7e66c5b8fdc6eb8 lib/galaxy/tools/parser/xml.py
--- a/lib/galaxy/tools/parser/xml.py
+++ b/lib/galaxy/tools/parser/xml.py
@@ -604,7 +604,7 @@
def __init__(self, root):
self.input_elem = root.find("inputs")
page_sources = []
- if self.input_elem:
+ if self.input_elem is not None:
pages_elem = self.input_elem.findall( "page" )
for page in ( pages_elem or [ self.input_elem ] ):
page_sources.append(XmlPageSource(page))
https://bitbucket.org/galaxy/galaxy-central/commits/cf6352cc45a4/
Changeset: cf6352cc45a4
User: jmchilton
Date: 2014-12-23 18:52:39+00:00
Summary: Start work on unit tests for galaxy.tools.ToolBox.
Affected #: 2 files
diff -r 50150dc1e84a33a2a5c9d73dd7e66c5b8fdc6eb8 -r cf6352cc45a45ffa3430d24944bd4ace50ba9c6a test/unit/tools/test_toolbox.py
--- /dev/null
+++ b/test/unit/tools/test_toolbox.py
@@ -0,0 +1,75 @@
+import os
+import unittest
+
+from galaxy.tools import ToolBox
+from galaxy.model.tool_shed_install import mapping
+import tools_support
+
+
+class ToolBoxTestCase( unittest.TestCase, tools_support.UsesApp, tools_support.UsesTools ):
+
+ def test_load_file( self ):
+ self._init_tool()
+ self.__add_config( """<toolbox><tool file="tool.xml" /></toolbox>""" )
+
+ toolbox = self.toolbox
+ assert toolbox.get_tool( "test_tool" ) is not None
+ assert toolbox.get_tool( "not_a_test_tool" ) is None
+
+ def test_load_file_in_section( self ):
+ self._init_tool()
+ self.__add_config( """<toolbox><section id="t" name="test"><tool file="tool.xml" /></section></toolbox>""" )
+
+ toolbox = self.toolbox
+ assert toolbox.get_tool( "test_tool" ) is not None
+ assert toolbox.get_tool( "not_a_test_tool" ) is None
+
+ def test_writes_integrate_tool_panel( self ):
+ self._init_tool()
+ self.__add_config( """<toolbox><tool file="tool.xml" /></toolbox>""" )
+
+ itp = os.path.join(self.test_directory, "integrated_tool_panel.xml")
+
+ assert not os.path.exists( itp )
+ self.toolbox
+ assert os.path.exists( itp )
+
+ def test_groups_tools( self ):
+ self._init_tool()
+ self.__add_config( """<toolbox><tool file="tool.xml" /></toolbox>""" )
+
+ def setUp( self ):
+ self.setup_app( mock_model=False )
+ itp_config = os.path.join(self.test_directory, "integrated_tool_panel.xml")
+ self.app.config.integrated_tool_panel_config = itp_config
+ self.__toolbox = None
+ self.config_files = []
+
+ @property
+ def toolbox( self ):
+ if self.__toolbox is None:
+ self.__toolbox = SimplifiedToolBox( self )
+ return self.__toolbox
+
+ def __add_config( self, xml, name="tool_conf.xml" ):
+ path = os.path.join( self.test_directory, "tool_conf.xml" )
+ with open( path, "w" ) as f:
+ f.write( xml )
+ self.config_files.append( path )
+
+
+class SimplifiedToolBox( ToolBox ):
+
+ def __init__( self, test_case ):
+ app = test_case.app
+ # Handle app/config stuff needed by toolbox but not by tools.
+ app.install_model = mapping.init( "sqlite:///:memory:", create_tables=True )
+ app.job_config.get_tool_resource_parameters = lambda tool_id: None
+ app.config.update_integrated_tool_panel = True
+ config_files = test_case.config_files
+ tool_root_dir = test_case.test_directory
+ super( SimplifiedToolBox, self ).__init__(
+ config_files,
+ tool_root_dir,
+ app,
+ )
diff -r 50150dc1e84a33a2a5c9d73dd7e66c5b8fdc6eb8 -r cf6352cc45a45ffa3430d24944bd4ace50ba9c6a test/unit/tools_support.py
--- a/test/unit/tools_support.py
+++ b/test/unit/tools_support.py
@@ -131,6 +131,7 @@
self.tool_data_tables = {}
self.dataset_collections_service = None
self.container_finder = NullContainerFinder()
+ self.name = "galaxy"
class MockContext(object):
https://bitbucket.org/galaxy/galaxy-central/commits/22151bb4fbca/
Changeset: 22151bb4fbca
User: jmchilton
Date: 2014-12-23 18:52:39+00:00
Summary: PEP-8 fixes to tool_shed.galaxy_install.tools.tool_panel_manager.
Affected #: 1 file
diff -r cf6352cc45a45ffa3430d24944bd4ace50ba9c6a -r 22151bb4fbca2519a7f97d71253b8890f5e9a472 lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
--- a/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
+++ b/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
@@ -1,5 +1,4 @@
import logging
-import os
import threading
import galaxy.tools
@@ -355,7 +354,7 @@
# If tool_panel_section_id is received, the section exists in the tool panel. In this
# case, the value of the received tool_panel_section_id must be the id retrieved from a
# tool panel config (e.g., tool_conf.xml, which may have getext). If new_tool_panel_section_label
- # is received, a new section will be added to the tool panel.
+ # is received, a new section will be added to the tool panel.
if new_tool_panel_section_label:
section_id = str( new_tool_panel_section_label.lower().replace( ' ', '_' ) )
tool_panel_section_key, tool_section = \
@@ -396,7 +395,6 @@
tool_section_dicts = tool_panel_dict[ tool_panel_dict.keys()[ 0 ] ]
tool_section_dict = tool_section_dicts[ 0 ]
original_section_id = tool_section_dict[ 'id' ]
- original_section_name = tool_section_dict[ 'name' ]
if original_section_id:
tool_panel_section_key, tool_section = \
self.get_or_create_tool_section( toolbox,
https://bitbucket.org/galaxy/galaxy-central/commits/c161028f01af/
Changeset: c161028f01af
User: jmchilton
Date: 2014-12-23 18:52:39+00:00
Summary: Introduce abstraction for reindexing tool search.
Fixes re-indexing after tool shed modifications for 5c44ac1 and reduces duplication.
Affected #: 2 files
diff -r 22151bb4fbca2519a7f97d71253b8890f5e9a472 -r c161028f01afc5a2aa3d5f701447fc84d1a9b578 lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -706,10 +706,7 @@
from galaxy import tools
self.toolbox = tools.ToolBox( tool_configs, self.config.tool_path, self )
- # Search support for tools
- import galaxy.tools.search
- index_help = getattr( self.config, "index_tool_help", True )
- self.toolbox_search = galaxy.tools.search.ToolBoxSearch( self.toolbox, index_help )
+ self.reindex_tool_search()
from galaxy.tools.deps import containers
galaxy_root_dir = os.path.abspath(self.config.root)
@@ -720,7 +717,13 @@
outputs_to_working_directory=self.config.outputs_to_working_directory,
container_image_cache_path=self.config.container_image_cache_path,
)
- self.container_finder = galaxy.tools.deps.containers.ContainerFinder(app_info)
+ self.container_finder = containers.ContainerFinder(app_info)
+
+ def reindex_tool_search( self ):
+ # Call this when tools are added or removed.
+ import galaxy.tools.search
+ index_help = getattr( self.config, "index_tool_help", True )
+ self.toolbox_search = galaxy.tools.search.ToolBoxSearch( self.toolbox, index_help )
def _configure_tool_data_tables( self, from_shed_config ):
from galaxy.tools.data import ToolDataTableManager
diff -r 22151bb4fbca2519a7f97d71253b8890f5e9a472 -r c161028f01afc5a2aa3d5f701447fc84d1a9b578 lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
--- a/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
+++ b/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
@@ -2,7 +2,6 @@
import threading
import galaxy.tools
-from galaxy.tools.search import ToolBoxSearch
from xml.etree import ElementTree as XmlET
from tool_shed.util import basic_util
@@ -81,7 +80,7 @@
if self.app.config.update_integrated_tool_panel:
# Write the current in-memory version of the integrated_tool_panel.xml file to disk.
self.app.toolbox.write_integrated_tool_panel_config_file()
- self.app.toolbox_search = ToolBoxSearch( self.app.toolbox )
+ self.app.reindex_tool_search()
def config_elems_to_xml_file( self, config_elems, config_filename, tool_path ):
"""
@@ -571,7 +570,7 @@
# Update the config_elems of the in-memory shed_tool_conf_dict.
shed_tool_conf_dict[ 'config_elems' ] = config_elems
self.app.toolbox.shed_tool_confs[ index ] = shed_tool_conf_dict
- self.app.toolbox_search = ToolBoxSearch( self.app.toolbox )
+ self.app.reindex_tool_search()
if uninstall and self.app.config.update_integrated_tool_panel:
# Write the current in-memory version of the integrated_tool_panel.xml file to disk.
self.app.toolbox.write_integrated_tool_panel_config_file()
https://bitbucket.org/galaxy/galaxy-central/commits/5328806e31ac/
Changeset: 5328806e31ac
User: jmchilton
Date: 2014-12-23 18:52:39+00:00
Summary: Introduce abstraction for updating ToolBox's shed configs.
Hides some details of writing out integrated tool panel, reindexing, etc... from tool shed install code and reduces duplicatation in tool shed's tool_panel_manager.
Add unit tests.
Affected #: 3 files
diff -r c161028f01afc5a2aa3d5f701447fc84d1a9b578 -r 5328806e31ac52e01f89b89d4d7873c38d9ae07b lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -244,6 +244,18 @@
return shed_config_dict
return default
+ def update_shed_config( self, shed_conf_index, shed_conf, integrated_panel_changes=True ):
+ """ Update the in-memory descriptions of tools and write out the changes
+ to integrated tool panel unless we are just deactivating a tool (since
+ that doesn't affect that file).
+ """
+ app = self.app
+ self.shed_tool_confs[ shed_conf_index ] = shed_conf
+ if integrated_panel_changes and app.config.update_integrated_tool_panel:
+ # Write the current in-memory version of the integrated_tool_panel.xml file to disk.
+ self.write_integrated_tool_panel_config_file()
+ app.reindex_tool_search()
+
def __resolve_tool_path(self, tool_path, config_filename):
if not tool_path:
# Default to backward compatible config setting.
diff -r c161028f01afc5a2aa3d5f701447fc84d1a9b578 -r 5328806e31ac52e01f89b89d4d7873c38d9ae07b lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
--- a/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
+++ b/lib/tool_shed/galaxy_install/tools/tool_panel_manager.py
@@ -76,11 +76,7 @@
guid=guid )
# Replace the old list of in-memory config_elems with the new list for this shed_tool_conf_dict.
shed_tool_conf_dict[ 'config_elems' ] = config_elems
- self.app.toolbox.shed_tool_confs[ index ] = shed_tool_conf_dict
- if self.app.config.update_integrated_tool_panel:
- # Write the current in-memory version of the integrated_tool_panel.xml file to disk.
- self.app.toolbox.write_integrated_tool_panel_config_file()
- self.app.reindex_tool_search()
+ self.app.toolbox.update_shed_config( index, shed_tool_conf_dict )
def config_elems_to_xml_file( self, config_elems, config_filename, tool_path ):
"""
@@ -569,8 +565,4 @@
config_elems.remove( config_elem )
# Update the config_elems of the in-memory shed_tool_conf_dict.
shed_tool_conf_dict[ 'config_elems' ] = config_elems
- self.app.toolbox.shed_tool_confs[ index ] = shed_tool_conf_dict
- self.app.reindex_tool_search()
- if uninstall and self.app.config.update_integrated_tool_panel:
- # Write the current in-memory version of the integrated_tool_panel.xml file to disk.
- self.app.toolbox.write_integrated_tool_panel_config_file()
+ self.app.toolbox.update_shed_config( index, shed_tool_conf_dict, integrated_panel_changes=uninstall )
diff -r c161028f01afc5a2aa3d5f701447fc84d1a9b578 -r 5328806e31ac52e01f89b89d4d7873c38d9ae07b test/unit/tools/test_toolbox.py
--- a/test/unit/tools/test_toolbox.py
+++ b/test/unit/tools/test_toolbox.py
@@ -28,23 +28,53 @@
self._init_tool()
self.__add_config( """<toolbox><tool file="tool.xml" /></toolbox>""" )
- itp = os.path.join(self.test_directory, "integrated_tool_panel.xml")
-
- assert not os.path.exists( itp )
+ self.assert_integerated_tool_panel(exists=False)
self.toolbox
- assert os.path.exists( itp )
+ self.assert_integerated_tool_panel(exists=True)
def test_groups_tools( self ):
self._init_tool()
self.__add_config( """<toolbox><tool file="tool.xml" /></toolbox>""" )
+ def test_update_shed_conf(self):
+ self.__setup_shed_tool_conf()
+ self.toolbox.update_shed_config( 0, {} )
+ assert self.reindexed
+ self.assert_integerated_tool_panel(exists=True)
+
+ def test_update_shed_conf_deactivate_only(self):
+ self.__setup_shed_tool_conf()
+ self.toolbox.update_shed_config( 0, {}, integrated_panel_changes=False )
+ assert self.reindexed
+ # No changes, should be regenerated
+ self.assert_integerated_tool_panel(exists=False)
+
def setUp( self ):
+ self.reindexed = False
self.setup_app( mock_model=False )
+ self.app.reindex_tool_search = self.__reindex
itp_config = os.path.join(self.test_directory, "integrated_tool_panel.xml")
self.app.config.integrated_tool_panel_config = itp_config
self.__toolbox = None
self.config_files = []
+ def __reindex( self ):
+ self.reindexed = True
+
+ def __remove_itp( self ):
+ os.remove( os.path)
+
+ @property
+ def integerated_tool_panel_path( self ):
+ return os.path.join(self.test_directory, "integrated_tool_panel.xml")
+
+ def assert_integerated_tool_panel( self, exists=True ):
+ does_exist = os.path.exists( self.integerated_tool_panel_path )
+ if exists:
+ assert does_exist
+ else:
+ assert not does_exist
+
@property
def toolbox( self ):
if self.__toolbox is None:
@@ -57,6 +87,14 @@
f.write( xml )
self.config_files.append( path )
+ def __setup_shed_tool_conf( self ):
+ self.__add_config( """<toolbox tool_path="."></toolbox>""" )
+
+ self.toolbox # create toolbox
+ assert not self.reindexed
+
+ os.remove( self.integerated_tool_panel_path )
+
class SimplifiedToolBox( ToolBox ):
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/3131a76ddd93/
Changeset: 3131a76ddd93
User: carlfeberhard
Date: 2014-12-22 19:58:44+00:00
Summary: merge
Affected #: 29 files
diff -r 1aa8a57c599455b2a9faeeadb980b62b8abecc1f -r 3131a76ddd932911a80838d83aaf71baf26a3d6f lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -254,6 +254,11 @@
"""
Get a History from the database by id, verifying ownership.
"""
+ if trans.user is None and trans.history:
+ if id == trans.security.encode_id( trans.history.id ):
+ return trans.history
+ raise ItemOwnershipException( "Must be logged in to manage Galaxy items", type='error' )
+
history = self.get_object( trans, id, 'History',
check_ownership=check_ownership, check_accessible=check_accessible, deleted=deleted )
history = self.security_check( trans, history, check_ownership, check_accessible )
diff -r 1aa8a57c599455b2a9faeeadb980b62b8abecc1f -r 3131a76ddd932911a80838d83aaf71baf26a3d6f test/casperjs/anon-history-tests.js
--- a/test/casperjs/anon-history-tests.js
+++ b/test/casperjs/anon-history-tests.js
@@ -7,127 +7,110 @@
spaceghost.test.begin( 'Testing histories for anonymous users', 0, function suite( test ){
spaceghost.start();
-// ===================================================================
+ // ===================================================================
+ var email = spaceghost.user.getRandomEmail(),
+ password = '123456';
+ if( spaceghost.fixtureData.testUser ){
+ email = spaceghost.fixtureData.testUser.email;
+ password = spaceghost.fixtureData.testUser.password;
+ spaceghost.info( 'Will use fixtureData.testUser: ' + email );
+ }
-var email = spaceghost.user.getRandomEmail(),
- password = '123456';
-if( spaceghost.fixtureData.testUser ){
- email = spaceghost.fixtureData.testUser.email;
- password = spaceghost.fixtureData.testUser.password;
- spaceghost.info( 'Will use fixtureData.testUser: ' + email );
-}
+ var editableTextClass = spaceghost.data.selectors.editableText,
+ editableTextInput = spaceghost.data.selectors.editableTextInput,
-var tooltipSelector = spaceghost.data.selectors.tooltipBalloon,
- editableTextClass = spaceghost.data.selectors.editableText,
- editableTextInput = spaceghost.data.selectors.editableTextInput,
+ unnamedName = spaceghost.historypanel.data.text.history.newName,
+ nameSelector = spaceghost.historypanel.data.selectors.history.name,
+ sizeSelector = spaceghost.historypanel.data.selectors.history.size,
+ initialSizeStr = spaceghost.historypanel.data.text.history.newSize,
+ tagIconSelector = spaceghost.historypanel.data.selectors.history.tagIcon,
+ annoIconSelector = spaceghost.historypanel.data.selectors.history.annoIcon,
+ emptyMsgSelector = spaceghost.historypanel.data.selectors.history.emptyMsg,
+ emptyMsgStr = spaceghost.historypanel.data.text.history.emptyMsg;
- unnamedName = spaceghost.historypanel.data.text.history.newName,
- nameSelector = spaceghost.historypanel.data.selectors.history.name,
- sizeSelector = spaceghost.historypanel.data.selectors.history.size,
- initialSizeStr = spaceghost.historypanel.data.text.history.newSize,
- tagIconSelector = spaceghost.historypanel.data.selectors.history.tagIcon,
- annoIconSelector = spaceghost.historypanel.data.selectors.history.annoIcon,
- emptyMsgSelector = spaceghost.historypanel.data.selectors.history.emptyMsg,
- emptyMsgStr = spaceghost.historypanel.data.text.history.emptyMsg,
- anonNameTooltip = spaceghost.historypanel.data.text.anonymous.tooltips.name;
+ var filenameToUpload = '1.txt',
+ filepathToUpload = '../../test-data/' + filenameToUpload;
-var historyFrameInfo = {},
- filenameToUpload = '1.txt',
- filepathToUpload = '../../test-data/' + filenameToUpload,
- testUploadedId = null,
- testUploadInfo = {};
+ // ------------------------------------------------------------------- check the anonymous new, history for form
+ spaceghost.openHomePage().historypanel.waitForHdas( function testPanelStructure(){
+ this.test.comment( 'history panel for anonymous user, new history' );
+ this.test.comment( "history name should exist, be visible, and have text " + unnamedName );
+ this.test.assertExists( nameSelector, nameSelector + ' exists' );
+ this.test.assertVisible( nameSelector, 'History name is visible' );
+ this.test.assertSelectorHasText( nameSelector, unnamedName, 'History name is ' + unnamedName );
-// =================================================================== TESTS
-// ------------------------------------------------------------------- check the anonymous new, history for form
-spaceghost.openHomePage().historypanel.waitForHdas( function testPanelStructure(){
- this.test.comment( 'history panel for anonymous user, new history' );
+ this.test.comment( "history should display size and size should be 0 bytes" );
+ this.test.assertExists( sizeSelector, 'Found ' + sizeSelector );
+ this.test.assertVisible( sizeSelector, 'History size is visible' );
+ this.test.assertSelectorHasText( sizeSelector, initialSizeStr,
+ 'History size has "' + initialSizeStr + '"' );
- this.test.comment( "history name should exist, be visible, and have text " + unnamedName );
- this.test.assertExists( nameSelector, nameSelector + ' exists' );
- this.test.assertVisible( nameSelector, 'History name is visible' );
- this.test.assertSelectorHasText( nameSelector, unnamedName, 'History name is ' + unnamedName );
+ this.test.comment( "NO tags or annotations icons should be available for an anonymous user" );
+ this.test.assertDoesntExist( tagIconSelector, 'Tag icon button not found' );
+ this.test.assertDoesntExist( annoIconSelector, 'Annotation icon button not found' );
- this.test.comment( "history should display size and size should be 0 bytes" );
- this.test.assertExists( sizeSelector, 'Found ' + sizeSelector );
- this.test.assertVisible( sizeSelector, 'History size is visible' );
- this.test.assertSelectorHasText( sizeSelector, initialSizeStr,
- 'History size has "' + initialSizeStr + '"' );
-
- this.test.comment( "NO tags or annotations icons should be available for an anonymous user" );
- this.test.assertDoesntExist( tagIconSelector, 'Tag icon button not found' );
- this.test.assertDoesntExist( annoIconSelector, 'Annotation icon button not found' );
-
- this.test.assertExists( emptyMsgSelector, emptyMsgSelector + ' exists' );
- this.test.comment( "A message about the current history being empty should be displayed" );
- this.test.assertVisible( emptyMsgSelector, 'Empty history message is visible' );
- this.test.assertSelectorHasText( emptyMsgSelector, emptyMsgStr,
- 'Message contains "' + emptyMsgStr + '"' );
-
- this.test.comment( 'name should NOT be editable when clicked by anon-user' );
- this.assertDoesntHaveClass( nameSelector, editableTextClass, "Name field is not classed as editable text" );
- this.click( nameSelector );
- this.test.assertDoesntExist( editableTextInput, "Clicking on name does not create an input" );
-});
-
-// ------------------------------------------------------------------- anon user can upload file
-spaceghost.then( function testAnonUpload(){
- this.test.comment( 'anon-user should be able to upload files' );
-
- var currHistory = spaceghost.api.histories.index()[0];
- spaceghost.api.tools.thenUpload( currHistory.id, {
- filepath: filepathToUpload
- }, function uploadCallback( uploadedId ){
- testUploadedId = uploadedId;
- });
-});
-spaceghost.openHomePage().historypanel.waitForHdas( function testAnonUpload(){
- this.test.comment( 'uploaded files should be well formed in the panel' );
-
- var hdaElement = spaceghost.getElementInfo( '#dataset-' + testUploadedId );
- this.debug( 'uploaded HDA info: ' + this.jsonStr( this.quickInfo( hdaElement ) ) );
-
- var hasHda = hdaElement,
- hasClass = hdaElement.attributes[ 'class' ],
- hasOkClass = hdaElement.attributes[ 'class' ].indexOf( 'state-ok' ) !== -1;
- this.test.assert( ( hasHda && hasClass && hasOkClass ), "Uploaded file: " + hdaElement.text );
- testUploadInfo = hdaElement;
-});
-spaceghost.then( function testAnonUpload(){
- this.test.comment( "empty should be NO LONGER be displayed" );
- this.test.assertNotVisible( emptyMsgSelector, 'Empty history message is not visible' );
-});
-
-// ------------------------------------------------------------------- anon user can run tool on file
-
-// ------------------------------------------------------------------- anon user registers/logs in -> same history
-spaceghost.user.loginOrRegisterUser( email, password ).openHomePage( function(){
- this.test.comment( 'anon-user should login and be associated with previous history' );
-
- var loggedInAs = spaceghost.user.loggedInAs();
- this.test.assert( loggedInAs === email, 'loggedInAs() matches email: "' + loggedInAs + '"' );
-
- this.historypanel.waitForHdas( function(){
- var hdaInfo = this.historypanel.hdaElementInfoByTitle( filenameToUpload );
- this.test.assert( hdaInfo !== null, "After logging in - found a matching hda by name and hid" );
- if( hdaInfo ){
- this.test.assert( testUploadInfo.attributes.id === hdaInfo.attributes.id,
- "After logging in - found a matching hda by hda view id: " + hdaInfo.attributes.id );
- }
- });
-});
-
-// ------------------------------------------------------------------- logs out -> new history
-spaceghost.user.logout().openHomePage( function(){
- this.test.comment( 'logging out should create a new, anonymous history' );
-
- this.historypanel.waitForHdas( function(){
- this.test.assertSelectorHasText( nameSelector, unnamedName, 'History name is ' + unnamedName );
+ this.test.assertExists( emptyMsgSelector, emptyMsgSelector + ' exists' );
+ this.test.comment( "A message about the current history being empty should be displayed" );
+ this.test.assertVisible( emptyMsgSelector, 'Empty history message is visible' );
this.test.assertSelectorHasText( emptyMsgSelector, emptyMsgStr,
'Message contains "' + emptyMsgStr + '"' );
+
+ this.test.comment( 'name should NOT be editable when clicked by anon-user' );
+ this.assertDoesntHaveClass( nameSelector, editableTextClass, "Name field is not classed as editable text" );
+ this.click( nameSelector );
+ this.test.assertDoesntExist( editableTextInput, "Clicking on name does not create an input" );
});
-});
-// ===================================================================
+ // ------------------------------------------------------------------- anon user can upload file
+ var uploadedId = null;
+ spaceghost.api.tools.thenUploadToCurrent({ filepath: filepathToUpload }, function( id, json ){
+ uploadedId = id;
+ });
+ spaceghost.openHomePage().historypanel.waitForHdas( function testAnonUpload(){
+ this.test.comment( 'anon-user should be able to upload files' );
+ this.test.assertExists( '#dataset-' + uploadedId, "found hda" );
+ var hdaElement = this.elementInfoOrNull( '#dataset-' + uploadedId );
+ this.debug( 'hdaElement: ' + hdaElement );
+ if( hdaElement ){
+ this.test.assert( hdaElement.attributes[ 'class' ].indexOf( 'state-ok' ) !== -1,
+ "Uploaded file: " + hdaElement.text );
+ }
+
+ this.test.comment( "empty should be NO LONGER be displayed" );
+ this.test.assertNotVisible( emptyMsgSelector, 'Empty history message is not visible' );
+ });
+
+ // ------------------------------------------------------------------- anon user can run tool on file
+
+ // ------------------------------------------------------------------- anon user registers/logs in -> same history
+ spaceghost.user.loginOrRegisterUser( email, password ).openHomePage( function(){
+ this.test.comment( 'anon-user should login and be associated with previous history' );
+
+ var loggedInAs = spaceghost.user.loggedInAs();
+ this.test.assert( loggedInAs === email, 'loggedInAs() matches email: "' + loggedInAs + '"' );
+
+ this.historypanel.waitForHdas( function(){
+ var hdaInfo = this.historypanel.hdaElementInfoByTitle( filenameToUpload );
+ this.test.assert( hdaInfo !== null, "After logging in - found a matching hda by name and hid" );
+ if( hdaInfo ){
+ this.test.assert( 'dataset-' + uploadedId === hdaInfo.attributes.id,
+ "After logging in - found a matching hda by hda view id: " + hdaInfo.attributes.id );
+ }
+ });
+ });
+
+ // ------------------------------------------------------------------- logs out -> new history
+ spaceghost.user.logout().openHomePage( function(){
+ this.test.comment( 'logging out should create a new, anonymous history' );
+
+ this.historypanel.waitForHdas( function(){
+ this.test.assertSelectorHasText( nameSelector, unnamedName, 'History name is ' + unnamedName );
+ this.test.assertSelectorHasText( emptyMsgSelector, emptyMsgStr,
+ 'Message contains "' + emptyMsgStr + '"' );
+ });
+ });
+
+ // ===================================================================
spaceghost.run( function(){ test.done(); });
});
diff -r 1aa8a57c599455b2a9faeeadb980b62b8abecc1f -r 3131a76ddd932911a80838d83aaf71baf26a3d6f test/casperjs/api-anon-history-permission-tests.js
--- a/test/casperjs/api-anon-history-permission-tests.js
+++ b/test/casperjs/api-anon-history-permission-tests.js
@@ -8,195 +8,194 @@
+ 'with anonymous users over the API', 0, function suite( test ){
spaceghost.start();
-// =================================================================== SET UP
-var email = spaceghost.user.getRandomEmail(),
- password = '123456';
-if( spaceghost.fixtureData.testUser ){
- email = spaceghost.fixtureData.testUser.email;
- password = spaceghost.fixtureData.testUser.password;
-}
-var inaccessibleHistory, accessibleHistory, publishedHistory,
- inaccessibleHdas, accessibleHdas, publishedHdas,
- accessibleLink;
+ // =================================================================== SET UP
+ var email = spaceghost.user.getRandomEmail(),
+ password = '123456';
+ if( spaceghost.fixtureData.testUser ){
+ email = spaceghost.fixtureData.testUser.email;
+ password = spaceghost.fixtureData.testUser.password;
+ }
+ var inaccessibleHistory, accessibleHistory, publishedHistory,
+ inaccessibleHdas, accessibleHdas, publishedHdas;
-//// ------------------------------------------------------------------------------------------- create 3 histories
-spaceghost.user.loginOrRegisterUser( email, password );
-spaceghost.thenOpen( spaceghost.baseUrl ).then( function(){
- // create three histories: make the 2nd importable (via the API), and the third published
+ //// ------------------------------------------------------------------------------------------- create 3 histories
+ spaceghost.user.loginOrRegisterUser( email, password );
+ spaceghost.openHomePage().then( function(){
+ // create three histories: make the 2nd importable (via the API), and the third published
- // make the current the inaccessible one
- inaccessibleHistory = this.api.histories.index()[0];
- this.api.histories.update( inaccessibleHistory.id, { name: 'inaccessible' });
- inaccessibleHistory = this.api.histories.index()[0];
+ // make the current the inaccessible one
+ inaccessibleHistory = this.api.histories.index()[0];
+ this.api.histories.update( inaccessibleHistory.id, { name: 'inaccessible' });
+ inaccessibleHistory = this.api.histories.index()[0];
- accessibleHistory = this.api.histories.create({ name: 'accessible' });
- var returned = this.api.histories.update( accessibleHistory.id, {
- importable : true
+ accessibleHistory = this.api.histories.create({ name: 'accessible' });
+ var returned = this.api.histories.update( accessibleHistory.id, {
+ importable : true
+ });
+ //this.debug( this.jsonStr( returned ) );
+ accessibleHistory = this.api.histories.show( accessibleHistory.id );
+
+ publishedHistory = this.api.histories.create({ name: 'published' });
+ returned = this.api.histories.update( publishedHistory.id, {
+ published : true
+ });
+ //this.debug( this.jsonStr( returned ) );
+ publishedHistory = this.api.histories.show( publishedHistory.id );
+
});
- //this.debug( this.jsonStr( returned ) );
- accessibleHistory = this.api.histories.show( accessibleHistory.id );
- publishedHistory = this.api.histories.create({ name: 'published' });
- returned = this.api.histories.update( publishedHistory.id, {
- published : true
+ //// ------------------------------------------------------------------------------------------- upload some files
+ spaceghost.then( function(){
+ this.api.tools.thenUpload( inaccessibleHistory.id, { filepath: '../../test-data/1.bed' });
+ this.api.tools.thenUpload( accessibleHistory.id, { filepath: '../../test-data/1.bed' });
+ this.api.tools.thenUpload( publishedHistory.id, { filepath: '../../test-data/1.bed' });
});
- //this.debug( this.jsonStr( returned ) );
- publishedHistory = this.api.histories.show( publishedHistory.id );
+ spaceghost.then( function(){
+ // check that they're there
+ inaccessibleHdas = this.api.hdas.index( inaccessibleHistory.id ),
+ accessibleHdas = this.api.hdas.index( accessibleHistory.id ),
+ publishedHdas = this.api.hdas.index( publishedHistory.id );
+ });
+ spaceghost.user.logout();
-});
+ // =================================================================== TESTS
+ //// ------------------------------------------------------------------------------------------- anon user
+ function testAnonReadFunctionsOnAccessible( history, hdas ){
+ this.test.comment( '---- testing read/accessibility functions for ACCESSIBLE history: ' + history.name );
-//// ------------------------------------------------------------------------------------------- upload some files
-spaceghost.then( function(){
- this.api.tools.thenUpload( inaccessibleHistory.id, { filepath: '../../test-data/1.bed' });
- this.api.tools.thenUpload( accessibleHistory.id, { filepath: '../../test-data/1.bed' });
- this.api.tools.thenUpload( publishedHistory.id, { filepath: '../../test-data/1.bed' });
-});
-spaceghost.then( function(){
- // check that they're there
- inaccessibleHdas = this.api.hdas.index( inaccessibleHistory.id ),
- accessibleHdas = this.api.hdas.index( accessibleHistory.id ),
- publishedHdas = this.api.hdas.index( publishedHistory.id );
-});
-spaceghost.user.logout();
+ // read functions for history
+ this.test.comment( 'show should work for history: ' + history.name );
+ this.test.assert( this.api.histories.show( history.id ).id === history.id,
+ 'show worked' );
+ this.test.comment( 'copying should fail for history (multiple histories not allowed): ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.histories.create({ history_id : history.id });
+ }, 403, 'API authentication required for this request', 'update authentication required' );
-// =================================================================== TESTS
-//// ------------------------------------------------------------------------------------------- anon user
-function testAnonReadFunctionsOnAccessible( history, hdas ){
- this.test.comment( '---- testing read/accessibility functions for ACCESSIBLE history: ' + history.name );
+ // read functions for history contents
+ this.test.comment( 'index of history contents should work for history: ' + history.name );
+ this.test.assert( this.api.hdas.index( history.id ).length === 1,
+ 'hda index worked' );
+ this.test.comment( 'showing of history contents should work for history: ' + history.name );
+ this.test.assert( this.api.hdas.show( history.id, hdas[0].id ).id === hdas[0].id,
+ 'hda show worked' );
- // read functions for history
- this.test.comment( 'show should work for history: ' + history.name );
- this.test.assert( this.api.histories.show( history.id ).id === history.id,
- 'show worked' );
- this.test.comment( 'copying should fail for history (multiple histories not allowed): ' + history.name );
- this.api.assertRaises( function(){
- this.api.histories.create({ history_id : history.id });
- }, 403, 'API authentication required for this request', 'update authentication required' );
-
- // read functions for history contents
- this.test.comment( 'index of history contents should work for history: ' + history.name );
- this.test.assert( this.api.hdas.index( history.id ).length === 1,
- 'hda index worked' );
- this.test.comment( 'showing of history contents should work for history: ' + history.name );
- this.test.assert( this.api.hdas.show( history.id, hdas[0].id ).id === hdas[0].id,
- 'hda show worked' );
-
- this.test.comment( 'Attempting to copy an accessible hda (default is accessible)'
- + ' should work from accessible history: ' + history.name );
- this.api.hdas.create( this.api.histories.index()[0].id, {
- source : 'hda',
- content : hdas[0].id
- });
-}
-
-function testAnonReadFunctionsOnInaccessible( history, hdas ){
- this.test.comment( '---- testing read/accessibility functions for INACCESSIBLE history: ' + history.name );
-
- // read functions for history
- this.test.comment( 'show should fail for history: ' + history.name );
- this.api.assertRaises( function(){
- this.api.histories.show( history.id );
- }, 403, 'History is not accessible to the current user', 'show failed with error' );
- this.test.comment( 'copying should fail for history (implicit multiple histories): ' + history.name );
- this.api.assertRaises( function(){
- this.api.histories.create({ history_id : history.id });
- }, 403, 'API authentication required for this request', 'copy failed with error' );
-
- // read functions for history contents
- this.test.comment( 'index and show of history contents should fail for history: ' + history.name );
- this.api.assertRaises( function(){
- this.api.hdas.index( history.id );
- }, 403, 'History is not accessible to the current user', 'hda index failed with error' );
- this.api.assertRaises( function(){
- this.api.hdas.show( history.id, hdas[0].id );
- }, 403, 'History is not accessible to the current user', 'hda show failed with error' );
-
- this.test.comment( 'Attempting to copy an accessible hda (default is accessible)'
- + ' from an inaccessible history should fail for: ' + history.name );
- this.api.assertRaises( function(){
- var returned = this.api.hdas.create( this.api.histories.index()[0].id, {
+ this.test.comment( 'Attempting to copy an accessible hda (default is accessible)'
+ + ' should work from accessible history: ' + history.name );
+ this.api.hdas.create( this.api.histories.index()[0].id, {
source : 'hda',
content : hdas[0].id
});
- this.debug( this.jsonStr( returned ) );
- }, 403, 'History is not accessible to the current user', 'hda copy from failed with error' );
+ }
-}
+ function testAnonReadFunctionsOnInaccessible( history, hdas ){
+ this.test.comment( '---- testing read/accessibility functions for INACCESSIBLE history: ' + history.name );
-function testAnonWriteFunctions( history, hdas ){
- this.test.comment( '---- testing write/ownership functions for history: ' + history.name );
+ // read functions for history
+ this.test.comment( 'show should fail for history: ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.histories.show( history.id );
+ }, 403, 'History is not accessible to the current user', 'show failed with error' );
+ this.test.comment( 'copying should fail for history (implicit multiple histories): ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.histories.create({ history_id : history.id });
+ }, 403, 'API authentication required for this request', 'copy failed with error' );
- this.test.comment( 'update should fail for history: ' + history.name );
- this.api.assertRaises( function(){
- this.api.histories.update( history.id, { deleted: true });
- }, 403, 'API authentication required for this request', 'update authentication required' );
- this.test.comment( 'delete should fail for history: ' + history.name );
- this.api.assertRaises( function(){
- this.api.histories.delete_( history.id );
- }, 403, 'API authentication required for this request', 'delete authentication required' );
+ // read functions for history contents
+ this.test.comment( 'index and show of history contents should fail for history: ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.hdas.index( history.id );
+ }, 403, 'History is not accessible to the current user', 'hda index failed with error' );
+ this.api.assertRaises( function(){
+ this.api.hdas.show( history.id, hdas[0].id );
+ }, 403, 'History is not accessible to the current user', 'hda show failed with error' );
- this.test.comment( 'hda updating should fail for history: ' + history.name );
- this.api.assertRaises( function(){
- this.api.hdas.update( history.id, hdas[0].id, { deleted: true });
- // anon hda update fails w/ this msg if trying to update non-current history hda
- }, 403, 'You must be logged in to update this history', 'hda update failed with error' );
- this.test.comment( 'hda deletion should fail for history: ' + history.name );
- this.api.assertRaises( function(){
- this.api.hdas.delete_( history.id, hdas[0].id );
- }, 403, 'API authentication required for this request', 'hda delete failed with error' );
+ this.test.comment( 'Attempting to copy an accessible hda (default is accessible)'
+ + ' from an inaccessible history should fail for: ' + history.name );
+ this.api.assertRaises( function(){
+ var returned = this.api.hdas.create( this.api.histories.index()[0].id, {
+ source : 'hda',
+ content : hdas[0].id
+ });
+ this.debug( this.jsonStr( returned ) );
+ }, 403, 'History is not accessible to the current user', 'hda copy from failed with error' );
- this.test.comment( 'copying hda into history should fail for history: ' + history.name );
- this.api.assertRaises( function(){
- this.api.hdas.create( history.id, {
- source : 'hda',
- // should error before it checks the id
- content : 'bler'
+ }
+
+ function testAnonWriteFunctions( history, hdas ){
+ this.test.comment( '---- testing write/ownership functions for history: ' + history.name );
+
+ this.test.comment( 'update should fail for history: ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.histories.update( history.id, { deleted: true });
+ }, 403, 'API authentication required for this request', 'update authentication required' );
+ this.test.comment( 'delete should fail for history: ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.histories.delete_( history.id );
+ }, 403, 'API authentication required for this request', 'delete authentication required' );
+
+ this.test.comment( 'hda updating should fail for history: ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.hdas.update( history.id, hdas[0].id, { deleted: true });
+ // anon hda update fails w/ this msg if trying to update non-current history hda
+ }, 403, 'You must be logged in to update this history', 'hda update failed with error' );
+ this.test.comment( 'hda deletion should fail for history: ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.hdas.delete_( history.id, hdas[0].id );
+ }, 403, 'API authentication required for this request', 'hda delete failed with error' );
+
+ this.test.comment( 'copying hda into history should fail for history: ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.hdas.create( history.id, {
+ source : 'hda',
+ // should error before it checks the id
+ content : 'bler'
+ });
+ }, 403, 'Must be logged in to manage Galaxy histories', 'hda copy to failed' );
+ }
+
+ function testAnonInaccessible( history, hdas ){
+ testAnonReadFunctionsOnInaccessible.call( this, history, hdas );
+ testAnonWriteFunctions.call( this, history, hdas );
+ }
+
+ function testAnonAccessible( history, hdas ){
+ testAnonReadFunctionsOnAccessible.call( this, history, hdas );
+ testAnonWriteFunctions.call( this, history, hdas );
+ }
+
+ spaceghost.thenOpen( spaceghost.baseUrl ).then( function(){
+ testAnonInaccessible.call( spaceghost, inaccessibleHistory, inaccessibleHdas );
+ testAnonAccessible.call( spaceghost, accessibleHistory, accessibleHdas );
+ testAnonAccessible.call( spaceghost, publishedHistory, publishedHdas );
+ });
+
+
+ // ------------------------------------------------------------------------------------------- user1 revoke perms
+ spaceghost.user.loginOrRegisterUser( email, password );
+ spaceghost.openHomePage().then( function(){
+ this.test.comment( 'revoking perms should prevent access' );
+ this.api.histories.update( accessibleHistory.id, {
+ importable : false
});
- }, 403, 'Must be logged in to manage Galaxy histories', 'hda copy to failed' );
-}
+ var returned = this.api.histories.show( accessibleHistory.id );
-function testAnonInaccessible( history, hdas ){
- testAnonReadFunctionsOnInaccessible.call( this, history, hdas );
- testAnonWriteFunctions.call( this, history, hdas );
-}
+ this.api.histories.update( publishedHistory.id, {
+ importable : false,
+ published : false
+ });
+ returned = this.api.histories.show( publishedHistory.id );
+ });
+ spaceghost.user.logout();
-function testAnonAccessible( history, hdas ){
- testAnonReadFunctionsOnAccessible.call( this, history, hdas );
- testAnonWriteFunctions.call( this, history, hdas );
-}
-spaceghost.thenOpen( spaceghost.baseUrl ).then( function(){
- testAnonInaccessible.call( spaceghost, inaccessibleHistory, inaccessibleHdas );
- testAnonAccessible.call( spaceghost, accessibleHistory, accessibleHdas );
- testAnonAccessible.call( spaceghost, publishedHistory, publishedHdas );
-});
+ // ------------------------------------------------------------------------------------------- anon retry perms
+ spaceghost.openHomePage().then( function(){
+ testAnonInaccessible.call( spaceghost, accessibleHistory, accessibleHdas );
+ testAnonInaccessible.call( spaceghost, publishedHistory, publishedHdas );
+ });
-// ------------------------------------------------------------------------------------------- user1 revoke perms
-spaceghost.user.loginOrRegisterUser( email, password );
-spaceghost.thenOpen( spaceghost.baseUrl ).then( function(){
- this.test.comment( 'revoking perms should prevent access' );
- this.api.histories.update( accessibleHistory.id, {
- importable : false
- });
- var returned = this.api.histories.show( accessibleHistory.id );
-
- this.api.histories.update( publishedHistory.id, {
- importable : false,
- published : false
- });
- returned = this.api.histories.show( publishedHistory.id );
-});
-spaceghost.user.logout();
-
-
-// ------------------------------------------------------------------------------------------- anon retry perms
-spaceghost.thenOpen( spaceghost.baseUrl ).then( function(){
- testAnonInaccessible.call( spaceghost, accessibleHistory, accessibleHdas );
- testAnonInaccessible.call( spaceghost, publishedHistory, publishedHdas );
-});
-
-
-// ===================================================================
+ // ===================================================================
spaceghost.run( function(){ test.done(); });
});
diff -r 1aa8a57c599455b2a9faeeadb980b62b8abecc1f -r 3131a76ddd932911a80838d83aaf71baf26a3d6f test/casperjs/api-anon-history-tests.js
--- a/test/casperjs/api-anon-history-tests.js
+++ b/test/casperjs/api-anon-history-tests.js
@@ -7,125 +7,116 @@
spaceghost.test.begin( 'Test API functions for histories with an anonymous user', 0, function suite( test ){
spaceghost.start();
-// =================================================================== TESTS
-spaceghost.thenOpen( spaceghost.baseUrl ).waitForSelector( spaceghost.historypanel.data.selectors.history.name );
-spaceghost.then( function(){
+ // =================================================================== TESTS
+ spaceghost.thenOpen( spaceghost.baseUrl ).waitForSelector( spaceghost.historypanel.data.selectors.history.name );
+ spaceghost.then( function(){
- // ------------------------------------------------------------------------------------------- anon allowed
- this.test.comment( 'index should get a list of histories' );
- var index = this.api.histories.index();
- this.test.assert( utils.isArray( index ), "index returned an array: length " + index.length );
- this.test.assert( index.length === 1, 'Has at least one history' );
+ // ------------------------------------------------------------------------------------------- anon allowed
+ this.test.comment( 'index should get a list of histories' );
+ var index = this.api.histories.index();
+ this.test.assert( utils.isArray( index ), "index returned an array: length " + index.length );
+ this.test.assert( index.length === 1, 'Has at least one history' );
- this.test.comment( 'show should get a history details object' );
- var historyShow = this.api.histories.show( index[0].id );
- //this.debug( this.jsonStr( historyShow ) );
- this.test.assert( historyShow.id === index[0].id, 'Is the first history' );
- this.test.assert( this.hasKeys( historyShow, [ 'id', 'name', 'user_id' ] ) );
+ this.test.comment( 'show should get a history details object' );
+ var historyShow = this.api.histories.show( index[0].id );
+ //this.debug( this.jsonStr( historyShow ) );
+ this.test.assert( historyShow.id === index[0].id, 'Is the first history' );
+ this.test.assert( this.hasKeys( historyShow, [ 'id', 'name', 'user_id' ] ) );
- // ------------------------------------------------------------------------------------------- anon forbidden
- //TODO: why not return the current history?
- this.test.comment( 'calling show with "most_recently_used" should return None for an anon user' );
- var recent = this.api.histories.show( 'most_recently_used' );
- this.test.assert( recent === null, 'most_recently_used returned None' );
+ // ------------------------------------------------------------------------------------------- anon forbidden
+ //TODO: why not return the current history?
+ this.test.comment( 'calling show with "most_recently_used" should return None for an anon user' );
+ var recent = this.api.histories.show( 'most_recently_used' );
+ this.test.assert( recent === null, 'most_recently_used returned None' );
- this.test.comment( 'Calling create should fail for an anonymous user' );
- this.api.assertRaises( function(){
- this.api.histories.create({ name: 'new' });
- }, 403, 'API authentication required for this request', 'create failed with error' );
+ this.test.comment( 'Calling create should fail for an anonymous user' );
+ this.api.assertRaises( function(){
+ this.api.histories.create({ name: 'new' });
+ }, 403, 'API authentication required for this request', 'create failed with error' );
- this.test.comment( 'Calling delete should fail for an anonymous user' );
- this.api.assertRaises( function(){
- this.api.histories.delete_( historyShow.id );
- }, 403, 'API authentication required for this request', 'create failed with error' );
+ this.test.comment( 'Calling delete should fail for an anonymous user' );
+ this.api.assertRaises( function(){
+ this.api.histories.delete_( historyShow.id );
+ }, 403, 'API authentication required for this request', 'create failed with error' );
- this.test.comment( 'Calling update should fail for an anonymous user' );
- this.api.assertRaises( function(){
- this.api.histories.update( historyShow.id, {} );
- }, 403, 'API authentication required for this request', 'update failed with error' );
+ this.test.comment( 'Calling update should fail for an anonymous user' );
+ this.api.assertRaises( function(){
+ this.api.histories.update( historyShow.id, {} );
+ }, 403, 'API authentication required for this request', 'update failed with error' );
- //TODO: need these two in api.js
- //this.test.comment( 'Calling archive_import should fail for an anonymous user' );
- //this.api.assertRaises( function(){
- // this.api.histories.archive_import( historyShow.id, {} );
- //}, 403, 'API authentication required for this request', 'archive_import failed with error' );
+ //TODO: need these two in api.js
+ //this.test.comment( 'Calling archive_import should fail for an anonymous user' );
+ //this.api.assertRaises( function(){
+ // this.api.histories.archive_import( historyShow.id, {} );
+ //}, 403, 'API authentication required for this request', 'archive_import failed with error' );
- //this.test.comment( 'Calling archive_download should fail for an anonymous user' );
- //this.api.assertRaises( function(){
- // this.api.histories.archive_download( historyShow.id, {} );
- //}, 403, 'API authentication required for this request', 'archive_download failed with error' );
+ //this.test.comment( 'Calling archive_download should fail for an anonymous user' );
+ //this.api.assertRaises( function(){
+ // this.api.histories.archive_download( historyShow.id, {} );
+ //}, 403, 'API authentication required for this request', 'archive_download failed with error' );
- // test server bad id protection
- spaceghost.test.comment( 'A bad id should throw an error' );
- this.api.assertRaises( function(){
- this.api.histories.show( '1234123412341234' );
- }, 400, 'unable to decode', 'Bad Request with invalid id: show' );
+ // test server bad id protection
+ spaceghost.test.comment( 'A bad id should throw an error' );
+ this.api.assertRaises( function(){
+ this.api.histories.show( '1234123412341234' );
+ }, 400, 'unable to decode', 'Bad Request with invalid id: show' );
-});
+ });
-// ------------------------------------------------------------------------------------------- hdas
-spaceghost.thenOpen( spaceghost.baseUrl ).waitForSelector( spaceghost.historypanel.data.selectors.history.name );
-spaceghost.then( function(){
- var currHistory = spaceghost.api.histories.index()[0];
- spaceghost.api.tools.thenUpload( currHistory.id, {
- filepath: '../../test-data/1.sam'
- }, function( uploadedId ){
- var hda = spaceghost.api.hdas.show( currHistory.id, uploadedId );
- this.test.assert( hda.state === 'ok', "Convenience function produced hda in ok state" );
- });
-});
+ // ------------------------------------------------------------------------------------------- hdas
+ spaceghost.thenOpen( spaceghost.baseUrl ).waitForSelector( spaceghost.historypanel.data.selectors.history.name );
+ spaceghost.api.tools.thenUploadToCurrent({ filepath: '../../test-data/1.sam' });
+ spaceghost.then( function(){
+ var current = this.api.histories.index()[0];
-spaceghost.then( function(){
- var current = this.api.histories.index()[0];
+ // ------------------------------------------------------------------------------------------- anon allowed
+ this.test.comment( 'anonymous users can index hdas in their current history' );
+ var hdaIndex = this.api.hdas.index( current.id );
+ this.test.assert( hdaIndex.length === 1, 'indexed hdas' );
- // ------------------------------------------------------------------------------------------- anon allowed
- this.test.comment( 'anonymous users can index hdas in their current history' );
- var hdaIndex = this.api.hdas.index( current.id );
- this.test.assert( hdaIndex.length === 1, 'indexed hdas' );
+ this.test.comment( 'anonymous users can show hdas in their current history' );
+ var hda = this.api.hdas.show( current.id, hdaIndex[0].id );
+ this.test.assert( this.hasKeys( hda, [ 'id', 'name' ] ), 'showed hda: ' + hda.name );
- this.test.comment( 'anonymous users can show hdas in their current history' );
- var hda = this.api.hdas.show( current.id, hdaIndex[0].id );
- this.test.assert( this.hasKeys( hda, [ 'id', 'name' ] ), 'showed hda: ' + hda.name );
+ this.test.comment( 'anonymous users can hide hdas in their current history' );
+ var changed = this.api.hdas.update( current.id, hda.id, { visible: false });
+ hda = this.api.hdas.show( current.id, hda.id );
+ this.test.assert( hda.visible === false, 'successfully hidden' );
- this.test.comment( 'anonymous users can hide hdas in their current history' );
- var changed = this.api.hdas.update( current.id, hda.id, { visible: false });
- hda = this.api.hdas.show( current.id, hda.id );
- this.test.assert( hda.visible === false, 'successfully hidden' );
+ this.test.comment( 'anonymous users can mark their hdas as deleted in their current history' );
+ changed = this.api.hdas.update( current.id, hda.id, { deleted: true });
+ hda = this.api.hdas.show( current.id, hda.id );
+ this.test.assert( hda.deleted, 'successfully deleted' );
- this.test.comment( 'anonymous users can mark their hdas as deleted in their current history' );
- changed = this.api.hdas.update( current.id, hda.id, { deleted: true });
- hda = this.api.hdas.show( current.id, hda.id );
- this.test.assert( hda.deleted, 'successfully deleted' );
+ // ------------------------------------------------------------------------------------------- anon forbidden
+ this.test.comment( 'Creating an hda should work for an anonymous user' );
+ var returned = this.api.hdas.create( current.id, { source: 'hda', content: hda.id });
+ //this.debug( this.jsonStr( returned ) );
+ this.test.assert( returned.name === hda.name, 'name matches: ' + returned.name );
+ this.test.assert( returned.id !== hda.id, 'new id: ' + returned.id );
- // ------------------------------------------------------------------------------------------- anon forbidden
- this.test.comment( 'Creating an hda should work for an anonymous user' );
- var returned = this.api.hdas.create( current.id, { source: 'hda', content: hda.id });
- //this.debug( this.jsonStr( returned ) );
- this.test.assert( returned.name === hda.name, 'name matches: ' + returned.name );
- this.test.assert( returned.id !== hda.id, 'new id: ' + returned.id );
+ //TODO: should be allowed
+ this.test.comment( 'Calling hda delete should fail for an anonymous user' );
+ this.api.assertRaises( function(){
+ this.api.hdas.delete_( current.id, hda.id );
+ }, 403, 'API authentication required for this request', 'delete failed with error' );
- //TODO: should be allowed
- this.test.comment( 'Calling hda delete should fail for an anonymous user' );
- this.api.assertRaises( function(){
- this.api.hdas.delete_( current.id, hda.id );
- }, 403, 'API authentication required for this request', 'delete failed with error' );
+ //TODO: only sharing, tags, annotations should be blocked/prevented
+ this.test.comment( 'Calling update with keys other than "visible" or "deleted" should fail silently' );
+ this.test.comment( 'Calling update on tags should fail silently' );
+ changed = this.api.hdas.update( current.id, hda.id, { tags: [ 'one' ] });
+ hda = this.api.hdas.show( current.id, hda.id );
+ this.test.assert( hda.tags.length === 0, 'tags were not set: ' + this.jsonStr( hda.tags ) );
- //TODO: only sharing, tags, annotations should be blocked/prevented
- this.test.comment( 'Calling update with keys other than "visible" or "deleted" should fail silently' );
- this.test.comment( 'Calling update on tags should fail silently' );
- changed = this.api.hdas.update( current.id, hda.id, { tags: [ 'one' ] });
- hda = this.api.hdas.show( current.id, hda.id );
- this.test.assert( hda.tags.length === 0, 'tags were not set: ' + this.jsonStr( hda.tags ) );
+ this.test.comment( 'Calling update on annotation should fail silently' );
+ changed = this.api.hdas.update( current.id, hda.id, { annotation: 'yup yup yup' });
+ hda = this.api.hdas.show( current.id, hda.id );
+ this.test.assert( !hda.annotation, 'annotation was not set: ' + hda.annotation );
- this.test.comment( 'Calling update on annotation should fail silently' );
- changed = this.api.hdas.update( current.id, hda.id, { annotation: 'yup yup yup' });
- hda = this.api.hdas.show( current.id, hda.id );
- this.test.assert( !hda.annotation, 'annotation was not set: ' + hda.annotation );
+ });
-});
-
-// ===================================================================
+ // ===================================================================
spaceghost.run( function(){ test.done(); });
});
diff -r 1aa8a57c599455b2a9faeeadb980b62b8abecc1f -r 3131a76ddd932911a80838d83aaf71baf26a3d6f test/casperjs/api-configuration-tests.js
--- a/test/casperjs/api-configuration-tests.js
+++ b/test/casperjs/api-configuration-tests.js
@@ -7,57 +7,55 @@
spaceghost.test.begin( 'Test the Galaxy configuration API', 0, function suite( test ){
spaceghost.start();
-// =================================================================== SET UP
-var email = spaceghost.user.getRandomEmail(),
- password = '123456';
-if( spaceghost.fixtureData.testUser ){
- email = spaceghost.fixtureData.testUser.email;
- password = spaceghost.fixtureData.testUser.password;
-}
-spaceghost.user.loginOrRegisterUser( email, password );
+ // =================================================================== SET UP
+ var email = spaceghost.user.getRandomEmail(),
+ password = '123456';
+ if( spaceghost.fixtureData.testUser ){
+ email = spaceghost.fixtureData.testUser.email;
+ password = spaceghost.fixtureData.testUser.password;
+ }
+ spaceghost.user.loginOrRegisterUser( email, password );
-// =================================================================== TESTS
-var normKeys = [
- 'enable_unique_workflow_defaults',
- 'ftp_upload_site',
- 'ftp_upload_dir',
- 'wiki_url',
- 'support_url',
- 'logo_url',
- 'terms_url',
- 'allow_user_dataset_purge'
- ],
- adminKeys = normKeys.concat([
- 'library_import_dir',
- 'user_library_import_dir',
- 'allow_library_path_paste',
- 'allow_user_creation',
- 'allow_user_deletion'
- ]);
+ // =================================================================== TESTS
+ var normKeys = [
+ 'enable_unique_workflow_defaults',
+ 'ftp_upload_site',
+ 'ftp_upload_dir',
+ 'wiki_url',
+ 'support_url',
+ 'logo_url',
+ 'terms_url',
+ 'allow_user_dataset_purge'
+ ],
+ adminKeys = normKeys.concat([
+ 'library_import_dir',
+ 'user_library_import_dir',
+ 'allow_library_path_paste',
+ 'allow_user_creation',
+ 'allow_user_deletion'
+ ]);
+ // ------------------------------------------------------------------------------------------- INDEX
+ spaceghost.openHomePage().then( function(){
+ this.test.comment( 'index should get a (shortened) list of configuration settings '
+ + 'when requested by a normal user' );
-// ------------------------------------------------------------------------------------------- INDEX
-spaceghost.thenOpen( spaceghost.baseUrl ).then( function(){
+ var configIndex = this.api.configuration.index();
+ this.debug( this.jsonStr( configIndex ) );
+ this.test.assert( utils.isObject( configIndex ), "index returned an object" );
+ this.test.assert( this.hasKeys( configIndex, normKeys ), 'Has the proper keys' );
- this.test.comment( 'index should get a (shortened) list of configuration settings '
- + 'when requested by a normal user' );
- var configIndex = this.api.configuration.index();
- this.debug( this.jsonStr( configIndex ) );
- this.test.assert( utils.isObject( configIndex ), "index returned an object" );
- this.test.assert( this.hasKeys( configIndex, normKeys ), 'Has the proper keys' );
+ });
+ spaceghost.user.logout();
-});
-spaceghost.user.logout();
+ // ------------------------------------------------------------------------------------------- INDEX (admin)
+ spaceghost.tryStepsCatch( function tryAdminLogin(){
+ spaceghost.user.loginAdmin();
+ }, function(){} );
-// ------------------------------------------------------------------------------------------- INDEX (admin)
-spaceghost.tryStepsCatch( function tryAdminLogin(){
- spaceghost.user.loginAdmin();
-}, function(){} );
-
-//}, function failedLoginRegister(){
-// this.info( 'Admin level configuration API tests not run: no admin account available' );
-spaceghost.thenOpen( spaceghost.baseUrl ).then( function(){
- spaceghost.waitForMasthead( function() {
+ //}, function failedLoginRegister(){
+ // this.info( 'Admin level configuration API tests not run: no admin account available' );
+ spaceghost.openHomePage().waitForMasthead( function(){
if( spaceghost.user.userIsAdmin() ){
this.test.comment( 'index should get a (full) list of configuration settings '
+ 'when requested by an admin user' );
@@ -70,9 +68,8 @@
this.info( 'Admin level configuration API tests not run: no admin account available' );
}
});
-});
-// ===================================================================
+ // ===================================================================
spaceghost.run( function(){ test.done(); });
});
diff -r 1aa8a57c599455b2a9faeeadb980b62b8abecc1f -r 3131a76ddd932911a80838d83aaf71baf26a3d6f test/casperjs/api-hda-tests.js
--- a/test/casperjs/api-hda-tests.js
+++ b/test/casperjs/api-hda-tests.js
@@ -7,363 +7,359 @@
spaceghost.test.begin( 'Test the HDA API', 0, function suite( test ){
spaceghost.start();
-// =================================================================== SET UP
-var email = spaceghost.user.getRandomEmail(),
- password = '123456';
-if( spaceghost.fixtureData.testUser ){
- email = spaceghost.fixtureData.testUser.email;
- password = spaceghost.fixtureData.testUser.password;
-}
-spaceghost.user.loginOrRegisterUser( email, password );
+ // =================================================================== SET UP
+ var email = spaceghost.user.getRandomEmail(),
+ password = '123456';
+ if( spaceghost.fixtureData.testUser ){
+ email = spaceghost.fixtureData.testUser.email;
+ password = spaceghost.fixtureData.testUser.password;
+ }
+ spaceghost.user.loginOrRegisterUser( email, password );
-spaceghost.thenOpen( spaceghost.baseUrl, function(){
- this.test.comment( '(logged in as ' + this.user.loggedInAs() + ')' );
- this.api.tools.thenUpload( spaceghost.api.histories.index()[0].id, {
+ spaceghost.openHomePage().api.tools.thenUploadToCurrent({
filepath: '../../test-data/1.sam'
});
-});
-// =================================================================== TESTS
-var summaryKeys = [ 'id', 'name', 'history_id', 'state', 'deleted', 'purged', 'visible', 'url', 'type' ],
- detailKeys = [
- // the following are always present regardless of datatype
- 'id', 'name', 'api_type', 'model_class',
- 'history_id', 'hid',
- 'accessible', 'deleted', 'visible', 'purged',
- 'state', 'data_type', 'file_ext', 'file_size',
- 'misc_info', 'misc_blurb',
- 'download_url', 'visualizations', 'display_apps', 'display_types',
- 'genome_build',
- // the following are NOT always present DEPENDING ON datatype
- 'metadata_dbkey',
- 'metadata_column_names', 'metadata_column_types', 'metadata_columns',
- 'metadata_comment_lines', 'metadata_data_lines'
- ];
+ // =================================================================== TESTS
+ var summaryKeys = [ 'id', 'name', 'history_id', 'state', 'deleted', 'purged', 'visible', 'url', 'type' ],
+ detailKeys = [
+ // the following are always present regardless of datatype
+ 'id', 'name', 'api_type', 'model_class',
+ 'history_id', 'hid',
+ 'accessible', 'deleted', 'visible', 'purged',
+ 'state', 'data_type', 'file_ext', 'file_size',
+ 'misc_info', 'misc_blurb',
+ 'download_url', 'visualizations', 'display_apps', 'display_types',
+ 'genome_build',
+ // the following are NOT always present DEPENDING ON datatype
+ 'metadata_dbkey',
+ 'metadata_column_names', 'metadata_column_types', 'metadata_columns',
+ 'metadata_comment_lines', 'metadata_data_lines'
+ ];
-// ------------------------------------------------------------------------------------------- logged in user
-spaceghost.then( function(){
-
- // ------------------------------------------------------------------------------------------- INDEX
- this.test.comment( 'index should return a list of summary data for each hda' );
- var histories = this.api.histories.index(),
- lastHistory = histories[0],
- hdaIndex = this.api.hdas.index( lastHistory.id );
- //this.debug( 'hdaIndex:' + this.jsonStr( hdaIndex ) );
+ // ------------------------------------------------------------------------------------------- logged in user
+ spaceghost.then( function(){
+ // ------------------------------------------------------------------------------------------- INDEX
+ this.test.comment( 'index should return a list of summary data for each hda' );
+ var histories = this.api.histories.index(),
+ lastHistory = histories[0],
+ hdaIndex = this.api.hdas.index( lastHistory.id );
+ //this.debug( 'hdaIndex:' + this.jsonStr( hdaIndex ) );
- this.test.assert( utils.isArray( hdaIndex ), "index returned an array: length " + hdaIndex.length );
- this.test.assert( hdaIndex.length >= 1, 'Has at least one hda' );
+ this.test.assert( utils.isArray( hdaIndex ), "index returned an array: length " + hdaIndex.length );
+ this.test.assert( hdaIndex.length >= 1, 'Has at least one hda' );
- var firstHda = hdaIndex[0];
- this.test.assert( this.hasKeys( firstHda, summaryKeys ), 'Has the proper keys' );
+ var firstHda = hdaIndex[0];
+ this.test.assert( this.hasKeys( firstHda, summaryKeys ), 'Has the proper keys' );
- this.test.assert( this.api.isEncodedId( firstHda.id ), 'Id appears well-formed: ' + firstHda.id );
- this.test.assert( firstHda.name === '1.sam', 'Title matches: ' + firstHda.name );
+ this.test.assert( this.api.isEncodedId( firstHda.id ), 'Id appears well-formed: ' + firstHda.id );
+ this.test.assert( firstHda.name === '1.sam', 'Title matches: ' + firstHda.name );
- // ------------------------------------------------------------------------------------------- SHOW
- this.test.comment( 'show should get an HDA details object' );
- var hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- //this.debug( this.jsonStr( hdaShow ) );
- this.test.assert( this.hasKeys( hdaShow, detailKeys ), 'Has the proper keys' );
+ // ------------------------------------------------------------------------------------------- SHOW
+ this.test.comment( 'show should get an HDA details object' );
+ var hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ //this.debug( this.jsonStr( hdaShow ) );
+ this.test.assert( this.hasKeys( hdaShow, detailKeys ), 'Has the proper keys' );
- //TODO: validate data in each hdaShow attribute...
+ //TODO: validate data in each hdaShow attribute...
- // ------------------------------------------------------------------------------------------- INDEX (detailed)
- this.test.comment( 'index should return a list of detailed data for each hda in "ids" when passed' );
- hdaIndex = this.api.hdas.index( lastHistory.id, [ firstHda.id ] );
- this.debug( 'hdaIndex:' + this.jsonStr( hdaIndex ) );
+ // ------------------------------------------------------------------------------------------- INDEX (detailed)
+ this.test.comment( 'index should return a list of detailed data for each hda in "ids" when passed' );
+ hdaIndex = this.api.hdas.index( lastHistory.id, [ firstHda.id ] );
+ this.debug( 'hdaIndex:' + this.jsonStr( hdaIndex ) );
- this.test.assert( utils.isArray( hdaIndex ), "index returned an array: length " + hdaIndex.length );
- this.test.assert( hdaIndex.length >= 1, 'Has at least one hda' );
+ this.test.assert( utils.isArray( hdaIndex ), "index returned an array: length " + hdaIndex.length );
+ this.test.assert( hdaIndex.length >= 1, 'Has at least one hda' );
- firstHda = hdaIndex[0];
- this.test.assert( this.hasKeys( firstHda, detailKeys ), 'Has the proper keys' );
+ firstHda = hdaIndex[0];
+ this.test.assert( this.hasKeys( firstHda, detailKeys ), 'Has the proper keys' );
- //TODO??: validate data in firstHda attribute? we ASSUME it's from a common method as show...
+ //TODO??: validate data in firstHda attribute? we ASSUME it's from a common method as show...
- // ------------------------------------------------------------------------------------------- CREATE
- //TODO: create from_ld_id
- this.test.comment( 'create should allow copying an accessible hda' );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- var returned = this.api.hdas.create( lastHistory.id, {
- source : 'hda',
- content : hdaShow.id
+ // ------------------------------------------------------------------------------------------- CREATE
+ //TODO: create from_ld_id
+ this.test.comment( 'create should allow copying an accessible hda' );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ var returned = this.api.hdas.create( lastHistory.id, {
+ source : 'hda',
+ content : hdaShow.id
+ });
+ //this.debug( 'returned:' + this.jsonStr( returned ) );
+ this.test.assert( this.hasKeys( returned, detailKeys ), 'Has the proper keys' );
+ this.test.assert( typeof returned.id !== 'number' && isNaN( Number( returned.id ) ),
+ 'id seems to be encoded: ' + returned.id );
+ this.test.assert( typeof returned.history_id !== 'number' && isNaN( Number( returned.history_id ) ),
+ 'history_id seems to be encoded: ' + returned.history_id );
+
+
+ // ------------------------------------------------------------------------------------------- UPDATE
+ // ........................................................................................... idiot proofing
+ this.test.comment( 'updating to the current value should return no value (no change)' );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ var returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ name : hdaShow.name
+ });
+ this.test.assert( this.countKeys( returned ) === 0, "No changed returned: " + this.jsonStr( returned ) );
+
+ this.test.comment( 'updating using a nonsense key should NOT fail with an error' );
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ konamiCode : 'uuddlrlrba'
+ });
+ this.test.assert( this.countKeys( returned ) === 0, "No changed returned: " + this.jsonStr( returned ) );
+
+ this.test.comment( 'updating by attempting to change type should cause an error' );
+ this.api.assertRaises( function(){
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ //name : false
+ deleted : 'sure why not'
+ });
+ }, 400, 'deleted must be a boolean', 'changing deleted type failed' );
+
+ // ........................................................................................... name
+ this.test.comment( 'update should allow changing the name' );
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ name : 'New name'
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.name === 'New name', "Name successfully set via update: " + hdaShow.name );
+
+ this.test.comment( 'update should sanitize any new name' );
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ name : 'New name<script type="text/javascript" src="bler">alert("blah");</script>'
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.name === 'New name', "Update sanitized name: " + hdaShow.name );
+
+ this.test.comment( 'update should allow unicode in names' );
+ var unicodeName = 'Ржевский сапоги';
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ name : unicodeName
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.name === unicodeName, "Update accepted unicode name: " + hdaShow.name );
+
+ this.test.comment( 'update should allow escaped quotations in names' );
+ var quotedName = '"Bler"';
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ name : quotedName
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.name === quotedName,
+ "Update accepted escaped quotations in name: " + hdaShow.name );
+
+
+ // ........................................................................................... deleted
+ this.test.comment( 'update should allow changing the deleted flag' );
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ deleted: true
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id, true );
+ this.test.assert( hdaShow.deleted === true, "Update set the deleted flag: " + hdaShow.deleted );
+
+ this.test.comment( 'update should allow changing the deleted flag back' );
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ deleted: false
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.deleted === false, "Update set the deleted flag: " + hdaShow.deleted );
+
+
+ // ........................................................................................... visible/hidden
+ this.test.comment( 'update should allow changing the visible flag' );
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ visible: false
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.visible === false, "Update set the visible flag: " + hdaShow.visible );
+
+
+ // ........................................................................................... genome/dbkey
+ this.test.comment( 'update should allow changing the genome_build' );
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ genome_build : 'hg18'
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ //this.debug( 'hdaShow:\n' + this.jsonStr( hdaShow ) );
+ this.test.assert( hdaShow.genome_build === 'hg18',
+ "genome_build successfully set via update: " + hdaShow.genome_build );
+ this.test.assert( hdaShow.metadata_dbkey === 'hg18',
+ "metadata_dbkey successfully set via the same update: " + hdaShow.metadata_dbkey );
+ this.test.comment( 'update should sanitize any genome_build' );
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ genome_build : 'hg18<script type="text/javascript" src="bler">alert("blah");</script>'
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.genome_build === 'hg18',
+ "Update sanitized genome_build: " + hdaShow.genome_build );
+ this.test.assert( hdaShow.metadata_dbkey === 'hg18',
+ "metadata_dbkey successfully set via the same update: " + hdaShow.metadata_dbkey );
+
+ this.test.comment( 'update should allow unicode in genome builds' );
+ var unicodeBuild = 'Ржевский18';
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ genome_build : unicodeBuild
+ });
+ this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.debug( 'hdaShow:\n' + this.jsonStr( hdaShow ) );
+ this.test.assert( hdaShow.genome_build === unicodeBuild,
+ "Update accepted unicode genome_build: " + hdaShow.genome_build );
+
+ // ........................................................................................... misc_info/info
+ this.test.comment( 'update should allow changing the misc_info' );
+ var newInfo = 'I\'ve made a huge mistake.';
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ misc_info : newInfo
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.misc_info === newInfo,
+ "misc_info successfully set via update: " + hdaShow.misc_info );
+
+ this.test.comment( 'update should sanitize any misc_info' );
+ var newInfo = 'You\'re going to get hop-ons.';
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ misc_info : newInfo + '<script type="text/javascript" src="bler">alert("blah");</script>'
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.misc_info === newInfo,
+ "Update sanitized misc_info: " + hdaShow.misc_info );
+
+ this.test.comment( 'update should allow unicode in misc_info' );
+ var unicodeInfo = '여보!';
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ misc_info : unicodeInfo
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.misc_info === unicodeInfo,
+ "Update accepted unicode misc_info: " + hdaShow.misc_info );
+
+ // ........................................................................................... annotation
+ // currently fails because no annotation is returned in details
+ this.test.comment( 'update should allow changing the annotation' );
+ var newAnnotation = 'Found this sample on a movie theatre floor';
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ annotation : newAnnotation
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.annotation === newAnnotation,
+ "Annotation successfully set via update: " + hdaShow.annotation );
+
+ this.test.comment( 'update should sanitize any new annotation' );
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ annotation : 'New annotation<script type="text/javascript" src="bler">alert("blah");</script>'
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.annotation === 'New annotation',
+ "Update sanitized annotation: " + hdaShow.annotation );
+
+ this.test.comment( 'update should allow unicode in annotations' );
+ var unicodeAnnotation = 'お願いは、それが落下させない';
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ annotation : unicodeAnnotation
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.annotation === unicodeAnnotation,
+ "Update accepted unicode annotation: " + hdaShow.annotation );
+
+ this.test.comment( 'update should allow escaped quotations in annotations' );
+ var quotedAnnotation = '"Bler"';
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ annotation : quotedAnnotation
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.annotation === quotedAnnotation,
+ "Update accepted escaped quotations in annotation: " + hdaShow.annotation );
+
+ // ------------------------------------------------------------------------------------------- ERRORS
+ this.test.comment( 'create should error with "Please define the source" when the param "from_ld_id" is not used' );
+ this.api.assertRaises( function(){
+ this.api.hdas.create( lastHistory.id, { bler: 'bler' } );
+ }, 400, "must be either 'library' or 'hda'", 'create with no source failed' );
+
+ this.test.comment( 'updating using a nonsense key should fail silently' );
+ returned = this.api.hdas.update( lastHistory.id, hdaShow.id, {
+ konamiCode : 'uuddlrlrba'
+ });
+ this.test.assert( returned.konamiCode === undefined, 'key was not set: ' + returned.konamiCode );
+
+ spaceghost.test.comment( 'A bad id should throw an error when using show' );
+ this.api.assertRaises( function(){
+ this.api.hdas.show( lastHistory.id, '1234123412341234' );
+ }, 400, 'unable to decode', 'Bad Request with invalid id: show' );
+ spaceghost.test.comment( 'A bad id should throw an error when using update' );
+ this.api.assertRaises( function(){
+ this.api.hdas.update( lastHistory.id, '1234123412341234', {} );
+ }, 400, 'unable to decode', 'Bad Request with invalid id: update' );
+ spaceghost.test.comment( 'A bad id should throw an error when using delete' );
+ this.api.assertRaises( function(){
+ this.api.hdas.delete_( lastHistory.id, '1234123412341234' );
+ }, 400, 'unable to decode', 'Bad Request with invalid id: delete' );
+ spaceghost.test.comment( 'A bad id should throw an error when using undelete' );
+
+ this.test.comment( 'updating by attempting to change type should cause an error' );
+ [ 'name', 'annotation', 'genome_build', 'misc_info' ].forEach( function( key ){
+ var updatedAttrs = {};
+ updatedAttrs[ key ] = false;
+ spaceghost.api.assertRaises( function(){
+ returned = spaceghost.api.hdas.update( hdaShow.history_id, hdaShow.id, updatedAttrs );
+ }, 400, key + ' must be a string or unicode', 'type validation error' );
+ });
+ [ 'deleted', 'visible' ].forEach( function( key ){
+ var updatedAttrs = {};
+ updatedAttrs[ key ] = 'straaang';
+ spaceghost.api.assertRaises( function(){
+ returned = spaceghost.api.hdas.update( hdaShow.history_id, hdaShow.id, updatedAttrs );
+ }, 400, key + ' must be a boolean', 'type validation error' );
+ });
+ [ 'you\'re it', [ true ] ].forEach( function( badVal ){
+ spaceghost.api.assertRaises( function(){
+ returned = spaceghost.api.hdas.update( hdaShow.history_id, hdaShow.id, { tags: badVal });
+ }, 400, 'tags must be a list', 'type validation error' );
+ });
+
+ // ------------------------------------------------------------------------------------------- DELETE
+ this.test.comment( 'calling delete on an hda should mark it as deleted but not change the history size' );
+ lastHistory = this.api.histories.show( lastHistory.id );
+ var sizeBeforeDelete = lastHistory.nice_size;
+
+ returned = this.api.hdas.delete_( lastHistory.id, firstHda.id );
+ //this.debug( this.jsonStr( returned ) );
+
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.deleted, 'hda is marked deleted' );
+ lastHistory = this.api.histories.show( lastHistory.id );
+ this.test.assert( lastHistory.nice_size === sizeBeforeDelete, 'history size has not changed' );
+
+ // by default, purging fails bc uni.ini:allow_user_dataset_purge=False
+ this.api.assertRaises( function(){
+ returned = this.api.hdas.delete_( lastHistory.id, firstHda.id, { purge : true });
+ }, 403, 'This instance does not allow user dataset purging', 'Purge failed' );
+ /*
+ */
});
- //this.debug( 'returned:' + this.jsonStr( returned ) );
- this.test.assert( this.hasKeys( returned, detailKeys ), 'Has the proper keys' );
- this.test.assert( typeof returned.id !== 'number' && isNaN( Number( returned.id ) ),
- 'id seems to be encoded: ' + returned.id );
- this.test.assert( typeof returned.history_id !== 'number' && isNaN( Number( returned.history_id ) ),
- 'history_id seems to be encoded: ' + returned.history_id );
+ //spaceghost.user.logout();
- // ------------------------------------------------------------------------------------------- UPDATE
- // ........................................................................................... idiot proofing
- this.test.comment( 'updating to the current value should return no value (no change)' );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- var returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- name : hdaShow.name
- });
- this.test.assert( this.countKeys( returned ) === 0, "No changed returned: " + this.jsonStr( returned ) );
-
- this.test.comment( 'updating using a nonsense key should NOT fail with an error' );
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- konamiCode : 'uuddlrlrba'
- });
- this.test.assert( this.countKeys( returned ) === 0, "No changed returned: " + this.jsonStr( returned ) );
-
- this.test.comment( 'updating by attempting to change type should cause an error' );
- this.api.assertRaises( function(){
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- //name : false
- deleted : 'sure why not'
- });
- }, 400, 'deleted must be a boolean', 'changing deleted type failed' );
-
- // ........................................................................................... name
- this.test.comment( 'update should allow changing the name' );
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- name : 'New name'
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.name === 'New name', "Name successfully set via update: " + hdaShow.name );
-
- this.test.comment( 'update should sanitize any new name' );
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- name : 'New name<script type="text/javascript" src="bler">alert("blah");</script>'
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.name === 'New name', "Update sanitized name: " + hdaShow.name );
-
- this.test.comment( 'update should allow unicode in names' );
- var unicodeName = 'Ржевский сапоги';
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- name : unicodeName
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.name === unicodeName, "Update accepted unicode name: " + hdaShow.name );
-
- this.test.comment( 'update should allow escaped quotations in names' );
- var quotedName = '"Bler"';
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- name : quotedName
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.name === quotedName,
- "Update accepted escaped quotations in name: " + hdaShow.name );
-
-
- // ........................................................................................... deleted
- this.test.comment( 'update should allow changing the deleted flag' );
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- deleted: true
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id, true );
- this.test.assert( hdaShow.deleted === true, "Update set the deleted flag: " + hdaShow.deleted );
-
- this.test.comment( 'update should allow changing the deleted flag back' );
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- deleted: false
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.deleted === false, "Update set the deleted flag: " + hdaShow.deleted );
-
-
- // ........................................................................................... visible/hidden
- this.test.comment( 'update should allow changing the visible flag' );
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- visible: false
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.visible === false, "Update set the visible flag: " + hdaShow.visible );
-
-
- // ........................................................................................... genome_build/dbkey
- this.test.comment( 'update should allow changing the genome_build' );
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- genome_build : 'hg18'
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- //this.debug( 'hdaShow:\n' + this.jsonStr( hdaShow ) );
- this.test.assert( hdaShow.genome_build === 'hg18',
- "genome_build successfully set via update: " + hdaShow.genome_build );
- this.test.assert( hdaShow.metadata_dbkey === 'hg18',
- "metadata_dbkey successfully set via the same update: " + hdaShow.metadata_dbkey );
- this.test.comment( 'update should sanitize any genome_build' );
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- genome_build : 'hg18<script type="text/javascript" src="bler">alert("blah");</script>'
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.genome_build === 'hg18',
- "Update sanitized genome_build: " + hdaShow.genome_build );
- this.test.assert( hdaShow.metadata_dbkey === 'hg18',
- "metadata_dbkey successfully set via the same update: " + hdaShow.metadata_dbkey );
-
- this.test.comment( 'update should allow unicode in genome builds' );
- var unicodeBuild = 'Ржевский18';
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- genome_build : unicodeBuild
- });
- this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.debug( 'hdaShow:\n' + this.jsonStr( hdaShow ) );
- this.test.assert( hdaShow.genome_build === unicodeBuild,
- "Update accepted unicode genome_build: " + hdaShow.genome_build );
-
- // ........................................................................................... misc_info/info
- this.test.comment( 'update should allow changing the misc_info' );
- var newInfo = 'I\'ve made a huge mistake.';
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- misc_info : newInfo
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.misc_info === newInfo,
- "misc_info successfully set via update: " + hdaShow.misc_info );
-
- this.test.comment( 'update should sanitize any misc_info' );
- var newInfo = 'You\'re going to get hop-ons.';
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- misc_info : newInfo + '<script type="text/javascript" src="bler">alert("blah");</script>'
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.misc_info === newInfo,
- "Update sanitized misc_info: " + hdaShow.misc_info );
-
- this.test.comment( 'update should allow unicode in misc_info' );
- var unicodeInfo = '여보!';
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- misc_info : unicodeInfo
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.misc_info === unicodeInfo,
- "Update accepted unicode misc_info: " + hdaShow.misc_info );
-
- // ........................................................................................... annotation
- // currently fails because no annotation is returned in details
- this.test.comment( 'update should allow changing the annotation' );
- var newAnnotation = 'Found this sample on a movie theatre floor';
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- annotation : newAnnotation
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.annotation === newAnnotation,
- "Annotation successfully set via update: " + hdaShow.annotation );
-
- this.test.comment( 'update should sanitize any new annotation' );
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- annotation : 'New annotation<script type="text/javascript" src="bler">alert("blah");</script>'
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.annotation === 'New annotation',
- "Update sanitized annotation: " + hdaShow.annotation );
-
- this.test.comment( 'update should allow unicode in annotations' );
- var unicodeAnnotation = 'お願いは、それが落下させない';
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- annotation : unicodeAnnotation
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.annotation === unicodeAnnotation,
- "Update accepted unicode annotation: " + hdaShow.annotation );
-
- this.test.comment( 'update should allow escaped quotations in annotations' );
- var quotedAnnotation = '"Bler"';
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- annotation : quotedAnnotation
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.annotation === quotedAnnotation,
- "Update accepted escaped quotations in annotation: " + hdaShow.annotation );
-
- // ------------------------------------------------------------------------------------------- ERRORS
- this.test.comment( 'create should error with "Please define the source" when the param "from_ld_id" is not used' );
- this.api.assertRaises( function(){
- this.api.hdas.create( lastHistory.id, { bler: 'bler' } );
- }, 400, "must be either 'library' or 'hda'", 'create with no source failed' );
-
- this.test.comment( 'updating using a nonsense key should fail silently' );
- returned = this.api.hdas.update( lastHistory.id, hdaShow.id, {
- konamiCode : 'uuddlrlrba'
- });
- this.test.assert( returned.konamiCode === undefined, 'key was not set: ' + returned.konamiCode );
-
- spaceghost.test.comment( 'A bad id should throw an error when using show' );
- this.api.assertRaises( function(){
- this.api.hdas.show( lastHistory.id, '1234123412341234' );
- }, 400, 'unable to decode', 'Bad Request with invalid id: show' );
- spaceghost.test.comment( 'A bad id should throw an error when using update' );
- this.api.assertRaises( function(){
- this.api.hdas.update( lastHistory.id, '1234123412341234', {} );
- }, 400, 'unable to decode', 'Bad Request with invalid id: update' );
- spaceghost.test.comment( 'A bad id should throw an error when using delete' );
- this.api.assertRaises( function(){
- this.api.hdas.delete_( lastHistory.id, '1234123412341234' );
- }, 400, 'unable to decode', 'Bad Request with invalid id: delete' );
- spaceghost.test.comment( 'A bad id should throw an error when using undelete' );
-
- this.test.comment( 'updating by attempting to change type should cause an error' );
- [ 'name', 'annotation', 'genome_build', 'misc_info' ].forEach( function( key ){
- var updatedAttrs = {};
- updatedAttrs[ key ] = false;
- spaceghost.api.assertRaises( function(){
- returned = spaceghost.api.hdas.update( hdaShow.history_id, hdaShow.id, updatedAttrs );
- }, 400, key + ' must be a string or unicode', 'type validation error' );
- });
- [ 'deleted', 'visible' ].forEach( function( key ){
- var updatedAttrs = {};
- updatedAttrs[ key ] = 'straaang';
- spaceghost.api.assertRaises( function(){
- returned = spaceghost.api.hdas.update( hdaShow.history_id, hdaShow.id, updatedAttrs );
- }, 400, key + ' must be a boolean', 'type validation error' );
- });
- [ 'you\'re it', [ true ] ].forEach( function( badVal ){
- spaceghost.api.assertRaises( function(){
- returned = spaceghost.api.hdas.update( hdaShow.history_id, hdaShow.id, { tags: badVal });
- }, 400, 'tags must be a list', 'type validation error' );
- });
-
- // ------------------------------------------------------------------------------------------- DELETE
- this.test.comment( 'calling delete on an hda should mark it as deleted but not change the history size' );
- lastHistory = this.api.histories.show( lastHistory.id );
- var sizeBeforeDelete = lastHistory.nice_size;
-
- returned = this.api.hdas.delete_( lastHistory.id, firstHda.id );
- //this.debug( this.jsonStr( returned ) );
-
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.deleted, 'hda is marked deleted' );
- lastHistory = this.api.histories.show( lastHistory.id );
- this.test.assert( lastHistory.nice_size === sizeBeforeDelete, 'history size has not changed' );
-
- // by default, purging fails bc uni.ini:allow_user_dataset_purge=False
- this.api.assertRaises( function(){
- returned = this.api.hdas.delete_( lastHistory.id, firstHda.id, { purge : true });
- }, 403, 'This instance does not allow user dataset purging', 'Purge failed' );
-/*
-*/
-});
-//spaceghost.user.logout();
-
-
-// ===================================================================
+ // ===================================================================
spaceghost.run( function(){ test.done(); });
});
This diff is so big that we needed to truncate the remainder.
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: UsesHistoryMixin, get_history: allow anon users to get their current history; update browser tests; remove unused selenium tests
by commits-noreply@bitbucket.org 22 Dec '14
by commits-noreply@bitbucket.org 22 Dec '14
22 Dec '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/501f510ff101/
Changeset: 501f510ff101
Branch: next-stable
User: carlfeberhard
Date: 2014-12-22 19:35:08+00:00
Summary: UsesHistoryMixin, get_history: allow anon users to get their current history; update browser tests; remove unused selenium tests
Affected #: 28 files
diff -r 05604a5d31c1b150d4a04347e68c0f30f2d0a598 -r 501f510ff101849c45d9b0925bb55fe59319088b lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -255,6 +255,11 @@
"""
Get a History from the database by id, verifying ownership.
"""
+ if trans.user is None and trans.history:
+ if id == trans.security.encode_id( trans.history.id ):
+ return trans.history
+ raise ItemOwnershipException( "Must be logged in to manage Galaxy items", type='error' )
+
history = self.get_object( trans, id, 'History',
check_ownership=check_ownership, check_accessible=check_accessible, deleted=deleted )
history = self.security_check( trans, history, check_ownership, check_accessible )
diff -r 05604a5d31c1b150d4a04347e68c0f30f2d0a598 -r 501f510ff101849c45d9b0925bb55fe59319088b test/casperjs/anon-history-tests.js
--- a/test/casperjs/anon-history-tests.js
+++ b/test/casperjs/anon-history-tests.js
@@ -7,117 +7,111 @@
spaceghost.test.begin( 'Testing histories for anonymous users', 0, function suite( test ){
spaceghost.start();
-// ===================================================================
+ // ===================================================================
+ var email = spaceghost.user.getRandomEmail(),
+ password = '123456';
+ if( spaceghost.fixtureData.testUser ){
+ email = spaceghost.fixtureData.testUser.email;
+ password = spaceghost.fixtureData.testUser.password;
+ spaceghost.info( 'Will use fixtureData.testUser: ' + email );
+ }
-var email = spaceghost.user.getRandomEmail(),
- password = '123456';
-if( spaceghost.fixtureData.testUser ){
- email = spaceghost.fixtureData.testUser.email;
- password = spaceghost.fixtureData.testUser.password;
- spaceghost.info( 'Will use fixtureData.testUser: ' + email );
-}
+ var editableTextClass = spaceghost.data.selectors.editableText,
+ editableTextInput = spaceghost.data.selectors.editableTextInput,
-var tooltipSelector = spaceghost.data.selectors.tooltipBalloon,
- editableTextClass = spaceghost.data.selectors.editableText,
- editableTextInput = spaceghost.data.selectors.editableTextInput,
+ unnamedName = spaceghost.historypanel.data.text.history.newName,
+ nameSelector = spaceghost.historypanel.data.selectors.history.name,
+ sizeSelector = spaceghost.historypanel.data.selectors.history.size,
+ initialSizeStr = spaceghost.historypanel.data.text.history.newSize,
+ tagIconSelector = spaceghost.historypanel.data.selectors.history.tagIcon,
+ annoIconSelector = spaceghost.historypanel.data.selectors.history.annoIcon,
+ emptyMsgSelector = spaceghost.historypanel.data.selectors.history.emptyMsg,
+ emptyMsgStr = spaceghost.historypanel.data.text.history.emptyMsg;
- unnamedName = spaceghost.historypanel.data.text.history.newName,
- nameSelector = spaceghost.historypanel.data.selectors.history.name,
- sizeSelector = spaceghost.historypanel.data.selectors.history.size,
- initialSizeStr = spaceghost.historypanel.data.text.history.newSize,
- tagIconSelector = spaceghost.historypanel.data.selectors.history.tagIcon,
- annoIconSelector = spaceghost.historypanel.data.selectors.history.annoIcon,
- emptyMsgSelector = spaceghost.historypanel.data.selectors.history.emptyMsg,
- emptyMsgStr = spaceghost.historypanel.data.text.history.emptyMsg,
- anonNameTooltip = spaceghost.historypanel.data.text.anonymous.tooltips.name;
+ var filenameToUpload = '1.txt',
+ filepathToUpload = '../../test-data/' + filenameToUpload;
-var historyFrameInfo = {},
- filenameToUpload = '1.txt',
- filepathToUpload = '../../test-data/' + filenameToUpload,
- testUploadInfo = {};
+ // ------------------------------------------------------------------- check the anonymous new, history for form
+ spaceghost.openHomePage().historypanel.waitForHdas( function testPanelStructure(){
+ this.test.comment( 'history panel for anonymous user, new history' );
-// =================================================================== TESTS
-// ------------------------------------------------------------------- check the anonymous new, history for form
-spaceghost.openHomePage().historypanel.waitForHdas( function testPanelStructure(){
- this.test.comment( 'history panel for anonymous user, new history' );
+ this.test.comment( "history name should exist, be visible, and have text " + unnamedName );
+ this.test.assertExists( nameSelector, nameSelector + ' exists' );
+ this.test.assertVisible( nameSelector, 'History name is visible' );
+ this.test.assertSelectorHasText( nameSelector, unnamedName, 'History name is ' + unnamedName );
- this.test.comment( "history name should exist, be visible, and have text " + unnamedName );
- this.test.assertExists( nameSelector, nameSelector + ' exists' );
- this.test.assertVisible( nameSelector, 'History name is visible' );
- this.test.assertSelectorHasText( nameSelector, unnamedName, 'History name is ' + unnamedName );
+ this.test.comment( "history should display size and size should be 0 bytes" );
+ this.test.assertExists( sizeSelector, 'Found ' + sizeSelector );
+ this.test.assertVisible( sizeSelector, 'History size is visible' );
+ this.test.assertSelectorHasText( sizeSelector, initialSizeStr,
+ 'History size has "' + initialSizeStr + '"' );
- this.test.comment( "history should display size and size should be 0 bytes" );
- this.test.assertExists( sizeSelector, 'Found ' + sizeSelector );
- this.test.assertVisible( sizeSelector, 'History size is visible' );
- this.test.assertSelectorHasText( sizeSelector, initialSizeStr,
- 'History size has "' + initialSizeStr + '"' );
+ this.test.comment( "NO tags or annotations icons should be available for an anonymous user" );
+ this.test.assertDoesntExist( tagIconSelector, 'Tag icon button not found' );
+ this.test.assertDoesntExist( annoIconSelector, 'Annotation icon button not found' );
- this.test.comment( "NO tags or annotations icons should be available for an anonymous user" );
- this.test.assertDoesntExist( tagIconSelector, 'Tag icon button not found' );
- this.test.assertDoesntExist( annoIconSelector, 'Annotation icon button not found' );
+ this.test.assertExists( emptyMsgSelector, emptyMsgSelector + ' exists' );
+ this.test.comment( "A message about the current history being empty should be displayed" );
+ this.test.assertVisible( emptyMsgSelector, 'Empty history message is visible' );
+ this.test.assertSelectorHasText( emptyMsgSelector, emptyMsgStr,
+ 'Message contains "' + emptyMsgStr + '"' );
- this.test.assertExists( emptyMsgSelector, emptyMsgSelector + ' exists' );
- this.test.comment( "A message about the current history being empty should be displayed" );
- this.test.assertVisible( emptyMsgSelector, 'Empty history message is visible' );
- this.test.assertSelectorHasText( emptyMsgSelector, emptyMsgStr,
- 'Message contains "' + emptyMsgStr + '"' );
-
- this.test.comment( 'name should NOT be editable when clicked by anon-user' );
- this.assertDoesntHaveClass( nameSelector, editableTextClass, "Name field is not classed as editable text" );
- this.click( nameSelector );
- this.test.assertDoesntExist( editableTextInput, "Clicking on name does not create an input" );
-});
-
-// ------------------------------------------------------------------- anon user can upload file
-spaceghost.then( function testAnonUpload(){
- this.test.comment( 'anon-user should be able to upload files' );
-
- spaceghost.tools.uploadFile( filepathToUpload, function uploadCallback( _uploadInfo ){
- this.debug( 'uploaded HDA info: ' + this.jsonStr( this.quickInfo( _uploadInfo.hdaElement ) ) );
- var hasHda = _uploadInfo.hdaElement,
- hasClass = _uploadInfo.hdaElement.attributes[ 'class' ],
- hasOkClass = _uploadInfo.hdaElement.attributes[ 'class' ].indexOf( 'state-ok' ) !== -1;
- this.test.assert( ( hasHda && hasClass && hasOkClass ), "Uploaded file: " + _uploadInfo.hdaElement.text );
- testUploadInfo = _uploadInfo;
+ this.test.comment( 'name should NOT be editable when clicked by anon-user' );
+ this.assertDoesntHaveClass( nameSelector, editableTextClass, "Name field is not classed as editable text" );
+ this.click( nameSelector );
+ this.test.assertDoesntExist( editableTextInput, "Clicking on name does not create an input" );
});
-});
-spaceghost.then( function testAnonUpload(){
- this.test.comment( "empty should be NO LONGER be displayed" );
- this.test.assertNotVisible( emptyMsgSelector, 'Empty history message is not visible' );
-});
+ // ------------------------------------------------------------------- anon user can upload file
+ var uploadedId = null;
+ spaceghost.api.tools.thenUploadToCurrent({ filepath: filepathToUpload }, function( id, json ){
+ uploadedId = id;
+ });
+ spaceghost.openHomePage().historypanel.waitForHdas( function testAnonUpload(){
+ this.test.comment( 'anon-user should be able to upload files' );
+ this.test.assertExists( '#dataset-' + uploadedId, "found hda" );
+ var hdaElement = this.elementInfoOrNull( '#dataset-' + uploadedId );
+ this.debug( 'hdaElement: ' + hdaElement );
+ if( hdaElement ){
+ this.test.assert( hdaElement.attributes[ 'class' ].indexOf( 'state-ok' ) !== -1,
+ "Uploaded file: " + hdaElement.text );
+ }
-// ------------------------------------------------------------------- anon user can run tool on file
+ this.test.comment( "empty should be NO LONGER be displayed" );
+ this.test.assertNotVisible( emptyMsgSelector, 'Empty history message is not visible' );
+ });
-// ------------------------------------------------------------------- anon user registers/logs in -> same history
-spaceghost.user.loginOrRegisterUser( email, password ).openHomePage( function(){
- this.test.comment( 'anon-user should login and be associated with previous history' );
+ // ------------------------------------------------------------------- anon user can run tool on file
- var loggedInAs = spaceghost.user.loggedInAs();
- this.test.assert( loggedInAs === email, 'loggedInAs() matches email: "' + loggedInAs + '"' );
+ // ------------------------------------------------------------------- anon user registers/logs in -> same history
+ spaceghost.user.loginOrRegisterUser( email, password ).openHomePage( function(){
+ this.test.comment( 'anon-user should login and be associated with previous history' );
- this.historypanel.waitForHdas( function(){
- var hdaInfo = this.historypanel.hdaElementInfoByTitle( filenameToUpload );
- this.test.assert( hdaInfo !== null, "After logging in - found a matching hda by name and hid" );
- if( hdaInfo ){
- this.test.assert( testUploadInfo.hdaElement.attributes.id === hdaInfo.attributes.id,
- "After logging in - found a matching hda by hda view id: " + hdaInfo.attributes.id );
- }
+ var loggedInAs = spaceghost.user.loggedInAs();
+ this.test.assert( loggedInAs === email, 'loggedInAs() matches email: "' + loggedInAs + '"' );
+
+ this.historypanel.waitForHdas( function(){
+ var hdaInfo = this.historypanel.hdaElementInfoByTitle( filenameToUpload );
+ this.test.assert( hdaInfo !== null, "After logging in - found a matching hda by name and hid" );
+ if( hdaInfo ){
+ this.test.assert( 'dataset-' + uploadedId === hdaInfo.attributes.id,
+ "After logging in - found a matching hda by hda view id: " + hdaInfo.attributes.id );
+ }
+ });
});
-});
-// ------------------------------------------------------------------- logs out -> new history
-spaceghost.user.logout().openHomePage( function(){
- this.test.comment( 'logging out should create a new, anonymous history' );
+ // ------------------------------------------------------------------- logs out -> new history
+ spaceghost.user.logout().openHomePage( function(){
+ this.test.comment( 'logging out should create a new, anonymous history' );
- this.historypanel.waitForHdas( function(){
- this.test.assertSelectorHasText( nameSelector, unnamedName, 'History name is ' + unnamedName );
- this.test.assertSelectorHasText( emptyMsgSelector, emptyMsgStr,
- 'Message contains "' + emptyMsgStr + '"' );
+ this.historypanel.waitForHdas( function(){
+ this.test.assertSelectorHasText( nameSelector, unnamedName, 'History name is ' + unnamedName );
+ this.test.assertSelectorHasText( emptyMsgSelector, emptyMsgStr,
+ 'Message contains "' + emptyMsgStr + '"' );
+ });
});
-});
-// ===================================================================
+ // ===================================================================
spaceghost.run( function(){ test.done(); });
});
diff -r 05604a5d31c1b150d4a04347e68c0f30f2d0a598 -r 501f510ff101849c45d9b0925bb55fe59319088b test/casperjs/api-anon-history-permission-tests.js
--- a/test/casperjs/api-anon-history-permission-tests.js
+++ b/test/casperjs/api-anon-history-permission-tests.js
@@ -8,195 +8,194 @@
+ 'with anonymous users over the API', 0, function suite( test ){
spaceghost.start();
-// =================================================================== SET UP
-var email = spaceghost.user.getRandomEmail(),
- password = '123456';
-if( spaceghost.fixtureData.testUser ){
- email = spaceghost.fixtureData.testUser.email;
- password = spaceghost.fixtureData.testUser.password;
-}
-var inaccessibleHistory, accessibleHistory, publishedHistory,
- inaccessibleHdas, accessibleHdas, publishedHdas,
- accessibleLink;
+ // =================================================================== SET UP
+ var email = spaceghost.user.getRandomEmail(),
+ password = '123456';
+ if( spaceghost.fixtureData.testUser ){
+ email = spaceghost.fixtureData.testUser.email;
+ password = spaceghost.fixtureData.testUser.password;
+ }
+ var inaccessibleHistory, accessibleHistory, publishedHistory,
+ inaccessibleHdas, accessibleHdas, publishedHdas;
-//// ------------------------------------------------------------------------------------------- create 3 histories
-spaceghost.user.loginOrRegisterUser( email, password );
-spaceghost.thenOpen( spaceghost.baseUrl ).then( function(){
- // create three histories: make the 2nd importable (via the API), and the third published
+ //// ------------------------------------------------------------------------------------------- create 3 histories
+ spaceghost.user.loginOrRegisterUser( email, password );
+ spaceghost.openHomePage().then( function(){
+ // create three histories: make the 2nd importable (via the API), and the third published
- // make the current the inaccessible one
- inaccessibleHistory = this.api.histories.index()[0];
- this.api.histories.update( inaccessibleHistory.id, { name: 'inaccessible' });
- inaccessibleHistory = this.api.histories.index()[0];
+ // make the current the inaccessible one
+ inaccessibleHistory = this.api.histories.index()[0];
+ this.api.histories.update( inaccessibleHistory.id, { name: 'inaccessible' });
+ inaccessibleHistory = this.api.histories.index()[0];
- accessibleHistory = this.api.histories.create({ name: 'accessible' });
- var returned = this.api.histories.update( accessibleHistory.id, {
- importable : true
+ accessibleHistory = this.api.histories.create({ name: 'accessible' });
+ var returned = this.api.histories.update( accessibleHistory.id, {
+ importable : true
+ });
+ //this.debug( this.jsonStr( returned ) );
+ accessibleHistory = this.api.histories.show( accessibleHistory.id );
+
+ publishedHistory = this.api.histories.create({ name: 'published' });
+ returned = this.api.histories.update( publishedHistory.id, {
+ published : true
+ });
+ //this.debug( this.jsonStr( returned ) );
+ publishedHistory = this.api.histories.show( publishedHistory.id );
+
});
- //this.debug( this.jsonStr( returned ) );
- accessibleHistory = this.api.histories.show( accessibleHistory.id );
- publishedHistory = this.api.histories.create({ name: 'published' });
- returned = this.api.histories.update( publishedHistory.id, {
- published : true
+ //// ------------------------------------------------------------------------------------------- upload some files
+ spaceghost.then( function(){
+ this.api.tools.thenUpload( inaccessibleHistory.id, { filepath: '../../test-data/1.bed' });
+ this.api.tools.thenUpload( accessibleHistory.id, { filepath: '../../test-data/1.bed' });
+ this.api.tools.thenUpload( publishedHistory.id, { filepath: '../../test-data/1.bed' });
});
- //this.debug( this.jsonStr( returned ) );
- publishedHistory = this.api.histories.show( publishedHistory.id );
+ spaceghost.then( function(){
+ // check that they're there
+ inaccessibleHdas = this.api.hdas.index( inaccessibleHistory.id ),
+ accessibleHdas = this.api.hdas.index( accessibleHistory.id ),
+ publishedHdas = this.api.hdas.index( publishedHistory.id );
+ });
+ spaceghost.user.logout();
-});
+ // =================================================================== TESTS
+ //// ------------------------------------------------------------------------------------------- anon user
+ function testAnonReadFunctionsOnAccessible( history, hdas ){
+ this.test.comment( '---- testing read/accessibility functions for ACCESSIBLE history: ' + history.name );
-//// ------------------------------------------------------------------------------------------- upload some files
-spaceghost.then( function(){
- this.api.tools.thenUpload( inaccessibleHistory.id, { filepath: '../../test-data/1.bed' });
- this.api.tools.thenUpload( accessibleHistory.id, { filepath: '../../test-data/1.bed' });
- this.api.tools.thenUpload( publishedHistory.id, { filepath: '../../test-data/1.bed' });
-});
-spaceghost.then( function(){
- // check that they're there
- inaccessibleHdas = this.api.hdas.index( inaccessibleHistory.id ),
- accessibleHdas = this.api.hdas.index( accessibleHistory.id ),
- publishedHdas = this.api.hdas.index( publishedHistory.id );
-});
-spaceghost.user.logout();
+ // read functions for history
+ this.test.comment( 'show should work for history: ' + history.name );
+ this.test.assert( this.api.histories.show( history.id ).id === history.id,
+ 'show worked' );
+ this.test.comment( 'copying should fail for history (multiple histories not allowed): ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.histories.create({ history_id : history.id });
+ }, 403, 'API authentication required for this request', 'update authentication required' );
-// =================================================================== TESTS
-//// ------------------------------------------------------------------------------------------- anon user
-function testAnonReadFunctionsOnAccessible( history, hdas ){
- this.test.comment( '---- testing read/accessibility functions for ACCESSIBLE history: ' + history.name );
+ // read functions for history contents
+ this.test.comment( 'index of history contents should work for history: ' + history.name );
+ this.test.assert( this.api.hdas.index( history.id ).length === 1,
+ 'hda index worked' );
+ this.test.comment( 'showing of history contents should work for history: ' + history.name );
+ this.test.assert( this.api.hdas.show( history.id, hdas[0].id ).id === hdas[0].id,
+ 'hda show worked' );
- // read functions for history
- this.test.comment( 'show should work for history: ' + history.name );
- this.test.assert( this.api.histories.show( history.id ).id === history.id,
- 'show worked' );
- this.test.comment( 'copying should fail for history (multiple histories not allowed): ' + history.name );
- this.api.assertRaises( function(){
- this.api.histories.create({ history_id : history.id });
- }, 403, 'API authentication required for this request', 'update authentication required' );
-
- // read functions for history contents
- this.test.comment( 'index of history contents should work for history: ' + history.name );
- this.test.assert( this.api.hdas.index( history.id ).length === 1,
- 'hda index worked' );
- this.test.comment( 'showing of history contents should work for history: ' + history.name );
- this.test.assert( this.api.hdas.show( history.id, hdas[0].id ).id === hdas[0].id,
- 'hda show worked' );
-
- this.test.comment( 'Attempting to copy an accessible hda (default is accessible)'
- + ' should work from accessible history: ' + history.name );
- this.api.hdas.create( this.api.histories.index()[0].id, {
- source : 'hda',
- content : hdas[0].id
- });
-}
-
-function testAnonReadFunctionsOnInaccessible( history, hdas ){
- this.test.comment( '---- testing read/accessibility functions for INACCESSIBLE history: ' + history.name );
-
- // read functions for history
- this.test.comment( 'show should fail for history: ' + history.name );
- this.api.assertRaises( function(){
- this.api.histories.show( history.id );
- }, 403, 'History is not accessible to the current user', 'show failed with error' );
- this.test.comment( 'copying should fail for history (implicit multiple histories): ' + history.name );
- this.api.assertRaises( function(){
- this.api.histories.create({ history_id : history.id });
- }, 403, 'API authentication required for this request', 'copy failed with error' );
-
- // read functions for history contents
- this.test.comment( 'index and show of history contents should fail for history: ' + history.name );
- this.api.assertRaises( function(){
- this.api.hdas.index( history.id );
- }, 403, 'History is not accessible to the current user', 'hda index failed with error' );
- this.api.assertRaises( function(){
- this.api.hdas.show( history.id, hdas[0].id );
- }, 403, 'History is not accessible to the current user', 'hda show failed with error' );
-
- this.test.comment( 'Attempting to copy an accessible hda (default is accessible)'
- + ' from an inaccessible history should fail for: ' + history.name );
- this.api.assertRaises( function(){
- var returned = this.api.hdas.create( this.api.histories.index()[0].id, {
+ this.test.comment( 'Attempting to copy an accessible hda (default is accessible)'
+ + ' should work from accessible history: ' + history.name );
+ this.api.hdas.create( this.api.histories.index()[0].id, {
source : 'hda',
content : hdas[0].id
});
- this.debug( this.jsonStr( returned ) );
- }, 403, 'History is not accessible to the current user', 'hda copy from failed with error' );
+ }
-}
+ function testAnonReadFunctionsOnInaccessible( history, hdas ){
+ this.test.comment( '---- testing read/accessibility functions for INACCESSIBLE history: ' + history.name );
-function testAnonWriteFunctions( history, hdas ){
- this.test.comment( '---- testing write/ownership functions for history: ' + history.name );
+ // read functions for history
+ this.test.comment( 'show should fail for history: ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.histories.show( history.id );
+ }, 403, 'History is not accessible to the current user', 'show failed with error' );
+ this.test.comment( 'copying should fail for history (implicit multiple histories): ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.histories.create({ history_id : history.id });
+ }, 403, 'API authentication required for this request', 'copy failed with error' );
- this.test.comment( 'update should fail for history: ' + history.name );
- this.api.assertRaises( function(){
- this.api.histories.update( history.id, { deleted: true });
- }, 403, 'API authentication required for this request', 'update authentication required' );
- this.test.comment( 'delete should fail for history: ' + history.name );
- this.api.assertRaises( function(){
- this.api.histories.delete_( history.id );
- }, 403, 'API authentication required for this request', 'delete authentication required' );
+ // read functions for history contents
+ this.test.comment( 'index and show of history contents should fail for history: ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.hdas.index( history.id );
+ }, 403, 'History is not accessible to the current user', 'hda index failed with error' );
+ this.api.assertRaises( function(){
+ this.api.hdas.show( history.id, hdas[0].id );
+ }, 403, 'History is not accessible to the current user', 'hda show failed with error' );
- this.test.comment( 'hda updating should fail for history: ' + history.name );
- this.api.assertRaises( function(){
- this.api.hdas.update( history.id, hdas[0].id, { deleted: true });
- // anon hda update fails w/ this msg if trying to update non-current history hda
- }, 403, 'You must be logged in to update this history', 'hda update failed with error' );
- this.test.comment( 'hda deletion should fail for history: ' + history.name );
- this.api.assertRaises( function(){
- this.api.hdas.delete_( history.id, hdas[0].id );
- }, 403, 'API authentication required for this request', 'hda delete failed with error' );
+ this.test.comment( 'Attempting to copy an accessible hda (default is accessible)'
+ + ' from an inaccessible history should fail for: ' + history.name );
+ this.api.assertRaises( function(){
+ var returned = this.api.hdas.create( this.api.histories.index()[0].id, {
+ source : 'hda',
+ content : hdas[0].id
+ });
+ this.debug( this.jsonStr( returned ) );
+ }, 403, 'History is not accessible to the current user', 'hda copy from failed with error' );
- this.test.comment( 'copying hda into history should fail for history: ' + history.name );
- this.api.assertRaises( function(){
- this.api.hdas.create( history.id, {
- source : 'hda',
- // should error before it checks the id
- content : 'bler'
+ }
+
+ function testAnonWriteFunctions( history, hdas ){
+ this.test.comment( '---- testing write/ownership functions for history: ' + history.name );
+
+ this.test.comment( 'update should fail for history: ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.histories.update( history.id, { deleted: true });
+ }, 403, 'API authentication required for this request', 'update authentication required' );
+ this.test.comment( 'delete should fail for history: ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.histories.delete_( history.id );
+ }, 403, 'API authentication required for this request', 'delete authentication required' );
+
+ this.test.comment( 'hda updating should fail for history: ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.hdas.update( history.id, hdas[0].id, { deleted: true });
+ // anon hda update fails w/ this msg if trying to update non-current history hda
+ }, 403, 'You must be logged in to update this history', 'hda update failed with error' );
+ this.test.comment( 'hda deletion should fail for history: ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.hdas.delete_( history.id, hdas[0].id );
+ }, 403, 'API authentication required for this request', 'hda delete failed with error' );
+
+ this.test.comment( 'copying hda into history should fail for history: ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.hdas.create( history.id, {
+ source : 'hda',
+ // should error before it checks the id
+ content : 'bler'
+ });
+ }, 403, 'Must be logged in to manage Galaxy histories', 'hda copy to failed' );
+ }
+
+ function testAnonInaccessible( history, hdas ){
+ testAnonReadFunctionsOnInaccessible.call( this, history, hdas );
+ testAnonWriteFunctions.call( this, history, hdas );
+ }
+
+ function testAnonAccessible( history, hdas ){
+ testAnonReadFunctionsOnAccessible.call( this, history, hdas );
+ testAnonWriteFunctions.call( this, history, hdas );
+ }
+
+ spaceghost.thenOpen( spaceghost.baseUrl ).then( function(){
+ testAnonInaccessible.call( spaceghost, inaccessibleHistory, inaccessibleHdas );
+ testAnonAccessible.call( spaceghost, accessibleHistory, accessibleHdas );
+ testAnonAccessible.call( spaceghost, publishedHistory, publishedHdas );
+ });
+
+
+ // ------------------------------------------------------------------------------------------- user1 revoke perms
+ spaceghost.user.loginOrRegisterUser( email, password );
+ spaceghost.openHomePage().then( function(){
+ this.test.comment( 'revoking perms should prevent access' );
+ this.api.histories.update( accessibleHistory.id, {
+ importable : false
});
- }, 403, 'Must be logged in to manage Galaxy histories', 'hda copy to failed' );
-}
+ var returned = this.api.histories.show( accessibleHistory.id );
-function testAnonInaccessible( history, hdas ){
- testAnonReadFunctionsOnInaccessible.call( this, history, hdas );
- testAnonWriteFunctions.call( this, history, hdas );
-}
+ this.api.histories.update( publishedHistory.id, {
+ importable : false,
+ published : false
+ });
+ returned = this.api.histories.show( publishedHistory.id );
+ });
+ spaceghost.user.logout();
-function testAnonAccessible( history, hdas ){
- testAnonReadFunctionsOnAccessible.call( this, history, hdas );
- testAnonWriteFunctions.call( this, history, hdas );
-}
-spaceghost.thenOpen( spaceghost.baseUrl ).then( function(){
- testAnonInaccessible.call( spaceghost, inaccessibleHistory, inaccessibleHdas );
- testAnonAccessible.call( spaceghost, accessibleHistory, accessibleHdas );
- testAnonAccessible.call( spaceghost, publishedHistory, publishedHdas );
-});
+ // ------------------------------------------------------------------------------------------- anon retry perms
+ spaceghost.openHomePage().then( function(){
+ testAnonInaccessible.call( spaceghost, accessibleHistory, accessibleHdas );
+ testAnonInaccessible.call( spaceghost, publishedHistory, publishedHdas );
+ });
-// ------------------------------------------------------------------------------------------- user1 revoke perms
-spaceghost.user.loginOrRegisterUser( email, password );
-spaceghost.thenOpen( spaceghost.baseUrl ).then( function(){
- this.test.comment( 'revoking perms should prevent access' );
- this.api.histories.update( accessibleHistory.id, {
- importable : false
- });
- var returned = this.api.histories.show( accessibleHistory.id );
-
- this.api.histories.update( publishedHistory.id, {
- importable : false,
- published : false
- });
- returned = this.api.histories.show( publishedHistory.id );
-});
-spaceghost.user.logout();
-
-
-// ------------------------------------------------------------------------------------------- anon retry perms
-spaceghost.thenOpen( spaceghost.baseUrl ).then( function(){
- testAnonInaccessible.call( spaceghost, accessibleHistory, accessibleHdas );
- testAnonInaccessible.call( spaceghost, publishedHistory, publishedHdas );
-});
-
-
-// ===================================================================
+ // ===================================================================
spaceghost.run( function(){ test.done(); });
});
diff -r 05604a5d31c1b150d4a04347e68c0f30f2d0a598 -r 501f510ff101849c45d9b0925bb55fe59319088b test/casperjs/api-anon-history-tests.js
--- a/test/casperjs/api-anon-history-tests.js
+++ b/test/casperjs/api-anon-history-tests.js
@@ -7,123 +7,116 @@
spaceghost.test.begin( 'Test API functions for histories with an anonymous user', 0, function suite( test ){
spaceghost.start();
-// =================================================================== TESTS
-spaceghost.thenOpen( spaceghost.baseUrl ).waitForSelector( spaceghost.historypanel.data.selectors.history.name );
-spaceghost.then( function(){
+ // =================================================================== TESTS
+ spaceghost.thenOpen( spaceghost.baseUrl ).waitForSelector( spaceghost.historypanel.data.selectors.history.name );
+ spaceghost.then( function(){
- // ------------------------------------------------------------------------------------------- anon allowed
- this.test.comment( 'index should get a list of histories' );
- var index = this.api.histories.index();
- this.test.assert( utils.isArray( index ), "index returned an array: length " + index.length );
- this.test.assert( index.length === 1, 'Has at least one history' );
+ // ------------------------------------------------------------------------------------------- anon allowed
+ this.test.comment( 'index should get a list of histories' );
+ var index = this.api.histories.index();
+ this.test.assert( utils.isArray( index ), "index returned an array: length " + index.length );
+ this.test.assert( index.length === 1, 'Has at least one history' );
- this.test.comment( 'show should get a history details object' );
- var historyShow = this.api.histories.show( index[0].id );
- //this.debug( this.jsonStr( historyShow ) );
- this.test.assert( historyShow.id === index[0].id, 'Is the first history' );
- this.test.assert( this.hasKeys( historyShow, [ 'id', 'name', 'user_id' ] ) );
+ this.test.comment( 'show should get a history details object' );
+ var historyShow = this.api.histories.show( index[0].id );
+ //this.debug( this.jsonStr( historyShow ) );
+ this.test.assert( historyShow.id === index[0].id, 'Is the first history' );
+ this.test.assert( this.hasKeys( historyShow, [ 'id', 'name', 'user_id' ] ) );
- // ------------------------------------------------------------------------------------------- anon forbidden
- //TODO: why not return the current history?
- this.test.comment( 'calling show with "most_recently_used" should return None for an anon user' );
- var recent = this.api.histories.show( 'most_recently_used' );
- this.test.assert( recent === null, 'most_recently_used returned None' );
+ // ------------------------------------------------------------------------------------------- anon forbidden
+ //TODO: why not return the current history?
+ this.test.comment( 'calling show with "most_recently_used" should return None for an anon user' );
+ var recent = this.api.histories.show( 'most_recently_used' );
+ this.test.assert( recent === null, 'most_recently_used returned None' );
- this.test.comment( 'Calling create should fail for an anonymous user' );
- this.api.assertRaises( function(){
- this.api.histories.create({ name: 'new' });
- }, 403, 'API authentication required for this request', 'create failed with error' );
+ this.test.comment( 'Calling create should fail for an anonymous user' );
+ this.api.assertRaises( function(){
+ this.api.histories.create({ name: 'new' });
+ }, 403, 'API authentication required for this request', 'create failed with error' );
- this.test.comment( 'Calling delete should fail for an anonymous user' );
- this.api.assertRaises( function(){
- this.api.histories.delete_( historyShow.id );
- }, 403, 'API authentication required for this request', 'create failed with error' );
+ this.test.comment( 'Calling delete should fail for an anonymous user' );
+ this.api.assertRaises( function(){
+ this.api.histories.delete_( historyShow.id );
+ }, 403, 'API authentication required for this request', 'create failed with error' );
- this.test.comment( 'Calling update should fail for an anonymous user' );
- this.api.assertRaises( function(){
- this.api.histories.update( historyShow.id, {} );
- }, 403, 'API authentication required for this request', 'update failed with error' );
+ this.test.comment( 'Calling update should fail for an anonymous user' );
+ this.api.assertRaises( function(){
+ this.api.histories.update( historyShow.id, {} );
+ }, 403, 'API authentication required for this request', 'update failed with error' );
- //TODO: need these two in api.js
- //this.test.comment( 'Calling archive_import should fail for an anonymous user' );
- //this.api.assertRaises( function(){
- // this.api.histories.archive_import( historyShow.id, {} );
- //}, 403, 'API authentication required for this request', 'archive_import failed with error' );
+ //TODO: need these two in api.js
+ //this.test.comment( 'Calling archive_import should fail for an anonymous user' );
+ //this.api.assertRaises( function(){
+ // this.api.histories.archive_import( historyShow.id, {} );
+ //}, 403, 'API authentication required for this request', 'archive_import failed with error' );
- //this.test.comment( 'Calling archive_download should fail for an anonymous user' );
- //this.api.assertRaises( function(){
- // this.api.histories.archive_download( historyShow.id, {} );
- //}, 403, 'API authentication required for this request', 'archive_download failed with error' );
+ //this.test.comment( 'Calling archive_download should fail for an anonymous user' );
+ //this.api.assertRaises( function(){
+ // this.api.histories.archive_download( historyShow.id, {} );
+ //}, 403, 'API authentication required for this request', 'archive_download failed with error' );
- // test server bad id protection
- spaceghost.test.comment( 'A bad id should throw an error' );
- this.api.assertRaises( function(){
- this.api.histories.show( '1234123412341234' );
- }, 400, 'unable to decode', 'Bad Request with invalid id: show' );
+ // test server bad id protection
+ spaceghost.test.comment( 'A bad id should throw an error' );
+ this.api.assertRaises( function(){
+ this.api.histories.show( '1234123412341234' );
+ }, 400, 'unable to decode', 'Bad Request with invalid id: show' );
-});
+ });
-// ------------------------------------------------------------------------------------------- hdas
-spaceghost.thenOpen( spaceghost.baseUrl ).waitForSelector( spaceghost.historypanel.data.selectors.history.name );
-spaceghost.then( function(){
- spaceghost.tools.uploadFile( '../../test-data/1.sam', function( uploadInfo ){
- this.test.assert( uploadInfo.hdaElement !== null, "Convenience function produced hda" );
- var state = this.historypanel.getHdaState( '#' + uploadInfo.hdaElement.attributes.id );
- this.test.assert( state === 'ok', "Convenience function produced hda in ok state" );
+ // ------------------------------------------------------------------------------------------- hdas
+ spaceghost.thenOpen( spaceghost.baseUrl ).waitForSelector( spaceghost.historypanel.data.selectors.history.name );
+ spaceghost.api.tools.thenUploadToCurrent({ filepath: '../../test-data/1.sam' });
+ spaceghost.then( function(){
+ var current = this.api.histories.index()[0];
+
+ // ------------------------------------------------------------------------------------------- anon allowed
+ this.test.comment( 'anonymous users can index hdas in their current history' );
+ var hdaIndex = this.api.hdas.index( current.id );
+ this.test.assert( hdaIndex.length === 1, 'indexed hdas' );
+
+ this.test.comment( 'anonymous users can show hdas in their current history' );
+ var hda = this.api.hdas.show( current.id, hdaIndex[0].id );
+ this.test.assert( this.hasKeys( hda, [ 'id', 'name' ] ), 'showed hda: ' + hda.name );
+
+ this.test.comment( 'anonymous users can hide hdas in their current history' );
+ var changed = this.api.hdas.update( current.id, hda.id, { visible: false });
+ hda = this.api.hdas.show( current.id, hda.id );
+ this.test.assert( hda.visible === false, 'successfully hidden' );
+
+ this.test.comment( 'anonymous users can mark their hdas as deleted in their current history' );
+ changed = this.api.hdas.update( current.id, hda.id, { deleted: true });
+ hda = this.api.hdas.show( current.id, hda.id );
+ this.test.assert( hda.deleted, 'successfully deleted' );
+
+ // ------------------------------------------------------------------------------------------- anon forbidden
+ this.test.comment( 'Creating an hda should work for an anonymous user' );
+ var returned = this.api.hdas.create( current.id, { source: 'hda', content: hda.id });
+ //this.debug( this.jsonStr( returned ) );
+ this.test.assert( returned.name === hda.name, 'name matches: ' + returned.name );
+ this.test.assert( returned.id !== hda.id, 'new id: ' + returned.id );
+
+ //TODO: should be allowed
+ this.test.comment( 'Calling hda delete should fail for an anonymous user' );
+ this.api.assertRaises( function(){
+ this.api.hdas.delete_( current.id, hda.id );
+ }, 403, 'API authentication required for this request', 'delete failed with error' );
+
+ //TODO: only sharing, tags, annotations should be blocked/prevented
+ this.test.comment( 'Calling update with keys other than "visible" or "deleted" should fail silently' );
+ this.test.comment( 'Calling update on tags should fail silently' );
+ changed = this.api.hdas.update( current.id, hda.id, { tags: [ 'one' ] });
+ hda = this.api.hdas.show( current.id, hda.id );
+ this.test.assert( hda.tags.length === 0, 'tags were not set: ' + this.jsonStr( hda.tags ) );
+
+ this.test.comment( 'Calling update on annotation should fail silently' );
+ changed = this.api.hdas.update( current.id, hda.id, { annotation: 'yup yup yup' });
+ hda = this.api.hdas.show( current.id, hda.id );
+ this.test.assert( !hda.annotation, 'annotation was not set: ' + hda.annotation );
+
});
-});
-spaceghost.then( function(){
- var current = this.api.histories.index()[0];
-
- // ------------------------------------------------------------------------------------------- anon allowed
- this.test.comment( 'anonymous users can index hdas in their current history' );
- var hdaIndex = this.api.hdas.index( current.id );
- this.test.assert( hdaIndex.length === 1, 'indexed hdas' );
-
- this.test.comment( 'anonymous users can show hdas in their current history' );
- var hda = this.api.hdas.show( current.id, hdaIndex[0].id );
- this.test.assert( this.hasKeys( hda, [ 'id', 'name' ] ), 'showed hda: ' + hda.name );
-
- this.test.comment( 'anonymous users can hide hdas in their current history' );
- var changed = this.api.hdas.update( current.id, hda.id, { visible: false });
- hda = this.api.hdas.show( current.id, hda.id );
- this.test.assert( hda.visible === false, 'successfully hidden' );
-
- this.test.comment( 'anonymous users can mark their hdas as deleted in their current history' );
- changed = this.api.hdas.update( current.id, hda.id, { deleted: true });
- hda = this.api.hdas.show( current.id, hda.id );
- this.test.assert( hda.deleted, 'successfully deleted' );
-
- // ------------------------------------------------------------------------------------------- anon forbidden
- this.test.comment( 'Creating an hda should work for an anonymous user' );
- var returned = this.api.hdas.create( current.id, { source: 'hda', content: hda.id });
- //this.debug( this.jsonStr( returned ) );
- this.test.assert( returned.name === hda.name, 'name matches: ' + returned.name );
- this.test.assert( returned.id !== hda.id, 'new id: ' + returned.id );
-
- //TODO: should be allowed
- this.test.comment( 'Calling hda delete should fail for an anonymous user' );
- this.api.assertRaises( function(){
- this.api.hdas.delete_( current.id, hda.id );
- }, 403, 'API authentication required for this request', 'delete failed with error' );
-
- //TODO: only sharing, tags, annotations should be blocked/prevented
- this.test.comment( 'Calling update with keys other than "visible" or "deleted" should fail silently' );
- this.test.comment( 'Calling update on tags should fail silently' );
- changed = this.api.hdas.update( current.id, hda.id, { tags: [ 'one' ] });
- hda = this.api.hdas.show( current.id, hda.id );
- this.test.assert( hda.tags.length === 0, 'tags were not set: ' + this.jsonStr( hda.tags ) );
-
- this.test.comment( 'Calling update on annotation should fail silently' );
- changed = this.api.hdas.update( current.id, hda.id, { annotation: 'yup yup yup' });
- hda = this.api.hdas.show( current.id, hda.id );
- this.test.assert( !hda.annotation, 'annotation was not set: ' + hda.annotation );
-
-});
-
-// ===================================================================
+ // ===================================================================
spaceghost.run( function(){ test.done(); });
});
diff -r 05604a5d31c1b150d4a04347e68c0f30f2d0a598 -r 501f510ff101849c45d9b0925bb55fe59319088b test/casperjs/api-configuration-tests.js
--- a/test/casperjs/api-configuration-tests.js
+++ b/test/casperjs/api-configuration-tests.js
@@ -7,57 +7,55 @@
spaceghost.test.begin( 'Test the Galaxy configuration API', 0, function suite( test ){
spaceghost.start();
-// =================================================================== SET UP
-var email = spaceghost.user.getRandomEmail(),
- password = '123456';
-if( spaceghost.fixtureData.testUser ){
- email = spaceghost.fixtureData.testUser.email;
- password = spaceghost.fixtureData.testUser.password;
-}
-spaceghost.user.loginOrRegisterUser( email, password );
+ // =================================================================== SET UP
+ var email = spaceghost.user.getRandomEmail(),
+ password = '123456';
+ if( spaceghost.fixtureData.testUser ){
+ email = spaceghost.fixtureData.testUser.email;
+ password = spaceghost.fixtureData.testUser.password;
+ }
+ spaceghost.user.loginOrRegisterUser( email, password );
-// =================================================================== TESTS
-var normKeys = [
- 'enable_unique_workflow_defaults',
- 'ftp_upload_site',
- 'ftp_upload_dir',
- 'wiki_url',
- 'support_url',
- 'logo_url',
- 'terms_url',
- 'allow_user_dataset_purge'
- ],
- adminKeys = normKeys.concat([
- 'library_import_dir',
- 'user_library_import_dir',
- 'allow_library_path_paste',
- 'allow_user_creation',
- 'allow_user_deletion'
- ]);
+ // =================================================================== TESTS
+ var normKeys = [
+ 'enable_unique_workflow_defaults',
+ 'ftp_upload_site',
+ 'ftp_upload_dir',
+ 'wiki_url',
+ 'support_url',
+ 'logo_url',
+ 'terms_url',
+ 'allow_user_dataset_purge'
+ ],
+ adminKeys = normKeys.concat([
+ 'library_import_dir',
+ 'user_library_import_dir',
+ 'allow_library_path_paste',
+ 'allow_user_creation',
+ 'allow_user_deletion'
+ ]);
+ // ------------------------------------------------------------------------------------------- INDEX
+ spaceghost.openHomePage().then( function(){
+ this.test.comment( 'index should get a (shortened) list of configuration settings '
+ + 'when requested by a normal user' );
-// ------------------------------------------------------------------------------------------- INDEX
-spaceghost.thenOpen( spaceghost.baseUrl ).then( function(){
+ var configIndex = this.api.configuration.index();
+ this.debug( this.jsonStr( configIndex ) );
+ this.test.assert( utils.isObject( configIndex ), "index returned an object" );
+ this.test.assert( this.hasKeys( configIndex, normKeys ), 'Has the proper keys' );
- this.test.comment( 'index should get a (shortened) list of configuration settings '
- + 'when requested by a normal user' );
- var configIndex = this.api.configuration.index();
- this.debug( this.jsonStr( configIndex ) );
- this.test.assert( utils.isObject( configIndex ), "index returned an object" );
- this.test.assert( this.hasKeys( configIndex, normKeys ), 'Has the proper keys' );
+ });
+ spaceghost.user.logout();
-});
-spaceghost.user.logout();
+ // ------------------------------------------------------------------------------------------- INDEX (admin)
+ spaceghost.tryStepsCatch( function tryAdminLogin(){
+ spaceghost.user.loginAdmin();
+ }, function(){} );
-// ------------------------------------------------------------------------------------------- INDEX (admin)
-spaceghost.tryStepsCatch( function tryAdminLogin(){
- spaceghost.user.loginAdmin();
-}, function(){} );
-
-//}, function failedLoginRegister(){
-// this.info( 'Admin level configuration API tests not run: no admin account available' );
-spaceghost.thenOpen( spaceghost.baseUrl ).then( function(){
- spaceghost.waitForMasthead( function() {
+ //}, function failedLoginRegister(){
+ // this.info( 'Admin level configuration API tests not run: no admin account available' );
+ spaceghost.openHomePage().waitForMasthead( function(){
if( spaceghost.user.userIsAdmin() ){
this.test.comment( 'index should get a (full) list of configuration settings '
+ 'when requested by an admin user' );
@@ -70,9 +68,8 @@
this.info( 'Admin level configuration API tests not run: no admin account available' );
}
});
-});
-// ===================================================================
+ // ===================================================================
spaceghost.run( function(){ test.done(); });
});
diff -r 05604a5d31c1b150d4a04347e68c0f30f2d0a598 -r 501f510ff101849c45d9b0925bb55fe59319088b test/casperjs/api-hda-tests.js
--- a/test/casperjs/api-hda-tests.js
+++ b/test/casperjs/api-hda-tests.js
@@ -7,363 +7,359 @@
spaceghost.test.begin( 'Test the HDA API', 0, function suite( test ){
spaceghost.start();
-// =================================================================== SET UP
-var email = spaceghost.user.getRandomEmail(),
- password = '123456';
-if( spaceghost.fixtureData.testUser ){
- email = spaceghost.fixtureData.testUser.email;
- password = spaceghost.fixtureData.testUser.password;
-}
-spaceghost.user.loginOrRegisterUser( email, password );
+ // =================================================================== SET UP
+ var email = spaceghost.user.getRandomEmail(),
+ password = '123456';
+ if( spaceghost.fixtureData.testUser ){
+ email = spaceghost.fixtureData.testUser.email;
+ password = spaceghost.fixtureData.testUser.password;
+ }
+ spaceghost.user.loginOrRegisterUser( email, password );
-spaceghost.thenOpen( spaceghost.baseUrl, function(){
- this.test.comment( '(logged in as ' + this.user.loggedInAs() + ')' );
- this.api.tools.thenUpload( spaceghost.api.histories.index()[0].id, {
+ spaceghost.openHomePage().api.tools.thenUploadToCurrent({
filepath: '../../test-data/1.sam'
});
-});
-// =================================================================== TESTS
-var summaryKeys = [ 'id', 'name', 'history_id', 'state', 'deleted', 'purged', 'visible', 'url', 'type' ],
- detailKeys = [
- // the following are always present regardless of datatype
- 'id', 'name', 'api_type', 'model_class',
- 'history_id', 'hid',
- 'accessible', 'deleted', 'visible', 'purged',
- 'state', 'data_type', 'file_ext', 'file_size',
- 'misc_info', 'misc_blurb',
- 'download_url', 'visualizations', 'display_apps', 'display_types',
- 'genome_build',
- // the following are NOT always present DEPENDING ON datatype
- 'metadata_dbkey',
- 'metadata_column_names', 'metadata_column_types', 'metadata_columns',
- 'metadata_comment_lines', 'metadata_data_lines'
- ];
+ // =================================================================== TESTS
+ var summaryKeys = [ 'id', 'name', 'history_id', 'state', 'deleted', 'purged', 'visible', 'url', 'type' ],
+ detailKeys = [
+ // the following are always present regardless of datatype
+ 'id', 'name', 'api_type', 'model_class',
+ 'history_id', 'hid',
+ 'accessible', 'deleted', 'visible', 'purged',
+ 'state', 'data_type', 'file_ext', 'file_size',
+ 'misc_info', 'misc_blurb',
+ 'download_url', 'visualizations', 'display_apps', 'display_types',
+ 'genome_build',
+ // the following are NOT always present DEPENDING ON datatype
+ 'metadata_dbkey',
+ 'metadata_column_names', 'metadata_column_types', 'metadata_columns',
+ 'metadata_comment_lines', 'metadata_data_lines'
+ ];
-// ------------------------------------------------------------------------------------------- logged in user
-spaceghost.then( function(){
-
- // ------------------------------------------------------------------------------------------- INDEX
- this.test.comment( 'index should return a list of summary data for each hda' );
- var histories = this.api.histories.index(),
- lastHistory = histories[0],
- hdaIndex = this.api.hdas.index( lastHistory.id );
- //this.debug( 'hdaIndex:' + this.jsonStr( hdaIndex ) );
+ // ------------------------------------------------------------------------------------------- logged in user
+ spaceghost.then( function(){
+ // ------------------------------------------------------------------------------------------- INDEX
+ this.test.comment( 'index should return a list of summary data for each hda' );
+ var histories = this.api.histories.index(),
+ lastHistory = histories[0],
+ hdaIndex = this.api.hdas.index( lastHistory.id );
+ //this.debug( 'hdaIndex:' + this.jsonStr( hdaIndex ) );
- this.test.assert( utils.isArray( hdaIndex ), "index returned an array: length " + hdaIndex.length );
- this.test.assert( hdaIndex.length >= 1, 'Has at least one hda' );
+ this.test.assert( utils.isArray( hdaIndex ), "index returned an array: length " + hdaIndex.length );
+ this.test.assert( hdaIndex.length >= 1, 'Has at least one hda' );
- var firstHda = hdaIndex[0];
- this.test.assert( this.hasKeys( firstHda, summaryKeys ), 'Has the proper keys' );
+ var firstHda = hdaIndex[0];
+ this.test.assert( this.hasKeys( firstHda, summaryKeys ), 'Has the proper keys' );
- this.test.assert( this.api.isEncodedId( firstHda.id ), 'Id appears well-formed: ' + firstHda.id );
- this.test.assert( firstHda.name === '1.sam', 'Title matches: ' + firstHda.name );
+ this.test.assert( this.api.isEncodedId( firstHda.id ), 'Id appears well-formed: ' + firstHda.id );
+ this.test.assert( firstHda.name === '1.sam', 'Title matches: ' + firstHda.name );
- // ------------------------------------------------------------------------------------------- SHOW
- this.test.comment( 'show should get an HDA details object' );
- var hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- //this.debug( this.jsonStr( hdaShow ) );
- this.test.assert( this.hasKeys( hdaShow, detailKeys ), 'Has the proper keys' );
+ // ------------------------------------------------------------------------------------------- SHOW
+ this.test.comment( 'show should get an HDA details object' );
+ var hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ //this.debug( this.jsonStr( hdaShow ) );
+ this.test.assert( this.hasKeys( hdaShow, detailKeys ), 'Has the proper keys' );
- //TODO: validate data in each hdaShow attribute...
+ //TODO: validate data in each hdaShow attribute...
- // ------------------------------------------------------------------------------------------- INDEX (detailed)
- this.test.comment( 'index should return a list of detailed data for each hda in "ids" when passed' );
- hdaIndex = this.api.hdas.index( lastHistory.id, [ firstHda.id ] );
- this.debug( 'hdaIndex:' + this.jsonStr( hdaIndex ) );
+ // ------------------------------------------------------------------------------------------- INDEX (detailed)
+ this.test.comment( 'index should return a list of detailed data for each hda in "ids" when passed' );
+ hdaIndex = this.api.hdas.index( lastHistory.id, [ firstHda.id ] );
+ this.debug( 'hdaIndex:' + this.jsonStr( hdaIndex ) );
- this.test.assert( utils.isArray( hdaIndex ), "index returned an array: length " + hdaIndex.length );
- this.test.assert( hdaIndex.length >= 1, 'Has at least one hda' );
+ this.test.assert( utils.isArray( hdaIndex ), "index returned an array: length " + hdaIndex.length );
+ this.test.assert( hdaIndex.length >= 1, 'Has at least one hda' );
- firstHda = hdaIndex[0];
- this.test.assert( this.hasKeys( firstHda, detailKeys ), 'Has the proper keys' );
+ firstHda = hdaIndex[0];
+ this.test.assert( this.hasKeys( firstHda, detailKeys ), 'Has the proper keys' );
- //TODO??: validate data in firstHda attribute? we ASSUME it's from a common method as show...
+ //TODO??: validate data in firstHda attribute? we ASSUME it's from a common method as show...
- // ------------------------------------------------------------------------------------------- CREATE
- //TODO: create from_ld_id
- this.test.comment( 'create should allow copying an accessible hda' );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- var returned = this.api.hdas.create( lastHistory.id, {
- source : 'hda',
- content : hdaShow.id
+ // ------------------------------------------------------------------------------------------- CREATE
+ //TODO: create from_ld_id
+ this.test.comment( 'create should allow copying an accessible hda' );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ var returned = this.api.hdas.create( lastHistory.id, {
+ source : 'hda',
+ content : hdaShow.id
+ });
+ //this.debug( 'returned:' + this.jsonStr( returned ) );
+ this.test.assert( this.hasKeys( returned, detailKeys ), 'Has the proper keys' );
+ this.test.assert( typeof returned.id !== 'number' && isNaN( Number( returned.id ) ),
+ 'id seems to be encoded: ' + returned.id );
+ this.test.assert( typeof returned.history_id !== 'number' && isNaN( Number( returned.history_id ) ),
+ 'history_id seems to be encoded: ' + returned.history_id );
+
+
+ // ------------------------------------------------------------------------------------------- UPDATE
+ // ........................................................................................... idiot proofing
+ this.test.comment( 'updating to the current value should return no value (no change)' );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ var returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ name : hdaShow.name
+ });
+ this.test.assert( this.countKeys( returned ) === 0, "No changed returned: " + this.jsonStr( returned ) );
+
+ this.test.comment( 'updating using a nonsense key should NOT fail with an error' );
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ konamiCode : 'uuddlrlrba'
+ });
+ this.test.assert( this.countKeys( returned ) === 0, "No changed returned: " + this.jsonStr( returned ) );
+
+ this.test.comment( 'updating by attempting to change type should cause an error' );
+ this.api.assertRaises( function(){
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ //name : false
+ deleted : 'sure why not'
+ });
+ }, 400, 'deleted must be a boolean', 'changing deleted type failed' );
+
+ // ........................................................................................... name
+ this.test.comment( 'update should allow changing the name' );
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ name : 'New name'
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.name === 'New name', "Name successfully set via update: " + hdaShow.name );
+
+ this.test.comment( 'update should sanitize any new name' );
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ name : 'New name<script type="text/javascript" src="bler">alert("blah");</script>'
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.name === 'New name', "Update sanitized name: " + hdaShow.name );
+
+ this.test.comment( 'update should allow unicode in names' );
+ var unicodeName = 'Ржевский сапоги';
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ name : unicodeName
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.name === unicodeName, "Update accepted unicode name: " + hdaShow.name );
+
+ this.test.comment( 'update should allow escaped quotations in names' );
+ var quotedName = '"Bler"';
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ name : quotedName
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.name === quotedName,
+ "Update accepted escaped quotations in name: " + hdaShow.name );
+
+
+ // ........................................................................................... deleted
+ this.test.comment( 'update should allow changing the deleted flag' );
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ deleted: true
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id, true );
+ this.test.assert( hdaShow.deleted === true, "Update set the deleted flag: " + hdaShow.deleted );
+
+ this.test.comment( 'update should allow changing the deleted flag back' );
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ deleted: false
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.deleted === false, "Update set the deleted flag: " + hdaShow.deleted );
+
+
+ // ........................................................................................... visible/hidden
+ this.test.comment( 'update should allow changing the visible flag' );
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ visible: false
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.visible === false, "Update set the visible flag: " + hdaShow.visible );
+
+
+ // ........................................................................................... genome/dbkey
+ this.test.comment( 'update should allow changing the genome_build' );
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ genome_build : 'hg18'
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ //this.debug( 'hdaShow:\n' + this.jsonStr( hdaShow ) );
+ this.test.assert( hdaShow.genome_build === 'hg18',
+ "genome_build successfully set via update: " + hdaShow.genome_build );
+ this.test.assert( hdaShow.metadata_dbkey === 'hg18',
+ "metadata_dbkey successfully set via the same update: " + hdaShow.metadata_dbkey );
+ this.test.comment( 'update should sanitize any genome_build' );
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ genome_build : 'hg18<script type="text/javascript" src="bler">alert("blah");</script>'
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.genome_build === 'hg18',
+ "Update sanitized genome_build: " + hdaShow.genome_build );
+ this.test.assert( hdaShow.metadata_dbkey === 'hg18',
+ "metadata_dbkey successfully set via the same update: " + hdaShow.metadata_dbkey );
+
+ this.test.comment( 'update should allow unicode in genome builds' );
+ var unicodeBuild = 'Ржевский18';
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ genome_build : unicodeBuild
+ });
+ this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.debug( 'hdaShow:\n' + this.jsonStr( hdaShow ) );
+ this.test.assert( hdaShow.genome_build === unicodeBuild,
+ "Update accepted unicode genome_build: " + hdaShow.genome_build );
+
+ // ........................................................................................... misc_info/info
+ this.test.comment( 'update should allow changing the misc_info' );
+ var newInfo = 'I\'ve made a huge mistake.';
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ misc_info : newInfo
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.misc_info === newInfo,
+ "misc_info successfully set via update: " + hdaShow.misc_info );
+
+ this.test.comment( 'update should sanitize any misc_info' );
+ var newInfo = 'You\'re going to get hop-ons.';
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ misc_info : newInfo + '<script type="text/javascript" src="bler">alert("blah");</script>'
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.misc_info === newInfo,
+ "Update sanitized misc_info: " + hdaShow.misc_info );
+
+ this.test.comment( 'update should allow unicode in misc_info' );
+ var unicodeInfo = '여보!';
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ misc_info : unicodeInfo
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.misc_info === unicodeInfo,
+ "Update accepted unicode misc_info: " + hdaShow.misc_info );
+
+ // ........................................................................................... annotation
+ // currently fails because no annotation is returned in details
+ this.test.comment( 'update should allow changing the annotation' );
+ var newAnnotation = 'Found this sample on a movie theatre floor';
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ annotation : newAnnotation
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.annotation === newAnnotation,
+ "Annotation successfully set via update: " + hdaShow.annotation );
+
+ this.test.comment( 'update should sanitize any new annotation' );
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ annotation : 'New annotation<script type="text/javascript" src="bler">alert("blah");</script>'
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.annotation === 'New annotation',
+ "Update sanitized annotation: " + hdaShow.annotation );
+
+ this.test.comment( 'update should allow unicode in annotations' );
+ var unicodeAnnotation = 'お願いは、それが落下させない';
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ annotation : unicodeAnnotation
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.annotation === unicodeAnnotation,
+ "Update accepted unicode annotation: " + hdaShow.annotation );
+
+ this.test.comment( 'update should allow escaped quotations in annotations' );
+ var quotedAnnotation = '"Bler"';
+ returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
+ annotation : quotedAnnotation
+ });
+ //this.debug( 'returned:\n' + this.jsonStr( returned ) );
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.annotation === quotedAnnotation,
+ "Update accepted escaped quotations in annotation: " + hdaShow.annotation );
+
+ // ------------------------------------------------------------------------------------------- ERRORS
+ this.test.comment( 'create should error with "Please define the source" when the param "from_ld_id" is not used' );
+ this.api.assertRaises( function(){
+ this.api.hdas.create( lastHistory.id, { bler: 'bler' } );
+ }, 400, "must be either 'library' or 'hda'", 'create with no source failed' );
+
+ this.test.comment( 'updating using a nonsense key should fail silently' );
+ returned = this.api.hdas.update( lastHistory.id, hdaShow.id, {
+ konamiCode : 'uuddlrlrba'
+ });
+ this.test.assert( returned.konamiCode === undefined, 'key was not set: ' + returned.konamiCode );
+
+ spaceghost.test.comment( 'A bad id should throw an error when using show' );
+ this.api.assertRaises( function(){
+ this.api.hdas.show( lastHistory.id, '1234123412341234' );
+ }, 400, 'unable to decode', 'Bad Request with invalid id: show' );
+ spaceghost.test.comment( 'A bad id should throw an error when using update' );
+ this.api.assertRaises( function(){
+ this.api.hdas.update( lastHistory.id, '1234123412341234', {} );
+ }, 400, 'unable to decode', 'Bad Request with invalid id: update' );
+ spaceghost.test.comment( 'A bad id should throw an error when using delete' );
+ this.api.assertRaises( function(){
+ this.api.hdas.delete_( lastHistory.id, '1234123412341234' );
+ }, 400, 'unable to decode', 'Bad Request with invalid id: delete' );
+ spaceghost.test.comment( 'A bad id should throw an error when using undelete' );
+
+ this.test.comment( 'updating by attempting to change type should cause an error' );
+ [ 'name', 'annotation', 'genome_build', 'misc_info' ].forEach( function( key ){
+ var updatedAttrs = {};
+ updatedAttrs[ key ] = false;
+ spaceghost.api.assertRaises( function(){
+ returned = spaceghost.api.hdas.update( hdaShow.history_id, hdaShow.id, updatedAttrs );
+ }, 400, key + ' must be a string or unicode', 'type validation error' );
+ });
+ [ 'deleted', 'visible' ].forEach( function( key ){
+ var updatedAttrs = {};
+ updatedAttrs[ key ] = 'straaang';
+ spaceghost.api.assertRaises( function(){
+ returned = spaceghost.api.hdas.update( hdaShow.history_id, hdaShow.id, updatedAttrs );
+ }, 400, key + ' must be a boolean', 'type validation error' );
+ });
+ [ 'you\'re it', [ true ] ].forEach( function( badVal ){
+ spaceghost.api.assertRaises( function(){
+ returned = spaceghost.api.hdas.update( hdaShow.history_id, hdaShow.id, { tags: badVal });
+ }, 400, 'tags must be a list', 'type validation error' );
+ });
+
+ // ------------------------------------------------------------------------------------------- DELETE
+ this.test.comment( 'calling delete on an hda should mark it as deleted but not change the history size' );
+ lastHistory = this.api.histories.show( lastHistory.id );
+ var sizeBeforeDelete = lastHistory.nice_size;
+
+ returned = this.api.hdas.delete_( lastHistory.id, firstHda.id );
+ //this.debug( this.jsonStr( returned ) );
+
+ hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
+ this.test.assert( hdaShow.deleted, 'hda is marked deleted' );
+ lastHistory = this.api.histories.show( lastHistory.id );
+ this.test.assert( lastHistory.nice_size === sizeBeforeDelete, 'history size has not changed' );
+
+ // by default, purging fails bc uni.ini:allow_user_dataset_purge=False
+ this.api.assertRaises( function(){
+ returned = this.api.hdas.delete_( lastHistory.id, firstHda.id, { purge : true });
+ }, 403, 'This instance does not allow user dataset purging', 'Purge failed' );
+ /*
+ */
});
- //this.debug( 'returned:' + this.jsonStr( returned ) );
- this.test.assert( this.hasKeys( returned, detailKeys ), 'Has the proper keys' );
- this.test.assert( typeof returned.id !== 'number' && isNaN( Number( returned.id ) ),
- 'id seems to be encoded: ' + returned.id );
- this.test.assert( typeof returned.history_id !== 'number' && isNaN( Number( returned.history_id ) ),
- 'history_id seems to be encoded: ' + returned.history_id );
+ //spaceghost.user.logout();
- // ------------------------------------------------------------------------------------------- UPDATE
- // ........................................................................................... idiot proofing
- this.test.comment( 'updating to the current value should return no value (no change)' );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- var returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- name : hdaShow.name
- });
- this.test.assert( this.countKeys( returned ) === 0, "No changed returned: " + this.jsonStr( returned ) );
-
- this.test.comment( 'updating using a nonsense key should NOT fail with an error' );
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- konamiCode : 'uuddlrlrba'
- });
- this.test.assert( this.countKeys( returned ) === 0, "No changed returned: " + this.jsonStr( returned ) );
-
- this.test.comment( 'updating by attempting to change type should cause an error' );
- this.api.assertRaises( function(){
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- //name : false
- deleted : 'sure why not'
- });
- }, 400, 'deleted must be a boolean', 'changing deleted type failed' );
-
- // ........................................................................................... name
- this.test.comment( 'update should allow changing the name' );
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- name : 'New name'
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.name === 'New name', "Name successfully set via update: " + hdaShow.name );
-
- this.test.comment( 'update should sanitize any new name' );
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- name : 'New name<script type="text/javascript" src="bler">alert("blah");</script>'
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.name === 'New name', "Update sanitized name: " + hdaShow.name );
-
- this.test.comment( 'update should allow unicode in names' );
- var unicodeName = 'Ржевский сапоги';
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- name : unicodeName
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.name === unicodeName, "Update accepted unicode name: " + hdaShow.name );
-
- this.test.comment( 'update should allow escaped quotations in names' );
- var quotedName = '"Bler"';
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- name : quotedName
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.name === quotedName,
- "Update accepted escaped quotations in name: " + hdaShow.name );
-
-
- // ........................................................................................... deleted
- this.test.comment( 'update should allow changing the deleted flag' );
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- deleted: true
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id, true );
- this.test.assert( hdaShow.deleted === true, "Update set the deleted flag: " + hdaShow.deleted );
-
- this.test.comment( 'update should allow changing the deleted flag back' );
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- deleted: false
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.deleted === false, "Update set the deleted flag: " + hdaShow.deleted );
-
-
- // ........................................................................................... visible/hidden
- this.test.comment( 'update should allow changing the visible flag' );
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- visible: false
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.visible === false, "Update set the visible flag: " + hdaShow.visible );
-
-
- // ........................................................................................... genome_build/dbkey
- this.test.comment( 'update should allow changing the genome_build' );
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- genome_build : 'hg18'
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- //this.debug( 'hdaShow:\n' + this.jsonStr( hdaShow ) );
- this.test.assert( hdaShow.genome_build === 'hg18',
- "genome_build successfully set via update: " + hdaShow.genome_build );
- this.test.assert( hdaShow.metadata_dbkey === 'hg18',
- "metadata_dbkey successfully set via the same update: " + hdaShow.metadata_dbkey );
- this.test.comment( 'update should sanitize any genome_build' );
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- genome_build : 'hg18<script type="text/javascript" src="bler">alert("blah");</script>'
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.genome_build === 'hg18',
- "Update sanitized genome_build: " + hdaShow.genome_build );
- this.test.assert( hdaShow.metadata_dbkey === 'hg18',
- "metadata_dbkey successfully set via the same update: " + hdaShow.metadata_dbkey );
-
- this.test.comment( 'update should allow unicode in genome builds' );
- var unicodeBuild = 'Ржевский18';
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- genome_build : unicodeBuild
- });
- this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.debug( 'hdaShow:\n' + this.jsonStr( hdaShow ) );
- this.test.assert( hdaShow.genome_build === unicodeBuild,
- "Update accepted unicode genome_build: " + hdaShow.genome_build );
-
- // ........................................................................................... misc_info/info
- this.test.comment( 'update should allow changing the misc_info' );
- var newInfo = 'I\'ve made a huge mistake.';
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- misc_info : newInfo
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.misc_info === newInfo,
- "misc_info successfully set via update: " + hdaShow.misc_info );
-
- this.test.comment( 'update should sanitize any misc_info' );
- var newInfo = 'You\'re going to get hop-ons.';
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- misc_info : newInfo + '<script type="text/javascript" src="bler">alert("blah");</script>'
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.misc_info === newInfo,
- "Update sanitized misc_info: " + hdaShow.misc_info );
-
- this.test.comment( 'update should allow unicode in misc_info' );
- var unicodeInfo = '여보!';
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- misc_info : unicodeInfo
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.misc_info === unicodeInfo,
- "Update accepted unicode misc_info: " + hdaShow.misc_info );
-
- // ........................................................................................... annotation
- // currently fails because no annotation is returned in details
- this.test.comment( 'update should allow changing the annotation' );
- var newAnnotation = 'Found this sample on a movie theatre floor';
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- annotation : newAnnotation
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.annotation === newAnnotation,
- "Annotation successfully set via update: " + hdaShow.annotation );
-
- this.test.comment( 'update should sanitize any new annotation' );
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- annotation : 'New annotation<script type="text/javascript" src="bler">alert("blah");</script>'
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.annotation === 'New annotation',
- "Update sanitized annotation: " + hdaShow.annotation );
-
- this.test.comment( 'update should allow unicode in annotations' );
- var unicodeAnnotation = 'お願いは、それが落下させない';
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- annotation : unicodeAnnotation
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.annotation === unicodeAnnotation,
- "Update accepted unicode annotation: " + hdaShow.annotation );
-
- this.test.comment( 'update should allow escaped quotations in annotations' );
- var quotedAnnotation = '"Bler"';
- returned = this.api.hdas.update( lastHistory.id, firstHda.id, {
- annotation : quotedAnnotation
- });
- //this.debug( 'returned:\n' + this.jsonStr( returned ) );
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.annotation === quotedAnnotation,
- "Update accepted escaped quotations in annotation: " + hdaShow.annotation );
-
- // ------------------------------------------------------------------------------------------- ERRORS
- this.test.comment( 'create should error with "Please define the source" when the param "from_ld_id" is not used' );
- this.api.assertRaises( function(){
- this.api.hdas.create( lastHistory.id, { bler: 'bler' } );
- }, 400, "must be either 'library' or 'hda'", 'create with no source failed' );
-
- this.test.comment( 'updating using a nonsense key should fail silently' );
- returned = this.api.hdas.update( lastHistory.id, hdaShow.id, {
- konamiCode : 'uuddlrlrba'
- });
- this.test.assert( returned.konamiCode === undefined, 'key was not set: ' + returned.konamiCode );
-
- spaceghost.test.comment( 'A bad id should throw an error when using show' );
- this.api.assertRaises( function(){
- this.api.hdas.show( lastHistory.id, '1234123412341234' );
- }, 400, 'unable to decode', 'Bad Request with invalid id: show' );
- spaceghost.test.comment( 'A bad id should throw an error when using update' );
- this.api.assertRaises( function(){
- this.api.hdas.update( lastHistory.id, '1234123412341234', {} );
- }, 400, 'unable to decode', 'Bad Request with invalid id: update' );
- spaceghost.test.comment( 'A bad id should throw an error when using delete' );
- this.api.assertRaises( function(){
- this.api.hdas.delete_( lastHistory.id, '1234123412341234' );
- }, 400, 'unable to decode', 'Bad Request with invalid id: delete' );
- spaceghost.test.comment( 'A bad id should throw an error when using undelete' );
-
- this.test.comment( 'updating by attempting to change type should cause an error' );
- [ 'name', 'annotation', 'genome_build', 'misc_info' ].forEach( function( key ){
- var updatedAttrs = {};
- updatedAttrs[ key ] = false;
- spaceghost.api.assertRaises( function(){
- returned = spaceghost.api.hdas.update( hdaShow.history_id, hdaShow.id, updatedAttrs );
- }, 400, key + ' must be a string or unicode', 'type validation error' );
- });
- [ 'deleted', 'visible' ].forEach( function( key ){
- var updatedAttrs = {};
- updatedAttrs[ key ] = 'straaang';
- spaceghost.api.assertRaises( function(){
- returned = spaceghost.api.hdas.update( hdaShow.history_id, hdaShow.id, updatedAttrs );
- }, 400, key + ' must be a boolean', 'type validation error' );
- });
- [ 'you\'re it', [ true ] ].forEach( function( badVal ){
- spaceghost.api.assertRaises( function(){
- returned = spaceghost.api.hdas.update( hdaShow.history_id, hdaShow.id, { tags: badVal });
- }, 400, 'tags must be a list', 'type validation error' );
- });
-
- // ------------------------------------------------------------------------------------------- DELETE
- this.test.comment( 'calling delete on an hda should mark it as deleted but not change the history size' );
- lastHistory = this.api.histories.show( lastHistory.id );
- var sizeBeforeDelete = lastHistory.nice_size;
-
- returned = this.api.hdas.delete_( lastHistory.id, firstHda.id );
- //this.debug( this.jsonStr( returned ) );
-
- hdaShow = this.api.hdas.show( lastHistory.id, firstHda.id );
- this.test.assert( hdaShow.deleted, 'hda is marked deleted' );
- lastHistory = this.api.histories.show( lastHistory.id );
- this.test.assert( lastHistory.nice_size === sizeBeforeDelete, 'history size has not changed' );
-
- // by default, purging fails bc uni.ini:allow_user_dataset_purge=False
- this.api.assertRaises( function(){
- returned = this.api.hdas.delete_( lastHistory.id, firstHda.id, { purge : true });
- }, 403, 'This instance does not allow user dataset purging', 'Purge failed' );
-/*
-*/
-});
-//spaceghost.user.logout();
-
-
-// ===================================================================
+ // ===================================================================
spaceghost.run( function(){ test.done(); });
});
This diff is so big that we needed to truncate the remainder.
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
10 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/9e973ebf7272/
Changeset: 9e973ebf7272
User: jmchilton
Date: 2014-12-22 18:16:25+00:00
Summary: Remove some unused imports from lib/galaxy/tools/__init__.py.
Affected #: 1 file
diff -r 815d38c48a5639d47eed92806ef4c196406f58f1 -r 9e973ebf7272bcd1ff684e82bfb62b4938875f94 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -7,20 +7,15 @@
import json
import logging
import os
-import pipes
import re
import shutil
-import sys
import string
import tarfile
import tempfile
import threading
-import traceback
import types
import urllib
-from math import isinf
-
from galaxy import eggs
eggs.require( "MarkupSafe" ) # MarkupSafe must load before mako
eggs.require( "Mako" )
@@ -35,10 +30,8 @@
from sqlalchemy import and_
from galaxy import jobs, model
-from galaxy.jobs.error_level import StdioErrorLevel
from galaxy.datatypes.metadata import JobExternalOutputMetadataWrapper
from galaxy import exceptions
-from galaxy.jobs import ParallelismInfo
from galaxy.tools import watcher
from galaxy.tools.actions import DefaultToolAction
from galaxy.tools.actions.data_source import DataSourceToolAction
@@ -58,12 +51,11 @@
from galaxy.tools.test import parse_tests
from galaxy.tools.parser import get_tool_source
from galaxy.tools.parser.xml import XmlPageSource
-from galaxy.util import listify, parse_xml, rst_to_html, string_as_bool, string_to_object, xml_text, xml_to_string
+from galaxy.util import listify, parse_xml, rst_to_html, string_as_bool, string_to_object
from galaxy.tools.parameters.meta import expand_meta_parameters
from galaxy.util.bunch import Bunch
from galaxy.util.expressions import ExpressionContext
from galaxy.util.hash_util import hmac_new
-from galaxy.util.none_like import NoneDataset
from galaxy.util.odict import odict
from galaxy.util.template import fill_template
from galaxy.web import url_for
@@ -73,7 +65,7 @@
from galaxy.model import Workflow
from tool_shed.util import common_util
from tool_shed.util import shed_util_common as suc
-from .loader import load_tool, template_macro_params, raw_tool_xml_tree, imported_macro_paths
+from .loader import template_macro_params, raw_tool_xml_tree, imported_macro_paths
from .execute import execute as execute_job
from .wrappers import (
ToolParameterValueWrapper,
https://bitbucket.org/galaxy/galaxy-central/commits/6e956fdb0034/
Changeset: 6e956fdb0034
User: jmchilton
Date: 2014-12-22 18:16:25+00:00
Summary: More PEP-8 style tweaks to lib/galaxy/tools/__init__.py.
Affected #: 1 file
diff -r 9e973ebf7272bcd1ff684e82bfb62b4938875f94 -r 6e956fdb003441f699e24750f02c61c43992a784 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -257,8 +257,9 @@
return tool_path
def __add_tool_to_tool_panel( self, tool, panel_component, section=False ):
- # See if a version of this tool is already loaded into the tool panel. The value of panel_component
- # will be a ToolSection (if the value of section=True) or self.tool_panel (if section=False).
+ # See if a version of this tool is already loaded into the tool panel.
+ # The value of panel_component will be a ToolSection (if the value of
+ # section=True) or self.tool_panel (if section=False).
tool_id = str( tool.id )
tool = self.tools_by_id[ tool_id ]
if section:
@@ -300,13 +301,17 @@
if not inserted:
inserted = True
if not inserted:
- if tool.guid is None or \
- tool.tool_shed is None or \
- tool.repository_name is None or \
- tool.repository_owner is None or \
- tool.installed_changeset_revision is None:
- # We have a tool that was not installed from the Tool Shed, but is also not yet defined in
- # integrated_tool_panel.xml, so append it to the tool panel.
+ if (
+ tool.guid is None or
+ tool.tool_shed is None or
+ tool.repository_name is None or
+ tool.repository_owner is None or
+ tool.installed_changeset_revision is None
+ ):
+ # We have a tool that was not installed from the Tool
+ # Shed, but is also not yet defined in
+ # integrated_tool_panel.xml, so append it to the tool
+ # panel.
panel_dict[ key ] = tool
log.debug( "Loaded tool id: %s, version: %s into tool panel.." % ( tool.id, tool.version ) )
else:
@@ -364,9 +369,10 @@
def load_integrated_tool_panel_keys( self ):
"""
- Load the integrated tool panel keys, setting values for tools and workflows to None. The values will
- be reset when the various tool panel config files are parsed, at which time the tools and workflows are
- loaded.
+ Load the integrated tool panel keys, setting values for tools and
+ workflows to None. The values will be reset when the various tool
+ panel config files are parsed, at which time the tools and workflows
+ are loaded.
"""
tree = parse_xml( self.integrated_tool_panel_config )
root = tree.getroot()
@@ -499,11 +505,11 @@
# We store only the port, if one exists, in the database.
tool_shed = common_util.remove_protocol_from_tool_shed_url( tool_shed )
return self.app.install_model.context.query( self.app.install_model.ToolShedRepository ) \
- .filter( and_( self.app.install_model.ToolShedRepository.table.c.tool_shed == tool_shed,
- self.app.install_model.ToolShedRepository.table.c.name == name,
- self.app.install_model.ToolShedRepository.table.c.owner == owner,
- self.app.install_model.ToolShedRepository.table.c.installed_changeset_revision == installed_changeset_revision ) ) \
- .first()
+ .filter( and_( self.app.install_model.ToolShedRepository.table.c.tool_shed == tool_shed,
+ self.app.install_model.ToolShedRepository.table.c.name == name,
+ self.app.install_model.ToolShedRepository.table.c.owner == owner,
+ self.app.install_model.ToolShedRepository.table.c.installed_changeset_revision == installed_changeset_revision ) ) \
+ .first()
def get_tool_components( self, tool_id, tool_version=None, get_loaded_tools_by_lineage=False, set_selected=False ):
"""
@@ -627,12 +633,14 @@
log.exception( "Error reading tool from path: %s" % path )
def __add_tool( self, tool, load_panel_dict, panel_dict ):
- # Allow for the same tool to be loaded into multiple places in the tool panel. We have to handle
- # the case where the tool is contained in a repository installed from the tool shed, and the Galaxy
- # administrator has retrieved updates to the installed repository. In this case, the tool may have
- # been updated, but the version was not changed, so the tool should always be reloaded here. We used
- # to only load the tool if it was not found in self.tools_by_id, but performing that check did
- # not enable this scenario.
+ # Allow for the same tool to be loaded into multiple places in the
+ # tool panel. We have to handle the case where the tool is contained
+ # in a repository installed from the tool shed, and the Galaxy
+ # administrator has retrieved updates to the installed repository. In
+ # this case, the tool may have been updated, but the version was not
+ # changed, so the tool should always be reloaded here. We used to
+ # only load the tool if it was not found in self.tools_by_id, but
+ # performing that check did not enable this scenario.
self.tools_by_id[ tool.id ] = tool
if load_panel_dict:
self.__add_tool_to_tool_panel( tool, panel_dict, section=isinstance( panel_dict, ToolSection ) )
@@ -787,8 +795,6 @@
:param tool_id: the tool ID from app.toolbox
:returns: tuple of tarball filename, success True/False, message/None
"""
- message = ''
- success = True
# Make sure the tool is actually loaded.
if tool_id not in self.tools_by_id:
return None, False, "No tool with id %s" % escape( tool_id )
@@ -870,7 +876,6 @@
if os.path.exists( sample_file ):
tarfile_path, tarfile_name = os.path.split( tar_file )
tarfile_path = os.path.join( 'tool-data', tarfile_name )
- sample_name = tarfile_path + '.sample'
tarball_files.append( ( sample_file, tarfile_path ) )
data_table_definitions.append( data_table.xml_string )
if len( data_table_definitions ) > 0:
https://bitbucket.org/galaxy/galaxy-central/commits/50a4c5ef908c/
Changeset: 50a4c5ef908c
User: jmchilton
Date: 2014-12-22 18:16:26+00:00
Summary: Small simplifications to lib/galaxy/tools/__init__.py.
Affected #: 1 file
diff -r 6e956fdb003441f699e24750f02c61c43992a784 -r 50a4c5ef908c38ecf6530d7ac9dd3a497d1ec313 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -289,8 +289,7 @@
for index, integrated_panel_key in enumerate( self.integrated_tool_panel.keys() ):
if key == integrated_panel_key:
panel_dict.insert( index, key, tool )
- if not inserted:
- inserted = True
+ inserted = True
if not inserted:
# Check the tool's installed versions.
for lineage_id in tool.lineage_ids:
@@ -298,8 +297,7 @@
for index, integrated_panel_key in enumerate( self.integrated_tool_panel.keys() ):
if lineage_id_key == integrated_panel_key:
panel_dict.insert( index, key, tool )
- if not inserted:
- inserted = True
+ inserted = True
if not inserted:
if (
tool.guid is None or
@@ -322,8 +320,7 @@
if lineage_id in self.tools_by_id:
loaded_version_key = 'tool_%s' % lineage_id
if loaded_version_key in panel_dict:
- if not already_loaded:
- already_loaded = True
+ already_loaded = True
if not already_loaded:
# If the tool is not defined in integrated_tool_panel.xml, append it to the tool panel.
panel_dict[ key ] = tool
https://bitbucket.org/galaxy/galaxy-central/commits/de3fff02e89f/
Changeset: de3fff02e89f
User: jmchilton
Date: 2014-12-22 18:16:26+00:00
Summary: Remove broken method fix_integrated_tool_panel_dict.
As of 5f6c670 (Jan 10, 2014) this does nothing (``if section_value is None`` followed by ``if isinstance( section_value, Tool ):``) and nobody seemed to notice - so I assume it is unneeded. If still needed - someone needs to fix it :).
Affected #: 1 file
diff -r 50a4c5ef908c38ecf6530d7ac9dd3a497d1ec313 -r de3fff02e89fd4697e9656742ca8e3f4928b1a53 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -163,24 +163,8 @@
# This will cover cases where the Galaxy administrator manually edited one or more of the tool panel
# config files, adding or removing locally developed tools or workflows. The value of integrated_tool_panel
# will be False when things like functional tests are the caller.
- self.fix_integrated_tool_panel_dict()
self.write_integrated_tool_panel_config_file()
- def fix_integrated_tool_panel_dict( self ):
- # HACK: instead of fixing after the fact, I suggest some combination of:
- # 1) adjusting init_tools() and called methods to get this right
- # 2) redesigning the code and/or data structure used to read/write integrated_tool_panel.xml
- for key, value in self.integrated_tool_panel.iteritems():
- if isinstance( value, ToolSection ):
- for section_key, section_value in value.elems.iteritems():
- if section_value is None:
- if isinstance( section_value, Tool ):
- tool_id = section_key[5:]
- value.elems[section_key] = self.tools_by_id.get( tool_id )
- elif isinstance( section_value, Workflow ):
- workflow_id = section_key[9:]
- value.elems[section_key] = self.workflows_by_id.get( workflow_id )
-
def init_tools( self, config_filename ):
"""
Read the configuration file and load each tool. The following tags are currently supported:
@@ -723,7 +707,6 @@
# This will cover cases where the Galaxy administrator manually edited one or more of the tool panel
# config files, adding or removing locally developed tools or workflows. The value of integrated_tool_panel
# will be False when things like functional tests are the caller.
- self.fix_integrated_tool_panel_dict()
self.write_integrated_tool_panel_config_file()
return tool.id
except Exception:
https://bitbucket.org/galaxy/galaxy-central/commits/79f06cadb486/
Changeset: 79f06cadb486
User: jmchilton
Date: 2014-12-22 18:16:27+00:00
Summary: Slightly rework lib/galaxy/workflow/modules.py for readability.
Affected #: 1 file
diff -r de3fff02e89fd4697e9656742ca8e3f4928b1a53 -r 79f06cadb4861bc6e66a1733a0c3bbfa4606240c lib/galaxy/workflow/modules.py
--- a/lib/galaxy/workflow/modules.py
+++ b/lib/galaxy/workflow/modules.py
@@ -506,16 +506,17 @@
@classmethod
def from_workflow_step( Class, trans, step ):
+ toolbox = trans.app.toolbox
tool_id = step.tool_id
- if trans.app.toolbox and tool_id not in trans.app.toolbox.tools_by_id:
+ if toolbox and tool_id not in toolbox.tools_by_id:
# See if we have access to a different version of the tool.
# TODO: If workflows are ever enhanced to use tool version
# in addition to tool id, enhance the selection process here
# to retrieve the correct version of the tool.
- tool = trans.app.toolbox.get_tool( tool_id )
+ tool = toolbox.get_tool( tool_id )
if tool:
tool_id = tool.id
- if ( trans.app.toolbox and tool_id in trans.app.toolbox.tools_by_id ):
+ if ( toolbox and tool_id in toolbox.tools_by_id ):
if step.config:
# This step has its state saved in the config field due to the
# tool being previously unavailable.
https://bitbucket.org/galaxy/galaxy-central/commits/4be779372d6b/
Changeset: 4be779372d6b
User: jmchilton
Date: 2014-12-22 18:16:27+00:00
Summary: Rework toolbox 'fix' tool tags when multiple configs are loaded.
Looks like the tool tag stuff still assumed there was just one config file - that said toolbox doesn't have a self.sa_session so I think tool tags are broken and have been for some time.
Affected #: 1 file
diff -r 79f06cadb4861bc6e66a1733a0c3bbfa4606240c -r 4be779372d6b89656276307f4ae1ed4a8e6a5737 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -143,6 +143,26 @@
self.tool_watcher = watcher.get_watcher( self, app.config )
self.filter_factory = FilterFactory( self )
self.init_dependency_manager()
+ self.init_tools_from_configs( config_filenames )
+ if self.app.name == 'galaxy' and self.integrated_tool_panel_config_has_contents:
+ # Load self.tool_panel based on the order in self.integrated_tool_panel.
+ self.load_tool_panel()
+ if app.config.update_integrated_tool_panel:
+ # Write the current in-memory integrated_tool_panel to the integrated_tool_panel.xml file.
+ # This will cover cases where the Galaxy administrator manually edited one or more of the tool panel
+ # config files, adding or removing locally developed tools or workflows. The value of integrated_tool_panel
+ # will be False when things like functional tests are the caller.
+ self.write_integrated_tool_panel_config_file()
+
+ def init_tools_from_configs( self, config_filenames ):
+ """ Read through all tool config files and initialize tools in each
+ with init_tools_from_config below.
+ """
+ if self.app.config.get_bool( 'enable_tool_tags', False ):
+ log.info("removing all tool tag associations (" + str( self.sa_session.query( self.app.model.ToolTagAssociation ).count() ) + ")" )
+ self.sa_session.query( self.app.model.ToolTagAssociation ).delete()
+ self.sa_session.flush()
+
config_filenames = listify( config_filenames )
for config_filename in config_filenames:
if os.path.isdir( config_filename ):
@@ -152,20 +172,11 @@
config_filenames.extend( directory_config_files )
for config_filename in config_filenames:
try:
- self.init_tools( config_filename )
+ self.init_tools_from_config( config_filename )
except:
log.exception( "Error loading tools defined in config %s", config_filename )
- if self.app.name == 'galaxy' and self.integrated_tool_panel_config_has_contents:
- # Load self.tool_panel based on the order in self.integrated_tool_panel.
- self.load_tool_panel()
- if app.config.update_integrated_tool_panel:
- # Write the current in-memory integrated_tool_panel to the integrated_tool_panel.xml file.
- # This will cover cases where the Galaxy administrator manually edited one or more of the tool panel
- # config files, adding or removing locally developed tools or workflows. The value of integrated_tool_panel
- # will be False when things like functional tests are the caller.
- self.write_integrated_tool_panel_config_file()
-
- def init_tools( self, config_filename ):
+
+ def init_tools_from_config( self, config_filename ):
"""
Read the configuration file and load each tool. The following tags are currently supported:
@@ -183,10 +194,6 @@
</toolbox>
"""
- if self.app.config.get_bool( 'enable_tool_tags', False ):
- log.info("removing all tool tag associations (" + str( self.sa_session.query( self.app.model.ToolTagAssociation ).count() ) + ")" )
- self.sa_session.query( self.app.model.ToolTagAssociation ).delete()
- self.sa_session.flush()
log.info( "Parsing the tool configuration %s" % config_filename )
tree = parse_xml( config_filename )
root = tree.getroot()
https://bitbucket.org/galaxy/galaxy-central/commits/267fa4b9ab6a/
Changeset: 267fa4b9ab6a
User: jmchilton
Date: 2014-12-22 18:16:28+00:00
Summary: Refactor tool tag handling out of toolbox.
Pretty sure this had been broken (toolbox didn't have a self.sa_session). Anyway - this probably didn't fix that but at least now the big read tool tag loop is more readable (cyclomatic complexity of that method down from 18 to 12).
Affected #: 3 files
diff -r 4be779372d6b89656276307f4ae1ed4a8e6a5737 -r 267fa4b9ab6a80a0ae0a1f2ab5f157303f68d46d lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -51,6 +51,7 @@
from galaxy.tools.test import parse_tests
from galaxy.tools.parser import get_tool_source
from galaxy.tools.parser.xml import XmlPageSource
+from galaxy.tools.toolbox import tool_tag_manager
from galaxy.util import listify, parse_xml, rst_to_html, string_as_bool, string_to_object
from galaxy.tools.parameters.meta import expand_meta_parameters
from galaxy.util.bunch import Bunch
@@ -143,6 +144,7 @@
self.tool_watcher = watcher.get_watcher( self, app.config )
self.filter_factory = FilterFactory( self )
self.init_dependency_manager()
+ self.tool_tag_manager = tool_tag_manager( app )
self.init_tools_from_configs( config_filenames )
if self.app.name == 'galaxy' and self.integrated_tool_panel_config_has_contents:
# Load self.tool_panel based on the order in self.integrated_tool_panel.
@@ -158,11 +160,7 @@
""" Read through all tool config files and initialize tools in each
with init_tools_from_config below.
"""
- if self.app.config.get_bool( 'enable_tool_tags', False ):
- log.info("removing all tool tag associations (" + str( self.sa_session.query( self.app.model.ToolTagAssociation ).count() ) + ")" )
- self.sa_session.query( self.app.model.ToolTagAssociation ).delete()
- self.sa_session.flush()
-
+ self.tool_tag_manager.reset_tags()
config_filenames = listify( config_filenames )
for config_filename in config_filenames:
if os.path.isdir( config_filename ):
@@ -588,27 +586,7 @@
self.app.install_model.context.flush()
# Load the tool's lineage ids.
tool.lineage_ids = tool.tool_version.get_version_ids( self.app )
- if self.app.config.get_bool( 'enable_tool_tags', False ):
- tag_names = elem.get( "tags", "" ).split( "," )
- for tag_name in tag_names:
- if tag_name == '':
- continue
- tag = self.sa_session.query( self.app.model.Tag ).filter_by( name=tag_name ).first()
- if not tag:
- tag = self.app.model.Tag( name=tag_name )
- self.sa_session.add( tag )
- self.sa_session.flush()
- tta = self.app.model.ToolTagAssociation( tool_id=tool.id, tag_id=tag.id )
- self.sa_session.add( tta )
- self.sa_session.flush()
- else:
- for tagged_tool in tag.tagged_tools:
- if tagged_tool.tool_id == tool.id:
- break
- else:
- tta = self.app.model.ToolTagAssociation( tool_id=tool.id, tag_id=tag.id )
- self.sa_session.add( tta )
- self.sa_session.flush()
+ self.tool_tag_manager.handle_tags( tool.id, elem )
self.__add_tool( tool, load_panel_dict, panel_dict )
# Always load the tool into the integrated_panel_dict, or it will not be included in the integrated_tool_panel.xml file.
if key in integrated_panel_dict or index is None:
diff -r 4be779372d6b89656276307f4ae1ed4a8e6a5737 -r 267fa4b9ab6a80a0ae0a1f2ab5f157303f68d46d lib/galaxy/tools/toolbox/__init__.py
--- /dev/null
+++ b/lib/galaxy/tools/toolbox/__init__.py
@@ -0,0 +1,7 @@
+""" API for this module containing functionality related to the tool box.
+"""
+
+from .tags import tool_tag_manager
+
+
+__all__ = ["tool_tag_manager"]
diff -r 4be779372d6b89656276307f4ae1ed4a8e6a5737 -r 267fa4b9ab6a80a0ae0a1f2ab5f157303f68d46d lib/galaxy/tools/toolbox/tags.py
--- /dev/null
+++ b/lib/galaxy/tools/toolbox/tags.py
@@ -0,0 +1,76 @@
+""" Handle details of tool tagging - perhaps a deprecated feature.
+"""
+from abc import ABCMeta
+from abc import abstractmethod
+
+import logging
+log = logging.getLogger( __name__ )
+
+
+def tool_tag_manager( app ):
+ """ Build a tool tag manager according to app's configuration
+ and return it.
+ """
+ if hasattr( app.config, "get_bool" ) and app.config.get_bool( 'enable_tool_tags', False ):
+ return PersistentToolTagManager( app )
+ else:
+ return NullToolTagManager()
+
+
+class AbstractToolTagManager( object ):
+ __metaclass__ = ABCMeta
+
+ @abstractmethod
+ def reset_tags( self ):
+ """ Starting to load tool panels, reset all tags.
+ """
+
+ @abstractmethod
+ def handle_tags( self, tool_id, tool_definition_source ):
+ """ Parse out tags and persist them.
+ """
+
+
+class NullToolTagManager( AbstractToolTagManager ):
+
+ def reset_tags( self ):
+ return None
+
+ def handle_tags( self, tool_id, tool_definition_source ):
+ return None
+
+
+class PersistentToolTagManager( AbstractToolTagManager ):
+
+ def __init__( self, app ):
+ self.app = app
+ self.sa_session = app.sa_session
+
+ def reset_tags( self ):
+ log.info("removing all tool tag associations (" + str( self.sa_session.query( self.app.model.ToolTagAssociation ).count() ) + ")" )
+ self.sa_session.query( self.app.model.ToolTagAssociation ).delete()
+ self.sa_session.flush()
+
+ def handle_tags( self, tool_id, tool_definition_source ):
+ elem = tool_definition_source
+ if self.app.config.get_bool( 'enable_tool_tags', False ):
+ tag_names = elem.get( "tags", "" ).split( "," )
+ for tag_name in tag_names:
+ if tag_name == '':
+ continue
+ tag = self.sa_session.query( self.app.model.Tag ).filter_by( name=tag_name ).first()
+ if not tag:
+ tag = self.app.model.Tag( name=tag_name )
+ self.sa_session.add( tag )
+ self.sa_session.flush()
+ tta = self.app.model.ToolTagAssociation( tool_id=tool_id, tag_id=tag.id )
+ self.sa_session.add( tta )
+ self.sa_session.flush()
+ else:
+ for tagged_tool in tag.tagged_tools:
+ if tagged_tool.tool_id == tool_id:
+ break
+ else:
+ tta = self.app.model.ToolTagAssociation( tool_id=tool_id, tag_id=tag.id )
+ self.sa_session.add( tta )
+ self.sa_session.flush()
https://bitbucket.org/galaxy/galaxy-central/commits/d0c38a7861e5/
Changeset: d0c38a7861e5
User: jmchilton
Date: 2014-12-22 18:16:28+00:00
Summary: Tweak completely broken DataTransfer._execute_workflow to respect toolbox abstraction.
Least of the brokeness at this point I suppose - but I would like to not expose tools_by_id external to the Toolbox.
Affected #: 1 file
diff -r 267fa4b9ab6a80a0ae0a1f2ab5f157303f68d46d -r d0c38a7861e5d42f6068963f0917a78cdc9e6860 lib/galaxy/jobs/deferred/data_transfer.py
--- a/lib/galaxy/jobs/deferred/data_transfer.py
+++ b/lib/galaxy/jobs/deferred/data_transfer.py
@@ -356,7 +356,7 @@
for i, step in enumerate( workflow.steps ):
job = None
if step.type == 'tool' or step.type is None:
- tool = self.app.toolbox.tools_by_id[ step.tool_id ]
+ tool = self.app.toolbox.get_tool( step.tool_id )
def callback( input, value, prefixed_name, prefixed_label ):
if isinstance( input, DataToolParameter ):
if prefixed_name in step.input_connections_by_name:
https://bitbucket.org/galaxy/galaxy-central/commits/34b3e1ca729d/
Changeset: 34b3e1ca729d
User: jmchilton
Date: 2014-12-22 18:16:30+00:00
Summary: Start decoupling Toolbox elements from XML (sections+labels).
Just a small tweak and some tests to verify these things can indeed be created from dictionaries. Also slightly simplifies galaxy.tools.
Affected #: 2 files
diff -r d0c38a7861e5d42f6068963f0917a78cdc9e6860 -r 34b3e1ca729df33c32e96ca9202d3a80836c21ed lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -330,12 +330,13 @@
elif isinstance( val, ToolSectionLabel ):
self.tool_panel[ key ] = val
elif isinstance( val, ToolSection ):
- elem = ElementTree.Element( 'section' )
- elem.attrib[ 'id' ] = val.id or ''
- elem.attrib[ 'name' ] = val.name or ''
- elem.attrib[ 'version' ] = val.version or ''
- section = ToolSection( elem )
- log.debug( "Loading section: %s" % elem.get( 'name' ) )
+ section_dict = {
+ 'id': val.id or '',
+ 'name': val.name or '',
+ 'version': val.version or '',
+ }
+ section = ToolSection( section_dict )
+ log.debug( "Loading section: %s" % section_dict.get( 'name' ) )
for section_key, section_val in val.elems.items():
if isinstance( section_val, Tool ):
tool_id = section_key.replace( 'tool_', '', 1 )
@@ -1050,6 +1051,8 @@
dict_collection_visible_keys = ( 'id', 'name', 'version' )
def __init__( self, elem=None ):
+ """ Build a ToolSection from an ElementTree element or a dictionary.
+ """
f = lambda elem, val: elem is not None and elem.get( val ) or ''
self.name = f( elem, 'name' )
self.id = f( elem, 'id' )
@@ -1089,6 +1092,9 @@
dict_collection_visible_keys = ( 'id', 'text', 'version' )
def __init__( self, elem ):
+ """ Build a ToolSectionLabel from an ElementTree element or a
+ dictionary.
+ """
self.text = elem.get( "text" )
self.id = elem.get( "id" )
self.version = elem.get( "version" ) or ''
diff -r d0c38a7861e5d42f6068963f0917a78cdc9e6860 -r 34b3e1ca729df33c32e96ca9202d3a80836c21ed test/unit/tools/test_tool_panel.py
--- /dev/null
+++ b/test/unit/tools/test_tool_panel.py
@@ -0,0 +1,26 @@
+from xml.etree import ElementTree as ET
+from galaxy.tools import ToolSection
+
+
+def test_tool_section( ):
+ elem = ET.Element( 'section' )
+ elem.attrib[ 'name' ] = "Cool Tools"
+ elem.attrib[ 'id' ] = "cool1"
+
+ section = ToolSection( elem )
+ assert section.id == "cool1"
+ assert section.name == "Cool Tools"
+ assert section.version == ""
+
+ section = ToolSection( dict(
+ id="cool1",
+ name="Cool Tools"
+ ) )
+ assert section.id == "cool1"
+ assert section.name == "Cool Tools"
+ assert section.version == ""
+
+ section = ToolSection()
+ assert section.id == ""
+ assert section.name == ""
+ assert section.version == ""
https://bitbucket.org/galaxy/galaxy-central/commits/1aa8a57c5994/
Changeset: 1aa8a57c5994
User: jmchilton
Date: 2014-12-22 18:16:30+00:00
Summary: Add comment to auto-generated integrated_tool_panel.xml.
Someone more familiar with integrated_tool_panel.xml should feel free to make this comment sharper - but something is better nothing I think.
Affected #: 1 file
diff -r 34b3e1ca729df33c32e96ca9202d3a80836c21ed -r 1aa8a57c599455b2a9faeeadb980b62b8abecc1f lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -96,6 +96,16 @@
HELP_UNINITIALIZED = threading.Lock()
+INTEGRATED_TOOL_PANEL_DESCRIPTION = """
+This is Galaxy's integrated tool panel and probably should not be modified
+directly. It will be regenerated each time Galaxy starts up. To modify locally
+managed tools (e.g. from tool_conf.xml) modify that file directly and restart
+Galaxy. Whenever possible Tool Shed managed tools (e.g. from shed_tool_conf.xml)
+should be managed from within the Galaxy interface of via is UI - but if changes
+are nessecary (such as to hide a tool or re-assign its section) modify that file
+and restart Galaxy.
+"""
+
class ToolNotFoundException( Exception ):
pass
@@ -396,6 +406,9 @@
fd, filename = tempfile.mkstemp()
os.write( fd, '<?xml version="1.0"?>\n' )
os.write( fd, '<toolbox>\n' )
+ os.write( fd, ' <!--\n ')
+ os.write( fd, '\n '.join( [ l for l in INTEGRATED_TOOL_PANEL_DESCRIPTION.split("\n") if l ] ) )
+ os.write( fd, '\n -->\n')
for key, item in self.integrated_tool_panel.items():
if item:
if isinstance( item, Tool ):
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
[galaxyproject/usegalaxy-playbook] 2680ce: update tool panel according to https://trello.com/...
by GitHub 19 Dec '14
by GitHub 19 Dec '14
19 Dec '14
Branch: refs/heads/master
Home: https://github.com/galaxyproject/usegalaxy-playbook
Commit: 2680ce8b73b35a77a2e59c4437cabe94f8621857
https://github.com/galaxyproject/usegalaxy-playbook/commit/2680ce8b73b35a77…
Author: martenson <cech.marten(a)gmail.com>
Date: 2014-12-19 (Fri, 19 Dec 2014)
Changed paths:
M files/galaxy/test.galaxyproject.org/var/integrated_tool_panel.xml
M files/galaxy/test.galaxyproject.org/var/migrated_tools_conf.xml
M files/galaxy/test.galaxyproject.org/var/shed_tool_conf.xml
Log Message:
-----------
update tool panel according to https://trello.com/c/SX4sNVVf/1344-revising-tools-on-main
1
0
19 Dec '14
Branch: refs/heads/master
Home: https://github.com/galaxyproject/usegalaxy-playbook
Commit: e5c6a1800135e1bc95d132cb11153d5670001842
https://github.com/galaxyproject/usegalaxy-playbook/commit/e5c6a1800135e1bc…
Author: martenson <cech.marten(a)gmail.com>
Date: 2014-12-19 (Fri, 19 Dec 2014)
Changed paths:
M files/galaxy/test.galaxyproject.org/var/integrated_tool_panel.xml
M files/galaxy/test.galaxyproject.org/var/shed_tool_conf.xml
M files/galaxy/test.galaxyproject.org/var/shed_tool_data_table_conf.xml
Log Message:
-----------
backup the updated conf files
1
0
Branch: refs/heads/master
Home: https://github.com/galaxyproject/usegalaxy-playbook
Commit: 91a2ad0daa89339e718578cf80dc8740bd4a53ca
https://github.com/galaxyproject/usegalaxy-playbook/commit/91a2ad0daa89339e…
Author: martenson <cech.marten(a)gmail.com>
Date: 2014-12-19 (Fri, 19 Dec 2014)
Changed paths:
M stage/group_vars/all.yml
Log Message:
-----------
update Test
1
0
6 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/10661dcd25e0/
Changeset: 10661dcd25e0
Branch: tmcg/this-pull-request-is-to-extend-the-get-a-1418417648750
User: tmcg
Date: 2014-12-12 20:54:33+00:00
Summary: This pull request is to extend the GET /api/jobs request/response.
1.) If the submitted api key is an admin's key AND the request has an included data_range_min
or date_range_max value, the response will include jobs from all galaxy users.
2.) The response for (1) is extended to include
a) external_id
b) galaxy job id
c) user email
3.) All users can submit a date range filter.
4.) Existing calls are unaffected by the change:
https://galaxy-ng.msi.umn.edu/api/jobs?key=xxxxxxxxxxxxxxxxxxxxxxx
[
{
"create_time": "2014-12-01T19:23:37.270768",
"exit_code": 0,
"id": "cffdbbf7257b6526",
"model_class": "Job",
"state": "ok",
"tool_id": "upload1",
"update_time": "2014-12-01T19:24:24.608105"
}
]
5.) Extended admin request:
https://galaxy-ng.msi.umn.edu/api/jobs?date_range_min=2014-11-01?&key=xxxxx…
...
{
"create_time": "2014-11-11T15:59:19.909902",
"exit_code": 0,
"external_id": "31325.nokomis0015.msi.umn.edu",
"id": "2003774561413b68",
"job_id": 3733,
"model_class": "Job",
"state": "ok",
"tool_id": "testtoolshed.g2.bx.psu.edu/repos/tmcgowan/fastqc/fastqc/0.60",
"update_time": "2014-11-11T16:00:10.872804",
"user_email": "mcgo0092+msistaff(a)msi.umn.edu"
},
{
"create_time": "2014-11-10T15:15:31.801047",
"exit_code": 0,
"external_id": "30299.nokomis0015.msi.umn.edu",
"id": "e330bc56cb5095a7",
"job_id": 3732,
"model_class": "Job",
"state": "ok",
"tool_id": "testtoolshed.g2.bx.psu.edu/repos/jjohnson/snpeff/snpEff/4.0.1",
"update_time": "2014-11-10T15:16:31.996148",
"user_email": "jj+support(a)msi.umn.edu"
}
...
Affected #: 1 file
diff -r efd0286e7629289c4c583898ebecb32646834c64 -r 10661dcd25e0888739a83f42b8424c0532efcaa7 lib/galaxy/webapps/galaxy/api/jobs.py
--- a/lib/galaxy/webapps/galaxy/api/jobs.py
+++ b/lib/galaxy/webapps/galaxy/api/jobs.py
@@ -24,9 +24,12 @@
@expose_api
def index( self, trans, **kwd ):
"""
- index( trans, state=None, tool_id=None, history_id=None )
+ index( trans, state=None, tool_id=None, history_id=None, date_range_min=None, date_range_max=None )
* GET /api/jobs:
return jobs for current user
+
+ !! if user is admin and date_range_[min|max], then
+ return jobs for all galaxy users based on filtering - this is an extended service
:type state: string or list
:param state: limit listing of jobs to those that match one of the included states. If none, all are returned.
@@ -36,6 +39,12 @@
:type tool_id: string or list
:param tool_id: limit listing of jobs to those that match one of the included tool_ids. If none, all are returned.
+ :type date_range_min: string '2014-01-01'
+ :param date_range_min: limit the listing of jobs to those updated on or after requested date
+
+ :type date_range_max: string '2014-12-31'
+ :param date_range_max: limit the listing of jobs to those updated on or before requested date
+
:type history_id: string
:param history_id: limit listing of jobs to those that match the history_id. If none, all are returned.
@@ -44,9 +53,15 @@
"""
state = kwd.get( 'state', None )
- query = trans.sa_session.query( trans.app.model.Job ).filter(
- trans.app.model.Job.user == trans.user
- )
+ if trans.user_is_admin() and (kwd.get('date_range_min', None) or kwd.get('date_range_max', None)):
+ is_extended_service = True
+ else:
+ is_extended_service = False
+
+ if is_extended_service:
+ query = trans.sa_session.query( trans.app.model.Job )
+ else:
+ query = trans.sa_session.query( trans.app.model.Job ).filter(trans.app.model.Job.user == trans.user)
def build_and_apply_filters( query, objects, filter_func ):
if objects is not None:
@@ -63,6 +78,9 @@
query = build_and_apply_filters( query, kwd.get( 'tool_id', None ), lambda t: trans.app.model.Job.tool_id == t )
query = build_and_apply_filters( query, kwd.get( 'tool_id_like', None ), lambda t: trans.app.model.Job.tool_id.like(t) )
+
+ query = build_and_apply_filters( query, kwd.get( 'date_range_min', None ), lambda dmin: trans.app.model.Job.table.c.update_time >= dmin )
+ query = build_and_apply_filters( query, kwd.get( 'date_range_max', None ), lambda dmax: trans.app.model.Job.table.c.update_time <= dmax )
history_id = kwd.get( 'history_id', None )
if history_id is not None:
@@ -78,7 +96,24 @@
else:
order_by = trans.app.model.Job.update_time.desc()
for job in query.order_by( order_by ).all():
- out.append( self.encode_all_ids( trans, job.to_dict( 'collection' ), True ) )
+ j = self.encode_all_ids( trans, job.to_dict( 'collection' ), True )
+
+ if is_extended_service:
+ def get_email_dict(trans):
+ user_email_dict = {}
+ user_query = trans.sa_session.query( trans.app.model.User )
+ for user in user_query.all():
+ u = user.to_dict()
+ user_email_dict[u['id']] = u['email']
+ return user_email_dict
+
+ user_emails = get_email_dict(trans)
+ j['external_id'] = job.job_runner_external_id
+ j['job_id'] = job.id
+ if job.user_id in user_emails:
+ j['user_email'] = user_emails[job.user_id]
+
+ out.append(j)
return out
@expose_api
https://bitbucket.org/galaxy/galaxy-central/commits/f09646961129/
Changeset: f09646961129
Branch: tmcg/this-pull-request-is-to-extend-the-get-a-1418417648750
User: tmcg
Date: 2014-12-15 16:21:36+00:00
Summary: Edits based on reviewer comments. Removed redundant email query, removed job_id from response. Added user_details as param.
Affected #: 1 file
diff -r 10661dcd25e0888739a83f42b8424c0532efcaa7 -r f09646961129434a993983b81df3d7937b8ed72b lib/galaxy/webapps/galaxy/api/jobs.py
--- a/lib/galaxy/webapps/galaxy/api/jobs.py
+++ b/lib/galaxy/webapps/galaxy/api/jobs.py
@@ -24,11 +24,11 @@
@expose_api
def index( self, trans, **kwd ):
"""
- index( trans, state=None, tool_id=None, history_id=None, date_range_min=None, date_range_max=None )
+ index( trans, state=None, tool_id=None, history_id=None, date_range_min=None, date_range_max=None, user_details=False )
* GET /api/jobs:
return jobs for current user
- !! if user is admin and date_range_[min|max], then
+ !! if user is admin and user_details is True, then
return jobs for all galaxy users based on filtering - this is an extended service
:type state: string or list
@@ -39,6 +39,9 @@
:type tool_id: string or list
:param tool_id: limit listing of jobs to those that match one of the included tool_ids. If none, all are returned.
+ :type user_details: boolean
+ :param user_details: if true, and requestor is an admin, will return external job id and user email.
+
:type date_range_min: string '2014-01-01'
:param date_range_min: limit the listing of jobs to those updated on or after requested date
@@ -51,9 +54,8 @@
:rtype: list
:returns: list of dictionaries containing summary job information
"""
-
state = kwd.get( 'state', None )
- if trans.user_is_admin() and (kwd.get('date_range_min', None) or kwd.get('date_range_max', None)):
+ if trans.user_is_admin() and kwd.get('user_details', False):
is_extended_service = True
else:
is_extended_service = False
@@ -96,24 +98,12 @@
else:
order_by = trans.app.model.Job.update_time.desc()
for job in query.order_by( order_by ).all():
- j = self.encode_all_ids( trans, job.to_dict( 'collection' ), True )
-
+ j = self.encode_all_ids( trans, job.to_dict( 'collection' ), True )
if is_extended_service:
- def get_email_dict(trans):
- user_email_dict = {}
- user_query = trans.sa_session.query( trans.app.model.User )
- for user in user_query.all():
- u = user.to_dict()
- user_email_dict[u['id']] = u['email']
- return user_email_dict
-
- user_emails = get_email_dict(trans)
j['external_id'] = job.job_runner_external_id
- j['job_id'] = job.id
- if job.user_id in user_emails:
- j['user_email'] = user_emails[job.user_id]
-
+ j['user_email'] = job.user.email
out.append(j)
+
return out
@expose_api
https://bitbucket.org/galaxy/galaxy-central/commits/f8331619132e/
Changeset: f8331619132e
User: jmchilton
Date: 2014-12-19 02:49:03+00:00
Summary: Merge pull request #610.
Affected #: 1 file
diff -r 114b0d3764700a69e87c39f07a1c925a76814261 -r f8331619132ead73b700c337f2fa2610ba92993f lib/galaxy/webapps/galaxy/api/jobs.py
--- a/lib/galaxy/webapps/galaxy/api/jobs.py
+++ b/lib/galaxy/webapps/galaxy/api/jobs.py
@@ -24,9 +24,12 @@
@expose_api
def index( self, trans, **kwd ):
"""
- index( trans, state=None, tool_id=None, history_id=None )
+ index( trans, state=None, tool_id=None, history_id=None, date_range_min=None, date_range_max=None, user_details=False )
* GET /api/jobs:
return jobs for current user
+
+ !! if user is admin and user_details is True, then
+ return jobs for all galaxy users based on filtering - this is an extended service
:type state: string or list
:param state: limit listing of jobs to those that match one of the included states. If none, all are returned.
@@ -36,17 +39,31 @@
:type tool_id: string or list
:param tool_id: limit listing of jobs to those that match one of the included tool_ids. If none, all are returned.
+ :type user_details: boolean
+ :param user_details: if true, and requestor is an admin, will return external job id and user email.
+
+ :type date_range_min: string '2014-01-01'
+ :param date_range_min: limit the listing of jobs to those updated on or after requested date
+
+ :type date_range_max: string '2014-12-31'
+ :param date_range_max: limit the listing of jobs to those updated on or before requested date
+
:type history_id: string
:param history_id: limit listing of jobs to those that match the history_id. If none, all are returned.
:rtype: list
:returns: list of dictionaries containing summary job information
"""
-
state = kwd.get( 'state', None )
- query = trans.sa_session.query( trans.app.model.Job ).filter(
- trans.app.model.Job.user == trans.user
- )
+ if trans.user_is_admin() and kwd.get('user_details', False):
+ is_extended_service = True
+ else:
+ is_extended_service = False
+
+ if is_extended_service:
+ query = trans.sa_session.query( trans.app.model.Job )
+ else:
+ query = trans.sa_session.query( trans.app.model.Job ).filter(trans.app.model.Job.user == trans.user)
def build_and_apply_filters( query, objects, filter_func ):
if objects is not None:
@@ -63,6 +80,9 @@
query = build_and_apply_filters( query, kwd.get( 'tool_id', None ), lambda t: trans.app.model.Job.tool_id == t )
query = build_and_apply_filters( query, kwd.get( 'tool_id_like', None ), lambda t: trans.app.model.Job.tool_id.like(t) )
+
+ query = build_and_apply_filters( query, kwd.get( 'date_range_min', None ), lambda dmin: trans.app.model.Job.table.c.update_time >= dmin )
+ query = build_and_apply_filters( query, kwd.get( 'date_range_max', None ), lambda dmax: trans.app.model.Job.table.c.update_time <= dmax )
history_id = kwd.get( 'history_id', None )
if history_id is not None:
@@ -78,7 +98,12 @@
else:
order_by = trans.app.model.Job.update_time.desc()
for job in query.order_by( order_by ).all():
- out.append( self.encode_all_ids( trans, job.to_dict( 'collection' ), True ) )
+ j = self.encode_all_ids( trans, job.to_dict( 'collection' ), True )
+ if is_extended_service:
+ j['external_id'] = job.job_runner_external_id
+ j['user_email'] = job.user.email
+ out.append(j)
+
return out
@expose_api
https://bitbucket.org/galaxy/galaxy-central/commits/8d37d708a96c/
Changeset: 8d37d708a96c
Branch: tmcg/this-pull-request-is-to-extend-the-get-a-1418417648750
User: jmchilton
Date: 2014-12-19 02:49:33+00:00
Summary: Close branch.
Affected #: 0 files
https://bitbucket.org/galaxy/galaxy-central/commits/943bc5a4c60a/
Changeset: 943bc5a4c60a
User: jmchilton
Date: 2014-12-19 02:50:15+00:00
Summary: PEP-8 fix for api/jobs.py.
Affected #: 1 file
diff -r f8331619132ead73b700c337f2fa2610ba92993f -r 943bc5a4c60a0706633660fad41fe9c71fdd8ca3 lib/galaxy/webapps/galaxy/api/jobs.py
--- a/lib/galaxy/webapps/galaxy/api/jobs.py
+++ b/lib/galaxy/webapps/galaxy/api/jobs.py
@@ -27,7 +27,7 @@
index( trans, state=None, tool_id=None, history_id=None, date_range_min=None, date_range_max=None, user_details=False )
* GET /api/jobs:
return jobs for current user
-
+
!! if user is admin and user_details is True, then
return jobs for all galaxy users based on filtering - this is an extended service
@@ -41,10 +41,10 @@
:type user_details: boolean
:param user_details: if true, and requestor is an admin, will return external job id and user email.
-
+
:type date_range_min: string '2014-01-01'
- :param date_range_min: limit the listing of jobs to those updated on or after requested date
-
+ :param date_range_min: limit the listing of jobs to those updated on or after requested date
+
:type date_range_max: string '2014-12-31'
:param date_range_max: limit the listing of jobs to those updated on or before requested date
@@ -59,7 +59,7 @@
is_extended_service = True
else:
is_extended_service = False
-
+
if is_extended_service:
query = trans.sa_session.query( trans.app.model.Job )
else:
@@ -80,7 +80,7 @@
query = build_and_apply_filters( query, kwd.get( 'tool_id', None ), lambda t: trans.app.model.Job.tool_id == t )
query = build_and_apply_filters( query, kwd.get( 'tool_id_like', None ), lambda t: trans.app.model.Job.tool_id.like(t) )
-
+
query = build_and_apply_filters( query, kwd.get( 'date_range_min', None ), lambda dmin: trans.app.model.Job.table.c.update_time >= dmin )
query = build_and_apply_filters( query, kwd.get( 'date_range_max', None ), lambda dmax: trans.app.model.Job.table.c.update_time <= dmax )
@@ -98,12 +98,12 @@
else:
order_by = trans.app.model.Job.update_time.desc()
for job in query.order_by( order_by ).all():
- j = self.encode_all_ids( trans, job.to_dict( 'collection' ), True )
+ j = self.encode_all_ids( trans, job.to_dict( 'collection' ), True )
if is_extended_service:
j['external_id'] = job.job_runner_external_id
j['user_email'] = job.user.email
out.append(j)
-
+
return out
@expose_api
https://bitbucket.org/galaxy/galaxy-central/commits/815d38c48a56/
Changeset: 815d38c48a56
User: jmchilton
Date: 2014-12-19 02:50:15+00:00
Summary: Increase consistency between job index and show.
Add tests for new date range and history filtering as well as to ensure only admins get to see external_id and command_line and that users cannot see each other's jobs.
Always allow admins to views all jobs on index (instead of only when user_details is specified) and show. Add user_email and external_id to show (for admins) to bring it inline with index and add command_line to index (for admins) to bring it in line with show.
Show still allow more details including job standard error and output as well as job metrics.
Affected #: 6 files
diff -r 943bc5a4c60a0706633660fad41fe9c71fdd8ca3 -r 815d38c48a5639d47eed92806ef4c196406f58f1 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -520,9 +520,15 @@
dataset.blurb = 'deleted'
dataset.peek = 'Job deleted'
dataset.info = 'Job output deleted by user before job completed'
- def to_dict( self, view='collection' ):
+
+ def to_dict( self, view='collection', system_details=False ):
rval = super( Job, self ).to_dict( view=view )
rval['tool_id'] = self.tool_id
+ if system_details:
+ # System level details that only admins should have.
+ rval['external_id'] = self.job_runner_external_id
+ rval['command_line'] = self.command_line
+
if view == 'element':
param_dict = dict( [ ( p.name, p.value ) for p in self.parameters ] )
rval['params'] = param_dict
diff -r 943bc5a4c60a0706633660fad41fe9c71fdd8ca3 -r 815d38c48a5639d47eed92806ef4c196406f58f1 lib/galaxy/web/security/__init__.py
--- a/lib/galaxy/web/security/__init__.py
+++ b/lib/galaxy/web/security/__init__.py
@@ -73,7 +73,7 @@
if not isinstance( rval, dict ):
return rval
for k, v in rval.items():
- if ( k == 'id' or k.endswith( '_id' ) ) and v is not None and k not in [ 'tool_id' ]:
+ if ( k == 'id' or k.endswith( '_id' ) ) and v is not None and k not in [ 'tool_id', 'external_id' ]:
try:
rval[ k ] = self.encode_id( v )
except Exception:
diff -r 943bc5a4c60a0706633660fad41fe9c71fdd8ca3 -r 815d38c48a5639d47eed92806ef4c196406f58f1 lib/galaxy/webapps/galaxy/api/jobs.py
--- a/lib/galaxy/webapps/galaxy/api/jobs.py
+++ b/lib/galaxy/webapps/galaxy/api/jobs.py
@@ -55,12 +55,10 @@
:returns: list of dictionaries containing summary job information
"""
state = kwd.get( 'state', None )
- if trans.user_is_admin() and kwd.get('user_details', False):
- is_extended_service = True
- else:
- is_extended_service = False
+ is_admin = trans.user_is_admin()
+ user_details = kwd.get('user_details', False)
- if is_extended_service:
+ if is_admin:
query = trans.sa_session.query( trans.app.model.Job )
else:
query = trans.sa_session.query( trans.app.model.Job ).filter(trans.app.model.Job.user == trans.user)
@@ -98,9 +96,9 @@
else:
order_by = trans.app.model.Job.update_time.desc()
for job in query.order_by( order_by ).all():
- j = self.encode_all_ids( trans, job.to_dict( 'collection' ), True )
- if is_extended_service:
- j['external_id'] = job.job_runner_external_id
+ job_dict = job.to_dict( 'collection', system_details=is_admin )
+ j = self.encode_all_ids( trans, job_dict, True )
+ if user_details:
j['user_email'] = job.user.email
out.append(j)
@@ -123,12 +121,13 @@
:returns: dictionary containing full description of job data
"""
job = self.__get_job( trans, id )
- job_dict = self.encode_all_ids( trans, job.to_dict( 'element' ), True )
+ is_admin = trans.user_is_admin()
+ job_dict = self.encode_all_ids( trans, job.to_dict( 'element', system_details=is_admin ), True )
full_output = util.asbool( kwd.get( 'full', 'false' ) )
if full_output:
job_dict.update( dict( stderr=job.stderr, stdout=job.stdout ) )
- if trans.user_is_admin():
- job_dict['command_line'] = job.command_line
+ if is_admin:
+ job_dict['user_email'] = job.user.email
def metric_to_dict(metric):
metric_name = metric.metric_name
@@ -199,10 +198,16 @@
decoded_job_id = trans.security.decode_id( id )
except Exception:
raise exceptions.MalformedId()
- query = trans.sa_session.query( trans.app.model.Job ).filter(
- trans.app.model.Job.user == trans.user,
- trans.app.model.Job.id == decoded_job_id
- )
+ query = trans.sa_session.query( trans.app.model.Job )
+ if trans.user_is_admin():
+ query = query.filter(
+ trans.app.model.Job.id == decoded_job_id
+ )
+ else:
+ query = query.filter(
+ trans.app.model.Job.user == trans.user,
+ trans.app.model.Job.id == decoded_job_id
+ )
job = query.first()
if job is None:
raise exceptions.ObjectNotFound()
diff -r 943bc5a4c60a0706633660fad41fe9c71fdd8ca3 -r 815d38c48a5639d47eed92806ef4c196406f58f1 test/api/test_jobs.py
--- a/test/api/test_jobs.py
+++ b/test/api/test_jobs.py
@@ -1,4 +1,6 @@
+import datetime
import json
+import time
from operator import itemgetter
from base import api
@@ -11,13 +13,18 @@
def test_index( self ):
# Create HDA to ensure at least one job exists...
self.__history_with_new_dataset()
- jobs_response = self._get( "jobs" )
+ jobs = self.__jobs_index()
+ assert "upload1" in map( itemgetter( "tool_id" ), jobs )
- self._assert_status_code_is( jobs_response, 200 )
+ def test_system_details_admin_only( self ):
+ self.__history_with_new_dataset()
+ jobs = self.__jobs_index( admin=False )
+ job = jobs[0]
+ self._assert_not_has_keys( job, "command_line", "external_id" )
- jobs = jobs_response.json()
- assert isinstance( jobs, list )
- assert "upload1" in map( itemgetter( "tool_id" ), jobs )
+ jobs = self.__jobs_index( admin=True )
+ job = jobs[0]
+ self._assert_has_keys( job, "command_line", "external_id" )
def test_index_state_filter( self ):
# Initial number of ok jobs
@@ -31,6 +38,33 @@
new_count = len( self.__uploads_with_state( "ok" ) )
assert original_count < new_count
+ def test_index_date_filter( self ):
+ self.__history_with_new_dataset()
+ two_weeks_ago = (datetime.datetime.utcnow() - datetime.timedelta(7)).isoformat()
+ last_week = (datetime.datetime.utcnow() - datetime.timedelta(7)).isoformat()
+ next_week = (datetime.datetime.utcnow() + datetime.timedelta(7)).isoformat()
+ today = datetime.datetime.utcnow().isoformat()
+ tomorrow = (datetime.datetime.utcnow() + datetime.timedelta(1)).isoformat()
+
+ jobs = self.__jobs_index( data={"date_range_min": today[0:10], "date_range_max": tomorrow[0:10]} )
+ assert len( jobs ) > 0
+ today_job_id = jobs[0]["id"]
+
+ jobs = self.__jobs_index( data={"date_range_min": two_weeks_ago, "date_range_max": last_week} )
+ assert today_job_id not in map(itemgetter("id"), jobs)
+
+ jobs = self.__jobs_index( data={"date_range_min": last_week, "date_range_max": next_week} )
+ assert today_job_id in map(itemgetter("id"), jobs)
+
+ def test_index_history( self ):
+ history_id, _ = self.__history_with_new_dataset()
+ jobs = self.__jobs_index( data={"history_id": history_id} )
+ assert len( jobs ) > 0
+
+ history_id = self._new_history()
+ jobs = self.__jobs_index( data={"history_id": history_id} )
+ assert len( jobs ) == 0
+
def test_index_multiple_states_filter( self ):
# Initial number of ok jobs
original_count = len( self.__uploads_with_state( "ok", "new" ) )
@@ -58,6 +92,22 @@
job_details = show_jobs_response.json()
self._assert_has_key( job_details, 'id', 'state', 'exit_code', 'update_time', 'create_time' )
+ def test_show_security( self ):
+ history_id, _ = self.__history_with_new_dataset()
+ jobs_response = self._get( "jobs", data={"history_id": history_id} )
+ job = jobs_response.json()[ 0 ]
+ job_id = job[ "id" ]
+
+ show_jobs_response = self._get( "jobs/%s" % job_id, admin=False )
+ self._assert_not_has_keys( show_jobs_response.json(), "command_line", "external_id" )
+
+ with self._different_user():
+ show_jobs_response = self._get( "jobs/%s" % job_id, admin=False )
+ self._assert_status_code_is( show_jobs_response, 404 )
+
+ show_jobs_response = self._get( "jobs/%s" % job_id, admin=True )
+ self._assert_has_keys( show_jobs_response.json(), "command_line", "external_id" )
+
def test_search( self ):
history_id, dataset_id = self.__history_with_ok_dataset()
@@ -133,3 +183,10 @@
history_id, dataset_id = self.__history_with_new_dataset()
self._wait_for_history( history_id, assert_ok=True )
return history_id, dataset_id
+
+ def __jobs_index( self, **kwds ):
+ jobs_response = self._get( "jobs", **kwds )
+ self._assert_status_code_is( jobs_response, 200 )
+ jobs = jobs_response.json()
+ assert isinstance( jobs, list )
+ return jobs
diff -r 943bc5a4c60a0706633660fad41fe9c71fdd8ca3 -r 815d38c48a5639d47eed92806ef4c196406f58f1 test/base/api.py
--- a/test/base/api.py
+++ b/test/base/api.py
@@ -11,6 +11,7 @@
from .api_asserts import (
assert_status_code_is,
assert_has_keys,
+ assert_not_has_keys,
assert_error_code_is,
)
@@ -83,6 +84,9 @@
def _assert_has_keys( self, response, *keys ):
assert_has_keys( response, *keys )
+ def _assert_not_has_keys( self, response, *keys ):
+ assert_not_has_keys( response, *keys )
+
def _assert_error_code_is( self, response, error_code ):
assert_error_code_is( response, error_code )
diff -r 943bc5a4c60a0706633660fad41fe9c71fdd8ca3 -r 815d38c48a5639d47eed92806ef4c196406f58f1 test/base/api_asserts.py
--- a/test/base/api_asserts.py
+++ b/test/base/api_asserts.py
@@ -20,6 +20,11 @@
assert key in response, "Response [%s] does not contain key [%s]" % ( response, key )
+def assert_not_has_keys( response, *keys ):
+ for key in keys:
+ assert key not in response, "Response [%s] contains invalid key [%s]" % ( response, key )
+
+
def assert_error_code_is( response, error_code ):
if hasattr( response, "json" ):
response = response.json()
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 bug in 8d5089f2ba8183439a866026f3583c377f8bfa74.
by commits-noreply@bitbucket.org 18 Dec '14
by commits-noreply@bitbucket.org 18 Dec '14
18 Dec '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/114b0d376470/
Changeset: 114b0d376470
User: jmchilton
Date: 2014-12-18 15:21:42+00:00
Summary: Fix bug in 8d5089f2ba8183439a866026f3583c377f8bfa74.
Affected #: 1 file
diff -r 5e5c0cf930bb96bf8af0bd19daad1a999b40c374 -r 114b0d3764700a69e87c39f07a1c925a76814261 lib/galaxy/workflow/run_request.py
--- a/lib/galaxy/workflow/run_request.py
+++ b/lib/galaxy/workflow/run_request.py
@@ -56,13 +56,13 @@
possible_input_keys = []
for inputs_by_el in inputs_by.split("|"):
if inputs_by_el == "step_id":
- possible_input_keys = [str( step.id )]
+ possible_input_keys.append(str( step.id ))
elif inputs_by_el == "step_index":
- possible_input_keys = [str( step.order_index )]
+ possible_input_keys.append(str( step.order_index ))
elif inputs_by_el == "step_uuid":
- possible_input_keys = [str( step.uuid )]
+ possible_input_keys.append(str( step.uuid ))
elif inputs_by_el == "name":
- possible_input_keys = [step.tool_inputs.get( 'name', None )]
+ possible_input_keys.append(step.tool_inputs.get( 'name', None ))
else:
message = "Workflow cannot be run because unexpected inputs_by value specified."
raise exceptions.MessageException( message )
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: Merged in jmchilton/galaxy-central-fork-1 (pull request #617)
by commits-noreply@bitbucket.org 17 Dec '14
by commits-noreply@bitbucket.org 17 Dec '14
17 Dec '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/5e5c0cf930bb/
Changeset: 5e5c0cf930bb
User: jmchilton
Date: 2014-12-17 20:47:54+00:00
Summary: Merged in jmchilton/galaxy-central-fork-1 (pull request #617)
Allow tool tests to assert properties about command, standard output, and standard error.
Affected #: 6 files
diff -r f24461d3e0b3f737f8e4c99b23475b571c32c61e -r 5e5c0cf930bb96bf8af0bd19daad1a999b40c374 lib/galaxy/tools/parser/xml.py
--- a/lib/galaxy/tools/parser/xml.py
+++ b/lib/galaxy/tools/parser/xml.py
@@ -186,6 +186,11 @@
rval = dict(
outputs=__parse_output_elems(test_elem),
inputs=__parse_input_elems(test_elem, i),
+ command=__parse_assert_list_from_elem( test_elem.find("assert_command") ),
+ stdout=__parse_assert_list_from_elem( test_elem.find("assert_stdout") ),
+ stderr=__parse_assert_list_from_elem( test_elem.find("assert_stderr") ),
+ expect_exit_code=test_elem.get("expect_exit_code"),
+ expect_failure=string_as_bool(test_elem.get("expect_failure", False)),
)
_copy_to_dict_if_present(test_elem, rval, ["interactor", "num_outputs"])
return rval
@@ -222,6 +227,11 @@
return name, file, attributes
+def __parse_command_elem( test_elem ):
+ assert_elem = test_elem.find("command")
+ return __parse_assert_list_from_elem( assert_elem )
+
+
def __parse_test_attributes( output_elem, attrib ):
assert_list = __parse_assert_list( output_elem )
file = attrib.pop( 'file', None )
@@ -252,6 +262,10 @@
def __parse_assert_list( output_elem ):
assert_elem = output_elem.find("assert_contents")
+ return __parse_assert_list_from_elem( assert_elem )
+
+
+def __parse_assert_list_from_elem( assert_elem ):
assert_list = None
def convert_elem(elem):
diff -r f24461d3e0b3f737f8e4c99b23475b571c32c61e -r 5e5c0cf930bb96bf8af0bd19daad1a999b40c374 lib/galaxy/tools/parser/yaml.py
--- a/lib/galaxy/tools/parser/yaml.py
+++ b/lib/galaxy/tools/parser/yaml.py
@@ -152,27 +152,47 @@
attributes["metadata"] = {}
# TODO
assert_list = []
- for key, assertion in attributes.get("asserts", {}).iteritems():
- # TODO: not handling nested assertions correctly,
- # not sure these are used though.
- children = []
- if "children" in assertion:
- children = assertion["children"]
- del assertion["children"]
- assert_dict = dict(
- tag=key,
- attributes=assertion,
- children=children,
- )
- assert_list.append(assert_dict)
+ assert_list = __to_test_assert_list( attributes.get("asserts", [] ) )
attributes["assert_list"] = assert_list
-
_ensure_has(attributes, defaults)
test_dict["outputs"] = new_outputs
+ test_dict["command"] = __to_test_assert_list( test_dict.get( "command", [] ) )
+ test_dict["stdout"] = __to_test_assert_list( test_dict.get( "stdout", [] ) )
+ test_dict["stderr"] = __to_test_assert_list( test_dict.get( "stderr", [] ) )
+ test_dict["expect_exit_code"] = test_dict.get( "expect_exit_code", None )
+ test_dict["expect_failure"] = test_dict.get( "expect_exit_code", False )
return test_dict
+def __to_test_assert_list(assertions):
+ def expand_dict_form(item):
+ key, value = item
+ new_value = value.copy()
+ new_value["that"] = key
+ return new_value
+
+ if isinstance( assertions, dict ):
+ assertions = map(expand_dict_form, assertions.items() )
+
+ assert_list = []
+ for assertion in assertions:
+ # TODO: not handling nested assertions correctly,
+ # not sure these are used though.
+ children = []
+ if "children" in assertion:
+ children = assertion["children"]
+ del assertion["children"]
+ assert_dict = dict(
+ tag=assertion["that"],
+ attributes=assertion,
+ children=children,
+ )
+ assert_list.append(assert_dict)
+
+ return assert_list or None # XML variant is None if no assertions made
+
+
class YamlPageSource(PageSource):
def __init__(self, inputs_list):
diff -r f24461d3e0b3f737f8e4c99b23475b571c32c61e -r 5e5c0cf930bb96bf8af0bd19daad1a999b40c374 lib/galaxy/tools/test.py
--- a/lib/galaxy/tools/test.py
+++ b/lib/galaxy/tools/test.py
@@ -127,6 +127,11 @@
if num_outputs:
num_outputs = int( num_outputs )
self.num_outputs = num_outputs
+ self.command_line = test_dict.get("command", None)
+ self.stdout = test_dict.get("stdout", None)
+ self.stderr = test_dict.get("stderr", None)
+ self.expect_exit_code = test_dict.get("expect_exit_code", None)
+ self.expect_failure = test_dict.get("expect_failure", False)
except Exception, e:
self.error = True
self.exception = e
diff -r f24461d3e0b3f737f8e4c99b23475b571c32c61e -r 5e5c0cf930bb96bf8af0bd19daad1a999b40c374 test/functional/test_toolbox.py
--- a/test/functional/test_toolbox.py
+++ b/test/functional/test_toolbox.py
@@ -1,6 +1,7 @@
import new
import sys
from base.twilltestcase import TwillTestCase
+from base.asserts import verify_assertions
from base.interactor import build_interactor, stage_data_in_history, RunToolException
from base.instrument import register_job_data
from galaxy.tools import DataManagerTool
@@ -92,6 +93,9 @@
raise Exception( "Test parse failure" )
def _verify_outputs( self, testdef, history, jobs, shed_tool_id, data_list, galaxy_interactor ):
+ assert len(jobs) == 1, "Test framework logic error, somehow tool test resulted in more than one job."
+ job = jobs[ 0 ]
+
maxseconds = testdef.maxseconds
if testdef.num_outputs is not None:
expected = testdef.num_outputs
@@ -102,7 +106,33 @@
raise Exception( message )
found_exceptions = []
- job_stdio = None
+ if testdef.expect_failure:
+ if testdef.outputs:
+ raise Exception("Cannot specify outputs in a test expecting failure.")
+
+ # Wait for the job to complete and register expections if the final
+ # status was not what test was expecting.
+ job_failed = False
+ try:
+ galaxy_interactor.wait_for_job( job[ 'id' ], history, maxseconds )
+ except Exception as e:
+ job_failed = True
+ if not testdef.expect_failure:
+ found_exceptions.append(e)
+
+ if not job_failed and testdef.expect_failure:
+ error = AssertionError("Expected job to fail but Galaxy indicated the job successfully completed.")
+ found_exceptions.append(error)
+
+ job_stdio = galaxy_interactor.get_job_stdio( job[ 'id' ] )
+
+ expect_exit_code = testdef.expect_exit_code
+ if expect_exit_code is not None:
+ exit_code = job_stdio["exit_code"]
+ if str(expect_exit_code) != str(exit_code):
+ error = AssertionError("Expected job to complete with exit code %s, found %s" % (expect_exit_code, exit_code))
+ found_exceptions.append(error)
+
for output_index, output_tuple in enumerate(testdef.outputs):
# Get the correct hid
name, outfile, attributes = output_tuple
@@ -123,14 +153,25 @@
except Exception as e:
if not found_exceptions:
# Only print this stuff out once.
- for job in jobs:
- job_stdio = galaxy_interactor.get_job_stdio( job[ 'id' ] )
- for stream in ['stdout', 'stderr']:
- if stream in job_stdio:
- print >>sys.stderr, self._format_stream( job_stdio[ stream ], stream=stream, format=True )
+ for stream in ['stdout', 'stderr']:
+ if stream in job_stdio:
+ print >>sys.stderr, self._format_stream( job_stdio[ stream ], stream=stream, format=True )
found_exceptions.append(e)
- if job_stdio is None:
- job_stdio = galaxy_interactor.get_job_stdio( jobs[0][ 'id' ] )
+
+ other_checks = {
+ "command_line": "Command produced by the job",
+ "stdout": "Standard output of the job",
+ "stderr": "Standard error of the job",
+ }
+ for what, description in other_checks.items():
+ if getattr( testdef, what, None ) is not None:
+ try:
+ data = job_stdio[what]
+ verify_assertions( data, getattr( testdef, what ) )
+ except AssertionError, err:
+ errmsg = '%s different than expected\n' % description
+ errmsg += str( err )
+ found_exceptions.append( AssertionError( errmsg ) )
if found_exceptions:
raise JobOutputsError(found_exceptions, job_stdio)
diff -r f24461d3e0b3f737f8e4c99b23475b571c32c61e -r 5e5c0cf930bb96bf8af0bd19daad1a999b40c374 test/functional/tools/job_properties.xml
--- /dev/null
+++ b/test/functional/tools/job_properties.xml
@@ -0,0 +1,62 @@
+<tool id="job_properties" name="Test Job Properties">
+ <command>
+ #if $thebool
+ echo "The bool is true";
+ echo "The bool is really true" 1>&2;
+ echo "This is a line of text." > $out_file1
+ #else
+ echo "The bool is not true";
+ echo "The bool is very not true" 1>&2;
+ echo "This is a different line of text." > $out_file1;
+ sh -c "exit 2"
+ #end if
+ #if $failbool
+ ; sh -c "exit 127"
+ #end if
+
+ </command>
+ <inputs>
+ <param name="thebool" type="boolean" label="The boolean property" />
+ <param name="failbool" type="boolean" label="The failure property" checked="false" />
+ </inputs>
+ <outputs>
+ <data name="out_file1" />
+ </outputs>
+ <stdio>
+ <exit_code range="127" level="fatal" description="Failing exit code." />
+ </stdio>
+ <tests>
+ <test expect_exit_code="0">
+ <param name="thebool" value="true" />
+ <output name="out_file1" file="simple_line.txt" />
+ <assert_command>
+ <has_text text="really" />
+ </assert_command>
+ <assert_stdout>
+ <has_line line="The bool is true" />
+ </assert_stdout>
+ <assert_stderr>
+ <has_line line="The bool is really true" />
+ </assert_stderr>
+ </test>
+ <test expect_exit_code="2">
+ <param name="thebool" value="false" />
+ <output name="out_file1" file="simple_line_alternative.txt" />
+ <assert_command>
+ <has_text text="very not" />
+ </assert_command>
+ <assert_stdout>
+ <has_line line="The bool is not true" />
+ </assert_stdout>
+ <assert_stderr>
+ <has_line line="The bool is very not true" />
+ </assert_stderr>
+ </test>
+ <test expect_exit_coded="127" expect_failure="true">
+ <param name="thebool" value="true" />
+ <param name="failbool" value="true" />
+ </test>
+ </tests>
+ <help>
+ </help>
+</tool>
diff -r f24461d3e0b3f737f8e4c99b23475b571c32c61e -r 5e5c0cf930bb96bf8af0bd19daad1a999b40c374 test/functional/tools/samples_tool_conf.xml
--- a/test/functional/tools/samples_tool_conf.xml
+++ b/test/functional/tools/samples_tool_conf.xml
@@ -13,6 +13,7 @@
<tool file="multi_output_assign_primary.xml" /><tool file="composite_output.xml" /><tool file="metadata.xml" />
+ <tool file="job_properties.xml" /><tool file="gzipped_inputs.xml" /><tool file="output_order.xml" /><tool file="output_format.xml" />
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/322c44f7519f/
Changeset: 322c44f7519f
User: jmchilton
Date: 2014-12-17 17:34:39+00:00
Summary: Allow tool tests to assert properties about command, standard output, and standard error.
See test/functional/tools/job_properties.xml for example. Provides full access to assertion based XML tags - tabular and XML based assertions probably not so interesting so these include - has_text, has_line, not_has_text, has_text_matching, has_line_matching.
Affected #: 6 files
diff -r cc7147514d77799989777fd21aa818e43d9f3d39 -r 322c44f7519fcbc57108a03402fdfdd211932266 lib/galaxy/tools/parser/xml.py
--- a/lib/galaxy/tools/parser/xml.py
+++ b/lib/galaxy/tools/parser/xml.py
@@ -186,6 +186,9 @@
rval = dict(
outputs=__parse_output_elems(test_elem),
inputs=__parse_input_elems(test_elem, i),
+ command=__parse_assert_list_from_elem( test_elem.find("assert_command") ),
+ stdout=__parse_assert_list_from_elem( test_elem.find("assert_stdout") ),
+ stderr=__parse_assert_list_from_elem( test_elem.find("assert_stderr") ),
)
_copy_to_dict_if_present(test_elem, rval, ["interactor", "num_outputs"])
return rval
@@ -222,6 +225,11 @@
return name, file, attributes
+def __parse_command_elem( test_elem ):
+ assert_elem = test_elem.find("command")
+ return __parse_assert_list_from_elem( assert_elem )
+
+
def __parse_test_attributes( output_elem, attrib ):
assert_list = __parse_assert_list( output_elem )
file = attrib.pop( 'file', None )
@@ -252,6 +260,10 @@
def __parse_assert_list( output_elem ):
assert_elem = output_elem.find("assert_contents")
+ return __parse_assert_list_from_elem( assert_elem )
+
+
+def __parse_assert_list_from_elem( assert_elem ):
assert_list = None
def convert_elem(elem):
diff -r cc7147514d77799989777fd21aa818e43d9f3d39 -r 322c44f7519fcbc57108a03402fdfdd211932266 lib/galaxy/tools/parser/yaml.py
--- a/lib/galaxy/tools/parser/yaml.py
+++ b/lib/galaxy/tools/parser/yaml.py
@@ -152,27 +152,45 @@
attributes["metadata"] = {}
# TODO
assert_list = []
- for key, assertion in attributes.get("asserts", {}).iteritems():
- # TODO: not handling nested assertions correctly,
- # not sure these are used though.
- children = []
- if "children" in assertion:
- children = assertion["children"]
- del assertion["children"]
- assert_dict = dict(
- tag=key,
- attributes=assertion,
- children=children,
- )
- assert_list.append(assert_dict)
+ assert_list = __to_test_assert_list( attributes.get("asserts", [] ) )
attributes["assert_list"] = assert_list
-
_ensure_has(attributes, defaults)
test_dict["outputs"] = new_outputs
+ test_dict["command"] = __to_test_assert_list( attributes.get( "command", [] ) )
+ test_dict["stdout"] = __to_test_assert_list( attributes.get( "stdout", [] ) )
+ test_dict["stderr"] = __to_test_assert_list( attributes.get( "stderr", [] ) )
return test_dict
+def __to_test_assert_list(assertions):
+ def expand_dict_form(item):
+ key, value = item
+ new_value = value.copy()
+ new_value["that"] = key
+ return new_value
+
+ if isinstance( assertions, dict ):
+ assertions = map(expand_dict_form, assertions.items() )
+
+ assert_list = []
+ for assertion in assertions:
+ # TODO: not handling nested assertions correctly,
+ # not sure these are used though.
+ children = []
+ if "children" in assertion:
+ children = assertion["children"]
+ del assertion["children"]
+ assert_dict = dict(
+ tag=assertion["that"],
+ attributes=assertion,
+ children=children,
+ )
+ assert_list.append(assert_dict)
+
+ return assert_list or None # XML variant is None if no assertions made
+
+
class YamlPageSource(PageSource):
def __init__(self, inputs_list):
diff -r cc7147514d77799989777fd21aa818e43d9f3d39 -r 322c44f7519fcbc57108a03402fdfdd211932266 lib/galaxy/tools/test.py
--- a/lib/galaxy/tools/test.py
+++ b/lib/galaxy/tools/test.py
@@ -127,6 +127,9 @@
if num_outputs:
num_outputs = int( num_outputs )
self.num_outputs = num_outputs
+ self.command_line = test_dict.get("command", None)
+ self.stdout = test_dict.get("stdout", None)
+ self.stderr = test_dict.get("stderr", None)
except Exception, e:
self.error = True
self.exception = e
diff -r cc7147514d77799989777fd21aa818e43d9f3d39 -r 322c44f7519fcbc57108a03402fdfdd211932266 test/functional/test_toolbox.py
--- a/test/functional/test_toolbox.py
+++ b/test/functional/test_toolbox.py
@@ -1,6 +1,7 @@
import new
import sys
from base.twilltestcase import TwillTestCase
+from base.asserts import verify_assertions
from base.interactor import build_interactor, stage_data_in_history, RunToolException
from base.instrument import register_job_data
from galaxy.tools import DataManagerTool
@@ -132,6 +133,21 @@
if job_stdio is None:
job_stdio = galaxy_interactor.get_job_stdio( jobs[0][ 'id' ] )
+ other_checks = {
+ "command_line": "Command produced by the job",
+ "stdout": "Standard output of the job",
+ "stderr": "Standard error of the job",
+ }
+ for what, description in other_checks.items():
+ if getattr( testdef, what, None ) is not None:
+ try:
+ data = job_stdio[what]
+ verify_assertions( data, getattr( testdef, what ) )
+ except AssertionError, err:
+ errmsg = '%s different than expected\n' % description
+ errmsg += str( err )
+ found_exceptions.append( AssertionError( errmsg ) )
+
if found_exceptions:
raise JobOutputsError(found_exceptions, job_stdio)
else:
diff -r cc7147514d77799989777fd21aa818e43d9f3d39 -r 322c44f7519fcbc57108a03402fdfdd211932266 test/functional/tools/job_properties.xml
--- /dev/null
+++ b/test/functional/tools/job_properties.xml
@@ -0,0 +1,53 @@
+<tool id="job_properties" name="Test Job Properties">
+ <command>
+ #if $thebool
+ echo "The bool is true";
+ echo "The bool is really true" 1>&2;
+ echo "This is a line of text." > $out_file1
+ #else
+ echo "The bool is not true";
+ echo "The bool is very not true" 1>&2;
+ echo "This is a different line of text." > $out_file1
+ #end if
+
+ </command>
+ <inputs>
+ <param name="thebool" type="boolean" label="The boolean property" />
+ </inputs>
+ <outputs>
+ <data name="out_file1" />
+ </outputs>
+ <stdio>
+ <exit_code range="127" level="fatal" description="Failing exit code." />
+ </stdio>
+ <tests>
+ <test>
+ <param name="thebool" value="true" />
+ <output name="out_file1" file="simple_line.txt" />
+ <assert_command>
+ <has_text text="really" />
+ </assert_command>
+ <assert_stdout>
+ <has_line line="The bool is true" />
+ </assert_stdout>
+ <assert_stderr>
+ <has_line line="The bool is really true" />
+ </assert_stderr>
+ </test>
+ <test>
+ <param name="thebool" value="false" />
+ <output name="out_file1" file="simple_line_alternative.txt" />
+ <assert_command>
+ <has_text text="very not" />
+ </assert_command>
+ <assert_stdout>
+ <has_line line="The bool is not true" />
+ </assert_stdout>
+ <assert_stderr>
+ <has_line line="The bool is very not true" />
+ </assert_stderr>
+ </test>
+ </tests>
+ <help>
+ </help>
+</tool>
diff -r cc7147514d77799989777fd21aa818e43d9f3d39 -r 322c44f7519fcbc57108a03402fdfdd211932266 test/functional/tools/samples_tool_conf.xml
--- a/test/functional/tools/samples_tool_conf.xml
+++ b/test/functional/tools/samples_tool_conf.xml
@@ -13,6 +13,7 @@
<tool file="multi_output_assign_primary.xml" /><tool file="composite_output.xml" /><tool file="metadata.xml" />
+ <tool file="job_properties.xml" /><tool file="gzipped_inputs.xml" /><tool file="output_order.xml" /><tool file="output_format.xml" />
https://bitbucket.org/galaxy/galaxy-central/commits/6a166c8b58e1/
Changeset: 6a166c8b58e1
User: jmchilton
Date: 2014-12-17 19:22:08+00:00
Summary: Implement expect_failure and expect_exit_code on test tag of tools.
Affected #: 5 files
diff -r 322c44f7519fcbc57108a03402fdfdd211932266 -r 6a166c8b58e13920e93ec22bffbbd87321d04520 lib/galaxy/tools/parser/xml.py
--- a/lib/galaxy/tools/parser/xml.py
+++ b/lib/galaxy/tools/parser/xml.py
@@ -189,6 +189,8 @@
command=__parse_assert_list_from_elem( test_elem.find("assert_command") ),
stdout=__parse_assert_list_from_elem( test_elem.find("assert_stdout") ),
stderr=__parse_assert_list_from_elem( test_elem.find("assert_stderr") ),
+ expect_exit_code=test_elem.get("expect_exit_code"),
+ expect_failure=string_as_bool(test_elem.get("expect_failure", False)),
)
_copy_to_dict_if_present(test_elem, rval, ["interactor", "num_outputs"])
return rval
diff -r 322c44f7519fcbc57108a03402fdfdd211932266 -r 6a166c8b58e13920e93ec22bffbbd87321d04520 lib/galaxy/tools/parser/yaml.py
--- a/lib/galaxy/tools/parser/yaml.py
+++ b/lib/galaxy/tools/parser/yaml.py
@@ -157,9 +157,11 @@
_ensure_has(attributes, defaults)
test_dict["outputs"] = new_outputs
- test_dict["command"] = __to_test_assert_list( attributes.get( "command", [] ) )
- test_dict["stdout"] = __to_test_assert_list( attributes.get( "stdout", [] ) )
- test_dict["stderr"] = __to_test_assert_list( attributes.get( "stderr", [] ) )
+ test_dict["command"] = __to_test_assert_list( test_dict.get( "command", [] ) )
+ test_dict["stdout"] = __to_test_assert_list( test_dict.get( "stdout", [] ) )
+ test_dict["stderr"] = __to_test_assert_list( test_dict.get( "stderr", [] ) )
+ test_dict["expect_exit_code"] = test_dict.get( "expect_exit_code", None )
+ test_dict["expect_failure"] = test_dict.get( "expect_exit_code", False )
return test_dict
diff -r 322c44f7519fcbc57108a03402fdfdd211932266 -r 6a166c8b58e13920e93ec22bffbbd87321d04520 lib/galaxy/tools/test.py
--- a/lib/galaxy/tools/test.py
+++ b/lib/galaxy/tools/test.py
@@ -130,6 +130,8 @@
self.command_line = test_dict.get("command", None)
self.stdout = test_dict.get("stdout", None)
self.stderr = test_dict.get("stderr", None)
+ self.expect_exit_code = test_dict.get("expect_exit_code", None)
+ self.expect_failure = test_dict.get("expect_failure", False)
except Exception, e:
self.error = True
self.exception = e
diff -r 322c44f7519fcbc57108a03402fdfdd211932266 -r 6a166c8b58e13920e93ec22bffbbd87321d04520 test/functional/test_toolbox.py
--- a/test/functional/test_toolbox.py
+++ b/test/functional/test_toolbox.py
@@ -93,6 +93,9 @@
raise Exception( "Test parse failure" )
def _verify_outputs( self, testdef, history, jobs, shed_tool_id, data_list, galaxy_interactor ):
+ assert len(jobs) == 1, "Test framework logic error, somehow tool test resulted in more than one job."
+ job = jobs[ 0 ]
+
maxseconds = testdef.maxseconds
if testdef.num_outputs is not None:
expected = testdef.num_outputs
@@ -103,7 +106,33 @@
raise Exception( message )
found_exceptions = []
- job_stdio = None
+ if testdef.expect_failure:
+ if testdef.outputs:
+ raise Exception("Cannot specify outputs in a test expecting failure.")
+
+ # Wait for the job to complete and register expections if the final
+ # status was not what test was expecting.
+ job_failed = False
+ try:
+ galaxy_interactor.wait_for_job( job[ 'id' ], history, maxseconds )
+ except Exception as e:
+ job_failed = True
+ if not testdef.expect_failure:
+ found_exceptions.append(e)
+
+ if not job_failed and testdef.expect_failure:
+ error = AssertionError("Expected job to fail but Galaxy indicated the job successfully completed.")
+ found_exceptions.append(error)
+
+ job_stdio = galaxy_interactor.get_job_stdio( job[ 'id' ] )
+
+ expect_exit_code = testdef.expect_exit_code
+ if expect_exit_code is not None:
+ exit_code = job_stdio["exit_code"]
+ if str(expect_exit_code) != str(exit_code):
+ error = AssertionError("Expected job to complete with exit code %s, found %s" % (expect_exit_code, exit_code))
+ found_exceptions.append(error)
+
for output_index, output_tuple in enumerate(testdef.outputs):
# Get the correct hid
name, outfile, attributes = output_tuple
@@ -124,14 +153,10 @@
except Exception as e:
if not found_exceptions:
# Only print this stuff out once.
- for job in jobs:
- job_stdio = galaxy_interactor.get_job_stdio( job[ 'id' ] )
- for stream in ['stdout', 'stderr']:
- if stream in job_stdio:
- print >>sys.stderr, self._format_stream( job_stdio[ stream ], stream=stream, format=True )
+ for stream in ['stdout', 'stderr']:
+ if stream in job_stdio:
+ print >>sys.stderr, self._format_stream( job_stdio[ stream ], stream=stream, format=True )
found_exceptions.append(e)
- if job_stdio is None:
- job_stdio = galaxy_interactor.get_job_stdio( jobs[0][ 'id' ] )
other_checks = {
"command_line": "Command produced by the job",
diff -r 322c44f7519fcbc57108a03402fdfdd211932266 -r 6a166c8b58e13920e93ec22bffbbd87321d04520 test/functional/tools/job_properties.xml
--- a/test/functional/tools/job_properties.xml
+++ b/test/functional/tools/job_properties.xml
@@ -7,12 +7,17 @@
#else
echo "The bool is not true";
echo "The bool is very not true" 1>&2;
- echo "This is a different line of text." > $out_file1
+ echo "This is a different line of text." > $out_file1;
+ sh -c "exit 2"
+ #end if
+ #if $failbool
+ ; sh -c "exit 127"
#end if
</command><inputs><param name="thebool" type="boolean" label="The boolean property" />
+ <param name="failbool" type="boolean" label="The failure property" checked="false" /></inputs><outputs><data name="out_file1" />
@@ -21,7 +26,7 @@
<exit_code range="127" level="fatal" description="Failing exit code." /></stdio><tests>
- <test>
+ <test expect_exit_code="0"><param name="thebool" value="true" /><output name="out_file1" file="simple_line.txt" /><assert_command>
@@ -34,7 +39,7 @@
<has_line line="The bool is really true" /></assert_stderr></test>
- <test>
+ <test expect_exit_code="2"><param name="thebool" value="false" /><output name="out_file1" file="simple_line_alternative.txt" /><assert_command>
@@ -47,6 +52,10 @@
<has_line line="The bool is very not true" /></assert_stderr></test>
+ <test expect_exit_coded="127" expect_failure="true">
+ <param name="thebool" value="true" />
+ <param name="failbool" value="true" />
+ </test></tests><help></help>
https://bitbucket.org/galaxy/galaxy-central/commits/5e5c0cf930bb/
Changeset: 5e5c0cf930bb
User: jmchilton
Date: 2014-12-17 20:47:54+00:00
Summary: Merged in jmchilton/galaxy-central-fork-1 (pull request #617)
Allow tool tests to assert properties about command, standard output, and standard error.
Affected #: 6 files
diff -r f24461d3e0b3f737f8e4c99b23475b571c32c61e -r 5e5c0cf930bb96bf8af0bd19daad1a999b40c374 lib/galaxy/tools/parser/xml.py
--- a/lib/galaxy/tools/parser/xml.py
+++ b/lib/galaxy/tools/parser/xml.py
@@ -186,6 +186,11 @@
rval = dict(
outputs=__parse_output_elems(test_elem),
inputs=__parse_input_elems(test_elem, i),
+ command=__parse_assert_list_from_elem( test_elem.find("assert_command") ),
+ stdout=__parse_assert_list_from_elem( test_elem.find("assert_stdout") ),
+ stderr=__parse_assert_list_from_elem( test_elem.find("assert_stderr") ),
+ expect_exit_code=test_elem.get("expect_exit_code"),
+ expect_failure=string_as_bool(test_elem.get("expect_failure", False)),
)
_copy_to_dict_if_present(test_elem, rval, ["interactor", "num_outputs"])
return rval
@@ -222,6 +227,11 @@
return name, file, attributes
+def __parse_command_elem( test_elem ):
+ assert_elem = test_elem.find("command")
+ return __parse_assert_list_from_elem( assert_elem )
+
+
def __parse_test_attributes( output_elem, attrib ):
assert_list = __parse_assert_list( output_elem )
file = attrib.pop( 'file', None )
@@ -252,6 +262,10 @@
def __parse_assert_list( output_elem ):
assert_elem = output_elem.find("assert_contents")
+ return __parse_assert_list_from_elem( assert_elem )
+
+
+def __parse_assert_list_from_elem( assert_elem ):
assert_list = None
def convert_elem(elem):
diff -r f24461d3e0b3f737f8e4c99b23475b571c32c61e -r 5e5c0cf930bb96bf8af0bd19daad1a999b40c374 lib/galaxy/tools/parser/yaml.py
--- a/lib/galaxy/tools/parser/yaml.py
+++ b/lib/galaxy/tools/parser/yaml.py
@@ -152,27 +152,47 @@
attributes["metadata"] = {}
# TODO
assert_list = []
- for key, assertion in attributes.get("asserts", {}).iteritems():
- # TODO: not handling nested assertions correctly,
- # not sure these are used though.
- children = []
- if "children" in assertion:
- children = assertion["children"]
- del assertion["children"]
- assert_dict = dict(
- tag=key,
- attributes=assertion,
- children=children,
- )
- assert_list.append(assert_dict)
+ assert_list = __to_test_assert_list( attributes.get("asserts", [] ) )
attributes["assert_list"] = assert_list
-
_ensure_has(attributes, defaults)
test_dict["outputs"] = new_outputs
+ test_dict["command"] = __to_test_assert_list( test_dict.get( "command", [] ) )
+ test_dict["stdout"] = __to_test_assert_list( test_dict.get( "stdout", [] ) )
+ test_dict["stderr"] = __to_test_assert_list( test_dict.get( "stderr", [] ) )
+ test_dict["expect_exit_code"] = test_dict.get( "expect_exit_code", None )
+ test_dict["expect_failure"] = test_dict.get( "expect_exit_code", False )
return test_dict
+def __to_test_assert_list(assertions):
+ def expand_dict_form(item):
+ key, value = item
+ new_value = value.copy()
+ new_value["that"] = key
+ return new_value
+
+ if isinstance( assertions, dict ):
+ assertions = map(expand_dict_form, assertions.items() )
+
+ assert_list = []
+ for assertion in assertions:
+ # TODO: not handling nested assertions correctly,
+ # not sure these are used though.
+ children = []
+ if "children" in assertion:
+ children = assertion["children"]
+ del assertion["children"]
+ assert_dict = dict(
+ tag=assertion["that"],
+ attributes=assertion,
+ children=children,
+ )
+ assert_list.append(assert_dict)
+
+ return assert_list or None # XML variant is None if no assertions made
+
+
class YamlPageSource(PageSource):
def __init__(self, inputs_list):
diff -r f24461d3e0b3f737f8e4c99b23475b571c32c61e -r 5e5c0cf930bb96bf8af0bd19daad1a999b40c374 lib/galaxy/tools/test.py
--- a/lib/galaxy/tools/test.py
+++ b/lib/galaxy/tools/test.py
@@ -127,6 +127,11 @@
if num_outputs:
num_outputs = int( num_outputs )
self.num_outputs = num_outputs
+ self.command_line = test_dict.get("command", None)
+ self.stdout = test_dict.get("stdout", None)
+ self.stderr = test_dict.get("stderr", None)
+ self.expect_exit_code = test_dict.get("expect_exit_code", None)
+ self.expect_failure = test_dict.get("expect_failure", False)
except Exception, e:
self.error = True
self.exception = e
diff -r f24461d3e0b3f737f8e4c99b23475b571c32c61e -r 5e5c0cf930bb96bf8af0bd19daad1a999b40c374 test/functional/test_toolbox.py
--- a/test/functional/test_toolbox.py
+++ b/test/functional/test_toolbox.py
@@ -1,6 +1,7 @@
import new
import sys
from base.twilltestcase import TwillTestCase
+from base.asserts import verify_assertions
from base.interactor import build_interactor, stage_data_in_history, RunToolException
from base.instrument import register_job_data
from galaxy.tools import DataManagerTool
@@ -92,6 +93,9 @@
raise Exception( "Test parse failure" )
def _verify_outputs( self, testdef, history, jobs, shed_tool_id, data_list, galaxy_interactor ):
+ assert len(jobs) == 1, "Test framework logic error, somehow tool test resulted in more than one job."
+ job = jobs[ 0 ]
+
maxseconds = testdef.maxseconds
if testdef.num_outputs is not None:
expected = testdef.num_outputs
@@ -102,7 +106,33 @@
raise Exception( message )
found_exceptions = []
- job_stdio = None
+ if testdef.expect_failure:
+ if testdef.outputs:
+ raise Exception("Cannot specify outputs in a test expecting failure.")
+
+ # Wait for the job to complete and register expections if the final
+ # status was not what test was expecting.
+ job_failed = False
+ try:
+ galaxy_interactor.wait_for_job( job[ 'id' ], history, maxseconds )
+ except Exception as e:
+ job_failed = True
+ if not testdef.expect_failure:
+ found_exceptions.append(e)
+
+ if not job_failed and testdef.expect_failure:
+ error = AssertionError("Expected job to fail but Galaxy indicated the job successfully completed.")
+ found_exceptions.append(error)
+
+ job_stdio = galaxy_interactor.get_job_stdio( job[ 'id' ] )
+
+ expect_exit_code = testdef.expect_exit_code
+ if expect_exit_code is not None:
+ exit_code = job_stdio["exit_code"]
+ if str(expect_exit_code) != str(exit_code):
+ error = AssertionError("Expected job to complete with exit code %s, found %s" % (expect_exit_code, exit_code))
+ found_exceptions.append(error)
+
for output_index, output_tuple in enumerate(testdef.outputs):
# Get the correct hid
name, outfile, attributes = output_tuple
@@ -123,14 +153,25 @@
except Exception as e:
if not found_exceptions:
# Only print this stuff out once.
- for job in jobs:
- job_stdio = galaxy_interactor.get_job_stdio( job[ 'id' ] )
- for stream in ['stdout', 'stderr']:
- if stream in job_stdio:
- print >>sys.stderr, self._format_stream( job_stdio[ stream ], stream=stream, format=True )
+ for stream in ['stdout', 'stderr']:
+ if stream in job_stdio:
+ print >>sys.stderr, self._format_stream( job_stdio[ stream ], stream=stream, format=True )
found_exceptions.append(e)
- if job_stdio is None:
- job_stdio = galaxy_interactor.get_job_stdio( jobs[0][ 'id' ] )
+
+ other_checks = {
+ "command_line": "Command produced by the job",
+ "stdout": "Standard output of the job",
+ "stderr": "Standard error of the job",
+ }
+ for what, description in other_checks.items():
+ if getattr( testdef, what, None ) is not None:
+ try:
+ data = job_stdio[what]
+ verify_assertions( data, getattr( testdef, what ) )
+ except AssertionError, err:
+ errmsg = '%s different than expected\n' % description
+ errmsg += str( err )
+ found_exceptions.append( AssertionError( errmsg ) )
if found_exceptions:
raise JobOutputsError(found_exceptions, job_stdio)
diff -r f24461d3e0b3f737f8e4c99b23475b571c32c61e -r 5e5c0cf930bb96bf8af0bd19daad1a999b40c374 test/functional/tools/job_properties.xml
--- /dev/null
+++ b/test/functional/tools/job_properties.xml
@@ -0,0 +1,62 @@
+<tool id="job_properties" name="Test Job Properties">
+ <command>
+ #if $thebool
+ echo "The bool is true";
+ echo "The bool is really true" 1>&2;
+ echo "This is a line of text." > $out_file1
+ #else
+ echo "The bool is not true";
+ echo "The bool is very not true" 1>&2;
+ echo "This is a different line of text." > $out_file1;
+ sh -c "exit 2"
+ #end if
+ #if $failbool
+ ; sh -c "exit 127"
+ #end if
+
+ </command>
+ <inputs>
+ <param name="thebool" type="boolean" label="The boolean property" />
+ <param name="failbool" type="boolean" label="The failure property" checked="false" />
+ </inputs>
+ <outputs>
+ <data name="out_file1" />
+ </outputs>
+ <stdio>
+ <exit_code range="127" level="fatal" description="Failing exit code." />
+ </stdio>
+ <tests>
+ <test expect_exit_code="0">
+ <param name="thebool" value="true" />
+ <output name="out_file1" file="simple_line.txt" />
+ <assert_command>
+ <has_text text="really" />
+ </assert_command>
+ <assert_stdout>
+ <has_line line="The bool is true" />
+ </assert_stdout>
+ <assert_stderr>
+ <has_line line="The bool is really true" />
+ </assert_stderr>
+ </test>
+ <test expect_exit_code="2">
+ <param name="thebool" value="false" />
+ <output name="out_file1" file="simple_line_alternative.txt" />
+ <assert_command>
+ <has_text text="very not" />
+ </assert_command>
+ <assert_stdout>
+ <has_line line="The bool is not true" />
+ </assert_stdout>
+ <assert_stderr>
+ <has_line line="The bool is very not true" />
+ </assert_stderr>
+ </test>
+ <test expect_exit_coded="127" expect_failure="true">
+ <param name="thebool" value="true" />
+ <param name="failbool" value="true" />
+ </test>
+ </tests>
+ <help>
+ </help>
+</tool>
diff -r f24461d3e0b3f737f8e4c99b23475b571c32c61e -r 5e5c0cf930bb96bf8af0bd19daad1a999b40c374 test/functional/tools/samples_tool_conf.xml
--- a/test/functional/tools/samples_tool_conf.xml
+++ b/test/functional/tools/samples_tool_conf.xml
@@ -13,6 +13,7 @@
<tool file="multi_output_assign_primary.xml" /><tool file="composite_output.xml" /><tool file="metadata.xml" />
+ <tool file="job_properties.xml" /><tool file="gzipped_inputs.xml" /><tool file="output_order.xml" /><tool file="output_format.xml" />
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