galaxy-commits
Threads by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- 15302 discussions
commit/galaxy-central: jgoecks: Trackster: resolve name collision due to refactoring.
by commits-noreply@bitbucket.org 24 Jul '14
by commits-noreply@bitbucket.org 24 Jul '14
24 Jul '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/9d8967752787/
Changeset: 9d8967752787
User: jgoecks
Date: 2014-07-24 15:26:39
Summary: Trackster: resolve name collision due to refactoring.
Affected #: 1 file
diff -r 6fbe4d95a8dc64bd222dbf1170bdadcc5321e855 -r 9d8967752787556b3d814e086fe2bd9eb1992170 static/scripts/viz/trackster.js
--- a/static/scripts/viz/trackster.js
+++ b/static/scripts/viz/trackster.js
@@ -103,8 +103,9 @@
var self = this,
menu = create_icon_buttons_menu([
{ icon_class: 'plus-button', title: 'Add tracks', on_click: function() {
- visualization.select_datasets(galaxy_config.root + "visualization/list_current_history_datasets", galaxy_config.root + "api/datasets", { 'f-dbkey': view.dbkey }, function(tracks) {
- _.each(tracks, function(track) {
+ visualization.select_datasets(galaxy_config.root + "visualization/list_current_history_datasets", galaxy_config.root + "api/datasets", { 'f-dbkey': view.dbkey },
+ function(new_tracks) {
+ _.each(new_tracks, function(track) {
view.add_drawable( tracks.object_from_template(track, view, view) );
});
});
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Fix missing import in the Tool Shed's ToolValidator.
by commits-noreply@bitbucket.org 23 Jul '14
by commits-noreply@bitbucket.org 23 Jul '14
23 Jul '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/6fbe4d95a8dc/
Changeset: 6fbe4d95a8dc
User: greg
Date: 2014-07-23 22:31:59
Summary: Fix missing import in the Tool Shed's ToolValidator.
Affected #: 1 file
diff -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 -r 6fbe4d95a8dc64bd222dbf1170bdadcc5321e855 lib/tool_shed/tools/tool_validator.py
--- a/lib/tool_shed/tools/tool_validator.py
+++ b/lib/tool_shed/tools/tool_validator.py
@@ -12,6 +12,7 @@
from tool_shed.util import hg_util
from tool_shed.util import shed_util_common as suc
from tool_shed.util import tool_util
+from tool_shed.util import xml_util
log = logging.getLogger( __name__ )
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/2ae881148949/
Changeset: 2ae881148949
User: dannon
Date: 2014-07-23 21:41:14
Summary: Fix 'decod_id' invocation to use the correct function when deleting user addresses.
Affected #: 1 file
diff -r 053943b668af334c480b464fe7351b50284b7099 -r 2ae881148949596af9c30f2c559dc8f627dda402 lib/galaxy/webapps/galaxy/controllers/user.py
--- a/lib/galaxy/webapps/galaxy/controllers/user.py
+++ b/lib/galaxy/webapps/galaxy/controllers/user.py
@@ -1514,7 +1514,7 @@
@web.expose
def delete_address( self, trans, cntrller, address_id=None, user_id=None ):
try:
- user_address = trans.sa_session.query( trans.app.model.UserAddress ).get( trans.security.decod_id( address_id ) )
+ user_address = trans.sa_session.query( trans.app.model.UserAddress ).get( trans.security.decode_id( address_id ) )
except:
message = 'Invalid address is (%s)' % address_id
status = 'error'
https://bitbucket.org/galaxy/galaxy-central/commits/4974ffd8b2cb/
Changeset: 4974ffd8b2cb
User: dannon
Date: 2014-07-23 21:42:23
Summary: Fix another variable definition issue in user address deletion.
Affected #: 1 file
diff -r 2ae881148949596af9c30f2c559dc8f627dda402 -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 lib/galaxy/webapps/galaxy/controllers/user.py
--- a/lib/galaxy/webapps/galaxy/controllers/user.py
+++ b/lib/galaxy/webapps/galaxy/controllers/user.py
@@ -1522,7 +1522,7 @@
user_address.deleted = True
trans.sa_session.add( user_address )
trans.sa_session.flush()
- 'Address (%s) deleted' % user_address.desc
+ message = 'Address (%s) deleted' % user_address.desc
status = 'done'
return trans.response.send_redirect( web.url_for( controller='user',
action='manage_user_info',
https://bitbucket.org/galaxy/galaxy-central/commits/7aade8875ea4/
Changeset: 7aade8875ea4
User: dannon
Date: 2014-07-23 22:27:42
Summary: Merge.
Affected #: 60 files
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 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
@@ -12,7 +12,6 @@
import tool_shed.repository_types.util as rt_util
from tool_shed.util import common_util
-from tool_shed.util import datatype_util
from tool_shed.util import encoding_util
from tool_shed.util import hg_util
from tool_shed.util import readme_util
@@ -25,6 +24,7 @@
from tool_shed.galaxy_install import dependency_display
from tool_shed.galaxy_install import install_manager
+from tool_shed.galaxy_install.datatypes import custom_datatype_manager
from tool_shed.galaxy_install.grids import admin_toolshed_grids
from tool_shed.galaxy_install.metadata.installed_repository_metadata_manager import InstalledRepositoryMetadataManager
from tool_shed.galaxy_install.repair_repository_manager import RepairRepositoryManager
@@ -256,17 +256,17 @@
dmh.remove_from_data_manager( tool_shed_repository )
if tool_shed_repository.includes_datatypes:
# Deactivate proprietary datatypes.
- installed_repository_dict = datatype_util.load_installed_datatypes( trans.app,
- tool_shed_repository,
- repository_install_dir,
- deactivate=True )
+ cdl = custom_datatype_manager.CustomDatatypeLoader( trans.app )
+ installed_repository_dict = cdl.load_installed_datatypes( tool_shed_repository,
+ repository_install_dir,
+ deactivate=True )
if installed_repository_dict:
converter_path = installed_repository_dict.get( 'converter_path' )
if converter_path is not None:
- datatype_util.load_installed_datatype_converters( trans.app, installed_repository_dict, deactivate=True )
+ cdl.load_installed_datatype_converters( installed_repository_dict, deactivate=True )
display_path = installed_repository_dict.get( 'display_path' )
if display_path is not None:
- datatype_util.load_installed_display_applications( trans.app, installed_repository_dict, deactivate=True )
+ cdl.load_installed_display_applications( installed_repository_dict, deactivate=True )
if remove_from_disk_checked:
try:
# Remove the repository from disk.
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 lib/galaxy/webapps/galaxy/controllers/history.py
--- a/lib/galaxy/webapps/galaxy/controllers/history.py
+++ b/lib/galaxy/webapps/galaxy/controllers/history.py
@@ -195,6 +195,7 @@
class HistoryController( BaseUIController, SharableMixin, UsesAnnotations, UsesItemRatings,
UsesHistoryMixin, UsesHistoryDatasetAssociationMixin, ExportsHistoryMixin,
ImportsHistoryMixin ):
+
def __init__( self, app ):
super( HistoryController, self ).__init__( app )
self.mgrs = util.bunch.Bunch(
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 lib/galaxy/webapps/galaxy/controllers/page.py
--- a/lib/galaxy/webapps/galaxy/controllers/page.py
+++ b/lib/galaxy/webapps/galaxy/controllers/page.py
@@ -1,5 +1,6 @@
from sqlalchemy import desc, and_
from galaxy import model, web
+from galaxy import managers
from galaxy.web import error, url_for
from galaxy.model.item_attrs import UsesItemRatings
from galaxy.web.base.controller import BaseUIController, SharableMixin, UsesHistoryMixin, UsesStoredWorkflowMixin, UsesVisualizationMixin
@@ -285,6 +286,12 @@
_page_selection_grid = PageSelectionGrid()
_visualization_selection_grid = VisualizationSelectionGrid()
+ def __init__( self, app ):
+ super( PageController, self ).__init__( app )
+ self.mgrs = util.bunch.Bunch(
+ histories=managers.histories.HistoryManager()
+ )
+
@web.expose
@web.require_login()
def list( self, trans, *args, **kwargs ):
@@ -718,6 +725,7 @@
"""
Returns html suitable for embedding in another page.
"""
+ #TODO: should be moved to history controller and/or called via ajax from the template
history = self.get_history( trans, id, False, True )
if not history:
return None
@@ -729,15 +737,22 @@
hda_dicts = []
datasets = self.get_history_datasets( trans, history )
- for hda in datasets:
- hda_dict = self.get_hda_dict( trans, hda )
- hda_dict[ 'annotation' ] = self.get_item_annotation_str( trans.sa_session, history.user, hda )
- hda_dicts.append( hda_dict )
- history_dict = self.get_history_dict( trans, history, hda_dictionaries=hda_dicts )
- history_dict[ 'annotation' ] = history.annotation
+ #for hda in datasets:
+ # hda_dict = self.get_hda_dict( trans, hda )
+ # hda_dict[ 'annotation' ] = self.get_item_annotation_str( trans.sa_session, history.user, hda )
+ # hda_dicts.append( hda_dict )
+ #history_dict = self.get_history_dict( trans, history, hda_dictionaries=hda_dicts )
+ #history_dict[ 'annotation' ] = history.annotation
+
+ # include all datasets: hidden, deleted, and purged
+ #TODO!: doubled query (hda_dictionaries + datasets)
+ history_data = self.mgrs.histories._get_history_data( trans, history )
+ history_dictionary = history_data[ 'history' ]
+ hda_dictionaries = history_data[ 'contents' ]
+ history_dictionary[ 'annotation' ] = history.annotation
filled = trans.fill_template( "history/embed.mako", item=history, item_data=datasets,
- user_is_owner=user_is_owner, history_dict=history_dict, hda_dicts=hda_dicts )
+ user_is_owner=user_is_owner, history_dict=history_dictionary, hda_dicts=hda_dictionaries )
return filled
def _get_embed_html( self, trans, item_class, item_id ):
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 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
@@ -1062,7 +1062,7 @@
action='browse_repositories',
message=message,
status=status ) )
- name = kwd.get( 'name', '' )
+ name = kwd.get( 'name', '' ).strip()
description = kwd.get( 'description', '' )
long_description = kwd.get( 'long_description', '' )
category_ids = util.listify( kwd.get( 'category_id', '' ) )
@@ -1262,7 +1262,11 @@
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans.app, repository_id, changeset_revision )
metadata = repository_metadata.metadata
toolshed_base_url = str( web.url_for( '/', qualified=True ) ).rstrip( '/' )
+ # Initialize the repository dependency RelationBuilder.
rb = relation_builder.RelationBuilder( trans.app, repository, repository_metadata, toolshed_base_url )
+ # Work-around to ensure repositories that contain packages needed only for compiling
+ # a dependent package are included in the capsule.
+ rb.set_filter_dependencies_needed_for_compiling( False )
# Get a dictionary of all repositories upon which the contents of the current repository_metadata record depend.
repository_dependencies = rb.get_repository_dependencies_for_changeset_revision()
if repository_dependencies:
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 lib/tool_shed/capsule/capsule_manager.py
--- a/lib/tool_shed/capsule/capsule_manager.py
+++ b/lib/tool_shed/capsule/capsule_manager.py
@@ -245,9 +245,13 @@
repository_metadata = suc.get_repository_metadata_by_changeset_revision( self.app,
self.repository_id,
self.changeset_revision )
- # Get a dictionary of all repositories upon which the contents of the current repository_metadata record depend.
+ # Get a dictionary of all repositories upon which the contents of the current
+ # repository_metadata record depend.
toolshed_base_url = str( web.url_for( '/', qualified=True ) ).rstrip( '/' )
rb = RelationBuilder( self.app, repository, repository_metadata, toolshed_base_url )
+ # Work-around to ensure repositories that contain packages needed only for compiling
+ # a dependent package are included in the capsule.
+ rb.set_filter_dependencies_needed_for_compiling( False )
repository_dependencies = rb.get_repository_dependencies_for_changeset_revision()
repo = hg_util.get_repo_for_repository( self.app,
repository=self.repository,
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 lib/tool_shed/dependencies/repository/relation_builder.py
--- a/lib/tool_shed/dependencies/repository/relation_builder.py
+++ b/lib/tool_shed/dependencies/repository/relation_builder.py
@@ -23,6 +23,11 @@
self.handled_key_rd_dicts = []
self.key_rd_dicts_to_be_processed = []
self.tool_shed_url = tool_shed_url
+ # This is a temporary work-around for handling repository dependencies that are needed
+ # only if compiling a dependent package. This value should be True unless exporting
+ # a repository capsule, in which case the set_filter_dependencies_needed_for_compiling()
+ # function is called.
+ self.filter_dependencies_needed_for_compiling = True
def can_add_to_key_rd_dicts( self, key_rd_dict, key_rd_dicts ):
"""Handle the case where an update to the changeset revision was done."""
@@ -389,9 +394,12 @@
current_repository_key_rd_dicts = \
self.get_updated_changeset_revisions_for_repository_dependencies( current_repository_key_rd_dicts )
for key_rd_dict in current_repository_key_rd_dicts:
- # Filter out repository dependencies that are required only if compiling the dependent
- # repository's tool dependency.
- key_rd_dict = self.filter_only_if_compiling_contained_td( key_rd_dict )
+ if self.filter_dependencies_needed_for_compiling:
+ # Filter out repository dependencies that are required only if compiling the dependent
+ # repository's tool dependency.
+ # TODO: this temporary work-around should be removed when the underlying framework
+ # support for handling only_if_compiling_contained_td-flagged repositories is completed.
+ key_rd_dict = self.filter_only_if_compiling_contained_td( key_rd_dict )
if key_rd_dict:
is_circular = False
in_handled_key_rd_dicts = self.in_key_rd_dicts( key_rd_dict, self.handled_key_rd_dicts )
@@ -483,6 +491,9 @@
clean_key_rd_dicts.append( new_key_rd_dict )
return clean_key_rd_dicts
+ def set_filter_dependencies_needed_for_compiling( self, value ):
+ self.filter_dependencies_needed_for_compiling = asbool( value )
+
def update_circular_repository_dependencies( self, repository_key, repository_dependency, repository_dependencies ):
repository_dependency_as_key = self.get_repository_dependency_as_key( repository_dependency )
repository_key_as_repository_dependency = repository_key.split( container_util.STRSEP )
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 lib/tool_shed/galaxy_install/datatypes/custom_datatype_manager.py
--- /dev/null
+++ b/lib/tool_shed/galaxy_install/datatypes/custom_datatype_manager.py
@@ -0,0 +1,218 @@
+import logging
+import os
+import tempfile
+
+from galaxy.util import asbool
+
+from tool_shed.util import basic_util
+from tool_shed.util import hg_util
+from tool_shed.util import tool_util
+from tool_shed.util import shed_util_common as suc
+from tool_shed.util import xml_util
+
+log = logging.getLogger( __name__ )
+
+
+class CustomDatatypeLoader( object ):
+
+ def __init__( self, app ):
+ self.app = app
+
+ def alter_config_and_load_prorietary_datatypes( self, datatypes_config, relative_install_dir,
+ deactivate=False, override=True ):
+ """
+ Parse a custom datatypes config (a datatypes_conf.xml file included in an installed
+ tool shed repository) and add information to appropriate element attributes that will
+ enable custom datatype class modules, datatypes converters and display applications
+ to be discovered and properly imported by the datatypes registry. The value of override
+ will be False when a tool shed repository is being installed. Since installation is
+ occurring after the datatypes registry has been initialized, the registry's contents
+ cannot be overridden by conflicting data types.
+ """
+ tree, error_message = xml_util.parse_xml( datatypes_config )
+ if tree is None:
+ return None, None
+ datatypes_config_root = tree.getroot()
+ registration = datatypes_config_root.find( 'registration' )
+ if registration is None:
+ # We have valid XML, but not a valid custom datatypes definition.
+ return None, None
+ sniffers = datatypes_config_root.find( 'sniffers' )
+ converter_path, display_path = self.get_converter_and_display_paths( registration,
+ relative_install_dir )
+ if converter_path:
+ # Path to datatype converters
+ registration.attrib[ 'proprietary_converter_path' ] = converter_path
+ if display_path:
+ # Path to datatype display applications
+ registration.attrib[ 'proprietary_display_path' ] = display_path
+ relative_path_to_datatype_file_name = None
+ datatype_files = datatypes_config_root.find( 'datatype_files' )
+ datatype_class_modules = []
+ if datatype_files is not None:
+ # The <datatype_files> tag set contains any number of <datatype_file> tags.
+ # <datatype_files>
+ # <datatype_file name="gmap.py"/>
+ # <datatype_file name="metagenomics.py"/>
+ # </datatype_files>
+ # We'll add attributes to the datatype tag sets so that the modules can be properly imported
+ # by the datatypes registry.
+ for elem in datatype_files.findall( 'datatype_file' ):
+ datatype_file_name = elem.get( 'name', None )
+ if datatype_file_name:
+ # Find the file in the installed repository.
+ for root, dirs, files in os.walk( relative_install_dir ):
+ if root.find( '.hg' ) < 0:
+ for name in files:
+ if name == datatype_file_name:
+ datatype_class_modules.append( os.path.join( root, name ) )
+ break
+ break
+ if datatype_class_modules:
+ for relative_path_to_datatype_file_name in datatype_class_modules:
+ datatype_file_name_path, datatype_file_name = os.path.split( relative_path_to_datatype_file_name )
+ for elem in registration.findall( 'datatype' ):
+ # Handle 'type' attribute which should be something like one of the following:
+ # type="gmap:GmapDB"
+ # type="galaxy.datatypes.gmap:GmapDB"
+ dtype = elem.get( 'type', None )
+ if dtype:
+ fields = dtype.split( ':' )
+ proprietary_datatype_module = fields[ 0 ]
+ if proprietary_datatype_module.find( '.' ) >= 0:
+ # Handle the case where datatype_module is "galaxy.datatypes.gmap".
+ proprietary_datatype_module = proprietary_datatype_module.split( '.' )[ -1 ]
+ # The value of proprietary_path must be an absolute path due to job_working_directory.
+ elem.attrib[ 'proprietary_path' ] = os.path.abspath( datatype_file_name_path )
+ elem.attrib[ 'proprietary_datatype_module' ] = proprietary_datatype_module
+ # Temporarily persist the custom datatypes configuration file so it can be loaded into the
+ # datatypes registry.
+ fd, proprietary_datatypes_config = tempfile.mkstemp( prefix="tmp-toolshed-acalpd" )
+ os.write( fd, '<?xml version="1.0"?>\n' )
+ os.write( fd, '<datatypes>\n' )
+ os.write( fd, '%s' % xml_util.xml_to_string( registration ) )
+ if sniffers is not None:
+ os.write( fd, '%s' % xml_util.xml_to_string( sniffers ) )
+ os.write( fd, '</datatypes>\n' )
+ os.close( fd )
+ os.chmod( proprietary_datatypes_config, 0644 )
+ # Load custom datatypes
+ self.app.datatypes_registry.load_datatypes( root_dir=self.app.config.root,
+ config=proprietary_datatypes_config,
+ deactivate=deactivate,
+ override=override )
+ if deactivate:
+ # Reload the upload tool to eliminate deactivated datatype extensions from the file_type
+ # select list.
+ tool_util.reload_upload_tools( self.app )
+ else:
+ self.append_to_datatypes_registry_upload_file_formats( registration )
+ tool_util.reload_upload_tools( self.app )
+ if datatype_files is not None:
+ try:
+ os.unlink( proprietary_datatypes_config )
+ except:
+ pass
+ return converter_path, display_path
+
+ def append_to_datatypes_registry_upload_file_formats( self, elem ):
+ # See if we have any datatypes that should be displayed in the upload tool's file_type select list.
+ for datatype_elem in elem.findall( 'datatype' ):
+ extension = datatype_elem.get( 'extension', None )
+ display_in_upload = datatype_elem.get( 'display_in_upload', None )
+ if extension is not None and display_in_upload is not None:
+ display_in_upload = asbool( str( display_in_upload ) )
+ if display_in_upload and extension not in self.app.datatypes_registry.upload_file_formats:
+ self.app.datatypes_registry.upload_file_formats.append( extension )
+
+ def create_repository_dict_for_proprietary_datatypes( self, tool_shed, name, owner, installed_changeset_revision,
+ tool_dicts, converter_path=None, display_path=None ):
+ return dict( tool_shed=tool_shed,
+ repository_name=name,
+ repository_owner=owner,
+ installed_changeset_revision=installed_changeset_revision,
+ tool_dicts=tool_dicts,
+ converter_path=converter_path,
+ display_path=display_path )
+
+ def get_converter_and_display_paths( self, registration_elem, relative_install_dir ):
+ """
+ Find the relative path to data type converters and display applications included
+ in installed tool shed repositories.
+ """
+ converter_path = None
+ display_path = None
+ for elem in registration_elem.findall( 'datatype' ):
+ if not converter_path:
+ # If any of the <datatype> tag sets contain <converter> tags, set the converter_path
+ # if it is not already set. This requires developers to place all converters in the
+ # same subdirectory within the repository hierarchy.
+ for converter in elem.findall( 'converter' ):
+ converter_config = converter.get( 'file', None )
+ if converter_config:
+ converter_config_file_name = basic_util.strip_path( converter_config )
+ for root, dirs, files in os.walk( relative_install_dir ):
+ if root.find( '.hg' ) < 0:
+ for name in files:
+ if name == converter_config_file_name:
+ # The value of converter_path must be absolute due to job_working_directory.
+ converter_path = os.path.abspath( root )
+ break
+ if converter_path:
+ break
+ if not display_path:
+ # If any of the <datatype> tag sets contain <display> tags, set the display_path
+ # if it is not already set. This requires developers to place all display acpplications
+ # in the same subdirectory within the repository hierarchy.
+ for display_app in elem.findall( 'display' ):
+ display_config = display_app.get( 'file', None )
+ if display_config:
+ display_config_file_name = basic_util.strip_path( display_config )
+ for root, dirs, files in os.walk( relative_install_dir ):
+ if root.find( '.hg' ) < 0:
+ for name in files:
+ if name == display_config_file_name:
+ # The value of display_path must be absolute due to job_working_directory.
+ display_path = os.path.abspath( root )
+ break
+ if display_path:
+ break
+ if converter_path and display_path:
+ break
+ return converter_path, display_path
+
+ def load_installed_datatype_converters( self, installed_repository_dict, deactivate=False ):
+ """Load or deactivate proprietary datatype converters."""
+ self.app.datatypes_registry.load_datatype_converters( self.app.toolbox,
+ installed_repository_dict=installed_repository_dict,
+ deactivate=deactivate )
+
+ def load_installed_datatypes( self, repository, relative_install_dir, deactivate=False ):
+ """
+ Load proprietary datatypes and return information needed for loading custom
+ datatypes converters and display applications later.
+ """
+ metadata = repository.metadata
+ repository_dict = None
+ datatypes_config = hg_util.get_config_from_disk( suc.DATATYPES_CONFIG_FILENAME, relative_install_dir )
+ if datatypes_config:
+ converter_path, display_path = \
+ self.alter_config_and_load_prorietary_datatypes( datatypes_config,
+ relative_install_dir,
+ deactivate=deactivate )
+ if converter_path or display_path:
+ # Create a dictionary of tool shed repository related information.
+ repository_dict = \
+ self.create_repository_dict_for_proprietary_datatypes( tool_shed=repository.tool_shed,
+ name=repository.name,
+ owner=repository.owner,
+ installed_changeset_revision=repository.installed_changeset_revision,
+ tool_dicts=metadata.get( 'tools', [] ),
+ converter_path=converter_path,
+ display_path=display_path )
+ return repository_dict
+
+ def load_installed_display_applications( self, installed_repository_dict, deactivate=False ):
+ """Load or deactivate custom datatype display applications."""
+ self.app.datatypes_registry.load_display_applications( installed_repository_dict=installed_repository_dict,
+ deactivate=deactivate )
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 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
@@ -18,7 +18,6 @@
from tool_shed.util import basic_util
from tool_shed.util import common_util
-from tool_shed.util import datatype_util
from tool_shed.util import encoding_util
from tool_shed.util import hg_util
from tool_shed.util import shed_util_common as suc
@@ -26,6 +25,7 @@
from tool_shed.util import tool_util
from tool_shed.util import xml_util
+from tool_shed.galaxy_install.datatypes import custom_datatype_manager
from tool_shed.galaxy_install.metadata.installed_repository_metadata_manager import InstalledRepositoryMetadataManager
from tool_shed.galaxy_install.repository_dependencies import repository_dependency_manager
from tool_shed.galaxy_install.tool_dependencies.recipe.env_file_builder import EnvFileBuilder
@@ -594,18 +594,19 @@
files_dir = os.path.join( shed_config_dict[ 'tool_path' ], files_dir )
datatypes_config = hg_util.get_config_from_disk( suc.DATATYPES_CONFIG_FILENAME, files_dir )
# Load data types required by tools.
+ cdl = custom_datatype_manager.CustomDatatypeLoader( self.app )
converter_path, display_path = \
- datatype_util.alter_config_and_load_prorietary_datatypes( self.app, datatypes_config, files_dir, override=False )
+ cdl.alter_config_and_load_prorietary_datatypes( datatypes_config, files_dir, override=False )
if converter_path or display_path:
# Create a dictionary of tool shed repository related information.
repository_dict = \
- datatype_util.create_repository_dict_for_proprietary_datatypes( tool_shed=tool_shed,
- name=tool_shed_repository.name,
- owner=tool_shed_repository.owner,
- installed_changeset_revision=tool_shed_repository.installed_changeset_revision,
- tool_dicts=metadata_dict.get( 'tools', [] ),
- converter_path=converter_path,
- display_path=display_path )
+ cdl.create_repository_dict_for_proprietary_datatypes( tool_shed=tool_shed,
+ name=tool_shed_repository.name,
+ owner=tool_shed_repository.owner,
+ installed_changeset_revision=tool_shed_repository.installed_changeset_revision,
+ tool_dicts=metadata_dict.get( 'tools', [] ),
+ converter_path=converter_path,
+ display_path=display_path )
if converter_path:
# Load proprietary datatype converters
self.app.datatypes_registry.load_datatype_converters( self.app.toolbox, installed_repository_dict=repository_dict )
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 lib/tool_shed/galaxy_install/installed_repository_manager.py
--- a/lib/tool_shed/galaxy_install/installed_repository_manager.py
+++ b/lib/tool_shed/galaxy_install/installed_repository_manager.py
@@ -7,12 +7,12 @@
from galaxy import util
from tool_shed.util import common_util
from tool_shed.util import container_util
-from tool_shed.util import datatype_util
from tool_shed.util import shed_util_common as suc
from tool_shed.util import tool_dependency_util
from tool_shed.util import xml_util
from galaxy.model.orm import and_
+from tool_shed.galaxy_install.datatypes import custom_datatype_manager
from tool_shed.galaxy_install.metadata.installed_repository_metadata_manager import InstalledRepositoryMetadataManager
from tool_shed.galaxy_install.repository_dependencies import repository_dependency_manager
from tool_shed.galaxy_install.tools import data_manager
@@ -114,17 +114,17 @@
else:
repository_install_dir = os.path.abspath( relative_install_dir )
# Activate proprietary datatypes.
- installed_repository_dict = datatype_util.load_installed_datatypes( self.app,
- repository,
- repository_install_dir,
- deactivate=False )
+ cdl = custom_datatype_manager.CustomDatatypeLoader( self.app )
+ installed_repository_dict = cdl.load_installed_datatypes( repository,
+ repository_install_dir,
+ deactivate=False )
if installed_repository_dict:
converter_path = installed_repository_dict.get( 'converter_path' )
if converter_path is not None:
- datatype_util.load_installed_datatype_converters( self.app, installed_repository_dict, deactivate=False )
+ cdl.load_installed_datatype_converters( installed_repository_dict, deactivate=False )
display_path = installed_repository_dict.get( 'display_path' )
if display_path is not None:
- datatype_util.load_installed_display_applications( self.app, installed_repository_dict, deactivate=False )
+ cdl.load_installed_display_applications( installed_repository_dict, deactivate=False )
def add_entry_to_installed_repository_dependencies_of_installed_repositories( self, repository ):
"""
@@ -732,22 +732,24 @@
self.add_entry_to_installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies( tool_dependency )
def load_proprietary_datatypes( self ):
+ cdl = custom_datatype_manager.CustomDatatypeLoader( self.app )
for tool_shed_repository in self.context.query( self.install_model.ToolShedRepository ) \
- .filter( and_( self.install_model.ToolShedRepository.table.c.includes_datatypes==True,
- self.install_model.ToolShedRepository.table.c.deleted==False ) ) \
- .order_by( self.install_model.ToolShedRepository.table.c.id ):
+ .filter( and_( self.install_model.ToolShedRepository.table.c.includes_datatypes==True,
+ self.install_model.ToolShedRepository.table.c.deleted==False ) ) \
+ .order_by( self.install_model.ToolShedRepository.table.c.id ):
relative_install_dir = self.get_repository_install_dir( tool_shed_repository )
if relative_install_dir:
- installed_repository_dict = datatype_util.load_installed_datatypes( self.app, tool_shed_repository, relative_install_dir )
+ installed_repository_dict = cdl.load_installed_datatypes( tool_shed_repository, relative_install_dir )
if installed_repository_dict:
self.installed_repository_dicts.append( installed_repository_dict )
def load_proprietary_converters_and_display_applications( self, deactivate=False ):
+ cdl = custom_datatype_manager.CustomDatatypeLoader( self.app )
for installed_repository_dict in self.installed_repository_dicts:
if installed_repository_dict[ 'converter_path' ]:
- datatype_util.load_installed_datatype_converters( self.app, installed_repository_dict, deactivate=deactivate )
+ cdl.load_installed_datatype_converters( installed_repository_dict, deactivate=deactivate )
if installed_repository_dict[ 'display_path' ]:
- datatype_util.load_installed_display_applications( self.app, installed_repository_dict, deactivate=deactivate )
+ cdl.load_installed_display_applications( installed_repository_dict, deactivate=deactivate )
def purge_repository( self, repository ):
"""Purge a repository with status New (a white ghost) from the database."""
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 lib/tool_shed/galaxy_install/tool_migration_manager.py
--- a/lib/tool_shed/galaxy_install/tool_migration_manager.py
+++ b/lib/tool_shed/galaxy_install/tool_migration_manager.py
@@ -14,6 +14,7 @@
from galaxy.util.odict import odict
from tool_shed.galaxy_install import install_manager
+from tool_shed.galaxy_install.datatypes import custom_datatype_manager
from tool_shed.galaxy_install.metadata.installed_repository_metadata_manager import InstalledRepositoryMetadataManager
from tool_shed.galaxy_install.tools import tool_panel_manager
@@ -22,7 +23,6 @@
from tool_shed.util import basic_util
from tool_shed.util import common_util
-from tool_shed.util import datatype_util
from tool_shed.util import hg_util
from tool_shed.util import shed_util_common as suc
from tool_shed.util import tool_dependency_util
@@ -492,6 +492,7 @@
print '\nThe ToolMigrationManager returned the following error while installing tool dependency ', installed_tool_dependency.name, ':'
print installed_tool_dependency.error_message, '\n\n'
if 'datatypes' in metadata_dict:
+ cdl = custom_datatype_manager.CustomDatatypeLoader( self.app )
tool_shed_repository.status = self.app.install_model.ToolShedRepository.installation_status.LOADING_PROPRIETARY_DATATYPES
if not tool_shed_repository.includes_datatypes:
tool_shed_repository.includes_datatypes = True
@@ -499,21 +500,27 @@
self.app.install_model.context.flush()
work_dir = tempfile.mkdtemp( prefix="tmp-toolshed-hrc" )
datatypes_config = hg_util.get_config_from_disk( suc.DATATYPES_CONFIG_FILENAME, repo_install_dir )
- # Load proprietary data types required by tools. The value of override is not important here since the Galaxy server will be started
- # after this installation completes.
- converter_path, display_path = datatype_util.alter_config_and_load_prorietary_datatypes( self.app, datatypes_config, repo_install_dir, override=False ) #repo_install_dir was relative_install_dir
+ # Load proprietary data types required by tools. The value of override is not
+ # important here since the Galaxy server will be started after this installation
+ #completes.
+ converter_path, display_path = \
+ cdl.alter_config_and_load_prorietary_datatypes( datatypes_config,
+ repo_install_dir,
+ override=False )
if converter_path or display_path:
# Create a dictionary of tool shed repository related information.
- repository_dict = datatype_util.create_repository_dict_for_proprietary_datatypes( tool_shed=self.tool_shed_url,
- name=tool_shed_repository.name,
- owner=self.repository_owner,
- installed_changeset_revision=tool_shed_repository.installed_changeset_revision,
- tool_dicts=metadata_dict.get( 'tools', [] ),
- converter_path=converter_path,
- display_path=display_path )
+ repository_dict = \
+ cdl.create_repository_dict_for_proprietary_datatypes( tool_shed=self.tool_shed_url,
+ name=tool_shed_repository.name,
+ owner=self.repository_owner,
+ installed_changeset_revision=tool_shed_repository.installed_changeset_revision,
+ tool_dicts=metadata_dict.get( 'tools', [] ),
+ converter_path=converter_path,
+ display_path=display_path )
if converter_path:
# Load proprietary datatype converters
- self.app.datatypes_registry.load_datatype_converters( self.toolbox, installed_repository_dict=repository_dict )
+ self.app.datatypes_registry.load_datatype_converters( self.toolbox,
+ installed_repository_dict=repository_dict )
if display_path:
# Load proprietary datatype display applications
self.app.datatypes_registry.load_display_applications( installed_repository_dict=repository_dict )
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 lib/tool_shed/util/datatype_util.py
--- a/lib/tool_shed/util/datatype_util.py
+++ /dev/null
@@ -1,187 +0,0 @@
-import logging
-import os
-import tempfile
-from galaxy import eggs
-from galaxy.util import asbool
-from tool_shed.util import basic_util
-from tool_shed.util import hg_util
-from tool_shed.util import tool_util
-from tool_shed.util import xml_util
-import tool_shed.util.shed_util_common as suc
-
-log = logging.getLogger( __name__ )
-
-def alter_config_and_load_prorietary_datatypes( app, datatypes_config, relative_install_dir, deactivate=False, override=True ):
- """
- Parse a proprietary datatypes config (a datatypes_conf.xml file included in an installed tool shed repository) and
- add information to appropriate element attributes that will enable proprietary datatype class modules, datatypes converters
- and display applications to be discovered and properly imported by the datatypes registry. The value of override will
- be False when a tool shed repository is being installed. Since installation is occurring after the datatypes registry
- has been initialized, the registry's contents cannot be overridden by conflicting data types.
- """
- tree, error_message = xml_util.parse_xml( datatypes_config )
- if tree is None:
- return None, None
- datatypes_config_root = tree.getroot()
- registration = datatypes_config_root.find( 'registration' )
- if registration is None:
- # We have valid XML, but not a valid proprietary datatypes definition.
- return None, None
- sniffers = datatypes_config_root.find( 'sniffers' )
- converter_path, display_path = get_converter_and_display_paths( registration, relative_install_dir )
- if converter_path:
- # Path to datatype converters
- registration.attrib[ 'proprietary_converter_path' ] = converter_path
- if display_path:
- # Path to datatype display applications
- registration.attrib[ 'proprietary_display_path' ] = display_path
- relative_path_to_datatype_file_name = None
- datatype_files = datatypes_config_root.find( 'datatype_files' )
- datatype_class_modules = []
- if datatype_files is not None:
- # The <datatype_files> tag set contains any number of <datatype_file> tags.
- # <datatype_files>
- # <datatype_file name="gmap.py"/>
- # <datatype_file name="metagenomics.py"/>
- # </datatype_files>
- # We'll add attributes to the datatype tag sets so that the modules can be properly imported by the datatypes registry.
- for elem in datatype_files.findall( 'datatype_file' ):
- datatype_file_name = elem.get( 'name', None )
- if datatype_file_name:
- # Find the file in the installed repository.
- for root, dirs, files in os.walk( relative_install_dir ):
- if root.find( '.hg' ) < 0:
- for name in files:
- if name == datatype_file_name:
- datatype_class_modules.append( os.path.join( root, name ) )
- break
- break
- if datatype_class_modules:
- for relative_path_to_datatype_file_name in datatype_class_modules:
- datatype_file_name_path, datatype_file_name = os.path.split( relative_path_to_datatype_file_name )
- for elem in registration.findall( 'datatype' ):
- # Handle 'type' attribute which should be something like one of the following:
- # type="gmap:GmapDB"
- # type="galaxy.datatypes.gmap:GmapDB"
- dtype = elem.get( 'type', None )
- if dtype:
- fields = dtype.split( ':' )
- proprietary_datatype_module = fields[ 0 ]
- if proprietary_datatype_module.find( '.' ) >= 0:
- # Handle the case where datatype_module is "galaxy.datatypes.gmap".
- proprietary_datatype_module = proprietary_datatype_module.split( '.' )[ -1 ]
- # The value of proprietary_path must be an absolute path due to job_working_directory.
- elem.attrib[ 'proprietary_path' ] = os.path.abspath( datatype_file_name_path )
- elem.attrib[ 'proprietary_datatype_module' ] = proprietary_datatype_module
- # Temporarily persist the proprietary datatypes configuration file so it can be loaded into the datatypes registry.
- fd, proprietary_datatypes_config = tempfile.mkstemp( prefix="tmp-toolshed-acalpd" )
- os.write( fd, '<?xml version="1.0"?>\n' )
- os.write( fd, '<datatypes>\n' )
- os.write( fd, '%s' % xml_util.xml_to_string( registration ) )
- if sniffers is not None:
- os.write( fd, '%s' % xml_util.xml_to_string( sniffers ) )
- os.write( fd, '</datatypes>\n' )
- os.close( fd )
- os.chmod( proprietary_datatypes_config, 0644 )
- # Load proprietary datatypes
- app.datatypes_registry.load_datatypes( root_dir=app.config.root, config=proprietary_datatypes_config, deactivate=deactivate, override=override )
- if deactivate:
- # Reload the upload tool to eliminate deactivated datatype extensions from the file_type select list.
- tool_util.reload_upload_tools( app )
- else:
- append_to_datatypes_registry_upload_file_formats( app, registration )
- tool_util.reload_upload_tools( app )
- if datatype_files is not None:
- try:
- os.unlink( proprietary_datatypes_config )
- except:
- pass
- return converter_path, display_path
-
-def append_to_datatypes_registry_upload_file_formats( app, elem ):
- # See if we have any datatypes that should be displayed in the upload tool's file_type select list.
- for datatype_elem in elem.findall( 'datatype' ):
- extension = datatype_elem.get( 'extension', None )
- display_in_upload = datatype_elem.get( 'display_in_upload', None )
- if extension is not None and display_in_upload is not None:
- display_in_upload = asbool( str( display_in_upload ) )
- if display_in_upload and extension not in app.datatypes_registry.upload_file_formats:
- app.datatypes_registry.upload_file_formats.append( extension )
-
-def create_repository_dict_for_proprietary_datatypes( tool_shed, name, owner, installed_changeset_revision, tool_dicts, converter_path=None, display_path=None ):
- return dict( tool_shed=tool_shed,
- repository_name=name,
- repository_owner=owner,
- installed_changeset_revision=installed_changeset_revision,
- tool_dicts=tool_dicts,
- converter_path=converter_path,
- display_path=display_path )
-
-def get_converter_and_display_paths( registration_elem, relative_install_dir ):
- """Find the relative path to data type converters and display applications included in installed tool shed repositories."""
- converter_path = None
- display_path = None
- for elem in registration_elem.findall( 'datatype' ):
- if not converter_path:
- # If any of the <datatype> tag sets contain <converter> tags, set the converter_path
- # if it is not already set. This requires developers to place all converters in the
- # same subdirectory within the repository hierarchy.
- for converter in elem.findall( 'converter' ):
- converter_config = converter.get( 'file', None )
- if converter_config:
- converter_config_file_name = basic_util.strip_path( converter_config )
- for root, dirs, files in os.walk( relative_install_dir ):
- if root.find( '.hg' ) < 0:
- for name in files:
- if name == converter_config_file_name:
- # The value of converter_path must be absolute due to job_working_directory.
- converter_path = os.path.abspath( root )
- break
- if converter_path:
- break
- if not display_path:
- # If any of the <datatype> tag sets contain <display> tags, set the display_path
- # if it is not already set. This requires developers to place all display acpplications
- # in the same subdirectory within the repository hierarchy.
- for display_app in elem.findall( 'display' ):
- display_config = display_app.get( 'file', None )
- if display_config:
- display_config_file_name = basic_util.strip_path( display_config )
- for root, dirs, files in os.walk( relative_install_dir ):
- if root.find( '.hg' ) < 0:
- for name in files:
- if name == display_config_file_name:
- # The value of display_path must be absolute due to job_working_directory.
- display_path = os.path.abspath( root )
- break
- if display_path:
- break
- if converter_path and display_path:
- break
- return converter_path, display_path
-
-def load_installed_datatype_converters( app, installed_repository_dict, deactivate=False ):
- # Load or deactivate proprietary datatype converters
- app.datatypes_registry.load_datatype_converters( app.toolbox, installed_repository_dict=installed_repository_dict, deactivate=deactivate )
-
-def load_installed_datatypes( app, repository, relative_install_dir, deactivate=False ):
- # Load proprietary datatypes and return information needed for loading proprietary datatypes converters and display applications later.
- metadata = repository.metadata
- repository_dict = None
- datatypes_config = hg_util.get_config_from_disk( suc.DATATYPES_CONFIG_FILENAME, relative_install_dir )
- if datatypes_config:
- converter_path, display_path = alter_config_and_load_prorietary_datatypes( app, datatypes_config, relative_install_dir, deactivate=deactivate )
- if converter_path or display_path:
- # Create a dictionary of tool shed repository related information.
- repository_dict = create_repository_dict_for_proprietary_datatypes( tool_shed=repository.tool_shed,
- name=repository.name,
- owner=repository.owner,
- installed_changeset_revision=repository.installed_changeset_revision,
- tool_dicts=metadata.get( 'tools', [] ),
- converter_path=converter_path,
- display_path=display_path )
- return repository_dict
-
-def load_installed_display_applications( app, installed_repository_dict, deactivate=False ):
- # Load or deactivate proprietary datatype display applications
- app.datatypes_registry.load_display_applications( installed_repository_dict=installed_repository_dict, deactivate=deactivate )
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 static/scripts/mvc/base-mvc.js
--- a/static/scripts/mvc/base-mvc.js
+++ b/static/scripts/mvc/base-mvc.js
@@ -14,7 +14,7 @@
* @example
* // Add to your models/views at the definition using chaining:
* var MyModel = Backbone.Model.extend( LoggableMixin ).extend({ // ... });
- *
+ *
* // or - more explicitly AFTER the definition:
* var MyModel = Backbone.Model.extend({
* logger : console
@@ -208,8 +208,23 @@
};
//==============================================================================
-return {
- LoggableMixin : LoggableMixin,
- SessionStorageModel : SessionStorageModel,
- HiddenUntilActivatedViewMixin : HiddenUntilActivatedViewMixin
-};});
+function mixin( mixinHash1, /* mixinHash2, etc: ... variadic */ propsHash ){
+ // usage: var NewModel = Something.extend( mixin( MyMixinA, MyMixinB, { ... }) );
+ //NOTE: this does not combine any hashes (like events, etc.) and you're expected to handle that
+
+ // simple reversal of param order on _.defaults() - to show mixins in top of definition
+ var args = Array.prototype.slice.call( arguments, 0 ),
+ lastArg = args.pop();
+ args.unshift( lastArg );
+ return _.defaults.apply( _, args );
+}
+
+
+//==============================================================================
+ return {
+ LoggableMixin : LoggableMixin,
+ SessionStorageModel : SessionStorageModel,
+ HiddenUntilActivatedViewMixin : HiddenUntilActivatedViewMixin,
+ mixin : mixin
+ };
+});
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 static/scripts/mvc/collection/collection-model.js
--- /dev/null
+++ b/static/scripts/mvc/collection/collection-model.js
@@ -0,0 +1,250 @@
+define([
+ "mvc/dataset/hda-model",
+ "mvc/base-mvc",
+ "utils/localization"
+], function( HDA_MODEL, BASE_MVC, _l ){
+//==============================================================================
+/** @class Backbone model for Dataset collection elements.
+ * DC Elements contain a sub-model named 'object'. This class moves that
+ * 'object' from the JSON in the attributes list to a full, instantiated
+ * sub-model found in this.object. This is done on intialization and
+ * everytime the 'change:object' event is fired.
+ *
+ * @borrows LoggableMixin#logger as #logger
+ * @borrows LoggableMixin#log as #log
+ * @constructs
+ */
+var DatasetCollectionElement = Backbone.Model.extend( BASE_MVC.LoggableMixin ).extend(
+/** @lends DatasetCollectionElement.prototype */{
+ //TODO:?? this model may be unneccessary - it reflects the api structure, but...
+ // if we munge the element with the element.object at parse, we can flatten the entire hierarchy
+
+ /** logger used to record this.log messages, commonly set to console */
+ // comment this out to suppress log output
+ //logger : console,
+
+ defaults : {
+ id : null,
+ model_class : 'DatasetCollectionElement',
+ element_identifier : null,
+ element_index : null,
+ element_type : null
+ },
+
+ /** Set up.
+ * @see Backbone.Collection#initialize
+ */
+ initialize : function( model, options ){
+ this.info( this + '.initialize:', model, options );
+ options = options || {};
+ //this._setUpListeners();
+
+ this.object = this._createObjectModel();
+ this.on( 'change:object', function(){
+ //console.log( 'change:object' );
+//TODO: prob. better to update the sub-model instead of re-creating it
+ this.object = this._createObjectModel();
+ });
+ },
+
+ _createObjectModel : function(){
+ //console.log( '_createObjectModel', this.get( 'object' ), this.object );
+ //TODO: same patterns as HDCA _createElementsModel - refactor to BASE_MVC.hasSubModel?
+ if( _.isUndefined( this.object ) ){ this.object = null; }
+ if( !this.get( 'object' ) ){ return this.object; }
+
+ var object = this.get( 'object' );
+ this.unset( 'object', { silent: true });
+
+ this.debug( 'DCE, element_type:', this.get( 'element_type' ) );
+ switch( this.get( 'element_type' ) ){
+ case 'dataset_collection':
+ this.object = new DatasetCollection( object );
+ break;
+ case 'hda':
+ this.object = new HDA_MODEL.HistoryDatasetAssociation( object );
+ break;
+ default:
+ throw new TypeError( 'Unknown element_type: ' + this.get( 'element_type' ) );
+ }
+ return this.object;
+ },
+
+ /** String representation. */
+ toString : function(){
+ var objStr = ( this.object )?( '' + this.object ):( this.get( 'element_identifier' ) );
+ return ([ 'DatasetCollectionElement(', objStr, ')' ].join( '' ));
+ }
+});
+
+
+//==============================================================================
+/** @class Backbone collection for DCEs.
+ * NOTE: used *only* in second level of list:paired collections (a
+ * collection that contains collections)
+ *
+ * @borrows LoggableMixin#logger as #logger
+ * @borrows LoggableMixin#log as #log
+ * @constructs
+ */
+var DatasetCollectionElementCollection = Backbone.Collection.extend( BASE_MVC.LoggableMixin ).extend(
+/** @lends DatasetCollectionElementCollection.prototype */{
+ model: DatasetCollectionElement,
+
+ // comment this out to suppress log output
+ /** logger used to record this.log messages, commonly set to console */
+ //logger : console,
+
+ /** Set up.
+ * @see Backbone.Collection#initialize
+ */
+ initialize : function( models, options ){
+ options = options || {};
+ this.info( this + '.initialize:', models, options );
+ //this._setUpListeners();
+ },
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'DatasetCollectionElementCollection(', this.length, ')' ].join( '' ));
+ }
+});
+
+
+//==============================================================================
+/** @class Backbone model for Dataset Collections.
+ * DCs contain a bbone collection named 'elements' using the class found in
+ * this.collectionClass (gen. DatasetCollectionElementCollection). DCs move
+ * that 'object' from the JSON in the attributes list to a full, instantiated
+ * collection found in this.elements. This is done on intialization and
+ * everytime the 'change:elements' event is fired.
+ *
+ * @borrows LoggableMixin#logger as #logger
+ * @borrows LoggableMixin#log as #log
+ * @constructs
+ */
+var DatasetCollection = Backbone.Model.extend( BASE_MVC.LoggableMixin ).extend(
+/** @lends ListDatasetCollection.prototype */{
+
+ //logger : console,
+
+ /** default attributes for a model */
+ defaults : {
+ collection_type : 'list'
+ },
+
+ collectionClass : DatasetCollectionElementCollection,
+
+ /** */
+ initialize : function( model, options ){
+ this.info( 'DatasetCollection.initialize:', model, options );
+ //historyContent.HistoryContent.prototype.initialize.call( this, attrs, options );
+ this.elements = this._createElementsModel();
+//TODO:?? no way to use parse here?
+ this.on( 'change:elements', function(){
+ this.log( 'change:elements' );
+//TODO: prob. better to update the collection instead of re-creating it
+ this.elements = this._createElementsModel();
+ });
+ },
+
+ /** move elements model attribute to full collection */
+ _createElementsModel : function(){
+ this.log( '_createElementsModel', this.get( 'elements' ), this.elements );
+//TODO: same patterns as DatasetCollectionElement _createObjectModel - refactor to BASE_MVC.hasSubModel?
+ var elements = this.get( 'elements' ) || [];
+ this.info( 'elements:', elements );
+ this.unset( 'elements', { silent: true });
+ this.elements = new this.collectionClass( elements );
+ return this.elements;
+ },
+
+ hasDetails : function(){
+//TODO: this is incorrect for (accidentally) empty collections
+ return this.elements.length !== 0;
+ },
+
+ // ........................................................................ misc
+ /** String representation */
+ toString : function(){
+ var idAndName = [ this.get( 'id' ), this.get( 'name' ) || this.get( 'element_identifier' ) ];
+ return 'DatasetCollection(' + ( idAndName.join(',') ) + ')';
+ }
+});
+
+
+//==============================================================================
+/** @class Backbone collection for a collection of collection collections collecting correctly. */
+var DatasetCollectionCollection = Backbone.Collection.extend( BASE_MVC.LoggableMixin ).extend({
+
+ model: DatasetCollection,
+
+ ///** logger used to record this.log messages, commonly set to console */
+ //// comment this out to suppress log output
+ //logger : console,
+
+ /** Set up.
+ * @see Backbone.Collection#initialize
+ */
+ initialize : function( models, options ){
+ options = options || {};
+ this.info( 'DatasetCollectionCollection.initialize:', models, options );
+ //this._setUpListeners();
+ },
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'DatasetCollectionCollection(', this.get( 'name' ), ')' ].join( '' ));
+ }
+});
+
+
+//NOTE: the following prototypes may not be necessary - but I wanted to specifiy
+// them (for now) and allow for the possibility of unique functionality
+//==============================================================================
+var ListDatasetCollection = DatasetCollection.extend(
+/** @lends ListDatasetCollection.prototype */{
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'ListDatasetCollection(', this.get( 'name' ), ')' ].join( '' ));
+ }
+});
+
+
+//==============================================================================
+var PairDatasetCollection = DatasetCollection.extend(
+/** @lends ListDatasetCollection.prototype */{
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'PairDatasetCollection(', this.get( 'name' ), ')' ].join( '' ));
+ }
+});
+
+
+//==============================================================================
+var ListPairedDatasetCollection = DatasetCollection.extend(
+/** @lends ListDatasetCollection.prototype */{
+
+ // list:paired is the only collection that itself contains collections
+ //collectionClass : DatasetCollectionCollection,
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'ListPairedDatasetCollection(', this.get( 'name' ), ')' ].join( '' ));
+ }
+});
+
+
+//==============================================================================
+ return {
+ DatasetCollectionElement : DatasetCollectionElement,
+ DatasetCollectionElementCollection : DatasetCollectionElementCollection,
+ DatasetCollection : DatasetCollection,
+ DatasetCollectionCollection : DatasetCollectionCollection,
+ ListDatasetCollection : ListDatasetCollection,
+ PairDatasetCollection : PairDatasetCollection,
+ ListPairedDatasetCollection : ListPairedDatasetCollection
+ };
+});
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 static/scripts/mvc/collection/collection-panel.js
--- /dev/null
+++ b/static/scripts/mvc/collection/collection-panel.js
@@ -0,0 +1,326 @@
+define([
+ "mvc/collection/dataset-collection-base",
+ "mvc/dataset/hda-base",
+ "mvc/base-mvc",
+ "utils/localization"
+], function( DC_BASE, HDA_BASE, BASE_MVC, _l ){
+/* =============================================================================
+TODO:
+
+============================================================================= */
+/** @class non-editable, read-only View/Controller for a dataset collection.
+ * @name CollectionPanel
+ *
+ * @augments Backbone.View
+ * @borrows LoggableMixin#logger as #logger
+ * @borrows LoggableMixin#log as #log
+ * @constructs
+ */
+var CollectionPanel = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend(
+/** @lends CollectionPanel.prototype */{
+
+ /** logger used to record this.log messages, commonly set to console */
+ // comment this out to suppress log output
+ //logger : console,
+
+ tagName : 'div',
+ className : 'history-panel',
+
+ /** (in ms) that jquery effects will use */
+ fxSpeed : 'fast',
+
+ // ......................................................................... SET UP
+ /** Set up the view, set up storage, bind listeners to HistoryContents events
+ * @param {Object} attributes optional settings for the panel
+ */
+ initialize : function( attributes ){
+ attributes = attributes || {};
+ // set the logger if requested
+ if( attributes.logger ){
+ this.logger = attributes.logger;
+ }
+ this.log( this + '.initialize:', attributes );
+
+ this.hasUser = attributes.hasUser;
+ this.HDAViewClass = attributes.HDAViewClass || HDA_BASE.HDABaseView;
+ },
+
+ /** create any event listeners for the panel
+ * @fires: rendered:initial on the first render
+ * @fires: empty-history when switching to a history with no HDAs or creating a new history
+ */
+ _setUpListeners : function(){
+ // debugging
+ //if( this.logger ){
+ this.on( 'all', function( event ){
+ this.log( this + '', arguments );
+ }, this );
+ //}
+ return this;
+ },
+
+ // ------------------------------------------------------------------------ history/hda event listening
+ /** listening for history and HDA events */
+ _setUpModelEventHandlers : function(){
+ return this;
+ },
+
+ // ------------------------------------------------------------------------ panel rendering
+ /** Render urls, historyPanel body, and hdas (if any are shown)
+ * @fires: rendered when the panel is attached and fully visible
+ * @see Backbone.View#render
+ */
+ render : function( speed, callback ){
+ this.log( 'render:', speed, callback );
+ // send a speed of 0 to have no fade in/out performed
+ speed = ( speed === undefined )?( this.fxSpeed ):( speed );
+ //console.debug( this + '.render, fxSpeed:', speed );
+ var panel = this,
+ $newRender;
+
+ // handle the possibility of no model (can occur if fetching the model returns an error)
+ if( !this.model ){
+ return this;
+ }
+ $newRender = this.renderModel();
+
+ // fade out existing, swap with the new, fade in, set up behaviours
+ $( panel ).queue( 'fx', [
+ function( next ){
+ if( speed && panel.$el.is( ':visible' ) ){
+ panel.$el.fadeOut( speed, next );
+ } else {
+ next();
+ }
+ },
+ function( next ){
+ // swap over from temp div newRender
+ panel.$el.empty();
+ if( $newRender ){
+ panel.$el.append( $newRender.children() );
+ }
+ next();
+ },
+ function( next ){
+ if( speed && !panel.$el.is( ':visible' ) ){
+ panel.$el.fadeIn( speed, next );
+ } else {
+ next();
+ }
+ },
+ function( next ){
+ //TODO: ideally, these would be set up before the fade in (can't because of async save text)
+ if( callback ){ callback.call( this ); }
+ panel.trigger( 'rendered', this );
+ next();
+ }
+ ]);
+ return this;
+ },
+
+ /** render with history data
+ * @returns {jQuery} dom fragment as temporary container to be swapped out later
+ */
+ renderModel : function( ){
+ // tmp div for final swap in render
+ var $newRender = $( '<div/>' ).append( CollectionPanel.templates.panel( this.model.toJSON() ) );
+ this._setUpBehaviours( $newRender );
+ this.renderContents( $newRender );
+ return $newRender;
+ },
+
+ /** Set up HistoryPanel js/widget behaviours */
+ _setUpBehaviours : function( $where ){
+ //TODO: these should be either sub-MVs, or handled by events
+ $where = $where || this.$el;
+ $where.find( '[title]' ).tooltip({ placement: 'bottom' });
+ return this;
+ },
+
+ // ------------------------------------------------------------------------ sub-$element shortcuts
+ /** the scroll container for this panel - can be $el, $el.parent(), or grandparent depending on context */
+ $container : function(){
+ return ( this.findContainerFn )?( this.findContainerFn.call( this ) ):( this.$el.parent() );
+ },
+ /** where hdaViews are attached */
+ $datasetsList : function( $where ){
+ return ( $where || this.$el ).find( '.datasets-list' );
+ },
+
+ // ------------------------------------------------------------------------ sub-views
+ /** Set up/render a view for each HDA to be shown, init with model and listeners.
+ * HDA views are cached to the map this.hdaViews (using the model.id as key).
+ * @param {jQuery} $whereTo what dom element to prepend the HDA views to
+ * @returns the number of visible hda views
+ */
+ renderContents : function( $whereTo ){
+ //console.debug( 'renderContents, elements:', this.model.elements );
+ $whereTo = $whereTo || this.$el;
+
+ var panel = this,
+ contentViews = {},
+ visibleContents = this.model.elements || [];
+ //this.log( 'renderContents, visibleContents:', visibleContents, $whereTo );
+
+ this.$datasetsList( $whereTo ).empty();
+ if( visibleContents && visibleContents.length ){
+ visibleContents.each( function( content ){
+ var contentId = content.id,
+ contentView = panel._createContentView( content );
+ contentViews[ contentId ] = contentView;
+ panel.attachContentView( contentView.render(), $whereTo );
+ });
+ }
+ this.contentViews = contentViews;
+ return this.contentViews;
+ },
+
+ /**
+ * @param {HistoryDatasetAssociation} content
+ */
+ _createContentView : function( content ){
+ //console.debug( 'content json:', JSON.stringify( content, null, ' ' ) );
+ var contentView = null,
+ ContentClass = this._getContentClass( content );
+ //console.debug( 'content.object json:', JSON.stringify( content.object, null, ' ' ) );
+ //console.debug( 'ContentClass:', ContentClass );
+ //console.debug( 'content:', content );
+ //console.debug( 'content.object:', content.object );
+ contentView = new ContentClass({
+ model : content.object,
+ linkTarget : this.linkTarget,
+ //draggable : true,
+ hasUser : this.hasUser,
+ logger : this.logger
+ });
+ //this._setUpHdaListeners( contentView );
+ return contentView;
+ },
+
+ _getContentClass : function( content ){
+ switch( content.get( 'element_type' ) ){
+ case 'hda':
+ return this.HDAViewClass;
+ case 'dataset_collection':
+ return DC_BASE.NestedDCEBaseView;
+ }
+ throw new TypeError( 'Unknown element type:', content.get( 'element_type' ) );
+ },
+
+// /** Set up HistoryPanel listeners for HDAView events. Currently binds:
+// * HDAView#body-visible, HDAView#body-hidden to store expanded states
+// * @param {HDAView} hdaView HDAView (base or edit) to listen to
+// */
+// _setUpHdaListeners : function( hdaView ){
+// var panel = this;
+// hdaView.on( 'error', function( model, xhr, options, msg ){
+// panel.errorHandler( model, xhr, options, msg );
+// });
+// // maintain a list of hdas whose bodies are expanded
+// hdaView.on( 'body-expanded', function( model ){
+// panel.storage.addExpandedHda( model );
+// });
+// hdaView.on( 'body-collapsed', function( id ){
+// panel.storage.removeExpandedHda( id );
+// });
+// return this;
+// },
+
+ /** attach an contentView to the panel */
+ attachContentView : function( contentView, $whereTo ){
+ $whereTo = $whereTo || this.$el;
+ var $datasetsList = this.$datasetsList( $whereTo );
+ $datasetsList.append( contentView.$el );
+ return this;
+ },
+
+ // ------------------------------------------------------------------------ panel events
+ /** event map */
+ events : {
+ 'click .panel-navigation-back' : 'close'
+ },
+
+ /** */
+ close : function( event ){
+ this.$el.remove();
+ this.trigger( 'collection-close' );
+ },
+
+ // ........................................................................ misc
+ /** Return a string rep of the history */
+ toString : function(){
+ return 'CollectionPanel(' + (( this.model )?( this.model.get( 'name' )):( '' )) + ')';
+ }
+});
+
+
+//------------------------------------------------------------------------------ TEMPLATES
+var _panelTemplate = [
+ '<div class="history-controls">',
+ '<div class="panel-navigation">',
+ '<a class="panel-navigation-back" href="javascript:void(0)">', _l( 'Back' ), '</a>',
+ '</div>',
+
+ '<div class="history-title">',
+ '<% if( collection.name ){ %>',
+ '<div class="history-name"><%= collection.hid %> : <%= collection.name %></div>',
+ '<% } %>',
+ '</div>',
+
+ //'<div class="history-subtitle clear">',
+ // '<% if( history.nice_size ){ %>',
+ // '<div class="history-size"><%= history.nice_size %></div>',
+ // '<% } %>',
+ // '<div class="history-secondary-actions"></div>',
+ //'</div>',
+ //
+ //'<% if( history.deleted ){ %>',
+ // '<div class="warningmessagesmall"><strong>',
+ // _l( 'You are currently viewing a deleted history!' ),
+ // '</strong></div>',
+ //'<% } %>',
+ //
+ //'<div class="message-container">',
+ // '<% if( history.message ){ %>',
+ // // should already be localized
+ // '<div class="<%= history.status %>message"><%= history.message %></div>',
+ // '<% } %>',
+ //'</div>',
+ //
+ //'<div class="quota-message errormessage">',
+ // _l( 'You are over your disk quota' ), '. ',
+ // _l( 'Tool execution is on hold until your disk usage drops below your allocated quota' ), '.',
+ //'</div>',
+ //
+ //'<div class="tags-display"></div>',
+ //'<div class="annotation-display"></div>',
+ //'<div class="history-dataset-actions">',
+ // '<div class="btn-group">',
+ // '<button class="history-select-all-datasets-btn btn btn-default"',
+ // 'data-mode="select">', _l( 'All' ), '</button>',
+ // '<button class="history-deselect-all-datasets-btn btn btn-default"',
+ // 'data-mode="select">', _l( 'None' ), '</button>',
+ // '</div>',
+ // '<button class="history-dataset-action-popup-btn btn btn-default">',
+ // _l( 'For all selected' ), '...</button>',
+ //'</div>',
+ '</div>',
+ // end history controls
+
+ // where the datasets/hdas are added
+ '<div class="datasets-list"></div>'
+
+].join( '' );
+
+CollectionPanel.templates = {
+ panel : function( JSON ){
+ return _.template( _panelTemplate, JSON, { variable: 'collection' });
+ }
+};
+
+
+//==============================================================================
+ return {
+ CollectionPanel: CollectionPanel
+ };
+});
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 static/scripts/mvc/collection/dataset-collection-base.js
--- a/static/scripts/mvc/collection/dataset-collection-base.js
+++ b/static/scripts/mvc/collection/dataset-collection-base.js
@@ -1,328 +1,151 @@
define([
- "mvc/history/history-content-base-view",
+ "mvc/base-mvc",
"utils/localization"
-], function( historyContentBaseView, _l ){
+], function( BASE_MVC, _l ){
/* global Backbone, LoggableMixin */
//==============================================================================
-/** @class Read only view for HistoryDatasetCollectionAssociation.
- * @name HDABaseView
+/** @class Read only view for DatasetCollection.
+ * @name DCBaseView
*
* @augments Backbone.View
* @borrows LoggableMixin#logger as #logger
* @borrows LoggableMixin#log as #log
* @constructs
*/
-var DatasetCollectionBaseView = historyContentBaseView.HistoryContentBaseView.extend({
- className : "dataset hda history-panel-hda",
- id : function(){ return 'hdca-' + this.model.get( 'id' ); },
+var DCBaseView = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend({
+
+ /** logger used to record this.log messages, commonly set to console */
+ // comment this out to suppress log output
+ //logger : console,
+
+ /** */
+ className : "dataset-collection",
+ /** */
+ fxSpeed : 'fast',
/** */
initialize : function( attributes ){
if( attributes.logger ){ this.logger = this.model.logger = attributes.logger; }
- this.log( this + '.initialize:', attributes );
- /** is the view currently in selection mode? */
- this.selectable = attributes.selectable || false;
- //this.log( '\t selectable:', this.selectable );
- /** is the view currently selected? */
- this.selected = attributes.selected || false;
- /** is the body of this collection view expanded/not? */
- this.expanded = attributes.expanded || false;
+ this.log( 'DCBaseView.initialize:', attributes );
},
- /** */
- render : function( fade ){
- var $newRender = this._buildNewRender();
-
- this._queueNewRender( $newRender, fade );
- return this;
- },
-
- /** */
- _buildNewRender : function(){
- var $newRender = $( DatasetCollectionBaseView.templates.skeleton( this.model.toJSON() ) );
- $newRender.find( '.dataset-primary-actions' ).append( this._render_titleButtons() );
- $newRender.children( '.dataset-body' ).replaceWith( this._render_body() );
- this._setUpBehaviors( $newRender );
- return $newRender;
- },
-
- /** */
- _queueNewRender : function( $newRender, fade ) {
- fade = ( fade === undefined )?( true ):( fade );
- var view = this;
-
- // fade the old render out (if desired)
- if( fade ){
- $( view ).queue( function( next ){ this.$el.fadeOut( view.fxSpeed, next ); });
- }
- // empty the old render, update to any new HDA state, swap in the new render contents, handle multi-select
- $( view ).queue( function( next ){
- this.$el.empty()
- .attr( 'class', view.className ).addClass( 'state-' + view.model.get( 'state' ) )
- .append( $newRender.children() );
- if( this.selectable ){ this.showSelector( 0 ); }
- next();
- });
- // fade the new in
- if( fade ){
- $( view ).queue( function( next ){ this.$el.fadeIn( view.fxSpeed, next ); });
- }
- // trigger an event to know we're ready
- $( view ).queue( function( next ){
- this.trigger( 'rendered', view );
- if( this.model.inReadyState() ){
- this.trigger( 'rendered:ready', view );
- }
- if( this.draggable ){ this.draggableOn(); }
- next();
- });
- },
-
- // ................................................................................ titlebar buttons
- /** Render icon-button group for the common, most easily accessed actions.
- * @returns {jQuery} rendered DOM
- */
- _render_titleButtons : function(){
- // render just the display for read-only
- return [ ];
- },
-
- // ......................................................................... state body renderers
- /** Render the enclosing div of the collection body and, if expanded, the html in the body
- * @returns {jQuery} rendered DOM
- */
- _render_body : function(){
- var $body = $( '<div>Error: unknown state "' + this.model.get( 'state' ) + '".</div>' ),
- // cheesy: get function by assumed matching name
- renderFn = this[ '_render_body_' + this.model.get( 'state' ) ];
- if( _.isFunction( renderFn ) ){
- $body = renderFn.call( this );
- }
- this._setUpBehaviors( $body );
-
- // only render the body html if it's being shown
- if( this.expanded ){
- $body.show();
- }
- return $body;
- },
-
- /** set up js behaviors, event handlers for elements within the given container
- * @param {jQuery} $container jq object that contains the elements to process (defaults to this.$el)
- */
- _setUpBehaviors : function( $container ){
- $container = $container || this.$el;
- // set up canned behavior on children (bootstrap, popupmenus, editable_text, etc.)
- make_popup_menus( $container );
- $container.find( '[title]' ).tooltip({ placement : 'bottom' });
- },
-
- // TODO: Eliminate duplication between following event map and one for HDAs.
-
- // ......................................................................... events
- /** event map */
- events : {
- // expand the body when the title is clicked or when in focus and space or enter is pressed
- 'click .dataset-title-bar' : 'toggleBodyVisibility',
- 'keydown .dataset-title-bar' : 'toggleBodyVisibility',
-
- // toggle selected state
- 'click .dataset-selector' : 'toggleSelect'
- },
-
- /** Show or hide the body/details of history content.
- * note: if the model does not have detailed data, fetch that data before showing the body
- * @param {Event} event the event that triggered this (@link HDABaseView#events)
- * @param {Boolean} expanded if true, expand; if false, collapse
- * @fires body-expanded when a body has been expanded
- * @fires body-collapsed when a body has been collapsed
- */
- toggleBodyVisibility : function( event, expand ){
- // bail (with propagation) if keydown and not space or enter
- var KEYCODE_SPACE = 32, KEYCODE_RETURN = 13;
- if( event && ( event.type === 'keydown' )
- && !( event.keyCode === KEYCODE_SPACE || event.keyCode === KEYCODE_RETURN ) ){
- return true;
- }
-
- var $body = this.$el.find( '.dataset-body' );
- expand = ( expand === undefined )?( !$body.is( ':visible' ) ):( expand );
- if( expand ){
- this.expandBody();
- } else {
- this.collapseBody();
- }
- return false;
- },
-
- /** Render and show the full, detailed body of this view including extra data and controls.
- * @fires body-expanded when a body has been expanded
- */
- expandBody : function(){
- var contentView = this;
-
- function _renderBodyAndExpand(){
- contentView.$el.children( '.dataset-body' ).replaceWith( contentView._render_body() );
- contentView.$el.children( '.dataset-body' ).slideDown( contentView.fxSpeed, function(){
- contentView.expanded = true;
- contentView.trigger( 'body-expanded', contentView.model );
- });
- }
- // TODO: Fetch more details like HDA view...
- _renderBodyAndExpand();
- },
-
- /** Hide the body/details of an HDA.
- * @fires body-collapsed when a body has been collapsed
- */
- collapseBody : function(){
- var hdaView = this;
- this.$el.children( '.dataset-body' ).slideUp( hdaView.fxSpeed, function(){
- hdaView.expanded = false;
- hdaView.trigger( 'body-collapsed', hdaView.model.id );
- });
- },
-
- /** Render an 'ok' collection.
- * @param {jQuery} parent DOM to which to append this body
- */
- _render_body_ok : function(){
- // most common state renderer and the most complicated
- var $body = $( DatasetCollectionBaseView.templates.body( this.model.toJSON() ) );
-
- // return shortened form if del'd (no display apps or peek?)
- if( this.model.get( 'deleted' ) ){
- return $body;
- }
-
- return $body;
- },
-
- // ......................................................................... selection
- /** display a (fa-icon) checkbox on the left of the hda that fires events when checked
- * Note: this also hides the primary actions
- */
- showSelector : function(){
- // make sure selected state is represented properly
- if( this.selected ){
- this.select( null, true );
- }
-
- this.selectable = true;
- this.trigger( 'selectable', true, this );
-
- this.$( '.dataset-primary-actions' ).hide();
- this.$( '.dataset-selector' ).show();
- },
-
- /** remove the selection checkbox */
- hideSelector : function(){
- // reverse the process from showSelect
- this.selectable = false;
- this.trigger( 'selectable', false, this );
-
- this.$( '.dataset-selector' ).hide();
- this.$( '.dataset-primary-actions' ).show();
- },
-
- toggleSelector : function(){
- if( !this.$el.find( '.dataset-selector' ).is( ':visible' ) ){
- this.showSelector();
- } else {
- this.hideSelector();
- }
- },
-
- /** event handler for selection (also programmatic selection)
- */
- select : function( event ){
- // switch icon, set selected, and trigger event
- this.$el.find( '.dataset-selector span' )
- .removeClass( 'fa-square-o' ).addClass( 'fa-check-square-o' );
- if( !this.selected ){
- this.trigger( 'selected', this, event );
- this.selected = true;
- }
- return false;
- },
-
- /** event handler for clearing selection (also programmatic deselection)
- */
- deselect : function( event ){
- // switch icon, set selected, and trigger event
- this.$el.find( '.dataset-selector span' )
- .removeClass( 'fa-check-square-o' ).addClass( 'fa-square-o' );
- if( this.selected ){
- this.trigger( 'de-selected', this, event );
- this.selected = false;
- }
- return false;
- },
-
- toggleSelect : function( event ){
- if( this.selected ){
- this.deselect( event );
- } else {
- this.select( event );
- }
- },
+//TODO: render has been removed from the inheritance chain here, so this won't work when called as is
// ......................................................................... misc
/** String representation */
toString : function(){
var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
- return 'HDCABaseView(' + modelString + ')';
+ return 'DCBaseView(' + modelString + ')';
}
});
-//------------------------------------------------------------------------------ TEMPLATES
-//TODO: possibly break these out into a sep. module
-var skeletonTemplate = _.template([
- '<div class="dataset hda">',
- '<div class="dataset-warnings">',
- '<% if ( collection.deleted ) { %>',
- '<div class="dataset-deleted-msg warningmessagesmall"><strong>',
- _l( 'This collection has been deleted.' ),
+/** templates for DCBaseViews (skeleton and body) */
+DCBaseView.templates = (function(){
+// use closure to run underscore template fn only once at module load
+ var skeletonTemplate = _.template([
+ '<div class="dataset hda">',
+ '<div class="dataset-warnings">',
+ '<% if ( collection.deleted ) { %>',
+ '<div class="dataset-deleted-msg warningmessagesmall"><strong>',
+ _l( 'This collection has been deleted.' ),
+ '</div>',
+ '<% } %>',
+ '<% if ( !collection.visible ) { %>',
+ '<div class="dataset-hidden-msg warningmessagesmall"><strong>',
+ _l( 'This collection has been hidden.' ),
+ '</div>',
+ '<% } %>',
+ '</div>',
+ '<div class="dataset-primary-actions"></div>',
+ '<div class="dataset-title-bar clear" tabindex="0">',
+ '<span class="dataset-state-icon state-icon"></span>',
+ '<div class="dataset-title">',
+ '<span class="dataset-name"><%- collection.name %></span>',
'</div>',
- '<% } %>',
- '<% if ( !collection.visible ) { %>',
- '<div class="dataset-hidden-msg warningmessagesmall"><strong>',
- _l( 'This collection has been hidden.' ),
- '</div>',
- '<% } %>',
- '</div>',
- '<div class="dataset-selector"><span class="fa fa-2x fa-square-o"></span></div>',
- '<div class="dataset-primary-actions"></div>',
- '<div class="dataset-title-bar clear" tabindex="0">',
- '<span class="dataset-state-icon state-icon"></span>',
- '<div class="dataset-title">',
- '<span class="hda-hid"><%= collection.hid %></span> ',
- '<span class="dataset-name"><%= collection.name %></span>',
'</div>',
- '</div>',
- '<div class="dataset-body"></div>',
- '</div>'
-].join( '' ));
+ '<div class="dataset-body"></div>',
+ '</div>'
+ ].join( '' ));
-var bodyTemplate = _.template([
- '<div class="dataset-body">',
- '<div class="dataset-summary">',
- _l( 'A dataset collection.' ),
- '</div>'
-].join( '' ));
+ var bodyTemplate = _.template([
+ '<div class="dataset-body">',
+ '<div class="dataset-summary">',
+ _l( 'A dataset collection.' ),
+ '</div>'
+ ].join( '' ));
-DatasetCollectionBaseView.templates = {
// we override here in order to pass the localizer (_L) into the template scope - since we use it as a fn within
- skeleton : function( collectionJSON ){
- return skeletonTemplate({ _l: _l, collection: collectionJSON });
- },
- body : function( collectionJSON ){
- return bodyTemplate({ _l: _l, collection: collectionJSON });
- }
-};
+ return {
+ skeleton : function( collectionJSON ){
+ return skeletonTemplate({ _l: _l, collection: collectionJSON });
+ },
+ body : function( collectionJSON ){
+ return bodyTemplate({ _l: _l, collection: collectionJSON });
+ }
+ };
+}());
+
+
+//TODO: unused
+////==============================================================================
+///** @class Read only view for DatasetCollectionElement.
+// * @name DCEBaseView
+// *
+// * @augments Backbone.View
+// * @borrows LoggableMixin#logger as #logger
+// * @borrows LoggableMixin#log as #log
+// * @constructs
+// */
+//var NestedDCBaseView = DCBaseView.extend({
+//
+// logger : console,
+//
+// /** */
+// initialize : function( attributes ){
+// if( attributes.logger ){ this.logger = this.model.logger = attributes.logger; }
+// this.warn( this + '.initialize:', attributes );
+// DCBaseView.prototype.initialize.call( this, attributes );
+// },
+//
+// _template : function(){
+// this.debug( this.model );
+// this.debug( this.model.toJSON() );
+// return NestedDCBaseView.templates.skeleton( this.model.toJSON() );
+// },
+//
+// // ......................................................................... misc
+// /** String representation */
+// toString : function(){
+// var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
+// return 'NestedDCBaseView(' + modelString + ')';
+// }
+//});
+//
+////------------------------------------------------------------------------------ TEMPLATES
+////TODO: possibly break these out into a sep. module
+//NestedDCBaseView.templates = (function(){
+// var skeleton = _.template([
+// '<div class="dataset hda history-panel-hda state-ok">',
+// '<div class="dataset-primary-actions"></div>',
+// '<div class="dataset-title-bar clear" tabindex="0">',
+// '<div class="dataset-title">',
+// '<span class="dataset-name"><%= collection.name %></span>',
+// '</div>',
+// '</div>',
+// '</div>'
+// ].join( '' ));
+// // we override here in order to pass the localizer (_L) into the template scope - since we use it as a fn within
+// return {
+// skeleton : function( json ){
+// return skeleton({ _l: _l, collection: json });
+// }
+// };
+//}());
+
//==============================================================================
return {
- DatasetCollectionBaseView : DatasetCollectionBaseView
+ DCBaseView : DCBaseView,
+ //NestedDCBaseView : NestedDCBaseView,
};
});
diff -r 4974ffd8b2cb5ee994a0d517c2332261898d4d46 -r 7aade8875ea4dde276b33922bbc7fdbc0630a9f5 static/scripts/mvc/collection/dataset-collection-edit.js
--- a/static/scripts/mvc/collection/dataset-collection-edit.js
+++ b/static/scripts/mvc/collection/dataset-collection-edit.js
@@ -1,75 +1,36 @@
define([
- "mvc/dataset/hda-model",
+ "mvc/dataset/states",
"mvc/collection/dataset-collection-base",
"utils/localization"
-], function( hdaModel, datasetCollectionBase, _l ){
+], function( STATES, DC_BASE_VIEW, _l ){
//==============================================================================
-/** @class Editing view for HistoryDatasetCollectionAssociation.
+var _super = DC_BASE_VIEW.DCBaseView;
+/** @class Editing view for DatasetCollection.
* @name DatasetCollectionEditView
*
- * @augments DatasetCollectionBaseView
+ * @augments DCBaseView
* @constructs
*/
-var DatasetCollectionEditView = datasetCollectionBase.DatasetCollectionBaseView.extend( {
+var DCEditView = _super.extend({
+
+ /** logger used to record this.log messages, commonly set to console */
+ // comment this out to suppress log output
+ //logger : console,
initialize : function( attributes ){
- datasetCollectionBase.DatasetCollectionBaseView.prototype.initialize.call( this, attributes );
- },
-
- // ......................................................................... edit attr, delete
- /** Render icon-button group for the common, most easily accessed actions.
- * Overrides _render_titleButtons to include editing related buttons.
- * @see DatasetCollectionBaseView#_render_titleButtons
- * @returns {jQuery} rendered DOM
- */
- _render_titleButtons : function(){
- // render the display, edit attr and delete icon-buttons
- return datasetCollectionBase.DatasetCollectionBaseView.prototype._render_titleButtons.call( this ).concat([
- this._render_deleteButton()
- ]);
- },
-
- /** Render icon-button to delete this hda.
- * @returns {jQuery} rendered DOM
- */
- _render_deleteButton : function(){
- // don't show delete if...
- if( ( this.model.get( 'state' ) === hdaModel.HistoryDatasetAssociation.STATES.NEW )
- || ( this.model.get( 'state' ) === hdaModel.HistoryDatasetAssociation.STATES.NOT_VIEWABLE )
- || ( !this.model.get( 'accessible' ) ) ){
- return null;
- }
-
- var self = this,
- deleteBtnData = {
- title : _l( 'Delete' ),
- classes : 'dataset-delete',
- onclick : function() {
- // ...bler... tooltips being left behind in DOM (hover out never called on deletion)
- self.$el.find( '.icon-btn.dataset-delete' ).trigger( 'mouseout' );
- self.model[ 'delete' ]();
- }
- };
- if( this.model.get( 'deleted' ) ){
- deleteBtnData = {
- title : _l( 'Dataset collection is already deleted' ),
- disabled : true
- };
- }
- deleteBtnData.faIcon = 'fa-times';
- return faIconButton( deleteBtnData );
+ _super.prototype.initialize.call( this, attributes );
},
// ......................................................................... misc
/** string rep */
toString : function(){
var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
- return 'HDCAEditView(' + modelString + ')';
+ return 'DCEditView(' + modelString + ')';
}
});
//==============================================================================
return {
- DatasetCollectionEditView : DatasetCollectionEditView
+ DCEditView : DCEditView
};
});
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: greg: Fix for exporting repositories that contain package recipes that define additional packages needed only for compiling the dependent package.
by commits-noreply@bitbucket.org 23 Jul '14
by commits-noreply@bitbucket.org 23 Jul '14
23 Jul '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/e45ed2368920/
Changeset: e45ed2368920
User: greg
Date: 2014-07-23 22:19:39
Summary: Fix for exporting repositories that contain package recipes that define additional packages needed only for compiling the dependent package.
Affected #: 3 files
diff -r b08a47eb8c3c15022b9e3f7d9990d40fd0fa70c0 -r e45ed2368920315ab1f9cfe28d81e07cefc5c955 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
@@ -1262,7 +1262,11 @@
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans.app, repository_id, changeset_revision )
metadata = repository_metadata.metadata
toolshed_base_url = str( web.url_for( '/', qualified=True ) ).rstrip( '/' )
+ # Initialize the repository dependency RelationBuilder.
rb = relation_builder.RelationBuilder( trans.app, repository, repository_metadata, toolshed_base_url )
+ # Work-around to ensure repositories that contain packages needed only for compiling
+ # a dependent package are included in the capsule.
+ rb.set_filter_dependencies_needed_for_compiling( False )
# Get a dictionary of all repositories upon which the contents of the current repository_metadata record depend.
repository_dependencies = rb.get_repository_dependencies_for_changeset_revision()
if repository_dependencies:
diff -r b08a47eb8c3c15022b9e3f7d9990d40fd0fa70c0 -r e45ed2368920315ab1f9cfe28d81e07cefc5c955 lib/tool_shed/capsule/capsule_manager.py
--- a/lib/tool_shed/capsule/capsule_manager.py
+++ b/lib/tool_shed/capsule/capsule_manager.py
@@ -245,9 +245,13 @@
repository_metadata = suc.get_repository_metadata_by_changeset_revision( self.app,
self.repository_id,
self.changeset_revision )
- # Get a dictionary of all repositories upon which the contents of the current repository_metadata record depend.
+ # Get a dictionary of all repositories upon which the contents of the current
+ # repository_metadata record depend.
toolshed_base_url = str( web.url_for( '/', qualified=True ) ).rstrip( '/' )
rb = RelationBuilder( self.app, repository, repository_metadata, toolshed_base_url )
+ # Work-around to ensure repositories that contain packages needed only for compiling
+ # a dependent package are included in the capsule.
+ rb.set_filter_dependencies_needed_for_compiling( False )
repository_dependencies = rb.get_repository_dependencies_for_changeset_revision()
repo = hg_util.get_repo_for_repository( self.app,
repository=self.repository,
diff -r b08a47eb8c3c15022b9e3f7d9990d40fd0fa70c0 -r e45ed2368920315ab1f9cfe28d81e07cefc5c955 lib/tool_shed/dependencies/repository/relation_builder.py
--- a/lib/tool_shed/dependencies/repository/relation_builder.py
+++ b/lib/tool_shed/dependencies/repository/relation_builder.py
@@ -23,6 +23,11 @@
self.handled_key_rd_dicts = []
self.key_rd_dicts_to_be_processed = []
self.tool_shed_url = tool_shed_url
+ # This is a temporary work-around for handling repository dependencies that are needed
+ # only if compiling a dependent package. This value should be True unless exporting
+ # a repository capsule, in which case the set_filter_dependencies_needed_for_compiling()
+ # function is called.
+ self.filter_dependencies_needed_for_compiling = True
def can_add_to_key_rd_dicts( self, key_rd_dict, key_rd_dicts ):
"""Handle the case where an update to the changeset revision was done."""
@@ -389,9 +394,12 @@
current_repository_key_rd_dicts = \
self.get_updated_changeset_revisions_for_repository_dependencies( current_repository_key_rd_dicts )
for key_rd_dict in current_repository_key_rd_dicts:
- # Filter out repository dependencies that are required only if compiling the dependent
- # repository's tool dependency.
- key_rd_dict = self.filter_only_if_compiling_contained_td( key_rd_dict )
+ if self.filter_dependencies_needed_for_compiling:
+ # Filter out repository dependencies that are required only if compiling the dependent
+ # repository's tool dependency.
+ # TODO: this temporary work-around should be removed when the underlying framework
+ # support for handling only_if_compiling_contained_td-flagged repositories is completed.
+ key_rd_dict = self.filter_only_if_compiling_contained_td( key_rd_dict )
if key_rd_dict:
is_circular = False
in_handled_key_rd_dicts = self.in_key_rd_dicts( key_rd_dict, self.handled_key_rd_dicts )
@@ -483,6 +491,9 @@
clean_key_rd_dicts.append( new_key_rd_dict )
return clean_key_rd_dicts
+ def set_filter_dependencies_needed_for_compiling( self, value ):
+ self.filter_dependencies_needed_for_compiling = asbool( value )
+
def update_circular_repository_dependencies( self, repository_key, repository_dependency, repository_dependencies ):
repository_dependency_as_key = self.get_repository_dependency_as_key( repository_dependency )
repository_key_as_repository_dependency = repository_key.split( container_util.STRSEP )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Strip repository names when creating in the Tool Shed.
by commits-noreply@bitbucket.org 23 Jul '14
by commits-noreply@bitbucket.org 23 Jul '14
23 Jul '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/b08a47eb8c3c/
Changeset: b08a47eb8c3c
User: greg
Date: 2014-07-23 19:40:23
Summary: Strip repository names when creating in the Tool Shed.
Affected #: 1 file
diff -r 598a4ec015f66237d41ed2176c673fd52b744f15 -r b08a47eb8c3c15022b9e3f7d9990d40fd0fa70c0 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
@@ -1062,7 +1062,7 @@
action='browse_repositories',
message=message,
status=status ) )
- name = kwd.get( 'name', '' )
+ name = kwd.get( 'name', '' ).strip()
description = kwd.get( 'description', '' )
long_description = kwd.get( 'long_description', '' )
category_ids = util.listify( kwd.get( 'category_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
commit/galaxy-central: carlfeberhard: History/Collection/HDA MVC: refactoring; Base MVC: create mixin shortcut to extend, use with HistoryContentMixin; Pages: allow display of collections; HDAs: fix annotation default overwriting existing when only partial model is saved; Style: begin separation of collections styles and prep for DOM class renaming; pack scripts
by commits-noreply@bitbucket.org 23 Jul '14
by commits-noreply@bitbucket.org 23 Jul '14
23 Jul '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/598a4ec015f6/
Changeset: 598a4ec015f6
User: carlfeberhard
Date: 2014-07-23 18:59:04
Summary: History/Collection/HDA MVC: refactoring; Base MVC: create mixin shortcut to extend, use with HistoryContentMixin; Pages: allow display of collections; HDAs: fix annotation default overwriting existing when only partial model is saved; Style: begin separation of collections styles and prep for DOM class renaming; pack scripts
Affected #: 50 files
diff -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 -r 598a4ec015f66237d41ed2176c673fd52b744f15 lib/galaxy/webapps/galaxy/controllers/history.py
--- a/lib/galaxy/webapps/galaxy/controllers/history.py
+++ b/lib/galaxy/webapps/galaxy/controllers/history.py
@@ -195,6 +195,7 @@
class HistoryController( BaseUIController, SharableMixin, UsesAnnotations, UsesItemRatings,
UsesHistoryMixin, UsesHistoryDatasetAssociationMixin, ExportsHistoryMixin,
ImportsHistoryMixin ):
+
def __init__( self, app ):
super( HistoryController, self ).__init__( app )
self.mgrs = util.bunch.Bunch(
diff -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 -r 598a4ec015f66237d41ed2176c673fd52b744f15 lib/galaxy/webapps/galaxy/controllers/page.py
--- a/lib/galaxy/webapps/galaxy/controllers/page.py
+++ b/lib/galaxy/webapps/galaxy/controllers/page.py
@@ -1,5 +1,6 @@
from sqlalchemy import desc, and_
from galaxy import model, web
+from galaxy import managers
from galaxy.web import error, url_for
from galaxy.model.item_attrs import UsesItemRatings
from galaxy.web.base.controller import BaseUIController, SharableMixin, UsesHistoryMixin, UsesStoredWorkflowMixin, UsesVisualizationMixin
@@ -285,6 +286,12 @@
_page_selection_grid = PageSelectionGrid()
_visualization_selection_grid = VisualizationSelectionGrid()
+ def __init__( self, app ):
+ super( PageController, self ).__init__( app )
+ self.mgrs = util.bunch.Bunch(
+ histories=managers.histories.HistoryManager()
+ )
+
@web.expose
@web.require_login()
def list( self, trans, *args, **kwargs ):
@@ -718,6 +725,7 @@
"""
Returns html suitable for embedding in another page.
"""
+ #TODO: should be moved to history controller and/or called via ajax from the template
history = self.get_history( trans, id, False, True )
if not history:
return None
@@ -729,15 +737,22 @@
hda_dicts = []
datasets = self.get_history_datasets( trans, history )
- for hda in datasets:
- hda_dict = self.get_hda_dict( trans, hda )
- hda_dict[ 'annotation' ] = self.get_item_annotation_str( trans.sa_session, history.user, hda )
- hda_dicts.append( hda_dict )
- history_dict = self.get_history_dict( trans, history, hda_dictionaries=hda_dicts )
- history_dict[ 'annotation' ] = history.annotation
+ #for hda in datasets:
+ # hda_dict = self.get_hda_dict( trans, hda )
+ # hda_dict[ 'annotation' ] = self.get_item_annotation_str( trans.sa_session, history.user, hda )
+ # hda_dicts.append( hda_dict )
+ #history_dict = self.get_history_dict( trans, history, hda_dictionaries=hda_dicts )
+ #history_dict[ 'annotation' ] = history.annotation
+
+ # include all datasets: hidden, deleted, and purged
+ #TODO!: doubled query (hda_dictionaries + datasets)
+ history_data = self.mgrs.histories._get_history_data( trans, history )
+ history_dictionary = history_data[ 'history' ]
+ hda_dictionaries = history_data[ 'contents' ]
+ history_dictionary[ 'annotation' ] = history.annotation
filled = trans.fill_template( "history/embed.mako", item=history, item_data=datasets,
- user_is_owner=user_is_owner, history_dict=history_dict, hda_dicts=hda_dicts )
+ user_is_owner=user_is_owner, history_dict=history_dictionary, hda_dicts=hda_dictionaries )
return filled
def _get_embed_html( self, trans, item_class, item_id ):
diff -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 -r 598a4ec015f66237d41ed2176c673fd52b744f15 static/scripts/mvc/base-mvc.js
--- a/static/scripts/mvc/base-mvc.js
+++ b/static/scripts/mvc/base-mvc.js
@@ -14,7 +14,7 @@
* @example
* // Add to your models/views at the definition using chaining:
* var MyModel = Backbone.Model.extend( LoggableMixin ).extend({ // ... });
- *
+ *
* // or - more explicitly AFTER the definition:
* var MyModel = Backbone.Model.extend({
* logger : console
@@ -208,8 +208,23 @@
};
//==============================================================================
-return {
- LoggableMixin : LoggableMixin,
- SessionStorageModel : SessionStorageModel,
- HiddenUntilActivatedViewMixin : HiddenUntilActivatedViewMixin
-};});
+function mixin( mixinHash1, /* mixinHash2, etc: ... variadic */ propsHash ){
+ // usage: var NewModel = Something.extend( mixin( MyMixinA, MyMixinB, { ... }) );
+ //NOTE: this does not combine any hashes (like events, etc.) and you're expected to handle that
+
+ // simple reversal of param order on _.defaults() - to show mixins in top of definition
+ var args = Array.prototype.slice.call( arguments, 0 ),
+ lastArg = args.pop();
+ args.unshift( lastArg );
+ return _.defaults.apply( _, args );
+}
+
+
+//==============================================================================
+ return {
+ LoggableMixin : LoggableMixin,
+ SessionStorageModel : SessionStorageModel,
+ HiddenUntilActivatedViewMixin : HiddenUntilActivatedViewMixin,
+ mixin : mixin
+ };
+});
diff -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 -r 598a4ec015f66237d41ed2176c673fd52b744f15 static/scripts/mvc/collection/collection-model.js
--- /dev/null
+++ b/static/scripts/mvc/collection/collection-model.js
@@ -0,0 +1,250 @@
+define([
+ "mvc/dataset/hda-model",
+ "mvc/base-mvc",
+ "utils/localization"
+], function( HDA_MODEL, BASE_MVC, _l ){
+//==============================================================================
+/** @class Backbone model for Dataset collection elements.
+ * DC Elements contain a sub-model named 'object'. This class moves that
+ * 'object' from the JSON in the attributes list to a full, instantiated
+ * sub-model found in this.object. This is done on intialization and
+ * everytime the 'change:object' event is fired.
+ *
+ * @borrows LoggableMixin#logger as #logger
+ * @borrows LoggableMixin#log as #log
+ * @constructs
+ */
+var DatasetCollectionElement = Backbone.Model.extend( BASE_MVC.LoggableMixin ).extend(
+/** @lends DatasetCollectionElement.prototype */{
+ //TODO:?? this model may be unneccessary - it reflects the api structure, but...
+ // if we munge the element with the element.object at parse, we can flatten the entire hierarchy
+
+ /** logger used to record this.log messages, commonly set to console */
+ // comment this out to suppress log output
+ //logger : console,
+
+ defaults : {
+ id : null,
+ model_class : 'DatasetCollectionElement',
+ element_identifier : null,
+ element_index : null,
+ element_type : null
+ },
+
+ /** Set up.
+ * @see Backbone.Collection#initialize
+ */
+ initialize : function( model, options ){
+ this.info( this + '.initialize:', model, options );
+ options = options || {};
+ //this._setUpListeners();
+
+ this.object = this._createObjectModel();
+ this.on( 'change:object', function(){
+ //console.log( 'change:object' );
+//TODO: prob. better to update the sub-model instead of re-creating it
+ this.object = this._createObjectModel();
+ });
+ },
+
+ _createObjectModel : function(){
+ //console.log( '_createObjectModel', this.get( 'object' ), this.object );
+ //TODO: same patterns as HDCA _createElementsModel - refactor to BASE_MVC.hasSubModel?
+ if( _.isUndefined( this.object ) ){ this.object = null; }
+ if( !this.get( 'object' ) ){ return this.object; }
+
+ var object = this.get( 'object' );
+ this.unset( 'object', { silent: true });
+
+ this.debug( 'DCE, element_type:', this.get( 'element_type' ) );
+ switch( this.get( 'element_type' ) ){
+ case 'dataset_collection':
+ this.object = new DatasetCollection( object );
+ break;
+ case 'hda':
+ this.object = new HDA_MODEL.HistoryDatasetAssociation( object );
+ break;
+ default:
+ throw new TypeError( 'Unknown element_type: ' + this.get( 'element_type' ) );
+ }
+ return this.object;
+ },
+
+ /** String representation. */
+ toString : function(){
+ var objStr = ( this.object )?( '' + this.object ):( this.get( 'element_identifier' ) );
+ return ([ 'DatasetCollectionElement(', objStr, ')' ].join( '' ));
+ }
+});
+
+
+//==============================================================================
+/** @class Backbone collection for DCEs.
+ * NOTE: used *only* in second level of list:paired collections (a
+ * collection that contains collections)
+ *
+ * @borrows LoggableMixin#logger as #logger
+ * @borrows LoggableMixin#log as #log
+ * @constructs
+ */
+var DatasetCollectionElementCollection = Backbone.Collection.extend( BASE_MVC.LoggableMixin ).extend(
+/** @lends DatasetCollectionElementCollection.prototype */{
+ model: DatasetCollectionElement,
+
+ // comment this out to suppress log output
+ /** logger used to record this.log messages, commonly set to console */
+ //logger : console,
+
+ /** Set up.
+ * @see Backbone.Collection#initialize
+ */
+ initialize : function( models, options ){
+ options = options || {};
+ this.info( this + '.initialize:', models, options );
+ //this._setUpListeners();
+ },
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'DatasetCollectionElementCollection(', this.length, ')' ].join( '' ));
+ }
+});
+
+
+//==============================================================================
+/** @class Backbone model for Dataset Collections.
+ * DCs contain a bbone collection named 'elements' using the class found in
+ * this.collectionClass (gen. DatasetCollectionElementCollection). DCs move
+ * that 'object' from the JSON in the attributes list to a full, instantiated
+ * collection found in this.elements. This is done on intialization and
+ * everytime the 'change:elements' event is fired.
+ *
+ * @borrows LoggableMixin#logger as #logger
+ * @borrows LoggableMixin#log as #log
+ * @constructs
+ */
+var DatasetCollection = Backbone.Model.extend( BASE_MVC.LoggableMixin ).extend(
+/** @lends ListDatasetCollection.prototype */{
+
+ //logger : console,
+
+ /** default attributes for a model */
+ defaults : {
+ collection_type : 'list'
+ },
+
+ collectionClass : DatasetCollectionElementCollection,
+
+ /** */
+ initialize : function( model, options ){
+ this.info( 'DatasetCollection.initialize:', model, options );
+ //historyContent.HistoryContent.prototype.initialize.call( this, attrs, options );
+ this.elements = this._createElementsModel();
+//TODO:?? no way to use parse here?
+ this.on( 'change:elements', function(){
+ this.log( 'change:elements' );
+//TODO: prob. better to update the collection instead of re-creating it
+ this.elements = this._createElementsModel();
+ });
+ },
+
+ /** move elements model attribute to full collection */
+ _createElementsModel : function(){
+ this.log( '_createElementsModel', this.get( 'elements' ), this.elements );
+//TODO: same patterns as DatasetCollectionElement _createObjectModel - refactor to BASE_MVC.hasSubModel?
+ var elements = this.get( 'elements' ) || [];
+ this.info( 'elements:', elements );
+ this.unset( 'elements', { silent: true });
+ this.elements = new this.collectionClass( elements );
+ return this.elements;
+ },
+
+ hasDetails : function(){
+//TODO: this is incorrect for (accidentally) empty collections
+ return this.elements.length !== 0;
+ },
+
+ // ........................................................................ misc
+ /** String representation */
+ toString : function(){
+ var idAndName = [ this.get( 'id' ), this.get( 'name' ) || this.get( 'element_identifier' ) ];
+ return 'DatasetCollection(' + ( idAndName.join(',') ) + ')';
+ }
+});
+
+
+//==============================================================================
+/** @class Backbone collection for a collection of collection collections collecting correctly. */
+var DatasetCollectionCollection = Backbone.Collection.extend( BASE_MVC.LoggableMixin ).extend({
+
+ model: DatasetCollection,
+
+ ///** logger used to record this.log messages, commonly set to console */
+ //// comment this out to suppress log output
+ //logger : console,
+
+ /** Set up.
+ * @see Backbone.Collection#initialize
+ */
+ initialize : function( models, options ){
+ options = options || {};
+ this.info( 'DatasetCollectionCollection.initialize:', models, options );
+ //this._setUpListeners();
+ },
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'DatasetCollectionCollection(', this.get( 'name' ), ')' ].join( '' ));
+ }
+});
+
+
+//NOTE: the following prototypes may not be necessary - but I wanted to specifiy
+// them (for now) and allow for the possibility of unique functionality
+//==============================================================================
+var ListDatasetCollection = DatasetCollection.extend(
+/** @lends ListDatasetCollection.prototype */{
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'ListDatasetCollection(', this.get( 'name' ), ')' ].join( '' ));
+ }
+});
+
+
+//==============================================================================
+var PairDatasetCollection = DatasetCollection.extend(
+/** @lends ListDatasetCollection.prototype */{
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'PairDatasetCollection(', this.get( 'name' ), ')' ].join( '' ));
+ }
+});
+
+
+//==============================================================================
+var ListPairedDatasetCollection = DatasetCollection.extend(
+/** @lends ListDatasetCollection.prototype */{
+
+ // list:paired is the only collection that itself contains collections
+ //collectionClass : DatasetCollectionCollection,
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'ListPairedDatasetCollection(', this.get( 'name' ), ')' ].join( '' ));
+ }
+});
+
+
+//==============================================================================
+ return {
+ DatasetCollectionElement : DatasetCollectionElement,
+ DatasetCollectionElementCollection : DatasetCollectionElementCollection,
+ DatasetCollection : DatasetCollection,
+ DatasetCollectionCollection : DatasetCollectionCollection,
+ ListDatasetCollection : ListDatasetCollection,
+ PairDatasetCollection : PairDatasetCollection,
+ ListPairedDatasetCollection : ListPairedDatasetCollection
+ };
+});
diff -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 -r 598a4ec015f66237d41ed2176c673fd52b744f15 static/scripts/mvc/collection/collection-panel.js
--- /dev/null
+++ b/static/scripts/mvc/collection/collection-panel.js
@@ -0,0 +1,326 @@
+define([
+ "mvc/collection/dataset-collection-base",
+ "mvc/dataset/hda-base",
+ "mvc/base-mvc",
+ "utils/localization"
+], function( DC_BASE, HDA_BASE, BASE_MVC, _l ){
+/* =============================================================================
+TODO:
+
+============================================================================= */
+/** @class non-editable, read-only View/Controller for a dataset collection.
+ * @name CollectionPanel
+ *
+ * @augments Backbone.View
+ * @borrows LoggableMixin#logger as #logger
+ * @borrows LoggableMixin#log as #log
+ * @constructs
+ */
+var CollectionPanel = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend(
+/** @lends CollectionPanel.prototype */{
+
+ /** logger used to record this.log messages, commonly set to console */
+ // comment this out to suppress log output
+ //logger : console,
+
+ tagName : 'div',
+ className : 'history-panel',
+
+ /** (in ms) that jquery effects will use */
+ fxSpeed : 'fast',
+
+ // ......................................................................... SET UP
+ /** Set up the view, set up storage, bind listeners to HistoryContents events
+ * @param {Object} attributes optional settings for the panel
+ */
+ initialize : function( attributes ){
+ attributes = attributes || {};
+ // set the logger if requested
+ if( attributes.logger ){
+ this.logger = attributes.logger;
+ }
+ this.log( this + '.initialize:', attributes );
+
+ this.hasUser = attributes.hasUser;
+ this.HDAViewClass = attributes.HDAViewClass || HDA_BASE.HDABaseView;
+ },
+
+ /** create any event listeners for the panel
+ * @fires: rendered:initial on the first render
+ * @fires: empty-history when switching to a history with no HDAs or creating a new history
+ */
+ _setUpListeners : function(){
+ // debugging
+ //if( this.logger ){
+ this.on( 'all', function( event ){
+ this.log( this + '', arguments );
+ }, this );
+ //}
+ return this;
+ },
+
+ // ------------------------------------------------------------------------ history/hda event listening
+ /** listening for history and HDA events */
+ _setUpModelEventHandlers : function(){
+ return this;
+ },
+
+ // ------------------------------------------------------------------------ panel rendering
+ /** Render urls, historyPanel body, and hdas (if any are shown)
+ * @fires: rendered when the panel is attached and fully visible
+ * @see Backbone.View#render
+ */
+ render : function( speed, callback ){
+ this.log( 'render:', speed, callback );
+ // send a speed of 0 to have no fade in/out performed
+ speed = ( speed === undefined )?( this.fxSpeed ):( speed );
+ //console.debug( this + '.render, fxSpeed:', speed );
+ var panel = this,
+ $newRender;
+
+ // handle the possibility of no model (can occur if fetching the model returns an error)
+ if( !this.model ){
+ return this;
+ }
+ $newRender = this.renderModel();
+
+ // fade out existing, swap with the new, fade in, set up behaviours
+ $( panel ).queue( 'fx', [
+ function( next ){
+ if( speed && panel.$el.is( ':visible' ) ){
+ panel.$el.fadeOut( speed, next );
+ } else {
+ next();
+ }
+ },
+ function( next ){
+ // swap over from temp div newRender
+ panel.$el.empty();
+ if( $newRender ){
+ panel.$el.append( $newRender.children() );
+ }
+ next();
+ },
+ function( next ){
+ if( speed && !panel.$el.is( ':visible' ) ){
+ panel.$el.fadeIn( speed, next );
+ } else {
+ next();
+ }
+ },
+ function( next ){
+ //TODO: ideally, these would be set up before the fade in (can't because of async save text)
+ if( callback ){ callback.call( this ); }
+ panel.trigger( 'rendered', this );
+ next();
+ }
+ ]);
+ return this;
+ },
+
+ /** render with history data
+ * @returns {jQuery} dom fragment as temporary container to be swapped out later
+ */
+ renderModel : function( ){
+ // tmp div for final swap in render
+ var $newRender = $( '<div/>' ).append( CollectionPanel.templates.panel( this.model.toJSON() ) );
+ this._setUpBehaviours( $newRender );
+ this.renderContents( $newRender );
+ return $newRender;
+ },
+
+ /** Set up HistoryPanel js/widget behaviours */
+ _setUpBehaviours : function( $where ){
+ //TODO: these should be either sub-MVs, or handled by events
+ $where = $where || this.$el;
+ $where.find( '[title]' ).tooltip({ placement: 'bottom' });
+ return this;
+ },
+
+ // ------------------------------------------------------------------------ sub-$element shortcuts
+ /** the scroll container for this panel - can be $el, $el.parent(), or grandparent depending on context */
+ $container : function(){
+ return ( this.findContainerFn )?( this.findContainerFn.call( this ) ):( this.$el.parent() );
+ },
+ /** where hdaViews are attached */
+ $datasetsList : function( $where ){
+ return ( $where || this.$el ).find( '.datasets-list' );
+ },
+
+ // ------------------------------------------------------------------------ sub-views
+ /** Set up/render a view for each HDA to be shown, init with model and listeners.
+ * HDA views are cached to the map this.hdaViews (using the model.id as key).
+ * @param {jQuery} $whereTo what dom element to prepend the HDA views to
+ * @returns the number of visible hda views
+ */
+ renderContents : function( $whereTo ){
+ //console.debug( 'renderContents, elements:', this.model.elements );
+ $whereTo = $whereTo || this.$el;
+
+ var panel = this,
+ contentViews = {},
+ visibleContents = this.model.elements || [];
+ //this.log( 'renderContents, visibleContents:', visibleContents, $whereTo );
+
+ this.$datasetsList( $whereTo ).empty();
+ if( visibleContents && visibleContents.length ){
+ visibleContents.each( function( content ){
+ var contentId = content.id,
+ contentView = panel._createContentView( content );
+ contentViews[ contentId ] = contentView;
+ panel.attachContentView( contentView.render(), $whereTo );
+ });
+ }
+ this.contentViews = contentViews;
+ return this.contentViews;
+ },
+
+ /**
+ * @param {HistoryDatasetAssociation} content
+ */
+ _createContentView : function( content ){
+ //console.debug( 'content json:', JSON.stringify( content, null, ' ' ) );
+ var contentView = null,
+ ContentClass = this._getContentClass( content );
+ //console.debug( 'content.object json:', JSON.stringify( content.object, null, ' ' ) );
+ //console.debug( 'ContentClass:', ContentClass );
+ //console.debug( 'content:', content );
+ //console.debug( 'content.object:', content.object );
+ contentView = new ContentClass({
+ model : content.object,
+ linkTarget : this.linkTarget,
+ //draggable : true,
+ hasUser : this.hasUser,
+ logger : this.logger
+ });
+ //this._setUpHdaListeners( contentView );
+ return contentView;
+ },
+
+ _getContentClass : function( content ){
+ switch( content.get( 'element_type' ) ){
+ case 'hda':
+ return this.HDAViewClass;
+ case 'dataset_collection':
+ return DC_BASE.NestedDCEBaseView;
+ }
+ throw new TypeError( 'Unknown element type:', content.get( 'element_type' ) );
+ },
+
+// /** Set up HistoryPanel listeners for HDAView events. Currently binds:
+// * HDAView#body-visible, HDAView#body-hidden to store expanded states
+// * @param {HDAView} hdaView HDAView (base or edit) to listen to
+// */
+// _setUpHdaListeners : function( hdaView ){
+// var panel = this;
+// hdaView.on( 'error', function( model, xhr, options, msg ){
+// panel.errorHandler( model, xhr, options, msg );
+// });
+// // maintain a list of hdas whose bodies are expanded
+// hdaView.on( 'body-expanded', function( model ){
+// panel.storage.addExpandedHda( model );
+// });
+// hdaView.on( 'body-collapsed', function( id ){
+// panel.storage.removeExpandedHda( id );
+// });
+// return this;
+// },
+
+ /** attach an contentView to the panel */
+ attachContentView : function( contentView, $whereTo ){
+ $whereTo = $whereTo || this.$el;
+ var $datasetsList = this.$datasetsList( $whereTo );
+ $datasetsList.append( contentView.$el );
+ return this;
+ },
+
+ // ------------------------------------------------------------------------ panel events
+ /** event map */
+ events : {
+ 'click .panel-navigation-back' : 'close'
+ },
+
+ /** */
+ close : function( event ){
+ this.$el.remove();
+ this.trigger( 'collection-close' );
+ },
+
+ // ........................................................................ misc
+ /** Return a string rep of the history */
+ toString : function(){
+ return 'CollectionPanel(' + (( this.model )?( this.model.get( 'name' )):( '' )) + ')';
+ }
+});
+
+
+//------------------------------------------------------------------------------ TEMPLATES
+var _panelTemplate = [
+ '<div class="history-controls">',
+ '<div class="panel-navigation">',
+ '<a class="panel-navigation-back" href="javascript:void(0)">', _l( 'Back' ), '</a>',
+ '</div>',
+
+ '<div class="history-title">',
+ '<% if( collection.name ){ %>',
+ '<div class="history-name"><%= collection.hid %> : <%= collection.name %></div>',
+ '<% } %>',
+ '</div>',
+
+ //'<div class="history-subtitle clear">',
+ // '<% if( history.nice_size ){ %>',
+ // '<div class="history-size"><%= history.nice_size %></div>',
+ // '<% } %>',
+ // '<div class="history-secondary-actions"></div>',
+ //'</div>',
+ //
+ //'<% if( history.deleted ){ %>',
+ // '<div class="warningmessagesmall"><strong>',
+ // _l( 'You are currently viewing a deleted history!' ),
+ // '</strong></div>',
+ //'<% } %>',
+ //
+ //'<div class="message-container">',
+ // '<% if( history.message ){ %>',
+ // // should already be localized
+ // '<div class="<%= history.status %>message"><%= history.message %></div>',
+ // '<% } %>',
+ //'</div>',
+ //
+ //'<div class="quota-message errormessage">',
+ // _l( 'You are over your disk quota' ), '. ',
+ // _l( 'Tool execution is on hold until your disk usage drops below your allocated quota' ), '.',
+ //'</div>',
+ //
+ //'<div class="tags-display"></div>',
+ //'<div class="annotation-display"></div>',
+ //'<div class="history-dataset-actions">',
+ // '<div class="btn-group">',
+ // '<button class="history-select-all-datasets-btn btn btn-default"',
+ // 'data-mode="select">', _l( 'All' ), '</button>',
+ // '<button class="history-deselect-all-datasets-btn btn btn-default"',
+ // 'data-mode="select">', _l( 'None' ), '</button>',
+ // '</div>',
+ // '<button class="history-dataset-action-popup-btn btn btn-default">',
+ // _l( 'For all selected' ), '...</button>',
+ //'</div>',
+ '</div>',
+ // end history controls
+
+ // where the datasets/hdas are added
+ '<div class="datasets-list"></div>'
+
+].join( '' );
+
+CollectionPanel.templates = {
+ panel : function( JSON ){
+ return _.template( _panelTemplate, JSON, { variable: 'collection' });
+ }
+};
+
+
+//==============================================================================
+ return {
+ CollectionPanel: CollectionPanel
+ };
+});
diff -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 -r 598a4ec015f66237d41ed2176c673fd52b744f15 static/scripts/mvc/collection/dataset-collection-base.js
--- a/static/scripts/mvc/collection/dataset-collection-base.js
+++ b/static/scripts/mvc/collection/dataset-collection-base.js
@@ -1,328 +1,151 @@
define([
- "mvc/history/history-content-base-view",
+ "mvc/base-mvc",
"utils/localization"
-], function( historyContentBaseView, _l ){
+], function( BASE_MVC, _l ){
/* global Backbone, LoggableMixin */
//==============================================================================
-/** @class Read only view for HistoryDatasetCollectionAssociation.
- * @name HDABaseView
+/** @class Read only view for DatasetCollection.
+ * @name DCBaseView
*
* @augments Backbone.View
* @borrows LoggableMixin#logger as #logger
* @borrows LoggableMixin#log as #log
* @constructs
*/
-var DatasetCollectionBaseView = historyContentBaseView.HistoryContentBaseView.extend({
- className : "dataset hda history-panel-hda",
- id : function(){ return 'hdca-' + this.model.get( 'id' ); },
+var DCBaseView = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend({
+
+ /** logger used to record this.log messages, commonly set to console */
+ // comment this out to suppress log output
+ //logger : console,
+
+ /** */
+ className : "dataset-collection",
+ /** */
+ fxSpeed : 'fast',
/** */
initialize : function( attributes ){
if( attributes.logger ){ this.logger = this.model.logger = attributes.logger; }
- this.log( this + '.initialize:', attributes );
- /** is the view currently in selection mode? */
- this.selectable = attributes.selectable || false;
- //this.log( '\t selectable:', this.selectable );
- /** is the view currently selected? */
- this.selected = attributes.selected || false;
- /** is the body of this collection view expanded/not? */
- this.expanded = attributes.expanded || false;
+ this.log( 'DCBaseView.initialize:', attributes );
},
- /** */
- render : function( fade ){
- var $newRender = this._buildNewRender();
-
- this._queueNewRender( $newRender, fade );
- return this;
- },
-
- /** */
- _buildNewRender : function(){
- var $newRender = $( DatasetCollectionBaseView.templates.skeleton( this.model.toJSON() ) );
- $newRender.find( '.dataset-primary-actions' ).append( this._render_titleButtons() );
- $newRender.children( '.dataset-body' ).replaceWith( this._render_body() );
- this._setUpBehaviors( $newRender );
- return $newRender;
- },
-
- /** */
- _queueNewRender : function( $newRender, fade ) {
- fade = ( fade === undefined )?( true ):( fade );
- var view = this;
-
- // fade the old render out (if desired)
- if( fade ){
- $( view ).queue( function( next ){ this.$el.fadeOut( view.fxSpeed, next ); });
- }
- // empty the old render, update to any new HDA state, swap in the new render contents, handle multi-select
- $( view ).queue( function( next ){
- this.$el.empty()
- .attr( 'class', view.className ).addClass( 'state-' + view.model.get( 'state' ) )
- .append( $newRender.children() );
- if( this.selectable ){ this.showSelector( 0 ); }
- next();
- });
- // fade the new in
- if( fade ){
- $( view ).queue( function( next ){ this.$el.fadeIn( view.fxSpeed, next ); });
- }
- // trigger an event to know we're ready
- $( view ).queue( function( next ){
- this.trigger( 'rendered', view );
- if( this.model.inReadyState() ){
- this.trigger( 'rendered:ready', view );
- }
- if( this.draggable ){ this.draggableOn(); }
- next();
- });
- },
-
- // ................................................................................ titlebar buttons
- /** Render icon-button group for the common, most easily accessed actions.
- * @returns {jQuery} rendered DOM
- */
- _render_titleButtons : function(){
- // render just the display for read-only
- return [ ];
- },
-
- // ......................................................................... state body renderers
- /** Render the enclosing div of the collection body and, if expanded, the html in the body
- * @returns {jQuery} rendered DOM
- */
- _render_body : function(){
- var $body = $( '<div>Error: unknown state "' + this.model.get( 'state' ) + '".</div>' ),
- // cheesy: get function by assumed matching name
- renderFn = this[ '_render_body_' + this.model.get( 'state' ) ];
- if( _.isFunction( renderFn ) ){
- $body = renderFn.call( this );
- }
- this._setUpBehaviors( $body );
-
- // only render the body html if it's being shown
- if( this.expanded ){
- $body.show();
- }
- return $body;
- },
-
- /** set up js behaviors, event handlers for elements within the given container
- * @param {jQuery} $container jq object that contains the elements to process (defaults to this.$el)
- */
- _setUpBehaviors : function( $container ){
- $container = $container || this.$el;
- // set up canned behavior on children (bootstrap, popupmenus, editable_text, etc.)
- make_popup_menus( $container );
- $container.find( '[title]' ).tooltip({ placement : 'bottom' });
- },
-
- // TODO: Eliminate duplication between following event map and one for HDAs.
-
- // ......................................................................... events
- /** event map */
- events : {
- // expand the body when the title is clicked or when in focus and space or enter is pressed
- 'click .dataset-title-bar' : 'toggleBodyVisibility',
- 'keydown .dataset-title-bar' : 'toggleBodyVisibility',
-
- // toggle selected state
- 'click .dataset-selector' : 'toggleSelect'
- },
-
- /** Show or hide the body/details of history content.
- * note: if the model does not have detailed data, fetch that data before showing the body
- * @param {Event} event the event that triggered this (@link HDABaseView#events)
- * @param {Boolean} expanded if true, expand; if false, collapse
- * @fires body-expanded when a body has been expanded
- * @fires body-collapsed when a body has been collapsed
- */
- toggleBodyVisibility : function( event, expand ){
- // bail (with propagation) if keydown and not space or enter
- var KEYCODE_SPACE = 32, KEYCODE_RETURN = 13;
- if( event && ( event.type === 'keydown' )
- && !( event.keyCode === KEYCODE_SPACE || event.keyCode === KEYCODE_RETURN ) ){
- return true;
- }
-
- var $body = this.$el.find( '.dataset-body' );
- expand = ( expand === undefined )?( !$body.is( ':visible' ) ):( expand );
- if( expand ){
- this.expandBody();
- } else {
- this.collapseBody();
- }
- return false;
- },
-
- /** Render and show the full, detailed body of this view including extra data and controls.
- * @fires body-expanded when a body has been expanded
- */
- expandBody : function(){
- var contentView = this;
-
- function _renderBodyAndExpand(){
- contentView.$el.children( '.dataset-body' ).replaceWith( contentView._render_body() );
- contentView.$el.children( '.dataset-body' ).slideDown( contentView.fxSpeed, function(){
- contentView.expanded = true;
- contentView.trigger( 'body-expanded', contentView.model );
- });
- }
- // TODO: Fetch more details like HDA view...
- _renderBodyAndExpand();
- },
-
- /** Hide the body/details of an HDA.
- * @fires body-collapsed when a body has been collapsed
- */
- collapseBody : function(){
- var hdaView = this;
- this.$el.children( '.dataset-body' ).slideUp( hdaView.fxSpeed, function(){
- hdaView.expanded = false;
- hdaView.trigger( 'body-collapsed', hdaView.model.id );
- });
- },
-
- /** Render an 'ok' collection.
- * @param {jQuery} parent DOM to which to append this body
- */
- _render_body_ok : function(){
- // most common state renderer and the most complicated
- var $body = $( DatasetCollectionBaseView.templates.body( this.model.toJSON() ) );
-
- // return shortened form if del'd (no display apps or peek?)
- if( this.model.get( 'deleted' ) ){
- return $body;
- }
-
- return $body;
- },
-
- // ......................................................................... selection
- /** display a (fa-icon) checkbox on the left of the hda that fires events when checked
- * Note: this also hides the primary actions
- */
- showSelector : function(){
- // make sure selected state is represented properly
- if( this.selected ){
- this.select( null, true );
- }
-
- this.selectable = true;
- this.trigger( 'selectable', true, this );
-
- this.$( '.dataset-primary-actions' ).hide();
- this.$( '.dataset-selector' ).show();
- },
-
- /** remove the selection checkbox */
- hideSelector : function(){
- // reverse the process from showSelect
- this.selectable = false;
- this.trigger( 'selectable', false, this );
-
- this.$( '.dataset-selector' ).hide();
- this.$( '.dataset-primary-actions' ).show();
- },
-
- toggleSelector : function(){
- if( !this.$el.find( '.dataset-selector' ).is( ':visible' ) ){
- this.showSelector();
- } else {
- this.hideSelector();
- }
- },
-
- /** event handler for selection (also programmatic selection)
- */
- select : function( event ){
- // switch icon, set selected, and trigger event
- this.$el.find( '.dataset-selector span' )
- .removeClass( 'fa-square-o' ).addClass( 'fa-check-square-o' );
- if( !this.selected ){
- this.trigger( 'selected', this, event );
- this.selected = true;
- }
- return false;
- },
-
- /** event handler for clearing selection (also programmatic deselection)
- */
- deselect : function( event ){
- // switch icon, set selected, and trigger event
- this.$el.find( '.dataset-selector span' )
- .removeClass( 'fa-check-square-o' ).addClass( 'fa-square-o' );
- if( this.selected ){
- this.trigger( 'de-selected', this, event );
- this.selected = false;
- }
- return false;
- },
-
- toggleSelect : function( event ){
- if( this.selected ){
- this.deselect( event );
- } else {
- this.select( event );
- }
- },
+//TODO: render has been removed from the inheritance chain here, so this won't work when called as is
// ......................................................................... misc
/** String representation */
toString : function(){
var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
- return 'HDCABaseView(' + modelString + ')';
+ return 'DCBaseView(' + modelString + ')';
}
});
-//------------------------------------------------------------------------------ TEMPLATES
-//TODO: possibly break these out into a sep. module
-var skeletonTemplate = _.template([
- '<div class="dataset hda">',
- '<div class="dataset-warnings">',
- '<% if ( collection.deleted ) { %>',
- '<div class="dataset-deleted-msg warningmessagesmall"><strong>',
- _l( 'This collection has been deleted.' ),
+/** templates for DCBaseViews (skeleton and body) */
+DCBaseView.templates = (function(){
+// use closure to run underscore template fn only once at module load
+ var skeletonTemplate = _.template([
+ '<div class="dataset hda">',
+ '<div class="dataset-warnings">',
+ '<% if ( collection.deleted ) { %>',
+ '<div class="dataset-deleted-msg warningmessagesmall"><strong>',
+ _l( 'This collection has been deleted.' ),
+ '</div>',
+ '<% } %>',
+ '<% if ( !collection.visible ) { %>',
+ '<div class="dataset-hidden-msg warningmessagesmall"><strong>',
+ _l( 'This collection has been hidden.' ),
+ '</div>',
+ '<% } %>',
+ '</div>',
+ '<div class="dataset-primary-actions"></div>',
+ '<div class="dataset-title-bar clear" tabindex="0">',
+ '<span class="dataset-state-icon state-icon"></span>',
+ '<div class="dataset-title">',
+ '<span class="dataset-name"><%- collection.name %></span>',
'</div>',
- '<% } %>',
- '<% if ( !collection.visible ) { %>',
- '<div class="dataset-hidden-msg warningmessagesmall"><strong>',
- _l( 'This collection has been hidden.' ),
- '</div>',
- '<% } %>',
- '</div>',
- '<div class="dataset-selector"><span class="fa fa-2x fa-square-o"></span></div>',
- '<div class="dataset-primary-actions"></div>',
- '<div class="dataset-title-bar clear" tabindex="0">',
- '<span class="dataset-state-icon state-icon"></span>',
- '<div class="dataset-title">',
- '<span class="hda-hid"><%= collection.hid %></span> ',
- '<span class="dataset-name"><%= collection.name %></span>',
'</div>',
- '</div>',
- '<div class="dataset-body"></div>',
- '</div>'
-].join( '' ));
+ '<div class="dataset-body"></div>',
+ '</div>'
+ ].join( '' ));
-var bodyTemplate = _.template([
- '<div class="dataset-body">',
- '<div class="dataset-summary">',
- _l( 'A dataset collection.' ),
- '</div>'
-].join( '' ));
+ var bodyTemplate = _.template([
+ '<div class="dataset-body">',
+ '<div class="dataset-summary">',
+ _l( 'A dataset collection.' ),
+ '</div>'
+ ].join( '' ));
-DatasetCollectionBaseView.templates = {
// we override here in order to pass the localizer (_L) into the template scope - since we use it as a fn within
- skeleton : function( collectionJSON ){
- return skeletonTemplate({ _l: _l, collection: collectionJSON });
- },
- body : function( collectionJSON ){
- return bodyTemplate({ _l: _l, collection: collectionJSON });
- }
-};
+ return {
+ skeleton : function( collectionJSON ){
+ return skeletonTemplate({ _l: _l, collection: collectionJSON });
+ },
+ body : function( collectionJSON ){
+ return bodyTemplate({ _l: _l, collection: collectionJSON });
+ }
+ };
+}());
+
+
+//TODO: unused
+////==============================================================================
+///** @class Read only view for DatasetCollectionElement.
+// * @name DCEBaseView
+// *
+// * @augments Backbone.View
+// * @borrows LoggableMixin#logger as #logger
+// * @borrows LoggableMixin#log as #log
+// * @constructs
+// */
+//var NestedDCBaseView = DCBaseView.extend({
+//
+// logger : console,
+//
+// /** */
+// initialize : function( attributes ){
+// if( attributes.logger ){ this.logger = this.model.logger = attributes.logger; }
+// this.warn( this + '.initialize:', attributes );
+// DCBaseView.prototype.initialize.call( this, attributes );
+// },
+//
+// _template : function(){
+// this.debug( this.model );
+// this.debug( this.model.toJSON() );
+// return NestedDCBaseView.templates.skeleton( this.model.toJSON() );
+// },
+//
+// // ......................................................................... misc
+// /** String representation */
+// toString : function(){
+// var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
+// return 'NestedDCBaseView(' + modelString + ')';
+// }
+//});
+//
+////------------------------------------------------------------------------------ TEMPLATES
+////TODO: possibly break these out into a sep. module
+//NestedDCBaseView.templates = (function(){
+// var skeleton = _.template([
+// '<div class="dataset hda history-panel-hda state-ok">',
+// '<div class="dataset-primary-actions"></div>',
+// '<div class="dataset-title-bar clear" tabindex="0">',
+// '<div class="dataset-title">',
+// '<span class="dataset-name"><%= collection.name %></span>',
+// '</div>',
+// '</div>',
+// '</div>'
+// ].join( '' ));
+// // we override here in order to pass the localizer (_L) into the template scope - since we use it as a fn within
+// return {
+// skeleton : function( json ){
+// return skeleton({ _l: _l, collection: json });
+// }
+// };
+//}());
+
//==============================================================================
return {
- DatasetCollectionBaseView : DatasetCollectionBaseView
+ DCBaseView : DCBaseView,
+ //NestedDCBaseView : NestedDCBaseView,
};
});
diff -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 -r 598a4ec015f66237d41ed2176c673fd52b744f15 static/scripts/mvc/collection/dataset-collection-edit.js
--- a/static/scripts/mvc/collection/dataset-collection-edit.js
+++ b/static/scripts/mvc/collection/dataset-collection-edit.js
@@ -1,75 +1,36 @@
define([
- "mvc/dataset/hda-model",
+ "mvc/dataset/states",
"mvc/collection/dataset-collection-base",
"utils/localization"
-], function( hdaModel, datasetCollectionBase, _l ){
+], function( STATES, DC_BASE_VIEW, _l ){
//==============================================================================
-/** @class Editing view for HistoryDatasetCollectionAssociation.
+var _super = DC_BASE_VIEW.DCBaseView;
+/** @class Editing view for DatasetCollection.
* @name DatasetCollectionEditView
*
- * @augments DatasetCollectionBaseView
+ * @augments DCBaseView
* @constructs
*/
-var DatasetCollectionEditView = datasetCollectionBase.DatasetCollectionBaseView.extend( {
+var DCEditView = _super.extend({
+
+ /** logger used to record this.log messages, commonly set to console */
+ // comment this out to suppress log output
+ //logger : console,
initialize : function( attributes ){
- datasetCollectionBase.DatasetCollectionBaseView.prototype.initialize.call( this, attributes );
- },
-
- // ......................................................................... edit attr, delete
- /** Render icon-button group for the common, most easily accessed actions.
- * Overrides _render_titleButtons to include editing related buttons.
- * @see DatasetCollectionBaseView#_render_titleButtons
- * @returns {jQuery} rendered DOM
- */
- _render_titleButtons : function(){
- // render the display, edit attr and delete icon-buttons
- return datasetCollectionBase.DatasetCollectionBaseView.prototype._render_titleButtons.call( this ).concat([
- this._render_deleteButton()
- ]);
- },
-
- /** Render icon-button to delete this hda.
- * @returns {jQuery} rendered DOM
- */
- _render_deleteButton : function(){
- // don't show delete if...
- if( ( this.model.get( 'state' ) === hdaModel.HistoryDatasetAssociation.STATES.NEW )
- || ( this.model.get( 'state' ) === hdaModel.HistoryDatasetAssociation.STATES.NOT_VIEWABLE )
- || ( !this.model.get( 'accessible' ) ) ){
- return null;
- }
-
- var self = this,
- deleteBtnData = {
- title : _l( 'Delete' ),
- classes : 'dataset-delete',
- onclick : function() {
- // ...bler... tooltips being left behind in DOM (hover out never called on deletion)
- self.$el.find( '.icon-btn.dataset-delete' ).trigger( 'mouseout' );
- self.model[ 'delete' ]();
- }
- };
- if( this.model.get( 'deleted' ) ){
- deleteBtnData = {
- title : _l( 'Dataset collection is already deleted' ),
- disabled : true
- };
- }
- deleteBtnData.faIcon = 'fa-times';
- return faIconButton( deleteBtnData );
+ _super.prototype.initialize.call( this, attributes );
},
// ......................................................................... misc
/** string rep */
toString : function(){
var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
- return 'HDCAEditView(' + modelString + ')';
+ return 'DCEditView(' + modelString + ')';
}
});
//==============================================================================
return {
- DatasetCollectionEditView : DatasetCollectionEditView
+ DCEditView : DCEditView
};
});
diff -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 -r 598a4ec015f66237d41ed2176c673fd52b744f15 static/scripts/mvc/collection/hdca-base.js
--- /dev/null
+++ b/static/scripts/mvc/collection/hdca-base.js
@@ -0,0 +1,116 @@
+define([
+ "mvc/base-mvc",
+ "mvc/collection/dataset-collection-base",
+ "mvc/history/history-content-base-view",
+ "utils/localization"
+], function( BASE_MVC, DC_BASE, HISTORY_CONTENT_BASE_VIEW, _l ){
+/* global Backbone, LoggableMixin */
+//==============================================================================
+var HCVMixin = HISTORY_CONTENT_BASE_VIEW.HistoryContentViewMixin,
+ _super = DC_BASE.DCBaseView;
+/** @class Read only view for HistoryDatasetCollectionAssociation.
+ * @name
+ *
+ * @augments Backbone.View
+ * @borrows LoggableMixin#logger as #logger
+ * @borrows LoggableMixin#log as #log
+ * @constructs
+ */
+var HDCABaseView = _super.extend( BASE_MVC.mixin( HCVMixin, {
+
+ /** logger used to record this.log messages, commonly set to console */
+ // comment this out to suppress log output
+ //logger : console,
+
+ /** */
+ className : "dataset hda history-panel-hda",
+
+ /** */
+ initialize : function( attributes ){
+ if( attributes.logger ){ this.logger = this.model.logger = attributes.logger; }
+ this.log( this + '.initialize:', attributes );
+ _super.prototype.initialize.call( this, attributes );
+ HCVMixin.initialize.call( this, attributes );
+ },
+
+ /** */
+ _template : function(){
+ return HDCABaseView.templates.skeleton( this.model.toJSON() );
+ },
+
+ /** */
+ events : _.extend( _.clone( HCVMixin.events ), {
+ }),
+
+ /** */
+ _renderBody : function(){
+ // override this
+ var $body = $( _super.templates.body( this.model.toJSON() ) );
+ if( this.expanded ){
+ $body.show();
+ }
+ return $body;
+ },
+
+ // ......................................................................... misc
+ /** String representation */
+ toString : function(){
+ var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
+ return 'HDCABaseView(' + modelString + ')';
+ }
+}));
+
+/** templates for HDCAs (skeleton and body) */
+HDCABaseView.templates = HDCABaseView.prototype.templates = (function(){
+// use closure to run underscore template fn only once at module load
+ var skeletonTemplate = _.template([
+ '<div class="dataset hda">',
+ '<div class="dataset-warnings">',
+ '<% if ( collection.deleted ) { %>',
+ '<div class="dataset-deleted-msg warningmessagesmall"><strong>',
+ _l( 'This collection has been deleted.' ),
+ '</div>',
+ '<% } %>',
+ '<% if ( !collection.visible ) { %>',
+ '<div class="dataset-hidden-msg warningmessagesmall"><strong>',
+ _l( 'This collection has been hidden.' ),
+ '</div>',
+ '<% } %>',
+ '</div>',
+ '<div class="dataset-selector"><span class="fa fa-2x fa-square-o"></span></div>',
+ '<div class="dataset-primary-actions"></div>',
+ '<div class="dataset-title-bar clear" tabindex="0">',
+ '<span class="dataset-state-icon state-icon"></span>',
+ '<div class="dataset-title">',
+ '<span class="hda-hid"><%- collection.hid %></span> ',
+ '<span class="dataset-name"><%- collection.name %></span>',
+ '</div>',
+ '</div>',
+ '<div class="dataset-body"></div>',
+ '</div>'
+ ].join( '' ));
+
+ var bodyTemplate = _.template([
+ '<div class="dataset-body">',
+ '<div class="dataset-summary">',
+ _l( 'A dataset collection.' ),
+ '</div>'
+ ].join( '' ));
+
+ // we override here in order to pass the localizer (_L) into the template scope - since we use it as a fn within
+ return {
+ skeleton : function( collectionJSON ){
+ return skeletonTemplate({ _l: _l, collection: collectionJSON });
+ },
+ body : function( collectionJSON ){
+ return bodyTemplate({ _l: _l, collection: collectionJSON });
+ }
+ };
+}());
+
+
+//==============================================================================
+ return {
+ HDCABaseView : HDCABaseView
+ };
+});
diff -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 -r 598a4ec015f66237d41ed2176c673fd52b744f15 static/scripts/mvc/collection/hdca-edit.js
--- /dev/null
+++ b/static/scripts/mvc/collection/hdca-edit.js
@@ -0,0 +1,74 @@
+define([
+ "mvc/dataset/states",
+ "mvc/collection/hdca-base",
+ "utils/localization"
+], function( STATES, HDCA_BASE, _l ){
+//==============================================================================
+var _super = HDCA_BASE.HDCABaseView;
+/** @class Editing view for HistoryDatasetCollectionAssociation.
+ * @name DatasetCollectionEditView
+ *
+ * @augments HDCABaseView
+ * @constructs
+ */
+var HDCAEditView = _super.extend({
+
+ /** logger used to record this.log messages, commonly set to console */
+ // comment this out to suppress log output
+ //logger : console,
+
+ initialize : function( attributes ){
+ _super.prototype.initialize.call( this, attributes );
+ },
+
+ // ......................................................................... edit attr, delete
+ /** Render icon-button group for the common, most easily accessed actions.
+ * Overrides _render_titleButtons to include editing related buttons.
+ * @returns {jQuery} rendered DOM
+ */
+ _render_titleButtons : function(){
+ this.log( this + '._render_titleButtons' );
+ // render the display, edit attr and delete icon-buttons
+ return _super.prototype._render_titleButtons.call( this )
+ .concat([
+ this._render_deleteButton()
+ ]);
+ },
+
+ /** Render icon-button to delete this hda.
+ * @returns {jQuery} rendered DOM
+ */
+ _render_deleteButton : function(){
+ var self = this,
+ deleteBtnData = {
+ title : _l( 'Delete' ),
+ classes : 'dataset-delete',
+ onclick : function() {
+ // ...bler... tooltips being left behind in DOM (hover out never called on deletion)
+ self.$el.find( '.icon-btn.dataset-delete' ).trigger( 'mouseout' );
+ self.model[ 'delete' ]();
+ }
+ };
+ if( self.model.get( 'deleted' ) ){
+ deleteBtnData = {
+ title : _l( 'Dataset collection is already deleted' ),
+ disabled : true
+ };
+ }
+ deleteBtnData.faIcon = 'fa-times';
+ return faIconButton( deleteBtnData );
+ },
+
+ // ......................................................................... misc
+ /** string rep */
+ toString : function(){
+ var modelString = ( this.model )?( this.model + '' ):( '(no model)' );
+ return 'HDCAEditView(' + modelString + ')';
+ }
+});
+
+//==============================================================================
+ return {
+ HDCAEditView : HDCAEditView
+ };
+});
diff -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 -r 598a4ec015f66237d41ed2176c673fd52b744f15 static/scripts/mvc/collection/hdca-model.js
--- a/static/scripts/mvc/collection/hdca-model.js
+++ b/static/scripts/mvc/collection/hdca-model.js
@@ -1,69 +1,89 @@
define([
"mvc/history/history-content-base",
+ "mvc/collection/collection-model",
"utils/localization"
-], function( historyContent, _l ){
+], function( HISTORY_CONTENT, DC_MODEL, _l ){
//==============================================================================
-var HistoryDatasetCollectionAssociation = historyContent.HistoryContent.extend(
-/** @lends HistoryDatasetCollectionAssociation.prototype */{
- /** default attributes for a model */
- defaults : {
- // parent (containing) history
- history_id : null,
- // often used with tagging
- model_class : 'HistoryDatasetCollectionAssociation',
- history_content_type : 'dataset_collection',
- hid : 0,
+var hcontentMixin = HISTORY_CONTENT.HistoryContentMixin,
+/** @class Backbone model for (generic) Dataset Collection within a History.
+ * @constructs
+ */
+ HistoryDatasetCollection = DC_MODEL.DatasetCollection.extend( hcontentMixin );
- id : null,
- name : '(unnamed dataset collection)',
- // one of HistoryDatasetAssociation.STATES, calling them all 'ok' for now.
- state : 'ok',
- accessible : true,
- deleted : false,
- visible : true,
+//NOTE: the following prototypes may not be necessary - but I wanted to specifiy
+// them (for now) and allow for the possibility of unique functionality
+//==============================================================================
+var ListDC = DC_MODEL.ListDatasetCollection,
+/** @class Backbone model for List Dataset Collection within a History.
+ * @constructs
+ */
+ HistoryListDatasetCollection = ListDC.extend( hcontentMixin ).extend(
+/** @lends HistoryListDatasetCollection.prototype */{
- purged : false, // Purged doesn't make sense for collections - at least right now.
-
- tags : [],
- annotation : ''
- },
- urls : function(){
+ initialize : function( model, options ){
+ ListDC.prototype.initialize.call( this, model, options );
+ hcontentMixin.initialize.call( this, model, options );
+ //TODO: in lieu of any state info for collections, show as 'ok'
+ this.set( 'state', 'ok', { silent: true });
},
- inReadyState : function(){
- return true; // TODO
- },
-
- // ........................................................................ search
- /** what attributes of an collection will be used in a text search */
- searchAttributes : [
- 'name'
- ],
-
- /** our attr keys don't often match the labels we display to the user - so, when using
- * attribute specifiers ('name="bler"') in a term, allow passing in aliases for the
- * following attr keys.
- */
- searchAliases : {
- title : 'name'
- // TODO: Add tag...
- },
-
- // ........................................................................ misc
- /** String representation */
+ /** String representation. */
toString : function(){
- var nameAndId = this.get( 'id' ) || '';
- if( this.get( 'name' ) ){
- nameAndId = this.get( 'hid' ) + ' :"' + this.get( 'name' ) + '",' + nameAndId;
- }
- return 'HDCA-' + this.get( 'collection_type' ) + '(' + nameAndId + ')';
+ return ([ 'HistoryListDatasetCollection(', this.get( 'name' ), ')' ].join( '' ));
}
});
//==============================================================================
+var PairDC = DC_MODEL.PairDatasetCollection,
+/** @class Backbone model for Pair Dataset Collection within a History.
+ * @constructs
+ */
+ HistoryPairDatasetCollection = PairDC.extend( hcontentMixin ).extend(
+/** @lends HistoryPairDatasetCollection.prototype */{
+
+ initialize : function( model, options ){
+ PairDC.prototype.initialize.call( this, model, options );
+ hcontentMixin.initialize.call( this, model, options );
+ //TODO: in lieu of any state info for collections, show as 'ok'
+ this.set( 'state', 'ok', { silent: true });
+ },
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'HistoryPairDatasetCollection(', this.get( 'name' ), ')' ].join( '' ));
+ }
+});
+
+
+//==============================================================================
+var ListPairedDC = DC_MODEL.ListPairedDatasetCollection,
+/** @class Backbone model for List of Pairs Dataset Collection within a History.
+ * @constructs
+ */
+ HistoryListPairedDatasetCollection = ListPairedDC.extend( hcontentMixin ).extend(
+/** @lends HistoryListPairedDatasetCollection.prototype */{
+
+ initialize : function( model, options ){
+ ListPairedDC.prototype.initialize.call( this, model, options );
+ hcontentMixin.initialize.call( this, model, options );
+ //TODO: in lieu of any state info for collections, show as 'ok'
+ this.set( 'state', 'ok', { silent: true });
+ },
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'HistoryListPairedDatasetCollection(', this.get( 'name' ), ')' ].join( '' ));
+ }
+});
+
+
+//==============================================================================
return {
- HistoryDatasetCollectionAssociation : HistoryDatasetCollectionAssociation
+ HistoryDatasetCollection : HistoryDatasetCollection,
+ HistoryListDatasetCollection : HistoryListDatasetCollection,
+ HistoryPairDatasetCollection : HistoryPairDatasetCollection,
+ HistoryListPairedDatasetCollection : HistoryListPairedDatasetCollection
};
});
diff -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 -r 598a4ec015f66237d41ed2176c673fd52b744f15 static/scripts/mvc/dataset/hda-base.js
--- a/static/scripts/mvc/dataset/hda-base.js
+++ b/static/scripts/mvc/dataset/hda-base.js
@@ -1,11 +1,12 @@
define([
- "mvc/dataset/hda-model",
+ "mvc/dataset/states",
"mvc/history/history-content-base-view",
"mvc/data",
"utils/localization"
-], function( hdaModel, historyContentBaseView, dataset, _l ){
+], function( STATES, HCONTENT_BASE_VIEW, DATA, _l ){
/* global Backbone */
//==============================================================================
+var _super = HCONTENT_BASE_VIEW.HistoryContentBaseView;
/** @class Read only view for HistoryDatasetAssociation.
* @name HDABaseView
*
@@ -14,11 +15,11 @@
* @borrows LoggableMixin#log as #log
* @constructs
*/
-var HDABaseView = historyContentBaseView.HistoryContentBaseView.extend(
+var HDABaseView = _super.extend(
/** @lends HDABaseView.prototype */{
- ///** logger used to record this.log messages, commonly set to console */
- //// comment this out to suppress log output
+ /** logger used to record this.log messages, commonly set to console */
+ // comment this out to suppress log output
//logger : console,
tagName : "div",
@@ -38,6 +39,8 @@
if( attributes.logger ){ this.logger = this.model.logger = attributes.logger; }
this.log( this + '.initialize:', attributes );
+ _super.prototype.initialize.call( this, attributes );
+
/** list of rendering functions for the default, primary icon-buttons. */
this.defaultPrimaryActionButtonRenderers = [
this._render_showParamsButton
@@ -46,15 +49,6 @@
/** where should pages from links be displayed? (default to new tab/window) */
this.linkTarget = attributes.linkTarget || '_blank';
- /** is the view currently in selection mode? */
- this.selectable = attributes.selectable || false;
- //this.log( '\t selectable:', this.selectable );
- /** is the view currently selected? */
- this.selected = attributes.selected || false;
- //this.log( '\t selected:', this.selected );
- /** is the body of this hda view expanded/not? */
- this.expanded = attributes.expanded || false;
- //this.log( '\t expanded:', this.expanded );
/** is the body of this hda view expanded/not? */
this.draggable = attributes.draggable || false;
//this.log( '\t draggable:', this.draggable );
@@ -86,77 +80,20 @@
// ......................................................................... render main
/** Render this HDA, set up ui.
* @param {Boolean} fade whether or not to fade out/in when re-rendering
- * @fires rendered when rendered
- * @fires rendered:ready when first rendered and NO running HDAs
* @returns {Object} this HDABaseView
*/
render : function( fade ){
//HACK: hover exit doesn't seem to be called on prev. tooltips when RE-rendering - so: no tooltip hide
// handle that here by removing previous view's tooltips
this.$el.find("[title]").tooltip( "destroy" );
-
// re-get web controller urls for functions relating to this hda. (new model data may have changed this)
this.urls = this.model.urls();
- var $newRender = this._buildNewRender();
- this._queueNewRender( $newRender, fade );
- return this;
-
+ return _super.prototype.render.call( this, fade );
},
- _buildNewRender : function(){
- // create a new render using a skeleton template, render title buttons, render body, and set up events, etc.
- var $newRender = $( HDABaseView.templates.skeleton( this.model.toJSON() ) );
- $newRender.find( '.dataset-primary-actions' ).append( this._render_titleButtons() );
- $newRender.children( '.dataset-body' ).replaceWith( this._render_body() );
- this._setUpBehaviors( $newRender );
- //this._renderSelectable( $newRender );
- return $newRender;
- },
-
- _queueNewRender : function( $newRender, fade ) {
- fade = ( fade === undefined )?( true ):( fade );
- var view = this;
-
- // fade the old render out (if desired)
- if( fade ){
- $( view ).queue( function( next ){ this.$el.fadeOut( view.fxSpeed, next ); });
- }
- // empty the old render, update to any new HDA state, swap in the new render contents, handle multi-select
- $( view ).queue( function( next ){
- this.$el.empty()
- .attr( 'class', view.className ).addClass( 'state-' + view.model.get( 'state' ) )
- .append( $newRender.children() );
- if( this.selectable ){ this.showSelector( 0 ); }
- next();
- });
- // fade the new in
- if( fade ){
- $( view ).queue( function( next ){ this.$el.fadeIn( view.fxSpeed, next ); });
- }
- // trigger an event to know we're ready
- $( view ).queue( function( next ){
- this.trigger( 'rendered', view );
- if( this.model.inReadyState() ){
- this.trigger( 'rendered:ready', view );
- }
- if( this.draggable ){ this.draggableOn(); }
- next();
- });
- },
-
- /** set up js behaviors, event handlers for elements within the given container
- * @param {jQuery} $container jq object that contains the elements to process (defaults to this.$el)
- */
- _setUpBehaviors : function( $container ){
- $container = $container || this.$el;
- // set up canned behavior on children (bootstrap, popupmenus, editable_text, etc.)
- make_popup_menus( $container );
- $container.find( '[title]' ).tooltip({ placement : 'bottom' });
- },
-
// ................................................................................ titlebar buttons
- /** Render icon-button group for the common, most easily accessed actions.
+ /** In this override, render the dataset display button
* @returns {jQuery} rendered DOM
*/
_render_titleButtons : function(){
@@ -170,8 +107,8 @@
_render_displayButton : function(){
// don't show display if not viewable or not accessible
// (do show if in error, running)
- if( ( this.model.get( 'state' ) === hdaModel.HistoryDatasetAssociation.STATES.NOT_VIEWABLE )
- || ( this.model.get( 'state' ) === hdaModel.HistoryDatasetAssociation.STATES.DISCARDED )
+ if( ( this.model.get( 'state' ) === STATES.NOT_VIEWABLE )
+ || ( this.model.get( 'state' ) === STATES.DISCARDED )
|| ( !this.model.get( 'accessible' ) ) ){
return null;
}
@@ -187,12 +124,12 @@
displayBtnData.title = _l( 'Cannot display datasets removed from disk' );
// disable if still uploading
- } else if( this.model.get( 'state' ) === hdaModel.HistoryDatasetAssociation.STATES.UPLOAD ){
+ } else if( this.model.get( 'state' ) === STATES.UPLOAD ){
displayBtnData.disabled = true;
displayBtnData.title = _l( 'This dataset must finish uploading before it can be viewed' );
// disable if still new
- } else if( this.model.get( 'state' ) === hdaModel.HistoryDatasetAssociation.STATES.NEW ){
+ } else if( this.model.get( 'state' ) === STATES.NEW ){
displayBtnData.disabled = true;
displayBtnData.title = _l( 'This dataset is not yet viewable' );
@@ -211,9 +148,9 @@
title : "Data Viewer: " + self.model.get( 'name' ),
type : "other",
content : function( parent_elt ){
- var new_dataset = new dataset.TabularDataset({ id: self.model.get( 'id' ) });
+ var new_dataset = new DATA.TabularDataset({ id: self.model.get( 'id' ) });
$.when( new_dataset.fetch() ).then( function(){
- dataset.createTabularDatasetChunkedView({
+ DATA.createTabularDatasetChunkedView({
model: new_dataset,
parent_elt: parent_elt,
embedded: true,
@@ -298,7 +235,7 @@
/** Render the enclosing div of the hda body and, if expanded, the html in the body
* @returns {jQuery} rendered DOM
*/
- _render_body : function(){
+ _renderBody : function(){
var $body = $( '<div>Error: unknown dataset state "' + this.model.get( 'state' ) + '".</div>' ),
// cheesy: get function by assumed matching name
renderFn = this[ '_render_body_' + this.model.get( 'state' ) ];
@@ -437,61 +374,23 @@
// ......................................................................... events
/** event map */
- events : {
- // expand the body when the title is clicked or when in focus and space or enter is pressed
- 'click .dataset-title-bar' : 'toggleBodyVisibility',
- 'keydown .dataset-title-bar' : 'toggleBodyVisibility',
+ events : _.extend( _.clone( _super.prototype.events ), {
+ }),
- // dragging - don't work, originalEvent === null
- //'dragstart .dataset-title-bar' : 'dragStartHandler',
- //'dragend .dataset-title-bar' : 'dragEndHandler'
-
- // toggle selected state
- 'click .dataset-selector' : 'toggleSelect'
- },
-
- /** Show or hide the body/details of history content.
- * note: if the model does not have detailed data, fetch that data before showing the body
- * @param {Event} event the event that triggered this (@link HDABaseView#events)
- * @param {Boolean} expanded if true, expand; if false, collapse
- * @fires body-expanded when a body has been expanded
- * @fires body-collapsed when a body has been collapsed
+ /** Override for expanding hda details (within the panel)
+ * note: in this override, the fetch for details does *not* fire a change event (silent == true)
+ * @fires expanded when a body has been expanded
*/
- toggleBodyVisibility : function( event, expand ){
- // bail (with propagation) if keydown and not space or enter
- var KEYCODE_SPACE = 32, KEYCODE_RETURN = 13;
- if( event && ( event.type === 'keydown' )
- && !( event.keyCode === KEYCODE_SPACE || event.keyCode === KEYCODE_RETURN ) ){
- return true;
- }
-
- var $body = this.$el.find( '.dataset-body' );
- expand = ( expand === undefined )?( !$body.is( ':visible' ) ):( expand );
- if( expand ){
- this.expandBody();
- } else {
- this.collapseBody();
- }
- return false;
- },
-
- /** Render and show the full, detailed body of this view including extra data and controls.
- * @fires body-expanded when a body has been expanded
- */
- expandBody : function(){
+ expand : function(){
var hdaView = this;
function _renderBodyAndExpand(){
- hdaView.$el.children( '.dataset-body' ).replaceWith( hdaView._render_body() );
+ hdaView.$el.children( '.dataset-body' ).replaceWith( hdaView._renderBody() );
+ //NOTE: needs to be set after the above or the slide will not show
+ hdaView.expanded = true;
hdaView.$el.children( '.dataset-body' ).slideDown( hdaView.fxSpeed, function(){
- hdaView.expanded = true;
- hdaView.trigger( 'body-expanded', hdaView.model );
+ hdaView.trigger( 'expanded', hdaView.model );
});
-
- //hdaView.render( false ).$el.children( '.dataset-body' ).slideDown( hdaView.fxSpeed, function(){
- // hdaView.expanded = true;
- // hdaView.trigger( 'body-expanded', hdaView.model.get( 'id' ) );
- //});
}
// fetch first if no details in the model
if( this.model.inReadyState() && !this.model.hasDetails() ){
@@ -505,128 +404,6 @@
}
},
- /** Hide the body/details of an HDA.
- * @fires body-collapsed when a body has been collapsed
- */
- collapseBody : function(){
- var hdaView = this;
- this.$el.children( '.dataset-body' ).slideUp( hdaView.fxSpeed, function(){
- hdaView.expanded = false;
- hdaView.trigger( 'body-collapsed', hdaView.model.id );
- });
- },
-
- // ......................................................................... selection
- /** display a (fa-icon) checkbox on the left of the hda that fires events when checked
- * Note: this also hides the primary actions
- */
- showSelector : function(){
- // make sure selected state is represented properly
- if( this.selected ){
- this.select( null, true );
- }
-
- this.selectable = true;
- this.trigger( 'selectable', true, this );
-
- this.$( '.dataset-primary-actions' ).hide();
- this.$( '.dataset-selector' ).show();
- },
-
- /** remove the selection checkbox */
- hideSelector : function(){
- // reverse the process from showSelect
- this.selectable = false;
- this.trigger( 'selectable', false, this );
-
- this.$( '.dataset-selector' ).hide();
- this.$( '.dataset-primary-actions' ).show();
- },
-
- toggleSelector : function(){
- if( !this.$el.find( '.dataset-selector' ).is( ':visible' ) ){
- this.showSelector();
- } else {
- this.hideSelector();
- }
- },
-
- /** event handler for selection (also programmatic selection)
- */
- select : function( event ){
- // switch icon, set selected, and trigger event
- this.$el.find( '.dataset-selector span' )
- .removeClass( 'fa-square-o' ).addClass( 'fa-check-square-o' );
- if( !this.selected ){
- this.trigger( 'selected', this, event );
- this.selected = true;
- }
- return false;
- },
-
- /** event handler for clearing selection (also programmatic deselection)
- */
- deselect : function( event ){
- // switch icon, set selected, and trigger event
- this.$el.find( '.dataset-selector span' )
- .removeClass( 'fa-check-square-o' ).addClass( 'fa-square-o' );
- if( this.selected ){
- this.trigger( 'de-selected', this, event );
- this.selected = false;
- }
- return false;
- },
-
- toggleSelect : function( event ){
- if( this.selected ){
- this.deselect( event );
- } else {
- this.select( event );
- }
- },
-
- // ......................................................................... drag/drop
- draggableOn : function(){
- this.draggable = true;
- //TODO: I have no idea why this doesn't work with the events hash or jq.on()...
- //this.$el.find( '.dataset-title-bar' )
- // .attr( 'draggable', true )
- // .bind( 'dragstart', this.dragStartHandler, false )
- // .bind( 'dragend', this.dragEndHandler, false );
- this.dragStartHandler = _.bind( this._dragStartHandler, this );
- this.dragEndHandler = _.bind( this._dragEndHandler, this );
-
- var titleBar = this.$el.find( '.dataset-title-bar' ).attr( 'draggable', true ).get(0);
- titleBar.addEventListener( 'dragstart', this.dragStartHandler, false );
- titleBar.addEventListener( 'dragend', this.dragEndHandler, false );
- },
- draggableOff : function(){
- this.draggable = false;
- var titleBar = this.$el.find( '.dataset-title-bar' ).attr( 'draggable', false ).get(0);
- titleBar.removeEventListener( 'dragstart', this.dragStartHandler, false );
- titleBar.removeEventListener( 'dragend', this.dragEndHandler, false );
- },
- toggleDraggable : function(){
- if( this.draggable ){
- this.draggableOff();
- } else {
- this.draggableOn();
- }
- },
- _dragStartHandler : function( event ){
- //console.debug( 'dragStartHandler:', this, event, arguments )
- this.trigger( 'dragstart', this );
- event.dataTransfer.effectAllowed = 'move';
- //TODO: all except IE: should be 'application/json', IE: must be 'text'
- event.dataTransfer.setData( 'text', JSON.stringify( this.model.toJSON() ) );
- return false;
- },
- _dragEndHandler : function( event ){
- this.trigger( 'dragend', this );
- //console.debug( 'dragEndHandler:', event )
- return false;
- },
-
// ......................................................................... removal
/** Remove this view's html from the DOM and remove all event listeners.
* @param {Function} callback an optional function called when removal is done
@@ -799,7 +576,7 @@
'</div>'
].join( '' ));
-HDABaseView.templates = {
+HDABaseView.templates = HDABaseView.prototype.templates = {
// we override here in order to pass the localizer (_L) into the template scope - since we use it as a fn within
skeleton : function( hdaJSON ){
return skeletonTemplate({ _l: _l, hda: hdaJSON });
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: greg: Add a CustomDatatypeLoader for Galaxy installs, eliminate the use of the tool shed's datatyps_util module.
by commits-noreply@bitbucket.org 23 Jul '14
by commits-noreply@bitbucket.org 23 Jul '14
23 Jul '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/74d7ff952ec9/
Changeset: 74d7ff952ec9
User: greg
Date: 2014-07-23 17:26:49
Summary: Add a CustomDatatypeLoader for Galaxy installs, eliminate the use of the tool shed's datatyps_util module.
Affected #: 7 files
diff -r 053943b668af334c480b464fe7351b50284b7099 -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 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
@@ -12,7 +12,6 @@
import tool_shed.repository_types.util as rt_util
from tool_shed.util import common_util
-from tool_shed.util import datatype_util
from tool_shed.util import encoding_util
from tool_shed.util import hg_util
from tool_shed.util import readme_util
@@ -25,6 +24,7 @@
from tool_shed.galaxy_install import dependency_display
from tool_shed.galaxy_install import install_manager
+from tool_shed.galaxy_install.datatypes import custom_datatype_manager
from tool_shed.galaxy_install.grids import admin_toolshed_grids
from tool_shed.galaxy_install.metadata.installed_repository_metadata_manager import InstalledRepositoryMetadataManager
from tool_shed.galaxy_install.repair_repository_manager import RepairRepositoryManager
@@ -256,17 +256,17 @@
dmh.remove_from_data_manager( tool_shed_repository )
if tool_shed_repository.includes_datatypes:
# Deactivate proprietary datatypes.
- installed_repository_dict = datatype_util.load_installed_datatypes( trans.app,
- tool_shed_repository,
- repository_install_dir,
- deactivate=True )
+ cdl = custom_datatype_manager.CustomDatatypeLoader( trans.app )
+ installed_repository_dict = cdl.load_installed_datatypes( tool_shed_repository,
+ repository_install_dir,
+ deactivate=True )
if installed_repository_dict:
converter_path = installed_repository_dict.get( 'converter_path' )
if converter_path is not None:
- datatype_util.load_installed_datatype_converters( trans.app, installed_repository_dict, deactivate=True )
+ cdl.load_installed_datatype_converters( installed_repository_dict, deactivate=True )
display_path = installed_repository_dict.get( 'display_path' )
if display_path is not None:
- datatype_util.load_installed_display_applications( trans.app, installed_repository_dict, deactivate=True )
+ cdl.load_installed_display_applications( installed_repository_dict, deactivate=True )
if remove_from_disk_checked:
try:
# Remove the repository from disk.
diff -r 053943b668af334c480b464fe7351b50284b7099 -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 lib/tool_shed/galaxy_install/datatypes/custom_datatype_manager.py
--- /dev/null
+++ b/lib/tool_shed/galaxy_install/datatypes/custom_datatype_manager.py
@@ -0,0 +1,218 @@
+import logging
+import os
+import tempfile
+
+from galaxy.util import asbool
+
+from tool_shed.util import basic_util
+from tool_shed.util import hg_util
+from tool_shed.util import tool_util
+from tool_shed.util import shed_util_common as suc
+from tool_shed.util import xml_util
+
+log = logging.getLogger( __name__ )
+
+
+class CustomDatatypeLoader( object ):
+
+ def __init__( self, app ):
+ self.app = app
+
+ def alter_config_and_load_prorietary_datatypes( self, datatypes_config, relative_install_dir,
+ deactivate=False, override=True ):
+ """
+ Parse a custom datatypes config (a datatypes_conf.xml file included in an installed
+ tool shed repository) and add information to appropriate element attributes that will
+ enable custom datatype class modules, datatypes converters and display applications
+ to be discovered and properly imported by the datatypes registry. The value of override
+ will be False when a tool shed repository is being installed. Since installation is
+ occurring after the datatypes registry has been initialized, the registry's contents
+ cannot be overridden by conflicting data types.
+ """
+ tree, error_message = xml_util.parse_xml( datatypes_config )
+ if tree is None:
+ return None, None
+ datatypes_config_root = tree.getroot()
+ registration = datatypes_config_root.find( 'registration' )
+ if registration is None:
+ # We have valid XML, but not a valid custom datatypes definition.
+ return None, None
+ sniffers = datatypes_config_root.find( 'sniffers' )
+ converter_path, display_path = self.get_converter_and_display_paths( registration,
+ relative_install_dir )
+ if converter_path:
+ # Path to datatype converters
+ registration.attrib[ 'proprietary_converter_path' ] = converter_path
+ if display_path:
+ # Path to datatype display applications
+ registration.attrib[ 'proprietary_display_path' ] = display_path
+ relative_path_to_datatype_file_name = None
+ datatype_files = datatypes_config_root.find( 'datatype_files' )
+ datatype_class_modules = []
+ if datatype_files is not None:
+ # The <datatype_files> tag set contains any number of <datatype_file> tags.
+ # <datatype_files>
+ # <datatype_file name="gmap.py"/>
+ # <datatype_file name="metagenomics.py"/>
+ # </datatype_files>
+ # We'll add attributes to the datatype tag sets so that the modules can be properly imported
+ # by the datatypes registry.
+ for elem in datatype_files.findall( 'datatype_file' ):
+ datatype_file_name = elem.get( 'name', None )
+ if datatype_file_name:
+ # Find the file in the installed repository.
+ for root, dirs, files in os.walk( relative_install_dir ):
+ if root.find( '.hg' ) < 0:
+ for name in files:
+ if name == datatype_file_name:
+ datatype_class_modules.append( os.path.join( root, name ) )
+ break
+ break
+ if datatype_class_modules:
+ for relative_path_to_datatype_file_name in datatype_class_modules:
+ datatype_file_name_path, datatype_file_name = os.path.split( relative_path_to_datatype_file_name )
+ for elem in registration.findall( 'datatype' ):
+ # Handle 'type' attribute which should be something like one of the following:
+ # type="gmap:GmapDB"
+ # type="galaxy.datatypes.gmap:GmapDB"
+ dtype = elem.get( 'type', None )
+ if dtype:
+ fields = dtype.split( ':' )
+ proprietary_datatype_module = fields[ 0 ]
+ if proprietary_datatype_module.find( '.' ) >= 0:
+ # Handle the case where datatype_module is "galaxy.datatypes.gmap".
+ proprietary_datatype_module = proprietary_datatype_module.split( '.' )[ -1 ]
+ # The value of proprietary_path must be an absolute path due to job_working_directory.
+ elem.attrib[ 'proprietary_path' ] = os.path.abspath( datatype_file_name_path )
+ elem.attrib[ 'proprietary_datatype_module' ] = proprietary_datatype_module
+ # Temporarily persist the custom datatypes configuration file so it can be loaded into the
+ # datatypes registry.
+ fd, proprietary_datatypes_config = tempfile.mkstemp( prefix="tmp-toolshed-acalpd" )
+ os.write( fd, '<?xml version="1.0"?>\n' )
+ os.write( fd, '<datatypes>\n' )
+ os.write( fd, '%s' % xml_util.xml_to_string( registration ) )
+ if sniffers is not None:
+ os.write( fd, '%s' % xml_util.xml_to_string( sniffers ) )
+ os.write( fd, '</datatypes>\n' )
+ os.close( fd )
+ os.chmod( proprietary_datatypes_config, 0644 )
+ # Load custom datatypes
+ self.app.datatypes_registry.load_datatypes( root_dir=self.app.config.root,
+ config=proprietary_datatypes_config,
+ deactivate=deactivate,
+ override=override )
+ if deactivate:
+ # Reload the upload tool to eliminate deactivated datatype extensions from the file_type
+ # select list.
+ tool_util.reload_upload_tools( self.app )
+ else:
+ self.append_to_datatypes_registry_upload_file_formats( registration )
+ tool_util.reload_upload_tools( self.app )
+ if datatype_files is not None:
+ try:
+ os.unlink( proprietary_datatypes_config )
+ except:
+ pass
+ return converter_path, display_path
+
+ def append_to_datatypes_registry_upload_file_formats( self, elem ):
+ # See if we have any datatypes that should be displayed in the upload tool's file_type select list.
+ for datatype_elem in elem.findall( 'datatype' ):
+ extension = datatype_elem.get( 'extension', None )
+ display_in_upload = datatype_elem.get( 'display_in_upload', None )
+ if extension is not None and display_in_upload is not None:
+ display_in_upload = asbool( str( display_in_upload ) )
+ if display_in_upload and extension not in self.app.datatypes_registry.upload_file_formats:
+ self.app.datatypes_registry.upload_file_formats.append( extension )
+
+ def create_repository_dict_for_proprietary_datatypes( self, tool_shed, name, owner, installed_changeset_revision,
+ tool_dicts, converter_path=None, display_path=None ):
+ return dict( tool_shed=tool_shed,
+ repository_name=name,
+ repository_owner=owner,
+ installed_changeset_revision=installed_changeset_revision,
+ tool_dicts=tool_dicts,
+ converter_path=converter_path,
+ display_path=display_path )
+
+ def get_converter_and_display_paths( self, registration_elem, relative_install_dir ):
+ """
+ Find the relative path to data type converters and display applications included
+ in installed tool shed repositories.
+ """
+ converter_path = None
+ display_path = None
+ for elem in registration_elem.findall( 'datatype' ):
+ if not converter_path:
+ # If any of the <datatype> tag sets contain <converter> tags, set the converter_path
+ # if it is not already set. This requires developers to place all converters in the
+ # same subdirectory within the repository hierarchy.
+ for converter in elem.findall( 'converter' ):
+ converter_config = converter.get( 'file', None )
+ if converter_config:
+ converter_config_file_name = basic_util.strip_path( converter_config )
+ for root, dirs, files in os.walk( relative_install_dir ):
+ if root.find( '.hg' ) < 0:
+ for name in files:
+ if name == converter_config_file_name:
+ # The value of converter_path must be absolute due to job_working_directory.
+ converter_path = os.path.abspath( root )
+ break
+ if converter_path:
+ break
+ if not display_path:
+ # If any of the <datatype> tag sets contain <display> tags, set the display_path
+ # if it is not already set. This requires developers to place all display acpplications
+ # in the same subdirectory within the repository hierarchy.
+ for display_app in elem.findall( 'display' ):
+ display_config = display_app.get( 'file', None )
+ if display_config:
+ display_config_file_name = basic_util.strip_path( display_config )
+ for root, dirs, files in os.walk( relative_install_dir ):
+ if root.find( '.hg' ) < 0:
+ for name in files:
+ if name == display_config_file_name:
+ # The value of display_path must be absolute due to job_working_directory.
+ display_path = os.path.abspath( root )
+ break
+ if display_path:
+ break
+ if converter_path and display_path:
+ break
+ return converter_path, display_path
+
+ def load_installed_datatype_converters( self, installed_repository_dict, deactivate=False ):
+ """Load or deactivate proprietary datatype converters."""
+ self.app.datatypes_registry.load_datatype_converters( self.app.toolbox,
+ installed_repository_dict=installed_repository_dict,
+ deactivate=deactivate )
+
+ def load_installed_datatypes( self, repository, relative_install_dir, deactivate=False ):
+ """
+ Load proprietary datatypes and return information needed for loading custom
+ datatypes converters and display applications later.
+ """
+ metadata = repository.metadata
+ repository_dict = None
+ datatypes_config = hg_util.get_config_from_disk( suc.DATATYPES_CONFIG_FILENAME, relative_install_dir )
+ if datatypes_config:
+ converter_path, display_path = \
+ self.alter_config_and_load_prorietary_datatypes( datatypes_config,
+ relative_install_dir,
+ deactivate=deactivate )
+ if converter_path or display_path:
+ # Create a dictionary of tool shed repository related information.
+ repository_dict = \
+ self.create_repository_dict_for_proprietary_datatypes( tool_shed=repository.tool_shed,
+ name=repository.name,
+ owner=repository.owner,
+ installed_changeset_revision=repository.installed_changeset_revision,
+ tool_dicts=metadata.get( 'tools', [] ),
+ converter_path=converter_path,
+ display_path=display_path )
+ return repository_dict
+
+ def load_installed_display_applications( self, installed_repository_dict, deactivate=False ):
+ """Load or deactivate custom datatype display applications."""
+ self.app.datatypes_registry.load_display_applications( installed_repository_dict=installed_repository_dict,
+ deactivate=deactivate )
diff -r 053943b668af334c480b464fe7351b50284b7099 -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 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
@@ -18,7 +18,6 @@
from tool_shed.util import basic_util
from tool_shed.util import common_util
-from tool_shed.util import datatype_util
from tool_shed.util import encoding_util
from tool_shed.util import hg_util
from tool_shed.util import shed_util_common as suc
@@ -26,6 +25,7 @@
from tool_shed.util import tool_util
from tool_shed.util import xml_util
+from tool_shed.galaxy_install.datatypes import custom_datatype_manager
from tool_shed.galaxy_install.metadata.installed_repository_metadata_manager import InstalledRepositoryMetadataManager
from tool_shed.galaxy_install.repository_dependencies import repository_dependency_manager
from tool_shed.galaxy_install.tool_dependencies.recipe.env_file_builder import EnvFileBuilder
@@ -594,18 +594,19 @@
files_dir = os.path.join( shed_config_dict[ 'tool_path' ], files_dir )
datatypes_config = hg_util.get_config_from_disk( suc.DATATYPES_CONFIG_FILENAME, files_dir )
# Load data types required by tools.
+ cdl = custom_datatype_manager.CustomDatatypeLoader( self.app )
converter_path, display_path = \
- datatype_util.alter_config_and_load_prorietary_datatypes( self.app, datatypes_config, files_dir, override=False )
+ cdl.alter_config_and_load_prorietary_datatypes( datatypes_config, files_dir, override=False )
if converter_path or display_path:
# Create a dictionary of tool shed repository related information.
repository_dict = \
- datatype_util.create_repository_dict_for_proprietary_datatypes( tool_shed=tool_shed,
- name=tool_shed_repository.name,
- owner=tool_shed_repository.owner,
- installed_changeset_revision=tool_shed_repository.installed_changeset_revision,
- tool_dicts=metadata_dict.get( 'tools', [] ),
- converter_path=converter_path,
- display_path=display_path )
+ cdl.create_repository_dict_for_proprietary_datatypes( tool_shed=tool_shed,
+ name=tool_shed_repository.name,
+ owner=tool_shed_repository.owner,
+ installed_changeset_revision=tool_shed_repository.installed_changeset_revision,
+ tool_dicts=metadata_dict.get( 'tools', [] ),
+ converter_path=converter_path,
+ display_path=display_path )
if converter_path:
# Load proprietary datatype converters
self.app.datatypes_registry.load_datatype_converters( self.app.toolbox, installed_repository_dict=repository_dict )
diff -r 053943b668af334c480b464fe7351b50284b7099 -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 lib/tool_shed/galaxy_install/installed_repository_manager.py
--- a/lib/tool_shed/galaxy_install/installed_repository_manager.py
+++ b/lib/tool_shed/galaxy_install/installed_repository_manager.py
@@ -7,12 +7,12 @@
from galaxy import util
from tool_shed.util import common_util
from tool_shed.util import container_util
-from tool_shed.util import datatype_util
from tool_shed.util import shed_util_common as suc
from tool_shed.util import tool_dependency_util
from tool_shed.util import xml_util
from galaxy.model.orm import and_
+from tool_shed.galaxy_install.datatypes import custom_datatype_manager
from tool_shed.galaxy_install.metadata.installed_repository_metadata_manager import InstalledRepositoryMetadataManager
from tool_shed.galaxy_install.repository_dependencies import repository_dependency_manager
from tool_shed.galaxy_install.tools import data_manager
@@ -114,17 +114,17 @@
else:
repository_install_dir = os.path.abspath( relative_install_dir )
# Activate proprietary datatypes.
- installed_repository_dict = datatype_util.load_installed_datatypes( self.app,
- repository,
- repository_install_dir,
- deactivate=False )
+ cdl = custom_datatype_manager.CustomDatatypeLoader( self.app )
+ installed_repository_dict = cdl.load_installed_datatypes( repository,
+ repository_install_dir,
+ deactivate=False )
if installed_repository_dict:
converter_path = installed_repository_dict.get( 'converter_path' )
if converter_path is not None:
- datatype_util.load_installed_datatype_converters( self.app, installed_repository_dict, deactivate=False )
+ cdl.load_installed_datatype_converters( installed_repository_dict, deactivate=False )
display_path = installed_repository_dict.get( 'display_path' )
if display_path is not None:
- datatype_util.load_installed_display_applications( self.app, installed_repository_dict, deactivate=False )
+ cdl.load_installed_display_applications( installed_repository_dict, deactivate=False )
def add_entry_to_installed_repository_dependencies_of_installed_repositories( self, repository ):
"""
@@ -732,22 +732,24 @@
self.add_entry_to_installed_runtime_dependent_tool_dependencies_of_installed_tool_dependencies( tool_dependency )
def load_proprietary_datatypes( self ):
+ cdl = custom_datatype_manager.CustomDatatypeLoader( self.app )
for tool_shed_repository in self.context.query( self.install_model.ToolShedRepository ) \
- .filter( and_( self.install_model.ToolShedRepository.table.c.includes_datatypes==True,
- self.install_model.ToolShedRepository.table.c.deleted==False ) ) \
- .order_by( self.install_model.ToolShedRepository.table.c.id ):
+ .filter( and_( self.install_model.ToolShedRepository.table.c.includes_datatypes==True,
+ self.install_model.ToolShedRepository.table.c.deleted==False ) ) \
+ .order_by( self.install_model.ToolShedRepository.table.c.id ):
relative_install_dir = self.get_repository_install_dir( tool_shed_repository )
if relative_install_dir:
- installed_repository_dict = datatype_util.load_installed_datatypes( self.app, tool_shed_repository, relative_install_dir )
+ installed_repository_dict = cdl.load_installed_datatypes( tool_shed_repository, relative_install_dir )
if installed_repository_dict:
self.installed_repository_dicts.append( installed_repository_dict )
def load_proprietary_converters_and_display_applications( self, deactivate=False ):
+ cdl = custom_datatype_manager.CustomDatatypeLoader( self.app )
for installed_repository_dict in self.installed_repository_dicts:
if installed_repository_dict[ 'converter_path' ]:
- datatype_util.load_installed_datatype_converters( self.app, installed_repository_dict, deactivate=deactivate )
+ cdl.load_installed_datatype_converters( installed_repository_dict, deactivate=deactivate )
if installed_repository_dict[ 'display_path' ]:
- datatype_util.load_installed_display_applications( self.app, installed_repository_dict, deactivate=deactivate )
+ cdl.load_installed_display_applications( installed_repository_dict, deactivate=deactivate )
def purge_repository( self, repository ):
"""Purge a repository with status New (a white ghost) from the database."""
diff -r 053943b668af334c480b464fe7351b50284b7099 -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 lib/tool_shed/galaxy_install/tool_migration_manager.py
--- a/lib/tool_shed/galaxy_install/tool_migration_manager.py
+++ b/lib/tool_shed/galaxy_install/tool_migration_manager.py
@@ -14,6 +14,7 @@
from galaxy.util.odict import odict
from tool_shed.galaxy_install import install_manager
+from tool_shed.galaxy_install.datatypes import custom_datatype_manager
from tool_shed.galaxy_install.metadata.installed_repository_metadata_manager import InstalledRepositoryMetadataManager
from tool_shed.galaxy_install.tools import tool_panel_manager
@@ -22,7 +23,6 @@
from tool_shed.util import basic_util
from tool_shed.util import common_util
-from tool_shed.util import datatype_util
from tool_shed.util import hg_util
from tool_shed.util import shed_util_common as suc
from tool_shed.util import tool_dependency_util
@@ -492,6 +492,7 @@
print '\nThe ToolMigrationManager returned the following error while installing tool dependency ', installed_tool_dependency.name, ':'
print installed_tool_dependency.error_message, '\n\n'
if 'datatypes' in metadata_dict:
+ cdl = custom_datatype_manager.CustomDatatypeLoader( self.app )
tool_shed_repository.status = self.app.install_model.ToolShedRepository.installation_status.LOADING_PROPRIETARY_DATATYPES
if not tool_shed_repository.includes_datatypes:
tool_shed_repository.includes_datatypes = True
@@ -499,21 +500,27 @@
self.app.install_model.context.flush()
work_dir = tempfile.mkdtemp( prefix="tmp-toolshed-hrc" )
datatypes_config = hg_util.get_config_from_disk( suc.DATATYPES_CONFIG_FILENAME, repo_install_dir )
- # Load proprietary data types required by tools. The value of override is not important here since the Galaxy server will be started
- # after this installation completes.
- converter_path, display_path = datatype_util.alter_config_and_load_prorietary_datatypes( self.app, datatypes_config, repo_install_dir, override=False ) #repo_install_dir was relative_install_dir
+ # Load proprietary data types required by tools. The value of override is not
+ # important here since the Galaxy server will be started after this installation
+ #completes.
+ converter_path, display_path = \
+ cdl.alter_config_and_load_prorietary_datatypes( datatypes_config,
+ repo_install_dir,
+ override=False )
if converter_path or display_path:
# Create a dictionary of tool shed repository related information.
- repository_dict = datatype_util.create_repository_dict_for_proprietary_datatypes( tool_shed=self.tool_shed_url,
- name=tool_shed_repository.name,
- owner=self.repository_owner,
- installed_changeset_revision=tool_shed_repository.installed_changeset_revision,
- tool_dicts=metadata_dict.get( 'tools', [] ),
- converter_path=converter_path,
- display_path=display_path )
+ repository_dict = \
+ cdl.create_repository_dict_for_proprietary_datatypes( tool_shed=self.tool_shed_url,
+ name=tool_shed_repository.name,
+ owner=self.repository_owner,
+ installed_changeset_revision=tool_shed_repository.installed_changeset_revision,
+ tool_dicts=metadata_dict.get( 'tools', [] ),
+ converter_path=converter_path,
+ display_path=display_path )
if converter_path:
# Load proprietary datatype converters
- self.app.datatypes_registry.load_datatype_converters( self.toolbox, installed_repository_dict=repository_dict )
+ self.app.datatypes_registry.load_datatype_converters( self.toolbox,
+ installed_repository_dict=repository_dict )
if display_path:
# Load proprietary datatype display applications
self.app.datatypes_registry.load_display_applications( installed_repository_dict=repository_dict )
diff -r 053943b668af334c480b464fe7351b50284b7099 -r 74d7ff952ec902e68cc99745fdcd3c14e86208b2 lib/tool_shed/util/datatype_util.py
--- a/lib/tool_shed/util/datatype_util.py
+++ /dev/null
@@ -1,187 +0,0 @@
-import logging
-import os
-import tempfile
-from galaxy import eggs
-from galaxy.util import asbool
-from tool_shed.util import basic_util
-from tool_shed.util import hg_util
-from tool_shed.util import tool_util
-from tool_shed.util import xml_util
-import tool_shed.util.shed_util_common as suc
-
-log = logging.getLogger( __name__ )
-
-def alter_config_and_load_prorietary_datatypes( app, datatypes_config, relative_install_dir, deactivate=False, override=True ):
- """
- Parse a proprietary datatypes config (a datatypes_conf.xml file included in an installed tool shed repository) and
- add information to appropriate element attributes that will enable proprietary datatype class modules, datatypes converters
- and display applications to be discovered and properly imported by the datatypes registry. The value of override will
- be False when a tool shed repository is being installed. Since installation is occurring after the datatypes registry
- has been initialized, the registry's contents cannot be overridden by conflicting data types.
- """
- tree, error_message = xml_util.parse_xml( datatypes_config )
- if tree is None:
- return None, None
- datatypes_config_root = tree.getroot()
- registration = datatypes_config_root.find( 'registration' )
- if registration is None:
- # We have valid XML, but not a valid proprietary datatypes definition.
- return None, None
- sniffers = datatypes_config_root.find( 'sniffers' )
- converter_path, display_path = get_converter_and_display_paths( registration, relative_install_dir )
- if converter_path:
- # Path to datatype converters
- registration.attrib[ 'proprietary_converter_path' ] = converter_path
- if display_path:
- # Path to datatype display applications
- registration.attrib[ 'proprietary_display_path' ] = display_path
- relative_path_to_datatype_file_name = None
- datatype_files = datatypes_config_root.find( 'datatype_files' )
- datatype_class_modules = []
- if datatype_files is not None:
- # The <datatype_files> tag set contains any number of <datatype_file> tags.
- # <datatype_files>
- # <datatype_file name="gmap.py"/>
- # <datatype_file name="metagenomics.py"/>
- # </datatype_files>
- # We'll add attributes to the datatype tag sets so that the modules can be properly imported by the datatypes registry.
- for elem in datatype_files.findall( 'datatype_file' ):
- datatype_file_name = elem.get( 'name', None )
- if datatype_file_name:
- # Find the file in the installed repository.
- for root, dirs, files in os.walk( relative_install_dir ):
- if root.find( '.hg' ) < 0:
- for name in files:
- if name == datatype_file_name:
- datatype_class_modules.append( os.path.join( root, name ) )
- break
- break
- if datatype_class_modules:
- for relative_path_to_datatype_file_name in datatype_class_modules:
- datatype_file_name_path, datatype_file_name = os.path.split( relative_path_to_datatype_file_name )
- for elem in registration.findall( 'datatype' ):
- # Handle 'type' attribute which should be something like one of the following:
- # type="gmap:GmapDB"
- # type="galaxy.datatypes.gmap:GmapDB"
- dtype = elem.get( 'type', None )
- if dtype:
- fields = dtype.split( ':' )
- proprietary_datatype_module = fields[ 0 ]
- if proprietary_datatype_module.find( '.' ) >= 0:
- # Handle the case where datatype_module is "galaxy.datatypes.gmap".
- proprietary_datatype_module = proprietary_datatype_module.split( '.' )[ -1 ]
- # The value of proprietary_path must be an absolute path due to job_working_directory.
- elem.attrib[ 'proprietary_path' ] = os.path.abspath( datatype_file_name_path )
- elem.attrib[ 'proprietary_datatype_module' ] = proprietary_datatype_module
- # Temporarily persist the proprietary datatypes configuration file so it can be loaded into the datatypes registry.
- fd, proprietary_datatypes_config = tempfile.mkstemp( prefix="tmp-toolshed-acalpd" )
- os.write( fd, '<?xml version="1.0"?>\n' )
- os.write( fd, '<datatypes>\n' )
- os.write( fd, '%s' % xml_util.xml_to_string( registration ) )
- if sniffers is not None:
- os.write( fd, '%s' % xml_util.xml_to_string( sniffers ) )
- os.write( fd, '</datatypes>\n' )
- os.close( fd )
- os.chmod( proprietary_datatypes_config, 0644 )
- # Load proprietary datatypes
- app.datatypes_registry.load_datatypes( root_dir=app.config.root, config=proprietary_datatypes_config, deactivate=deactivate, override=override )
- if deactivate:
- # Reload the upload tool to eliminate deactivated datatype extensions from the file_type select list.
- tool_util.reload_upload_tools( app )
- else:
- append_to_datatypes_registry_upload_file_formats( app, registration )
- tool_util.reload_upload_tools( app )
- if datatype_files is not None:
- try:
- os.unlink( proprietary_datatypes_config )
- except:
- pass
- return converter_path, display_path
-
-def append_to_datatypes_registry_upload_file_formats( app, elem ):
- # See if we have any datatypes that should be displayed in the upload tool's file_type select list.
- for datatype_elem in elem.findall( 'datatype' ):
- extension = datatype_elem.get( 'extension', None )
- display_in_upload = datatype_elem.get( 'display_in_upload', None )
- if extension is not None and display_in_upload is not None:
- display_in_upload = asbool( str( display_in_upload ) )
- if display_in_upload and extension not in app.datatypes_registry.upload_file_formats:
- app.datatypes_registry.upload_file_formats.append( extension )
-
-def create_repository_dict_for_proprietary_datatypes( tool_shed, name, owner, installed_changeset_revision, tool_dicts, converter_path=None, display_path=None ):
- return dict( tool_shed=tool_shed,
- repository_name=name,
- repository_owner=owner,
- installed_changeset_revision=installed_changeset_revision,
- tool_dicts=tool_dicts,
- converter_path=converter_path,
- display_path=display_path )
-
-def get_converter_and_display_paths( registration_elem, relative_install_dir ):
- """Find the relative path to data type converters and display applications included in installed tool shed repositories."""
- converter_path = None
- display_path = None
- for elem in registration_elem.findall( 'datatype' ):
- if not converter_path:
- # If any of the <datatype> tag sets contain <converter> tags, set the converter_path
- # if it is not already set. This requires developers to place all converters in the
- # same subdirectory within the repository hierarchy.
- for converter in elem.findall( 'converter' ):
- converter_config = converter.get( 'file', None )
- if converter_config:
- converter_config_file_name = basic_util.strip_path( converter_config )
- for root, dirs, files in os.walk( relative_install_dir ):
- if root.find( '.hg' ) < 0:
- for name in files:
- if name == converter_config_file_name:
- # The value of converter_path must be absolute due to job_working_directory.
- converter_path = os.path.abspath( root )
- break
- if converter_path:
- break
- if not display_path:
- # If any of the <datatype> tag sets contain <display> tags, set the display_path
- # if it is not already set. This requires developers to place all display acpplications
- # in the same subdirectory within the repository hierarchy.
- for display_app in elem.findall( 'display' ):
- display_config = display_app.get( 'file', None )
- if display_config:
- display_config_file_name = basic_util.strip_path( display_config )
- for root, dirs, files in os.walk( relative_install_dir ):
- if root.find( '.hg' ) < 0:
- for name in files:
- if name == display_config_file_name:
- # The value of display_path must be absolute due to job_working_directory.
- display_path = os.path.abspath( root )
- break
- if display_path:
- break
- if converter_path and display_path:
- break
- return converter_path, display_path
-
-def load_installed_datatype_converters( app, installed_repository_dict, deactivate=False ):
- # Load or deactivate proprietary datatype converters
- app.datatypes_registry.load_datatype_converters( app.toolbox, installed_repository_dict=installed_repository_dict, deactivate=deactivate )
-
-def load_installed_datatypes( app, repository, relative_install_dir, deactivate=False ):
- # Load proprietary datatypes and return information needed for loading proprietary datatypes converters and display applications later.
- metadata = repository.metadata
- repository_dict = None
- datatypes_config = hg_util.get_config_from_disk( suc.DATATYPES_CONFIG_FILENAME, relative_install_dir )
- if datatypes_config:
- converter_path, display_path = alter_config_and_load_prorietary_datatypes( app, datatypes_config, relative_install_dir, deactivate=deactivate )
- if converter_path or display_path:
- # Create a dictionary of tool shed repository related information.
- repository_dict = create_repository_dict_for_proprietary_datatypes( tool_shed=repository.tool_shed,
- name=repository.name,
- owner=repository.owner,
- installed_changeset_revision=repository.installed_changeset_revision,
- tool_dicts=metadata.get( 'tools', [] ),
- converter_path=converter_path,
- display_path=display_path )
- return repository_dict
-
-def load_installed_display_applications( app, installed_repository_dict, deactivate=False ):
- # Load or deactivate proprietary datatype display applications
- app.datatypes_registry.load_display_applications( installed_repository_dict=installed_repository_dict, deactivate=deactivate )
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: More standardized (if still terse) exception handling in AuthenticationController.
by commits-noreply@bitbucket.org 23 Jul '14
by commits-noreply@bitbucket.org 23 Jul '14
23 Jul '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/053943b668af/
Changeset: 053943b668af
User: jmchilton
Date: 2014-07-23 16:16:08
Summary: More standardized (if still terse) exception handling in AuthenticationController.
Affected #: 3 files
diff -r f24d7ac8ee9549fc19435aa1448854e9024982ff -r 053943b668af334c480b464fe7351b50284b7099 lib/galaxy/exceptions/__init__.py
--- a/lib/galaxy/exceptions/__init__.py
+++ b/lib/galaxy/exceptions/__init__.py
@@ -86,6 +86,11 @@
err_code = error_codes.USER_REQUEST_INVALID_PARAMETER
+class AuthenticationFailed( MessageException ):
+ status_code = 401
+ err_code = error_codes.USER_AUTHENTICATION_FAILED
+
+
class AuthenticationRequired( MessageException ):
status_code = 403
#TODO: as 401 and send WWW-Authenticate: ???
diff -r f24d7ac8ee9549fc19435aa1448854e9024982ff -r 053943b668af334c480b464fe7351b50284b7099 lib/galaxy/exceptions/error_codes.json
--- a/lib/galaxy/exceptions/error_codes.json
+++ b/lib/galaxy/exceptions/error_codes.json
@@ -60,6 +60,11 @@
"message": "Supplied incorrect or incompatible tool meta parameters."
},
{
+ "name": "USER_AUTHENTICATION_FAILED",
+ "code": 401001,
+ "message": "Authentication failed, invalid credentials supplied."
+ },
+ {
"name": "USER_NO_API_KEY",
"code": 403001,
"message": "API authentication required for this request"
diff -r f24d7ac8ee9549fc19435aa1448854e9024982ff -r 053943b668af334c480b464fe7351b50284b7099 lib/galaxy/webapps/galaxy/api/authenticate.py
--- a/lib/galaxy/webapps/galaxy/api/authenticate.py
+++ b/lib/galaxy/webapps/galaxy/api/authenticate.py
@@ -12,11 +12,10 @@
"""
from base64 import b64decode
-from paste.httpexceptions import HTTPBadRequest
from urllib import unquote
-from galaxy import web
-from galaxy.exceptions import ObjectNotFound
+from galaxy.web import _future_expose_api_anonymous as expose_api_anonymous
+from galaxy import exceptions
from galaxy.web.base.controller import BaseAPIController, CreatesApiKeysMixin
import logging
@@ -25,7 +24,7 @@
class AuthenticationController( BaseAPIController, CreatesApiKeysMixin ):
- @web.expose_api_anonymous
+ @expose_api_anonymous
def get_api_key( self, trans, **kwd ):
"""
def get_api_key( self, trans, **kwd )
@@ -43,7 +42,7 @@
if ( len( user ) is not 1 ):
# DB is inconsistent and we have more users with same email
- raise ObjectNotFound
+ raise exceptions.ObjectNotFound()
else:
user = user[0]
is_valid_user = user.check_password( password )
@@ -54,8 +53,7 @@
key = self.create_api_key( trans, user )
return dict( api_key=key )
else:
- trans.response.status = 500
- return "invalid password"
+ raise exceptions.AuthenticationFailed()
def _decode_baseauth( self, encoded_str ):
"""
@@ -81,7 +79,7 @@
try:
email, password = b64decode( split[ 0 ] ).split( ':' )
except:
- raise HTTPBadRequest
+ raise exceptions.ActionInputError()
# If there are only two elements, check the first and ensure it says
# 'basic' so that we know we're about to decode the right thing. If not,
@@ -91,13 +89,13 @@
try:
email, password = b64decode( split[ 1 ] ).split( ':' )
except:
- raise HTTPBadRequest
+ raise exceptions.ActionInputError()
else:
- raise HTTPBadRequest
+ raise exceptions.ActionInputError()
# If there are more than 2 elements, something crazy must be happening.
# Bail.
else:
- raise HTTPBadRequest
+ raise exceptions.ActionInputError()
return unquote( email ), unquote( password )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Fixes in exception handlers in the Tool Shed's create_categories and create_users API modules.
by commits-noreply@bitbucket.org 23 Jul '14
by commits-noreply@bitbucket.org 23 Jul '14
23 Jul '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f24d7ac8ee95/
Changeset: f24d7ac8ee95
User: greg
Date: 2014-07-23 15:47:21
Summary: Fixes in exception handlers in the Tool Shed's create_categories and create_users API modules.
Affected #: 2 files
diff -r 0c62ccbc86246c9aebf8ff78c550234dfa6d5bd5 -r f24d7ac8ee9549fc19435aa1448854e9024982ff lib/tool_shed/scripts/api/create_categories.py
--- a/lib/tool_shed/scripts/api/create_categories.py
+++ b/lib/tool_shed/scripts/api/create_categories.py
@@ -44,7 +44,7 @@
response = submit( url, data, api_key )
except Exception, e:
response = str( e )
- log.exception( str( e ) )
+ print "Error attempting to create category using URL: ", url, " exception: ", str( e )
create_response_dict = dict( response=response )
create_response_dicts.append( create_response_dict )
diff -r 0c62ccbc86246c9aebf8ff78c550234dfa6d5bd5 -r f24d7ac8ee9549fc19435aa1448854e9024982ff lib/tool_shed/scripts/api/create_users.py
--- a/lib/tool_shed/scripts/api/create_users.py
+++ b/lib/tool_shed/scripts/api/create_users.py
@@ -47,7 +47,7 @@
response = submit( url, data, api_key )
except Exception, e:
response = str( e )
- log.exception( str( e ) )
+ print "Error attempting to create user using URL: ", url, " exception: ", str( e )
create_response_dict = dict( response=response )
create_response_dicts.append( create_response_dict )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Move some functions out of the Tool Shed's shed_util_common module.
by commits-noreply@bitbucket.org 22 Jul '14
by commits-noreply@bitbucket.org 22 Jul '14
22 Jul '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/0c62ccbc8624/
Changeset: 0c62ccbc8624
User: greg
Date: 2014-07-22 22:46:30
Summary: Move some functions out of the Tool Shed's shed_util_common module.
Affected #: 7 files
diff -r 4ee9e584dbc016727e4c90f73bbf53081f775c5a -r 0c62ccbc86246c9aebf8ff78c550234dfa6d5bd5 lib/tool_shed/capsule/capsule_manager.py
--- a/lib/tool_shed/capsule/capsule_manager.py
+++ b/lib/tool_shed/capsule/capsule_manager.py
@@ -9,6 +9,7 @@
from time import strftime
from galaxy import web
+from galaxy.model.orm import and_
from galaxy.util import asbool
from galaxy.util import CHUNK_SIZE
from galaxy.util.odict import odict
@@ -408,7 +409,7 @@
flush = True
# Do not allow dependent repository revisions to be automatically installed if population
# resulted in errors.
- dependent_downloadable_revisions = suc.get_dependent_downloadable_revisions( self.app, repository_metadata )
+ dependent_downloadable_revisions = self.get_dependent_downloadable_revisions( repository_metadata )
for dependent_downloadable_revision in dependent_downloadable_revisions:
if dependent_downloadable_revision.downloadable:
dependent_downloadable_revision.downloadable = False
@@ -541,6 +542,66 @@
archives.append( archive_file_name )
return archives, error_message
+ def get_dependent_downloadable_revisions( self, repository_metadata ):
+ """
+ Return all repository_metadata records that are downloadable and that depend upon the received
+ repository_metadata record.
+ """
+ # This method is called only from the tool shed.
+ sa_session = self.app.model.context.current
+ rm_changeset_revision = repository_metadata.changeset_revision
+ rm_repository = repository_metadata.repository
+ rm_repository_name = str( rm_repository.name )
+ rm_repository_owner = str( rm_repository.user.username )
+ dependent_downloadable_revisions = []
+ for repository in sa_session.query( self.app.model.Repository ) \
+ .filter( and_( self.app.model.Repository.table.c.id != rm_repository.id,
+ self.app.model.Repository.table.c.deleted == False,
+ self.app.model.Repository.table.c.deprecated == False ) ):
+ downloadable_revisions = repository.downloadable_revisions
+ if downloadable_revisions:
+ for downloadable_revision in downloadable_revisions:
+ if downloadable_revision.has_repository_dependencies:
+ metadata = downloadable_revision.metadata
+ if metadata:
+ repository_dependencies_dict = metadata.get( 'repository_dependencies', {} )
+ repository_dependencies_tups = repository_dependencies_dict.get( 'repository_dependencies', [] )
+ for repository_dependencies_tup in repository_dependencies_tups:
+ tool_shed, \
+ name, \
+ owner, \
+ changeset_revision, \
+ prior_installation_required, \
+ only_if_compiling_contained_td = \
+ common_util.parse_repository_dependency_tuple( repository_dependencies_tup )
+ if name == rm_repository_name and owner == rm_repository_owner:
+ # We've discovered a repository revision that depends upon the repository associated
+ # with the received repository_metadata record, but we need to make sure it depends
+ # upon the revision.
+ if changeset_revision == rm_changeset_revision:
+ dependent_downloadable_revisions.append( downloadable_revision )
+ else:
+ # Make sure the defined changeset_revision is current.
+ defined_repository_metadata = \
+ sa_session.query( self.app.model.RepositoryMetadata ) \
+ .filter( self.app.model.RepositoryMetadata.table.c.changeset_revision == changeset_revision ) \
+ .first()
+ if defined_repository_metadata is None:
+ # The defined changeset_revision is not associated with a repository_metadata
+ # record, so updates must be necessary.
+ defined_repository = suc.get_repository_by_name_and_owner( self.app, name, owner )
+ defined_repo = hg_util.get_repo_for_repository( self.app,
+ repository=defined_repository,
+ repo_path=None,
+ create=False )
+ updated_changeset_revision = \
+ suc.get_next_downloadable_changeset_revision( defined_repository,
+ defined_repo,
+ changeset_revision )
+ if updated_changeset_revision == rm_changeset_revision:
+ dependent_downloadable_revisions.append( downloadable_revision )
+ return dependent_downloadable_revisions
+
def get_export_info_dict( self, export_info_file_path ):
"""
Parse the export_info.xml file contained within the capsule and return a dictionary
diff -r 4ee9e584dbc016727e4c90f73bbf53081f775c5a -r 0c62ccbc86246c9aebf8ff78c550234dfa6d5bd5 lib/tool_shed/galaxy_install/installed_repository_manager.py
--- a/lib/tool_shed/galaxy_install/installed_repository_manager.py
+++ b/lib/tool_shed/galaxy_install/installed_repository_manager.py
@@ -342,8 +342,8 @@
installed_rd_tups = []
missing_rd_tups = []
for tsr in repository.repository_dependencies:
- prior_installation_required = suc.set_prior_installation_required( self.app, repository, tsr )
- only_if_compiling_contained_td = suc.set_only_if_compiling_contained_td( repository, tsr )
+ prior_installation_required = self.set_prior_installation_required( repository, tsr )
+ only_if_compiling_contained_td = self.set_only_if_compiling_contained_td( repository, tsr )
rd_tup = [ tsr.tool_shed,
tsr.name,
tsr.owner,
@@ -957,6 +957,47 @@
return True
return False
+ def set_only_if_compiling_contained_td( self, repository, required_repository ):
+ """
+ Return True if the received required_repository is only needed to compile a tool
+ dependency defined for the received repository.
+ """
+ # This method is called only from Galaxy when rendering repository dependencies
+ # for an installed tool shed repository.
+ # TODO: Do we need to check more than changeset_revision here?
+ required_repository_tup = [ required_repository.tool_shed, \
+ required_repository.name, \
+ required_repository.owner, \
+ required_repository.changeset_revision ]
+ for tup in repository.tuples_of_repository_dependencies_needed_for_compiling_td:
+ partial_tup = tup[ 0:4 ]
+ if partial_tup == required_repository_tup:
+ return 'True'
+ return 'False'
+
+ def set_prior_installation_required( self, repository, required_repository ):
+ """
+ Return True if the received required_repository must be installed before the
+ received repository.
+ """
+ tool_shed_url = common_util.get_tool_shed_url_from_tool_shed_registry( self.app,
+ str( required_repository.tool_shed ) )
+ required_repository_tup = [ tool_shed_url,
+ str( required_repository.name ),
+ str( required_repository.owner ),
+ str( required_repository.changeset_revision ) ]
+ # Get the list of repository dependency tuples associated with the received repository
+ # where prior_installation_required is True.
+ required_rd_tups_that_must_be_installed = repository.requires_prior_installation_of
+ for required_rd_tup in required_rd_tups_that_must_be_installed:
+ # Repository dependency tuples in metadata include a prior_installation_required value,
+ # so strip it for comparision.
+ partial_required_rd_tup = required_rd_tup[ 0:4 ]
+ if partial_required_rd_tup == required_repository_tup:
+ # Return the string value of prior_installation_required, which defaults to 'False'.
+ return str( required_rd_tup[ 4 ] )
+ return 'False'
+
def update_existing_tool_dependency( self, repository, original_dependency_dict, new_dependencies_dict ):
"""
Update an exsiting tool dependency whose definition was updated in a change set
diff -r 4ee9e584dbc016727e4c90f73bbf53081f775c5a -r 0c62ccbc86246c9aebf8ff78c550234dfa6d5bd5 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
@@ -2,9 +2,9 @@
Class encapsulating the management of repository dependencies installed or being installed
into Galaxy from the Tool Shed.
"""
-
import json
import logging
+import os
import urllib
import urllib2
@@ -63,11 +63,10 @@
break
if d_repository is None:
# The dependent repository is not in the received list so look in the database.
- d_repository = suc.get_or_create_tool_shed_repository( self.app,
- d_toolshed,
- d_name,
- d_owner,
- d_changeset_revision )
+ d_repository = self.get_or_create_tool_shed_repository( d_toolshed,
+ d_name,
+ d_owner,
+ d_changeset_revision )
# Process each repository_dependency defined for the current dependent repository.
for repository_dependency_components_list in val:
required_repository = None
@@ -87,11 +86,10 @@
break
if required_repository is None:
# The required repository is not in the received list so look in the database.
- required_repository = suc.get_or_create_tool_shed_repository( self.app,
- rd_toolshed,
- rd_name,
- rd_owner,
- rd_changeset_revision )
+ required_repository = self.get_or_create_tool_shed_repository( rd_toolshed,
+ rd_name,
+ rd_owner,
+ rd_changeset_revision )
# Ensure there is a repository_dependency relationship between d_repository and required_repository.
rrda = None
for rd in d_repository.repository_dependencies:
@@ -257,6 +255,35 @@
self.build_repository_dependency_relationships( all_repo_info_dicts, all_created_or_updated_tool_shed_repositories )
return created_or_updated_tool_shed_repositories, tool_panel_section_keys, all_repo_info_dicts, filtered_repo_info_dicts
+ def get_or_create_tool_shed_repository( self, tool_shed, name, owner, changeset_revision ):
+ """
+ Return a tool shed repository database record defined by the combination of
+ tool shed, repository name, repository owner and changeset_revision or
+ installed_changeset_revision. A new tool shed repository record will be
+ created if one is not located.
+ """
+ install_model = self.app.install_model
+ # We store the port in the database.
+ tool_shed = common_util.remove_protocol_from_tool_shed_url( tool_shed )
+ # This method is used only in Galaxy, not the tool shed.
+ repository = suc.get_repository_for_dependency_relationship( self.app, tool_shed, name, owner, changeset_revision )
+ if not repository:
+ tool_shed_url = common_util.get_tool_shed_url_from_tool_shed_registry( self.app, tool_shed )
+ repository_clone_url = os.path.join( tool_shed_url, 'repos', owner, name )
+ ctx_rev = suc.get_ctx_rev( self.app, tool_shed_url, name, owner, changeset_revision )
+ repository = suc.create_or_update_tool_shed_repository( app=self.app,
+ name=name,
+ description=None,
+ installed_changeset_revision=changeset_revision,
+ ctx_rev=ctx_rev,
+ repository_clone_url=repository_clone_url,
+ metadata_dict={},
+ status=install_model.ToolShedRepository.installation_status.NEW,
+ current_changeset_revision=None,
+ owner=owner,
+ dist_to_shed=False )
+ return repository
+
def get_repository_dependencies_for_installed_tool_shed_repository( self, app, repository ):
"""
Send a request to the appropriate tool shed to retrieve the dictionary of repository dependencies defined
diff -r 4ee9e584dbc016727e4c90f73bbf53081f775c5a -r 0c62ccbc86246c9aebf8ff78c550234dfa6d5bd5 lib/tool_shed/metadata/repository_metadata_manager.py
--- a/lib/tool_shed/metadata/repository_metadata_manager.py
+++ b/lib/tool_shed/metadata/repository_metadata_manager.py
@@ -410,7 +410,7 @@
repo = hg_util.get_repo_for_repository( self.app, repository=repository, repo_path=None, create=False )
for changeset in repo.changelog:
changeset_hash = str( repo.changectx( changeset ) )
- skip_tool_test = suc.get_skip_tool_test_by_changeset_revision( self.app, changeset_hash )
+ skip_tool_test = self.get_skip_tool_test_by_changeset_revision( changeset_hash )
if skip_tool_test:
# We found a skip_tool_test record associated with the changeset_revision,
# so see if it has a valid repository_revision.
@@ -521,6 +521,16 @@
return self.sa_session.query( self.app.model.Repository ) \
.filter( self.app.model.Repository.table.c.deleted == False )
+ def get_skip_tool_test_by_changeset_revision( self, changeset_revision ):
+ """
+ Return a skip_tool_test record whose initial_changeset_revision is the received
+ changeset_revision.
+ """
+ # There should only be one, but we'll use first() so callers won't have to handle exceptions.
+ return self.sa_session.query( self.app.model.SkipToolTest ) \
+ .filter( self.app.model.SkipToolTest.table.c.initial_changeset_revision == changeset_revision ) \
+ .first()
+
def new_datatypes_metadata_required( self, repository_metadata, metadata_dict ):
"""
Compare the last saved metadata for each datatype in the repository with the new metadata
diff -r 4ee9e584dbc016727e4c90f73bbf53081f775c5a -r 0c62ccbc86246c9aebf8ff78c550234dfa6d5bd5 lib/tool_shed/tools/data_table_manager.py
--- a/lib/tool_shed/tools/data_table_manager.py
+++ b/lib/tool_shed/tools/data_table_manager.py
@@ -2,8 +2,9 @@
import os
import shutil
+from xml.etree import ElementTree as XmlET
+
from tool_shed.util import hg_util
-from tool_shed.util import shed_util_common as suc
from tool_shed.util import xml_util
log = logging.getLogger( __name__ )
@@ -14,6 +15,36 @@
def __init__( self, app ):
self.app = app
+ def generate_repository_info_elem( self, tool_shed, repository_name, changeset_revision, owner,
+ parent_elem=None, **kwd ):
+ """Create and return an ElementTree repository info Element."""
+ if parent_elem is None:
+ elem = XmlET.Element( 'tool_shed_repository' )
+ else:
+ elem = XmlET.SubElement( parent_elem, 'tool_shed_repository' )
+ tool_shed_elem = XmlET.SubElement( elem, 'tool_shed' )
+ tool_shed_elem.text = tool_shed
+ repository_name_elem = XmlET.SubElement( elem, 'repository_name' )
+ repository_name_elem.text = repository_name
+ repository_owner_elem = XmlET.SubElement( elem, 'repository_owner' )
+ repository_owner_elem.text = owner
+ changeset_revision_elem = XmlET.SubElement( elem, 'installed_changeset_revision' )
+ changeset_revision_elem.text = changeset_revision
+ #add additional values
+ #TODO: enhance additional values to allow e.g. use of dict values that will recurse
+ for key, value in kwd.iteritems():
+ new_elem = XmlET.SubElement( elem, key )
+ new_elem.text = value
+ return elem
+
+ def generate_repository_info_elem_from_repository( self, tool_shed_repository, parent_elem=None, **kwd ):
+ return self.generate_repository_info_elem( tool_shed_repository.tool_shed,
+ tool_shed_repository.name,
+ tool_shed_repository.installed_changeset_revision,
+ tool_shed_repository.owner,
+ parent_elem=parent_elem,
+ **kwd )
+
def get_tool_index_sample_files( self, sample_files ):
"""
Try to return the list of all appropriate tool data sample files included
@@ -129,7 +160,7 @@
if path:
file_elem.set( 'path', os.path.normpath( os.path.join( target_dir, os.path.split( path )[1] ) ) )
# Store repository info in the table tag set for trace-ability.
- repo_elem = suc.generate_repository_info_elem_from_repository( tool_shed_repository, parent_elem=elem )
+ repo_elem = self.generate_repository_info_elem_from_repository( tool_shed_repository, parent_elem=elem )
if elems:
# Remove old data_table
os.unlink( tool_data_table_conf_filename )
diff -r 4ee9e584dbc016727e4c90f73bbf53081f775c5a -r 0c62ccbc86246c9aebf8ff78c550234dfa6d5bd5 lib/tool_shed/util/metadata_util.py
--- a/lib/tool_shed/util/metadata_util.py
+++ b/lib/tool_shed/util/metadata_util.py
@@ -7,6 +7,18 @@
log = logging.getLogger( __name__ )
+def get_latest_changeset_revision( app, repository, repo ):
+ repository_tip = repository.tip( app )
+ repository_metadata = suc.get_repository_metadata_by_changeset_revision( app,
+ app.security.encode_id( repository.id ),
+ repository_tip )
+ if repository_metadata and repository_metadata.downloadable:
+ return repository_tip
+ changeset_revisions = suc.get_ordered_metadata_changeset_revisions( repository, repo, downloadable=False )
+ if changeset_revisions:
+ return changeset_revisions[ -1 ]
+ return hg_util.INITIAL_CHANGELOG_HASH
+
def get_latest_repository_metadata( app, decoded_repository_id, downloadable=False ):
"""Get last metadata defined for a specified repository from the database."""
sa_session = app.model.context.current
@@ -15,7 +27,7 @@
if downloadable:
changeset_revision = suc.get_latest_downloadable_changeset_revision( app, repository, repo )
else:
- changeset_revision = suc.get_latest_changeset_revision( app, repository, repo )
+ changeset_revision = get_latest_changeset_revision( app, repository, repo )
return suc.get_repository_metadata_by_changeset_revision( app,
app.security.encode_id( repository.id ),
changeset_revision )
diff -r 4ee9e584dbc016727e4c90f73bbf53081f775c5a -r 0c62ccbc86246c9aebf8ff78c550234dfa6d5bd5 lib/tool_shed/util/shed_util_common.py
--- a/lib/tool_shed/util/shed_util_common.py
+++ b/lib/tool_shed/util/shed_util_common.py
@@ -17,7 +17,6 @@
from tool_shed.util import encoding_util
from tool_shed.util import hg_util
-from xml.etree import ElementTree as XmlET
from urllib2 import HTTPError
log = logging.getLogger( __name__ )
@@ -165,35 +164,6 @@
components_list = [ toolshed, name, owner, changeset_revision, prior_installation_required, only_if_compiling_contained_td ]
return components_list
-def generate_repository_info_elem( tool_shed, repository_name, changeset_revision, owner, parent_elem=None, **kwd ):
- """Create and return an ElementTree repository info Element."""
- if parent_elem is None:
- elem = XmlET.Element( 'tool_shed_repository' )
- else:
- elem = XmlET.SubElement( parent_elem, 'tool_shed_repository' )
- tool_shed_elem = XmlET.SubElement( elem, 'tool_shed' )
- tool_shed_elem.text = tool_shed
- repository_name_elem = XmlET.SubElement( elem, 'repository_name' )
- repository_name_elem.text = repository_name
- repository_owner_elem = XmlET.SubElement( elem, 'repository_owner' )
- repository_owner_elem.text = owner
- changeset_revision_elem = XmlET.SubElement( elem, 'installed_changeset_revision' )
- changeset_revision_elem.text = changeset_revision
- #add additional values
- #TODO: enhance additional values to allow e.g. use of dict values that will recurse
- for key, value in kwd.iteritems():
- new_elem = XmlET.SubElement( elem, key )
- new_elem.text = value
- return elem
-
-def generate_repository_info_elem_from_repository( tool_shed_repository, parent_elem=None, **kwd ):
- return generate_repository_info_elem( tool_shed_repository.tool_shed,
- tool_shed_repository.name,
- tool_shed_repository.installed_changeset_revision,
- tool_shed_repository.owner,
- parent_elem=parent_elem,
- **kwd )
-
def generate_sharable_link_for_repository_in_tool_shed( repository, changeset_revision=None ):
"""Generate the URL for sharing a repository that is in the tool shed."""
base_url = url_for( '/', qualified=True ).rstrip( '/' )
@@ -291,61 +261,6 @@
return repository_metadata
return None
-def get_dependent_downloadable_revisions( app, repository_metadata ):
- """
- Return all repository_metadata records that are downloadable and that depend upon the received
- repository_metadata record.
- """
- # This method is called only from the tool shed.
- sa_session = app.model.context.current
- rm_changeset_revision = repository_metadata.changeset_revision
- rm_repository = repository_metadata.repository
- rm_repository_name = str( rm_repository.name )
- rm_repository_owner = str( rm_repository.user.username )
- dependent_downloadable_revisions = []
- for repository in sa_session.query( app.model.Repository ) \
- .filter( and_( app.model.Repository.table.c.id != rm_repository.id,
- app.model.Repository.table.c.deleted == False,
- app.model.Repository.table.c.deprecated == False ) ):
- downloadable_revisions = repository.downloadable_revisions
- if downloadable_revisions:
- for downloadable_revision in downloadable_revisions:
- if downloadable_revision.has_repository_dependencies:
- metadata = downloadable_revision.metadata
- if metadata:
- repository_dependencies_dict = metadata.get( 'repository_dependencies', {} )
- repository_dependencies_tups = repository_dependencies_dict.get( 'repository_dependencies', [] )
- for repository_dependencies_tup in repository_dependencies_tups:
- tool_shed, name, owner, changeset_revision, prior_installation_required, only_if_compiling_contained_td = \
- common_util.parse_repository_dependency_tuple( repository_dependencies_tup )
- if name == rm_repository_name and owner == rm_repository_owner:
- # We've discovered a repository revision that depends upon the repository associated
- # with the received repository_metadata record, but we need to make sure it depends
- # upon the revision.
- if changeset_revision == rm_changeset_revision:
- dependent_downloadable_revisions.append( downloadable_revision )
- else:
- # Make sure the defined changeset_revision is current.
- defined_repository_metadata = \
- sa_session.query( app.model.RepositoryMetadata ) \
- .filter( app.model.RepositoryMetadata.table.c.changeset_revision == changeset_revision ) \
- .first()
- if defined_repository_metadata is None:
- # The defined changeset_revision is not associated with a repository_metadata
- # record, so updates must be necessary.
- defined_repository = get_repository_by_name_and_owner( app, name, owner )
- defined_repo = hg_util.get_repo_for_repository( app,
- repository=defined_repository,
- repo_path=None,
- create=False )
- updated_changeset_revision = \
- get_next_downloadable_changeset_revision( defined_repository,
- defined_repo,
- changeset_revision )
- if updated_changeset_revision == rm_changeset_revision:
- dependent_downloadable_revisions.append( downloadable_revision )
- return dependent_downloadable_revisions
-
def get_ids_of_tool_shed_repositories_being_installed( app, as_string=False ):
installing_repository_ids = []
new_status = app.install_model.ToolShedRepository.installation_status.NEW
@@ -365,18 +280,6 @@
return ','.join( installing_repository_ids )
return installing_repository_ids
-def get_latest_changeset_revision( app, repository, repo ):
- repository_tip = repository.tip( app )
- repository_metadata = get_repository_metadata_by_changeset_revision( app,
- app.security.encode_id( repository.id ),
- repository_tip )
- if repository_metadata and repository_metadata.downloadable:
- return repository_tip
- changeset_revisions = get_ordered_metadata_changeset_revisions( repository, repo, downloadable=False )
- if changeset_revisions:
- return changeset_revisions[ -1 ]
- return hg_util.INITIAL_CHANGELOG_HASH
-
def get_latest_downloadable_changeset_revision( app, repository, repo ):
repository_tip = repository.tip( app )
repository_metadata = get_repository_metadata_by_changeset_revision( app, app.security.encode_id( repository.id ), repository_tip )
@@ -441,37 +344,11 @@
continue
return key
-def get_or_create_tool_shed_repository( app, tool_shed, name, owner, changeset_revision ):
+def get_ordered_metadata_changeset_revisions( repository, repo, downloadable=True ):
"""
- Return a tool shed repository database record defined by the combination of
- tool shed, repository name, repository owner and changeset_revision or
- installed_changeset_revision. A new tool shed repository record will be
- created if one is not located.
+ Return an ordered list of changeset_revisions that are associated with metadata
+ where order is defined by the repository changelog.
"""
- install_model = app.install_model
- # We store the port in the database.
- tool_shed = common_util.remove_protocol_from_tool_shed_url( tool_shed )
- # This method is used only in Galaxy, not the tool shed.
- repository = get_repository_for_dependency_relationship( app, tool_shed, name, owner, changeset_revision )
- if not repository:
- tool_shed_url = common_util.get_tool_shed_url_from_tool_shed_registry( app, tool_shed )
- repository_clone_url = os.path.join( tool_shed_url, 'repos', owner, name )
- ctx_rev = get_ctx_rev( app, tool_shed_url, name, owner, changeset_revision )
- repository = create_or_update_tool_shed_repository( app=app,
- name=name,
- description=None,
- installed_changeset_revision=changeset_revision,
- ctx_rev=ctx_rev,
- repository_clone_url=repository_clone_url,
- metadata_dict={},
- status=install_model.ToolShedRepository.installation_status.NEW,
- current_changeset_revision=None,
- owner=owner,
- dist_to_shed=False )
- return repository
-
-def get_ordered_metadata_changeset_revisions( repository, repo, downloadable=True ):
- """Return an ordered list of changeset_revisions that are associated with metadata where order is defined by the repository changelog."""
if downloadable:
metadata_revisions = repository.downloadable_revisions
else:
@@ -491,9 +368,11 @@
def get_prior_import_or_install_required_dict( app, tsr_ids, repo_info_dicts ):
"""
- This method is used in the Tool Shed when exporting a repository and its dependencies, and in Galaxy when a repository and its dependencies
- are being installed. Return a dictionary whose keys are the received tsr_ids and whose values are a list of tsr_ids, each of which is contained
- in the received list of tsr_ids and whose associated repository must be imported or installed prior to the repository associated with the tsr_id key.
+ This method is used in the Tool Shed when exporting a repository and its dependencies,
+ and in Galaxy when a repository and its dependencies are being installed. Return a
+ dictionary whose keys are the received tsr_ids and whose values are a list of tsr_ids,
+ each of which is contained in the received list of tsr_ids and whose associated repository
+ must be imported or installed prior to the repository associated with the tsr_id key.
"""
# Initialize the dictionary.
prior_import_or_install_required_dict = {}
@@ -698,11 +577,14 @@
def get_repository_ids_requiring_prior_import_or_install( app, tsr_ids, repository_dependencies ):
"""
- This method is used in the Tool Shed when exporting a repository and its dependencies, and in Galaxy when a repository and its dependencies
- are being installed. Inspect the received repository_dependencies and determine if the encoded id of each required repository is in the received
- tsr_ids. If so, then determine whether that required repository should be imported / installed prior to its dependent repository. Return a list
- of encoded repository ids, each of which is contained in the received list of tsr_ids, and whose associated repositories must be imported / installed
- prior to the dependent repository associated with the received repository_dependencies.
+ This method is used in the Tool Shed when exporting a repository and its dependencies,
+ and in Galaxy when a repository and its dependencies are being installed. Inspect the
+ received repository_dependencies and determine if the encoded id of each required
+ repository is in the received tsr_ids. If so, then determine whether that required
+ repository should be imported / installed prior to its dependent repository. Return a
+ list of encoded repository ids, each of which is contained in the received list of tsr_ids,
+ and whose associated repositories must be imported / installed prior to the dependent
+ repository associated with the received repository_dependencies.
"""
prior_tsr_ids = []
if repository_dependencies:
@@ -710,20 +592,32 @@
if key in [ 'description', 'root_key' ]:
continue
for rd_tup in rd_tups:
- tool_shed, name, owner, changeset_revision, prior_installation_required, only_if_compiling_contained_td = \
+ tool_shed, \
+ name, \
+ owner, \
+ changeset_revision, \
+ prior_installation_required, \
+ only_if_compiling_contained_td = \
common_util.parse_repository_dependency_tuple( rd_tup )
- # If only_if_compiling_contained_td is False, then the repository dependency is not required to be installed prior to the dependent
- # repository even if prior_installation_required is True. This is because the only meaningful content of the repository dependency
- # is its contained tool dependency, which is required in order to compile the dependent repository's tool dependency. In the scenario
- # where the repository dependency is not installed prior to the dependent repository's tool dependency compilation process, the tool
- # dependency compilation framework will install the repository dependency prior to compilation of the dependent repository's tool
- # dependency.
+ # If only_if_compiling_contained_td is False, then the repository dependency
+ # is not required to be installed prior to the dependent repository even if
+ # prior_installation_required is True. This is because the only meaningful
+ # content of the repository dependency is its contained tool dependency, which
+ # is required in order to compile the dependent repository's tool dependency.
+ # In the scenario where the repository dependency is not installed prior to the
+ # dependent repository's tool dependency compilation process, the tool dependency
+ # compilation framework will install the repository dependency prior to compilation
+ # of the dependent repository's tool dependency.
if not util.asbool( only_if_compiling_contained_td ):
if util.asbool( prior_installation_required ):
if is_tool_shed_client( app ):
# We store the port, if one exists, in the database.
tool_shed = common_util.remove_protocol_from_tool_shed_url( tool_shed )
- repository = get_repository_for_dependency_relationship( app, tool_shed, name, owner, changeset_revision )
+ repository = get_repository_for_dependency_relationship( app,
+ tool_shed,
+ name,
+ owner,
+ changeset_revision )
else:
repository = get_repository_by_name_and_owner( app, name, owner )
if repository:
@@ -779,14 +673,6 @@
query = app.model.context.query( app.model.Repository )
return query
-def get_skip_tool_test_by_changeset_revision( app, changeset_revision ):
- """Return a skip_tool_test record whose initial_changeset_revision is the received changeset_revision."""
- # There should only be one, but we'll use first() so callers won't have to handle exceptions.
- sa_session = app.model.context.current
- return sa_session.query( app.model.SkipToolTest ) \
- .filter( app.model.SkipToolTest.table.c.initial_changeset_revision == changeset_revision ) \
- .first()
-
def get_tool_panel_config_tool_path_install_dir( app, repository ):
"""
Return shed-related tool panel config, the tool_path configured in it, and the relative path to
@@ -1220,42 +1106,6 @@
text = re.sub( r'\.\. image:: (?!https?://)/?(.+)', r'.. image:: %s/\1' % route_to_images, text )
return text
-def set_only_if_compiling_contained_td( repository, required_repository ):
- """
- Return True if the received required_repository is only needed to compile a tool
- dependency defined for the received repository.
- """
- # This method is called only from Galaxy when rendering repository dependencies
- # for an installed tool shed repository.
- # TODO: Do we need to check more than changeset_revision here?
- required_repository_tup = [ required_repository.tool_shed, \
- required_repository.name, \
- required_repository.owner, \
- required_repository.changeset_revision ]
- for tup in repository.tuples_of_repository_dependencies_needed_for_compiling_td:
- partial_tup = tup[ 0:4 ]
- if partial_tup == required_repository_tup:
- return 'True'
- return 'False'
-
-def set_prior_installation_required( app, repository, required_repository ):
- """Return True if the received required_repository must be installed before the received repository."""
- # This method is called only from Galaxy when rendering repository dependencies for an installed Tool Shed repository.
- tool_shed_url = common_util.get_tool_shed_url_from_tool_shed_registry( app, str( required_repository.tool_shed ) )
- required_repository_tup = [ tool_shed_url,
- str( required_repository.name ),
- str( required_repository.owner ),
- str( required_repository.changeset_revision ) ]
- # Get the list of repository dependency tuples associated with the received repository where prior_installation_required is True.
- required_rd_tups_that_must_be_installed = repository.requires_prior_installation_of
- for required_rd_tup in required_rd_tups_that_must_be_installed:
- # Repository dependency tuples in metadata include a prior_installation_required value, so strip it for comparision.
- partial_required_rd_tup = required_rd_tup[ 0:4 ]
- if partial_required_rd_tup == required_repository_tup:
- # Return the string value of prior_installation_required, which defaults to 'False'.
- return str( required_rd_tup[ 4 ] )
- return 'False'
-
def set_repository_attributes( app, repository, status, error_message, deleted, uninstalled, remove_from_disk=False ):
if remove_from_disk:
relative_install_dir = repository.repo_path( app )
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