galaxy-commits
Threads by month
- ----- 2025 -----
- 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
March 2013
- 1 participants
- 183 discussions

commit/galaxy-central: greg: Move the many Grid classes out of the tool shed's repository controller into the new location for tool shed grids: ~/tool_shed/grids.
by commits-noreply@bitbucket.org 04 Mar '13
by commits-noreply@bitbucket.org 04 Mar '13
04 Mar '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/db8a3bd35841/
changeset: db8a3bd35841
user: greg
date: 2013-03-04 15:26:59
summary: Move the many Grid classes out of the tool shed's repository controller into the new location for tool shed grids: ~/tool_shed/grids.
affected #: 8 files
diff -r 7369eda82e2cf7e10338232569ed9185bc3b526b -r db8a3bd35841ce033aff283510a0f7fe3aec3ab0 lib/galaxy/webapps/tool_shed/controllers/admin.py
--- a/lib/galaxy/webapps/tool_shed/controllers/admin.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/admin.py
@@ -6,7 +6,7 @@
from galaxy.web.framework.helpers import time_ago, grids
from galaxy.util import inflector
import tool_shed.util.shed_util_common as suc
-from repository import RepositoryGrid, CategoryGrid
+from tool_shed.grids.repository_grids import RepositoryGrid, CategoryGrid
from galaxy import eggs
eggs.require( 'mercurial' )
diff -r 7369eda82e2cf7e10338232569ed9185bc3b526b -r db8a3bd35841ce033aff283510a0f7fe3aec3ab0 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
@@ -1,10 +1,10 @@
-import os, logging, re, tempfile, shutil, ConfigParser, string
+import os, logging, re, tempfile, ConfigParser, string
from time import gmtime, strftime
from datetime import date, datetime
from galaxy import util, web
from galaxy.util.odict import odict
from galaxy.web.base.controller import BaseUIController
-from galaxy.web.form_builder import CheckboxField, SelectField, build_select_field
+from galaxy.web.form_builder import CheckboxField, build_select_field
from galaxy.webapps.tool_shed import model
from galaxy.webapps.tool_shed.model import directory_hash_id
from galaxy.web.framework.helpers import grids
@@ -15,12 +15,12 @@
from galaxy.webapps.tool_shed.util import workflow_util
from galaxy.webapps.tool_shed.util import common_util
import galaxy.tools
+import tool_shed.grids.repository_grids as repository_grids
+import tool_shed.grids.util as grids_util
from galaxy import eggs
eggs.require('mercurial')
from mercurial import hg, ui, patch, commands
-eggs.require('markupsafe')
-from markupsafe import escape as escape_html
log = logging.getLogger( __name__ )
@@ -29,1003 +29,25 @@
malicious_error_can_push = " Correct this changeset as soon as possible, it potentially produces malicious behavior or contains inappropriate content."
-class CategoryGrid( grids.Grid ):
-
-
- class NameColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, category ):
- return category.name
-
-
- class DescriptionColumn( grids.TextColumn ):
- def get_value( self, trans, grid, category ):
- return category.description
-
-
- class RepositoriesColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, category ):
- if category.repositories:
- viewable_repositories = 0
- for rca in category.repositories:
- if not rca.repository.deleted and not rca.repository.deprecated:
- viewable_repositories += 1
- return viewable_repositories
- return 0
-
- title = "Categories"
- model_class = model.Category
- template='/webapps/tool_shed/category/grid.mako'
- default_sort_key = "name"
- columns = [
- NameColumn( "Name",
- key="Category.name",
- link=( lambda item: dict( operation="repositories_by_category", id=item.id ) ),
- attach_popup=False ),
- DescriptionColumn( "Description",
- key="Category.description",
- attach_popup=False ),
- RepositoriesColumn( "Repositories",
- model_class=model.Repository,
- attach_popup=False )
- ]
- # Override these
- default_filter = {}
- global_actions = []
- operations = []
- standard_filters = []
- num_rows_per_page = 50
- preserve_state = False
- use_paging = True
-
-
-class ValidCategoryGrid( CategoryGrid ):
-
-
- class RepositoriesColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, category ):
- if category.repositories:
- viewable_repositories = 0
- for rca in category.repositories:
- repository = rca.repository
- if not repository.deleted and not repository.deprecated and repository.downloadable_revisions:
- viewable_repositories += 1
- return viewable_repositories
- return 0
-
- title = "Categories of valid repositories"
- model_class = model.Category
- template='/webapps/tool_shed/category/valid_grid.mako'
- default_sort_key = "name"
- columns = [
- CategoryGrid.NameColumn( "Name",
- key="Category.name",
- link=( lambda item: dict( operation="valid_repositories_by_category", id=item.id ) ),
- attach_popup=False ),
- CategoryGrid.DescriptionColumn( "Description",
- key="Category.description",
- attach_popup=False ),
- # Columns that are valid for filtering but are not visible.
- RepositoriesColumn( "Valid repositories",
- model_class=model.Repository,
- attach_popup=False )
- ]
- # Override these
- default_filter = {}
- global_actions = []
- operations = []
- standard_filters = []
- num_rows_per_page = 50
- preserve_state = False
- use_paging = True
-
-
-class RepositoryGrid( grids.Grid ):
-
-
- class NameColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, repository ):
- return escape_html( repository.name )
-
-
- class MetadataRevisionColumn( grids.GridColumn ):
-
- def __init__( self, col_name ):
- grids.GridColumn.__init__( self, col_name )
-
- def get_value( self, trans, grid, repository ):
- """Display a SelectField whose options are the changeset_revision strings of all metadata revisions of this repository."""
- # A repository's metadata revisions may not all be installable, as some may contain only invalid tools.
- select_field = build_changeset_revision_select_field( trans, repository, downloadable=False )
- if len( select_field.options ) > 1:
- return select_field.get_html()
- elif len( select_field.options ) == 1:
- return select_field.options[ 0 ][ 0 ]
- return ''
-
-
- class TipRevisionColumn( grids.GridColumn ):
-
- def __init__( self, col_name ):
- grids.GridColumn.__init__( self, col_name )
-
- def get_value( self, trans, grid, repository ):
- """Display the repository tip revision label."""
- return escape_html( repository.revision( trans.app ) )
-
-
- class DescriptionColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, repository ):
- return escape_html( repository.description )
-
-
- class CategoryColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, repository ):
- rval = '<ul>'
- if repository.categories:
- for rca in repository.categories:
- rval += '<li><a href="browse_repositories?operation=repositories_by_category&id=%s">%s</a></li>' \
- % ( trans.security.encode_id( rca.category.id ), rca.category.name )
- else:
- rval += '<li>not set</li>'
- rval += '</ul>'
- return rval
-
-
- class RepositoryCategoryColumn( grids.GridColumn ):
-
- def filter( self, trans, user, query, column_filter ):
- """Modify query to filter by category."""
- if column_filter == "All":
- return query
- return query.filter( model.Category.name == column_filter )
-
-
- class UserColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, repository ):
- if repository.user:
- return escape_html( repository.user.username )
- return 'no user'
-
-
- class EmailColumn( grids.TextColumn ):
-
- def filter( self, trans, user, query, column_filter ):
- if column_filter == 'All':
- return query
- return query.filter( and_( model.Repository.table.c.user_id == model.User.table.c.id,
- model.User.table.c.email == column_filter ) )
-
-
- class EmailAlertsColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, repository ):
- if trans.user and repository.email_alerts and trans.user.email in json.from_json_string( repository.email_alerts ):
- return 'yes'
- return ''
-
-
- class DeprecatedColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, repository ):
- if repository.deprecated:
- return 'yes'
- return ''
-
- title = "Repositories"
- model_class = model.Repository
- template='/webapps/tool_shed/repository/grid.mako'
- default_sort_key = "name"
- columns = [
- NameColumn( "Name",
- key="name",
- link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
- attach_popup=True ),
- DescriptionColumn( "Synopsis",
- key="description",
- attach_popup=False ),
- MetadataRevisionColumn( "Metadata Revisions" ),
- TipRevisionColumn( "Tip Revision" ),
- CategoryColumn( "Category",
- model_class=model.Category,
- key="Category.name",
- attach_popup=False ),
- UserColumn( "Owner",
- model_class=model.User,
- link=( lambda item: dict( operation="repositories_by_user", id=item.id ) ),
- attach_popup=False,
- key="User.username" ),
- # Columns that are valid for filtering but are not visible.
- EmailColumn( "Email",
- model_class=model.User,
- key="email",
- visible=False ),
- RepositoryCategoryColumn( "Category",
- model_class=model.Category,
- key="Category.name",
- visible=False )
- ]
- columns.append( grids.MulticolFilterColumn( "Search repository name, description",
- cols_to_filter=[ columns[0], columns[1] ],
- key="free-text-search",
- visible=False,
- filterable="standard" ) )
- operations = [ grids.GridOperation( "Receive email alerts",
- allow_multiple=False,
- condition=( lambda item: not item.deleted ),
- async_compatible=False ) ]
- standard_filters = []
- default_filter = dict( deleted="False" )
- num_rows_per_page = 50
- preserve_state = False
- use_paging = True
-
- def build_initial_query( self, trans, **kwd ):
- return trans.sa_session.query( model.Repository ) \
- .filter( and_( model.Repository.table.c.deleted == False,
- model.Repository.table.c.deprecated == False ) ) \
- .join( model.User.table ) \
- .outerjoin( model.RepositoryCategoryAssociation.table ) \
- .outerjoin( model.Category.table )
-
-
-class RepositoriesByUserGrid( RepositoryGrid ):
- title = "Repositories by user"
- columns = [
- RepositoryGrid.NameColumn( "Name",
- key="name",
- link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
- attach_popup=False ),
- RepositoryGrid.MetadataRevisionColumn( "Metadata Revisions" ),
- RepositoryGrid.TipRevisionColumn( "Tip Revision" ),
- RepositoryGrid.DescriptionColumn( "Synopsis",
- key="description",
- attach_popup=False ),
- RepositoryGrid.CategoryColumn( "Category",
- model_class=model.Category,
- key="Category.name",
- attach_popup=False )
- ]
- operations = []
- standard_filters = []
- default_filter = dict( deleted="False" )
- num_rows_per_page = 50
- preserve_state = False
- use_paging = True
-
- def build_initial_query( self, trans, **kwd ):
- decoded_user_id = trans.security.decode_id( kwd[ 'user_id' ] )
- return trans.sa_session.query( model.Repository ) \
- .filter( and_( model.Repository.table.c.deleted == False,
- model.Repository.table.c.deprecated == False,
- model.Repository.table.c.user_id == decoded_user_id ) ) \
- .join( model.User.table ) \
- .outerjoin( model.RepositoryCategoryAssociation.table ) \
- .outerjoin( model.Category.table )
-
-
-class RepositoriesIOwnGrid( RepositoryGrid ):
- title = "Repositories I own"
- columns = [
- RepositoryGrid.NameColumn( "Name",
- key="name",
- link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
- attach_popup=True ),
- RepositoryGrid.MetadataRevisionColumn( "Metadata Revisions" ),
- RepositoryGrid.TipRevisionColumn( "Tip Revision" ),
- RepositoryGrid.CategoryColumn( "Category",
- model_class=model.Category,
- key="Category.name",
- attach_popup=False ),
- RepositoryGrid.DeprecatedColumn( "Deprecated" )
- ]
- columns.append( grids.MulticolFilterColumn( "Search repository name",
- cols_to_filter=[ columns[0] ],
- key="free-text-search",
- visible=False,
- filterable="standard" ) )
- operations = [ grids.GridOperation( "Mark as deprecated",
- allow_multiple=False,
- condition=( lambda item: not item.deleted and not item.deprecated ),
- async_compatible=False,
- confirm="Are you sure that you want to deprecate this repository?" ),
- grids.GridOperation( "Mark as not deprecated",
- allow_multiple=False,
- condition=( lambda item: not item.deleted and item.deprecated ),
- async_compatible=False ) ]
-
- def build_initial_query( self, trans, **kwd ):
- return trans.sa_session.query( model.Repository ) \
- .filter( and_( model.Repository.table.c.deleted == False,
- model.Repository.table.c.user_id == trans.user.id ) ) \
- .join( model.User.table ) \
- .outerjoin( model.RepositoryCategoryAssociation.table ) \
- .outerjoin( model.Category.table )
-
-
-class DeprecatedRepositoriesIOwnGrid( RepositoriesIOwnGrid ):
- title = "Deprecated repositories I own"
- columns = [
- RepositoriesIOwnGrid.NameColumn( "Name",
- key="name",
- link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
- attach_popup=True ),
- RepositoriesIOwnGrid.MetadataRevisionColumn( "Metadata Revisions" ),
- RepositoriesIOwnGrid.TipRevisionColumn( "Tip Revision" ),
- RepositoriesIOwnGrid.CategoryColumn( "Category",
- model_class=model.Category,
- key="Category.name",
- attach_popup=False ),
- ]
- columns.append( grids.MulticolFilterColumn( "Search repository name",
- cols_to_filter=[ columns[0] ],
- key="free-text-search",
- visible=False,
- filterable="standard" ) )
-
- def build_initial_query( self, trans, **kwd ):
- return trans.sa_session.query( model.Repository ) \
- .filter( and_( model.Repository.table.c.deleted == False,
- model.Repository.table.c.user_id == trans.user.id,
- model.Repository.table.c.deprecated == True ) ) \
- .join( model.User.table ) \
- .outerjoin( model.RepositoryCategoryAssociation.table ) \
- .outerjoin( model.Category.table )
-
-
-class EmailAlertsRepositoryGrid( RepositoryGrid ):
- columns = [
- RepositoryGrid.NameColumn( "Name",
- key="name",
- link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
- attach_popup=False ),
- RepositoryGrid.DescriptionColumn( "Synopsis",
- key="description",
- attach_popup=False ),
- RepositoryGrid.UserColumn( "Owner",
- model_class=model.User,
- link=( lambda item: dict( operation="repositories_by_user", id=item.id ) ),
- attach_popup=False,
- key="User.username" ),
- RepositoryGrid.EmailAlertsColumn( "Alert", attach_popup=False ),
- # Columns that are valid for filtering but are not visible.
- grids.DeletedColumn( "Deleted",
- key="deleted",
- visible=False,
- filterable="advanced" )
- ]
- operations = [ grids.GridOperation( "Receive email alerts",
- allow_multiple=True,
- condition=( lambda item: not item.deleted ),
- async_compatible=False ) ]
- global_actions = [
- grids.GridAction( "User preferences", dict( controller='user', action='index', cntrller='repository' ) )
- ]
-
-
-class MyWritableRepositoriesGrid( RepositoryGrid ):
- # This grid filters out repositories that have been marked as either deprecated or deleted.
- columns = [
- RepositoryGrid.NameColumn( "Name",
- key="name",
- link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
- attach_popup=True ),
- RepositoryGrid.MetadataRevisionColumn( "Metadata Revisions" ),
- RepositoryGrid.TipRevisionColumn( "Tip Revision" ),
- RepositoryGrid.UserColumn( "Owner",
- model_class=model.User,
- link=( lambda item: dict( operation="repositories_by_user", id=item.id ) ),
- attach_popup=False,
- key="User.username" ),
- RepositoryGrid.EmailAlertsColumn( "Alert", attach_popup=False ),
- # Columns that are valid for filtering but are not visible.
- RepositoryGrid.EmailColumn( "Email",
- model_class=model.User,
- key="email",
- visible=False ),
- RepositoryGrid.RepositoryCategoryColumn( "Category",
- model_class=model.Category,
- key="Category.name",
- visible=False )
- ]
- columns.append( grids.MulticolFilterColumn( "Search repository name",
- cols_to_filter=[ columns[0] ],
- key="free-text-search",
- visible=False,
- filterable="standard" ) )
- operations = [ grids.GridOperation( "Receive email alerts",
- allow_multiple=False,
- condition=( lambda item: not item.deleted ),
- async_compatible=False ) ]
-
- def build_initial_query( self, trans, **kwd ):
- # TODO: improve performance by adding a db table associating users with repositories for which they have write access.
- username = trans.user.username
- clause_list = []
- for repository in trans.sa_session.query( model.Repository ) \
- .filter( and_( model.Repository.table.c.deprecated == False,
- model.Repository.table.c.deleted == False ) ):
- allow_push = repository.allow_push( trans.app )
- if allow_push:
- allow_push_usernames = allow_push.split( ',' )
- if username in allow_push_usernames:
- clause_list.append( model.Repository.table.c.id == repository.id )
- if clause_list:
- return trans.sa_session.query( model.Repository ) \
- .filter( or_( *clause_list ) ) \
- .join( model.User.table ) \
- .outerjoin( model.RepositoryCategoryAssociation.table ) \
- .outerjoin( model.Category.table )
- # Return an empty query.
- return trans.sa_session.query( model.Repository ) \
- .filter( model.Repository.table.c.id < 0 )
-
-
-class ValidRepositoryGrid( RepositoryGrid ):
- # This grid filters out repositories that have been marked as either deleted or deprecated.
-
-
- class CategoryColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, repository ):
- rval = '<ul>'
- if repository.categories:
- for rca in repository.categories:
- rval += '<li><a href="browse_repositories?operation=valid_repositories_by_category&id=%s">%s</a></li>' \
- % ( trans.security.encode_id( rca.category.id ), rca.category.name )
- else:
- rval += '<li>not set</li>'
- rval += '</ul>'
- return rval
-
-
- class RepositoryCategoryColumn( grids.GridColumn ):
-
- def filter( self, trans, user, query, column_filter ):
- """Modify query to filter by category."""
- if column_filter == "All":
- return query
- return query.filter( model.Category.name == column_filter )
-
-
- class RevisionColumn( grids.GridColumn ):
-
- def __init__( self, col_name ):
- grids.GridColumn.__init__( self, col_name )
-
- def get_value( self, trans, grid, repository ):
- """Display a SelectField whose options are the changeset_revision strings of all download-able revisions of this repository."""
- select_field = build_changeset_revision_select_field( trans, repository, downloadable=True )
- if len( select_field.options ) > 1:
- return select_field.get_html()
- elif len( select_field.options ) == 1:
- return select_field.options[ 0 ][ 0 ]
- return ''
-
- title = "Valid repositories"
- columns = [
- RepositoryGrid.NameColumn( "Name",
- key="name",
- attach_popup=True ),
- RepositoryGrid.DescriptionColumn( "Synopsis",
- key="description",
- attach_popup=False ),
- RevisionColumn( "Installable Revisions" ),
- RepositoryGrid.UserColumn( "Owner",
- model_class=model.User,
- attach_popup=False ),
- # Columns that are valid for filtering but are not visible.
- RepositoryCategoryColumn( "Category",
- model_class=model.Category,
- key="Category.name",
- visible=False )
- ]
- columns.append( grids.MulticolFilterColumn( "Search repository name, description",
- cols_to_filter=[ columns[0], columns[1] ],
- key="free-text-search",
- visible=False,
- filterable="standard" ) )
- operations = []
-
- def build_initial_query( self, trans, **kwd ):
- if 'id' in kwd:
- # The user is browsing categories of valid repositories, so filter the request by the received id, which is a category id.
- return trans.sa_session.query( model.Repository ) \
- .filter( and_( model.Repository.table.c.deleted == False,
- model.Repository.table.c.deprecated == False ) ) \
- .join( model.RepositoryMetadata.table ) \
- .join( model.User.table ) \
- .join( model.RepositoryCategoryAssociation.table ) \
- .join( model.Category.table ) \
- .filter( and_( model.Category.table.c.id == trans.security.decode_id( kwd[ 'id' ] ),
- model.RepositoryMetadata.table.c.downloadable == True ) )
- # The user performed a free text search on the ValidCategoryGrid.
- return trans.sa_session.query( model.Repository ) \
- .filter( and_( model.Repository.table.c.deleted == False,
- model.Repository.table.c.deprecated == False ) ) \
- .join( model.RepositoryMetadata.table ) \
- .join( model.User.table ) \
- .outerjoin( model.RepositoryCategoryAssociation.table ) \
- .outerjoin( model.Category.table ) \
- .filter( model.RepositoryMetadata.table.c.downloadable == True )
-
-
-class MatchedRepositoryGrid( grids.Grid ):
- # This grid filters out repositories that have been marked as deprecated.
-
-
- class NameColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, repository_metadata ):
- return repository_metadata.repository.name
-
-
- class DescriptionColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, repository_metadata ):
- return repository_metadata.repository.description
-
-
- class RevisionColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, repository_metadata ):
- return repository_metadata.changeset_revision
-
-
- class UserColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, repository_metadata ):
- if repository_metadata.repository.user:
- return repository_metadata.repository.user.username
- return 'no user'
-
- # Grid definition
- title = "Matching repositories"
- model_class = model.RepositoryMetadata
- template='/webapps/tool_shed/repository/grid.mako'
- default_sort_key = "Repository.name"
- columns = [
- NameColumn( "Repository name",
- link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
- attach_popup=True ),
- DescriptionColumn( "Synopsis",
- attach_popup=False ),
- RevisionColumn( "Revision" ),
- UserColumn( "Owner",
- model_class=model.User,
- attach_popup=False )
- ]
- operations = [
- grids.GridOperation( "Install to Galaxy", allow_multiple=True )
- ]
- standard_filters = []
- default_filter = {}
- num_rows_per_page = 50
- preserve_state = False
- use_paging = True
-
- def build_initial_query( self, trans, **kwd ):
- match_tuples = kwd.get( 'match_tuples', [] )
- clause_list = []
- if match_tuples:
- for match_tuple in match_tuples:
- repository_id, changeset_revision = match_tuple
- clause_list.append( "%s=%d and %s='%s'" % ( model.RepositoryMetadata.table.c.repository_id,
- int( repository_id ),
- model.RepositoryMetadata.table.c.changeset_revision,
- changeset_revision ) )
- return trans.sa_session.query( model.RepositoryMetadata ) \
- .join( model.Repository ) \
- .filter( and_( model.Repository.table.c.deleted == False,
- model.Repository.table.c.deprecated == False ) ) \
- .join( model.User.table ) \
- .filter( or_( *clause_list ) ) \
- .order_by( model.Repository.name )
- # Return an empty query
- return trans.sa_session.query( model.RepositoryMetadata ) \
- .filter( model.RepositoryMetadata.id < 0 )
-
-
-class InstallMatchedRepositoryGrid( MatchedRepositoryGrid ):
- columns = [ col for col in MatchedRepositoryGrid.columns ]
- # Override the NameColumn
- columns[ 0 ] = MatchedRepositoryGrid.NameColumn( "Name",
- link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
- attach_popup=False )
-
-
-class RepositoryMetadataGrid( grids.Grid ):
-
-
- class RepositoryNameColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, repository_metadata ):
- repository = repository_metadata.repository
- return escape_html( repository.name )
-
-
- class RepositoryOwnerColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, repository_metadata ):
- repository = repository_metadata.repository
- return escape_html( repository.user.username )
-
-
- class ChangesetRevisionColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, repository_metadata ):
- return escape_html( repository_metadata.changeset_revision )
-
-
- class MaliciousColumn( grids.BooleanColumn ):
- def get_value( self, trans, grid, repository_metadata ):
- if repository_metadata.malicious:
- return 'yes'
- return ''
-
-
- class DownloadableColumn( grids.BooleanColumn ):
- def get_value( self, trans, grid, repository_metadata ):
- if repository_metadata.downloadable:
- return 'yes'
- return ''
-
-
- class ToolsFunctionallyCorrectColumn( grids.BooleanColumn ):
- def get_value( self, trans, grid, repository_metadata ):
- if repository_metadata.tools_functionally_correct:
- return 'yes'
- return ''
-
-
- class DoNotTestColumn( grids.BooleanColumn ):
- def get_value( self, trans, grid, repository_metadata ):
- if repository_metadata.do_not_test:
- return 'yes'
- return ''
-
-
- class TimeLastTestedColumn( grids.DateTimeColumn ):
- def get_value( self, trans, grid, repository_metadata ):
- return repository_metadata.time_last_tested
-
-
- class HasRepositoryDependenciesColumn( grids.BooleanColumn ):
- def get_value( self, trans, grid, repository_metadata ):
- if repository_metadata.has_repository_dependencies:
- return 'yes'
- return ''
-
-
- class IncludesDatatypesColumn( grids.BooleanColumn ):
- def get_value( self, trans, grid, repository_metadata ):
- if repository_metadata.includes_datatypes:
- return 'yes'
- return ''
-
-
- class IncludesToolsColumn( grids.BooleanColumn ):
- def get_value( self, trans, grid, repository_metadata ):
- if repository_metadata.includes_tools:
- return 'yes'
- return ''
-
-
- class IncludesToolDependenciesColumn( grids.BooleanColumn ):
- def get_value( self, trans, grid, repository_metadata ):
- if repository_metadata.includes_tool_dependencies:
- return 'yes'
- return ''
-
-
- class IncludesWorkflowsColumn( grids.BooleanColumn ):
- def get_value( self, trans, grid, repository_metadata ):
- if repository_metadata.includes_workflows:
- return 'yes'
- return ''
-
- title = "Repository metadata"
- model_class = model.RepositoryMetadata
- template='/webapps/tool_shed/repository/grid.mako'
- default_sort_key = "Repository.name"
- columns = [
- RepositoryNameColumn( "Repository name",
- link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
- attach_popup=False ),
- RepositoryOwnerColumn( "Owner",
- model_class=model.User,
- attach_popup=False,
- key="User.username" )
- ]
- columns.append( grids.MulticolFilterColumn( "Search repository name, description",
- cols_to_filter=[ columns[0], columns[1] ],
- key="free-text-search",
- visible=False,
- filterable="standard" ) )
- operations = []
- standard_filters = []
- default_filter = dict( malicious="False" )
- num_rows_per_page = 50
- preserve_state = False
- use_paging = True
-
- def build_initial_query( self, trans, **kwd ):
- return trans.sa_session.query( model.RepositoryMetadata ) \
- .join( model.Repository ) \
- .filter( and_( model.Repository.table.c.deleted == False,
- model.Repository.table.c.deprecated == False ) ) \
- .join( model.User.table ) \
- .order_by( model.Repository.name )
-
-
-class RepositoryDependenciesGrid( RepositoryMetadataGrid ):
-
-
- class RequiredRepositoryColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, repository_metadata ):
- rd_str = ''
- if repository_metadata:
- metadata = repository_metadata.metadata
- if metadata:
- rd_dict = metadata.get( 'repository_dependencies', {} )
- if rd_dict:
- rd_tups = rd_dict[ 'repository_dependencies' ]
- # "repository_dependencies": [["http://localhost:9009", "bwa059", "test", "a07baa797d53"]]
- # Sort rd_tups by by required repository name.
- sorted_rd_tups = sorted( rd_tups, key=lambda rd_tup: rd_tup[ 1 ] )
- num_tups = len( sorted_rd_tups )
- for index, rd_tup in enumerate( sorted_rd_tups ):
- name = rd_tup[ 1 ]
- owner = rd_tup[ 2 ]
- required_repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
- if required_repository:
- required_repository_id = trans.security.encode_id( required_repository.id )
- rd_str += '<a href="browse_repository_dependencies?operation=browse_repository&id=%s">' % required_repository_id
- rd_str += '<b>name:</b> %s | <b>owner:</b> %s | <b>revision:</b> %s' % ( escape_html( rd_tup[ 1 ] ), escape_html( rd_tup[ 2 ] ), escape_html( rd_tup[ 3 ] ) )
- if required_repository:
- rd_str += '</a>'
- if index < num_tups - 1:
- rd_str += '<br/>'
- return rd_str
-
- title = "Repository dependency definitions in this tool shed"
- columns = [
- RepositoryMetadataGrid.RepositoryNameColumn( "Repository name",
- model_class=model.Repository,
- link=( lambda item: dict( operation="browse_repository", id=item.repository.id ) ),
- attach_popup=False,
- key="Repository.name" ),
- RepositoryMetadataGrid.RepositoryOwnerColumn( "Owner",
- model_class=model.User,
- attach_popup=False,
- key="User.username" ),
- RepositoryMetadataGrid.ChangesetRevisionColumn( "Revision",
- attach_popup=False ),
- RequiredRepositoryColumn( "Repository dependency",
- attach_popup=False )
- ]
- columns.append( grids.MulticolFilterColumn( "Search repository name, owner",
- cols_to_filter=[ columns[0], columns[1] ],
- key="free-text-search",
- visible=False,
- filterable="standard" ) )
-
- def build_initial_query( self, trans, **kwd ):
- return trans.sa_session.query( model.RepositoryMetadata ) \
- .join( model.Repository ) \
- .filter( and_( model.RepositoryMetadata.table.c.has_repository_dependencies == True,
- model.Repository.table.c.deleted == False,
- model.Repository.table.c.deprecated == False ) ) \
- .join( model.User.table ) \
- .order_by( model.Repository.name )
-
-
-class ToolDependenciesGrid( RepositoryMetadataGrid ):
-
-
- class ToolDependencyColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, repository_metadata ):
- td_str = ''
- if repository_metadata:
- metadata = repository_metadata.metadata
- if metadata:
- tds_dict = metadata.get( 'tool_dependencies', {} )
- if tds_dict:
- # Example: {"bwa/0.5.9": {"name": "bwa", "type": "package", "version": "0.5.9"}}
- sorted_keys = sorted( [ k for k in tds_dict.keys() ] )
- num_keys = len( sorted_keys )
- # Handle environment settings first.
- if 'set_environment' in sorted_keys:
- # Example: "set_environment": [{"name": "JAVA_JAR_FILE", "type": "set_environment"}]
- env_dicts = tds_dict[ 'set_environment' ]
- num_env_dicts = len( env_dicts )
- td_str += '<b>environment:</b> '
- for index, env_dict in enumerate( env_dicts ):
- td_str += '%s' % escape_html( env_dict[ 'name' ] )
- if index < num_env_dicts - 1:
- td_str += ', '
- td_str += '<br/>'
- for index, key in enumerate( sorted_keys ):
- if key == 'set_environment':
- continue
- td_dict = tds_dict[ key ]
- # Example: {"name": "bwa", "type": "package", "version": "0.5.9"}
- name = td_dict[ 'name' ]
- type = td_dict[ 'type' ]
- version = td_dict[ 'version' ]
- td_str += '<b>%s</b> version <b>%s</b>' % ( escape_html( name ), escape_html( version ) )
- if index < num_keys - 1:
- td_str += '<br/>'
- return td_str
-
- title = "Tool dependency definitions in this tool shed"
- columns = [
- RepositoryMetadataGrid.RepositoryNameColumn( "Repository name",
- model_class=model.Repository,
- link=( lambda item: dict( operation="browse_repository", id=item.repository.id ) ),
- attach_popup=False,
- key="Repository.name" ),
- RepositoryMetadataGrid.RepositoryOwnerColumn( "Owner",
- model_class=model.User,
- attach_popup=False,
- key="User.username" ),
- RepositoryMetadataGrid.ChangesetRevisionColumn( "Revision",
- attach_popup=False ),
- ToolDependencyColumn( "Tool dependency",
- attach_popup=False )
- ]
- columns.append( grids.MulticolFilterColumn( "Search repository name, owner",
- cols_to_filter=[ columns[0], columns[1] ],
- key="free-text-search",
- visible=False,
- filterable="standard" ) )
-
- def build_initial_query( self, trans, **kwd ):
- return trans.sa_session.query( model.RepositoryMetadata ) \
- .join( model.Repository ) \
- .filter( and_( model.RepositoryMetadata.table.c.includes_tool_dependencies == True,
- model.Repository.table.c.deleted == False,
- model.Repository.table.c.deprecated == False ) ) \
- .join( model.User.table ) \
- .order_by( model.Repository.name )
-
-
-class ToolsGrid( RepositoryMetadataGrid ):
-
-
- class ToolsColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, repository_metadata ):
- tool_str = ''
- if repository_metadata:
- metadata = repository_metadata.metadata
- if metadata:
- tool_dicts = metadata.get( 'tools', [] )
- if tool_dicts:
- num_tool_dicts = len( tool_dicts )
- for index, tool_dict in enumerate( tool_dicts ):
- tool_id = tool_dict[ 'id' ]
- name = tool_dict[ 'name' ]
- version = tool_dict[ 'version' ]
- tool_str += '<b>%s</b> | %s | %s' % ( escape_html( tool_id ), escape_html( name ), escape_html( version ) )
- if index < num_tool_dicts - 1:
- tool_str += '<br/>'
- return tool_str
-
- title = "Valid tools in this tool shed"
- columns = [
- RepositoryMetadataGrid.RepositoryNameColumn( "Repository name",
- model_class=model.Repository,
- link=( lambda item: dict( operation="view_or_manage_repository", id=item.repository.id ) ),
- attach_popup=False,
- key="Repository.name" ),
- RepositoryMetadataGrid.RepositoryOwnerColumn( "Owner",
- model_class=model.User,
- attach_popup=False,
- key="User.username" ),
- RepositoryMetadataGrid.ChangesetRevisionColumn( "Revision",
- attach_popup=False ),
- ToolsColumn( "Tool id | name | version",
- attach_popup=False )
- ]
- columns.append( grids.MulticolFilterColumn( "Search repository name, owner",
- cols_to_filter=[ columns[0], columns[1] ],
- key="free-text-search",
- visible=False,
- filterable="standard" ) )
-
- def build_initial_query( self, trans, **kwd ):
- return trans.sa_session.query( model.RepositoryMetadata ) \
- .join( model.Repository ) \
- .filter( and_( model.RepositoryMetadata.table.c.includes_tools == True,
- model.Repository.table.c.deleted == False,
- model.Repository.table.c.deprecated == False ) ) \
- .join( model.User.table ) \
- .order_by( model.Repository.name )
-
-
-class DatatypesGrid( RepositoryMetadataGrid ):
-
-
- class DatatypesColumn( grids.TextColumn ):
-
- def get_value( self, trans, grid, repository_metadata ):
- datatype_str = ''
- if repository_metadata:
- metadata = repository_metadata.metadata
- if metadata:
- datatype_dicts = metadata.get( 'datatypes', [] )
- if datatype_dicts:
- num_datatype_dicts = len( datatype_dicts )
- for index, datatype_dict in enumerate( datatype_dicts ):
- # Example: {"display_in_upload": "true", "dtype": "galaxy.datatypes.blast:BlastXml", "extension": "blastxml", "mimetype": "application/xml"}
- extension = datatype_dict.get( 'extension', '' )
- dtype = datatype_dict.get( 'dtype', '' )
- mimetype = datatype_dict.get( 'mimetype', '' )
- display_in_upload = datatype_dict.get( 'display_in_upload', False )
- datatype_str += '<b>%s</b> | %s | %s' % ( escape_html( extension ), escape_html( dtype ), escape_html( mimetype ) )
- if index < num_datatype_dicts - 1:
- datatype_str += '<br/>'
- return datatype_str
-
- title = "Custom datatypes in this tool shed"
- columns = [
- RepositoryMetadataGrid.RepositoryNameColumn( "Repository name",
- model_class=model.Repository,
- link=( lambda item: dict( operation="view_or_manage_repository", id=item.repository.id ) ),
- attach_popup=False,
- key="Repository.name" ),
- RepositoryMetadataGrid.RepositoryOwnerColumn( "Owner",
- model_class=model.User,
- attach_popup=False,
- key="User.username" ),
- RepositoryMetadataGrid.ChangesetRevisionColumn( "Revision",
- attach_popup=False ),
- DatatypesColumn( "Datatype extension | Type | Mimetype",
- attach_popup=False )
- ]
- columns.append( grids.MulticolFilterColumn( "Search repository name, owner",
- cols_to_filter=[ columns[0], columns[1] ],
- key="free-text-search",
- visible=False,
- filterable="standard" ) )
-
- def build_initial_query( self, trans, **kwd ):
- return trans.sa_session.query( model.RepositoryMetadata ) \
- .join( model.Repository ) \
- .filter( and_( model.RepositoryMetadata.table.c.includes_datatypes == True,
- model.Repository.table.c.deleted == False,
- model.Repository.table.c.deprecated == False ) ) \
- .join( model.User.table ) \
- .order_by( model.Repository.name )
-
class RepositoryController( BaseUIController, common_util.ItemRatings ):
- category_grid = CategoryGrid()
- datatypes_grid = DatatypesGrid()
- deprecated_repositories_i_own_grid = DeprecatedRepositoriesIOwnGrid()
- email_alerts_repository_grid = EmailAlertsRepositoryGrid()
- install_matched_repository_grid = InstallMatchedRepositoryGrid()
- matched_repository_grid = MatchedRepositoryGrid()
- my_writable_repositories_grid = MyWritableRepositoriesGrid()
- repositories_by_user_grid = RepositoriesByUserGrid()
- repositories_i_own_grid = RepositoriesIOwnGrid()
- repository_dependencies_grid = RepositoryDependenciesGrid()
- repository_grid = RepositoryGrid()
+ category_grid = repository_grids.CategoryGrid()
+ datatypes_grid = repository_grids.DatatypesGrid()
+ deprecated_repositories_i_own_grid = repository_grids.DeprecatedRepositoriesIOwnGrid()
+ email_alerts_repository_grid = repository_grids.EmailAlertsRepositoryGrid()
+ install_matched_repository_grid = repository_grids.InstallMatchedRepositoryGrid()
+ matched_repository_grid = repository_grids.MatchedRepositoryGrid()
+ my_writable_repositories_grid = repository_grids.MyWritableRepositoriesGrid()
+ repositories_by_user_grid = repository_grids.RepositoriesByUserGrid()
+ repositories_i_own_grid = repository_grids.RepositoriesIOwnGrid()
+ repository_dependencies_grid = repository_grids.RepositoryDependenciesGrid()
+ repository_grid = repository_grids.RepositoryGrid()
# The repository_metadata_grid is not currently displayed, but is sub-classed by several grids.
- repository_metadata_grid = RepositoryMetadataGrid()
- tool_dependencies_grid = ToolDependenciesGrid()
- tools_grid = ToolsGrid()
- valid_category_grid = ValidCategoryGrid()
- valid_repository_grid = ValidRepositoryGrid()
+ repository_metadata_grid = repository_grids.RepositoryMetadataGrid()
+ tool_dependencies_grid = repository_grids.ToolDependenciesGrid()
+ tools_grid = repository_grids.ToolsGrid()
+ valid_category_grid = repository_grids.ValidCategoryGrid()
+ valid_repository_grid = repository_grids.ValidRepositoryGrid()
@web.expose
def browse_categories( self, trans, **kwd ):
@@ -2579,11 +1601,11 @@
allow_push_select_field = self.__build_allow_push_select_field( trans, current_allow_push_list )
checked = alerts_checked or user.email in email_alerts
alerts_check_box = CheckboxField( 'alerts', checked=checked )
- changeset_revision_select_field = build_changeset_revision_select_field( trans,
- repository,
- selected_value=changeset_revision,
- add_id_to_name=False,
- downloadable=False )
+ changeset_revision_select_field = grids_util.build_changeset_revision_select_field( trans,
+ repository,
+ selected_value=changeset_revision,
+ add_id_to_name=False,
+ downloadable=False )
revision_label = suc.get_revision_label( trans, repository, repository.tip( trans.app ) )
repository_metadata = None
repository_metadata_id = None
@@ -2749,11 +1771,11 @@
metadata = None
repository_dependencies = None
revision_label = suc.get_revision_label( trans, repository, changeset_revision )
- changeset_revision_select_field = build_changeset_revision_select_field( trans,
- repository,
- selected_value=changeset_revision,
- add_id_to_name=False,
- downloadable=False )
+ changeset_revision_select_field = grids_util.build_changeset_revision_select_field( trans,
+ repository,
+ selected_value=changeset_revision,
+ add_id_to_name=False,
+ downloadable=False )
containers_dict = suc.build_repository_containers_for_tool_shed( trans, repository, changeset_revision, repository_dependencies, repository_metadata )
return trans.fill_template( '/webapps/tool_shed/repository/preview_tools_in_changeset.mako',
repository=repository,
@@ -3378,11 +2400,11 @@
trans.sa_session.flush()
checked = alerts_checked or ( user and user.email in email_alerts )
alerts_check_box = CheckboxField( 'alerts', checked=checked )
- changeset_revision_select_field = build_changeset_revision_select_field( trans,
- repository,
- selected_value=changeset_revision,
- add_id_to_name=False,
- downloadable=False )
+ changeset_revision_select_field = grids_util.build_changeset_revision_select_field( trans,
+ repository,
+ selected_value=changeset_revision,
+ add_id_to_name=False,
+ downloadable=False )
revision_label = suc.get_revision_label( trans, repository, changeset_revision )
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, id, changeset_revision )
if repository_metadata:
@@ -3500,11 +2522,11 @@
metadata = None
#tool_test_errors = None
is_malicious = suc.changeset_is_malicious( trans, repository_id, repository.tip( trans.app ) )
- changeset_revision_select_field = build_changeset_revision_select_field( trans,
- repository,
- selected_value=changeset_revision,
- add_id_to_name=False,
- downloadable=False )
+ changeset_revision_select_field = grids_util.build_changeset_revision_select_field( trans,
+ repository,
+ selected_value=changeset_revision,
+ add_id_to_name=False,
+ downloadable=False )
trans.app.config.tool_data_path = original_tool_data_path
reviewed_by_user = suc.changeset_revision_reviewed_by_user( trans, trans.user, repository, changeset_revision )
if reviewed_by_user:
@@ -3552,56 +2574,3 @@
metadata=metadata,
message=message,
status=status )
-
-# ----- Utility methods -----
-
-def build_changeset_revision_select_field( trans, repository, selected_value=None, add_id_to_name=True,
- downloadable=False, reviewed=False, not_reviewed=False ):
- """Build a SelectField whose options are the changeset_rev strings of certain revisions of the received repository."""
- options = []
- changeset_tups = []
- refresh_on_change_values = []
- if downloadable:
- # Restrict the options to downloadable revisions.
- repository_metadata_revisions = repository.downloadable_revisions
- elif reviewed:
- # Restrict the options to revisions that have been reviewed.
- repository_metadata_revisions = []
- metadata_changeset_revision_hashes = []
- for metadata_revision in repository.metadata_revisions:
- metadata_changeset_revision_hashes.append( metadata_revision.changeset_revision )
- for review in repository.reviews:
- if review.changeset_revision in metadata_changeset_revision_hashes:
- repository_metadata_revisions.append( review.repository_metadata )
- elif not_reviewed:
- # Restrict the options to revisions that have not yet been reviewed.
- repository_metadata_revisions = []
- reviewed_metadata_changeset_revision_hashes = []
- for review in repository.reviews:
- reviewed_metadata_changeset_revision_hashes.append( review.changeset_revision )
- for metadata_revision in repository.metadata_revisions:
- if metadata_revision.changeset_revision not in reviewed_metadata_changeset_revision_hashes:
- repository_metadata_revisions.append( metadata_revision )
- else:
- # Restrict the options to all revisions that have associated metadata.
- repository_metadata_revisions = repository.metadata_revisions
- for repository_metadata in repository_metadata_revisions:
- rev, label, changeset_revision = suc.get_rev_label_changeset_revision_from_repository_metadata( trans, repository_metadata, repository=repository )
- changeset_tups.append( ( rev, label, changeset_revision ) )
- refresh_on_change_values.append( changeset_revision )
- # Sort options by the revision label. Even though the downloadable_revisions query sorts by update_time,
- # the changeset revisions may not be sorted correctly because setting metadata over time will reset update_time.
- for changeset_tup in sorted( changeset_tups ):
- # Display the latest revision first.
- options.insert( 0, ( changeset_tup[1], changeset_tup[2] ) )
- if add_id_to_name:
- name = 'changeset_revision_%d' % repository.id
- else:
- name = 'changeset_revision'
- select_field = SelectField( name=name,
- refresh_on_change=True,
- refresh_on_change_values=refresh_on_change_values )
- for option_tup in options:
- selected = selected_value and option_tup[1] == selected_value
- select_field.add_option( option_tup[0], option_tup[1], selected=selected )
- return select_field
diff -r 7369eda82e2cf7e10338232569ed9185bc3b526b -r db8a3bd35841ce033aff283510a0f7fe3aec3ab0 lib/galaxy/webapps/tool_shed/controllers/repository_review.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository_review.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository_review.py
@@ -8,7 +8,7 @@
from sqlalchemy.sql.expression import func
from galaxy.webapps.tool_shed.util import common_util
from galaxy.webapps.tool_shed.util.container_util import STRSEP
-from repository import RepositoryGrid
+from tool_shed.grids.repository_grids import RepositoryGrid
import tool_shed.util.shed_util_common as suc
from galaxy.util.odict import odict
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: jgoecks: Trackster: (a) handle corner case when feature starts at tile boundary and (b) remove poor tile index usage. Pack script.
by commits-noreply@bitbucket.org 01 Mar '13
by commits-noreply@bitbucket.org 01 Mar '13
01 Mar '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/7369eda82e2c/
changeset: 7369eda82e2c
user: jgoecks
date: 2013-03-01 22:18:23
summary: Trackster: (a) handle corner case when feature starts at tile boundary and (b) remove poor tile index usage. Pack script.
affected #: 2 files
diff -r 5f20704ea90836a5fa54f63c78ceaa536010c4e8 -r 7369eda82e2cf7e10338232569ed9185bc3b526b static/scripts/packed/viz/trackster/painters.js
--- a/static/scripts/packed/viz/trackster/painters.js
+++ b/static/scripts/packed/viz/trackster/painters.js
@@ -1,1 +1,1 @@
-define(["libs/underscore"],function(_){var extend=_.extend;var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(first_region,second_region){var first_start=first_region[0],first_end=first_region[1],second_start=second_region[0],second_end=second_region[1],overlap;if(first_start<second_start){if(first_end<second_start){overlap=BEFORE}else{if(first_end<=second_end){overlap=OVERLAP_START}else{overlap=CONTAINS}}}else{if(first_start>second_end){overlap=AFTER}else{if(first_end<=second_end){overlap=CONTAINED_BY}else{overlap=OVERLAP_END}}}return overlap};var is_overlap=function(first_region,second_region){var overlap=compute_overlap(first_region,second_region);return(overlap!==BEFORE&&overlap!==AFTER)};var dashedLine=function(ctx,x1,y1,x2,y2,dashLen){if(dashLen===undefined){dashLen=4}var dX=x2-x1;var dY=y2-y1;var dashes=Math.floor(Math.sqrt(dX*dX+dY*dY)/dashLen);var dashX=dX/dashes;var dashY=dY/dashes;var q;for(q=0;q<dashes;q++,x1+=dashX,y1+=dashY){if(q%2!==0){continue}ctx.fillRect(x1,y1,dashLen,1)}};var drawDownwardEquilateralTriangle=function(ctx,down_vertex_x,down_vertex_y,side_len){var x1=down_vertex_x-side_len/2,x2=down_vertex_x+side_len/2,y=down_vertex_y-Math.sqrt(side_len*3/2);ctx.beginPath();ctx.moveTo(x1,y);ctx.lineTo(x2,y);ctx.lineTo(down_vertex_x,down_vertex_y);ctx.lineTo(x1,y);ctx.strokeStyle=this.fillStyle;ctx.fill();ctx.stroke();ctx.closePath()};var Scaler=function(default_val){this.default_val=(default_val?default_val:1)};Scaler.prototype.gen_val=function(input){return this.default_val};var Painter=function(data,view_start,view_end,prefs,mode){this.data=data;this.view_start=view_start;this.view_end=view_end;this.prefs=extend({},this.default_prefs,prefs);this.mode=mode};Painter.prototype.default_prefs={};Painter.prototype.draw=function(ctx,width,height,w_scale){};var SummaryTreePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode)};SummaryTreePainter.prototype.default_prefs={show_counts:false};SummaryTreePainter.prototype.draw=function(ctx,width,height,w_scale){var view_start=this.view_start,points=this.data.data,max=(this.prefs.histogram_max?this.prefs.histogram_max:this.data.max),base_y=height;delta_x_px=Math.ceil(this.data.delta*w_scale);ctx.save();for(var i=0,len=points.length;i<len;i++){var x=Math.floor((points[i][0]-view_start)*w_scale);var y=points[i][1];if(!y){continue}var y_px=y/max*height;if(y!==0&&y_px<1){y_px=1}ctx.fillStyle=this.prefs.block_color;ctx.fillRect(x,base_y-y_px,delta_x_px,y_px);var text_padding_req_x=4;if(this.prefs.show_counts&&(ctx.measureText(y).width+text_padding_req_x)<delta_x_px){ctx.fillStyle=this.prefs.label_color;ctx.textAlign="center";ctx.fillText(y,x+(delta_x_px/2),10)}}ctx.restore()};var LinePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][1])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][1])}this.prefs.max_value=max_value}};LinePainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};LinePainter.prototype.draw=function(ctx,width,height,w_scale){var in_path=false,min_value=this.prefs.min_value,max_value=this.prefs.max_value,vertical_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data;ctx.save();var y_zero=Math.round(height+min_value/vertical_range*height);if(mode!=="Intensity"){ctx.fillStyle="#aaa";ctx.fillRect(0,y_zero,width,1)}ctx.beginPath();var x_scaled,y,delta_x_px;if(data.length>1){delta_x_px=Math.ceil((data[1][0]-data[0][0])*w_scale)}else{delta_x_px=10}var pref_color=parseInt(this.prefs.color.slice(1),16),pref_r=(pref_color&16711680)>>16,pref_g=(pref_color&65280)>>8,pref_b=pref_color&255;for(var i=0,len=data.length;i<len;i++){ctx.fillStyle=ctx.strokeStyle=this.prefs.color;x_scaled=Math.round((data[i][0]-view_start-0.5)*w_scale);y=data[i][1];var top_overflow=false,bot_overflow=false;if(y===null){if(in_path&&mode==="Filled"){ctx.lineTo(x_scaled,height_px)}in_path=false;continue}if(y<min_value){bot_overflow=true;y=min_value}else{if(y>max_value){top_overflow=true;y=max_value}}if(mode==="Histogram"){y=Math.round(y/vertical_range*height_px);ctx.fillRect(x_scaled,y_zero,delta_x_px,-y)}else{if(mode==="Intensity"){var saturation=(y-min_value)/vertical_range,new_r=Math.round(pref_r+(255-pref_r)*(1-saturation)),new_g=Math.round(pref_g+(255-pref_g)*(1-saturation)),new_b=Math.round(pref_b+(255-pref_b)*(1-saturation));ctx.fillStyle="rgb("+new_r+","+new_g+","+new_b+")";ctx.fillRect(x_scaled,0,delta_x_px,height_px)}else{y=Math.round(height_px-(y-min_value)/vertical_range*height_px);if(in_path){ctx.lineTo(x_scaled,y)}else{in_path=true;if(mode==="Filled"){ctx.moveTo(x_scaled,height_px);ctx.lineTo(x_scaled,y)}else{ctx.moveTo(x_scaled,y)}}}}ctx.fillStyle=this.prefs.overflow_color;if(top_overflow||bot_overflow){var overflow_x;if(mode==="Histogram"||mode==="Intensity"){overflow_x=delta_x_px}else{x_scaled-=2;overflow_x=4}if(top_overflow){ctx.fillRect(x_scaled,0,overflow_x,3)}if(bot_overflow){ctx.fillRect(x_scaled,height_px-3,overflow_x,3)}}ctx.fillStyle=this.prefs.color}if(mode==="Filled"){if(in_path){ctx.lineTo(x_scaled,y_zero);ctx.lineTo(0,y_zero)}ctx.fill()}else{ctx.stroke()}ctx.restore()};var FeaturePositionMapper=function(slot_height){this.feature_positions={};this.slot_height=slot_height;this.translation=0;this.y_translation=0};FeaturePositionMapper.prototype.map_feature_data=function(feature_data,slot,x_start,x_end){if(!this.feature_positions[slot]){this.feature_positions[slot]=[]}this.feature_positions[slot].push({data:feature_data,x_start:x_start,x_end:x_end})};FeaturePositionMapper.prototype.get_feature_data=function(x,y){var slot=Math.floor((y-this.y_translation)/this.slot_height),feature_dict;if(!this.feature_positions[slot]){return null}x+=this.translation;for(var i=0;i<this.feature_positions[slot].length;i++){feature_dict=this.feature_positions[slot][i];if(x>=feature_dict.x_start&&x<=feature_dict.x_end){return feature_dict.data}}};var FeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){Painter.call(this,data,view_start,view_end,prefs,mode);this.alpha_scaler=(alpha_scaler?alpha_scaler:new Scaler());this.height_scaler=(height_scaler?height_scaler:new Scaler())};FeaturePainter.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};extend(FeaturePainter.prototype,{get_required_height:function(rows_required,width){var required_height=this.get_row_height(),y_scale=required_height,mode=this.mode;if(mode==="no_detail"||mode==="Squish"||mode==="Pack"){required_height=rows_required*y_scale}return required_height+this.get_top_padding(width)+this.get_bottom_padding(width)},get_top_padding:function(width){return 0},get_bottom_padding:function(width){return Math.max(Math.round(this.get_row_height()/2),5)},draw:function(ctx,width,height,w_scale,slots){var data=this.data,view_start=this.view_start,view_end=this.view_end;ctx.save();ctx.fillStyle=this.prefs.block_color;ctx.textAlign="right";var y_scale=this.get_row_height(),feature_mapper=new FeaturePositionMapper(y_scale),x_draw_coords;for(var i=0,len=data.length;i<len;i++){var feature=data[i],feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],slot=(slots&&slots[feature_uid]!==undefined?slots[feature_uid]:null);if((feature_start<view_end&&feature_end>view_start)&&(this.mode==="Dense"||slot!==null)){x_draw_coords=this.draw_element(ctx,this.mode,feature,slot,view_start,view_end,w_scale,y_scale,width);feature_mapper.map_feature_data(feature,slot,x_draw_coords[0],x_draw_coords[1])}}ctx.restore();feature_mapper.y_translation=this.get_top_padding(width);return feature_mapper},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){console.log("WARNING: Unimplemented function.");return[0,0]}});var DENSE_TRACK_HEIGHT=10,NO_DETAIL_TRACK_HEIGHT=3,SQUISH_TRACK_HEIGHT=5,PACK_TRACK_HEIGHT=10,NO_DETAIL_FEATURE_HEIGHT=1,DENSE_FEATURE_HEIGHT=9,SQUISH_FEATURE_HEIGHT=3,PACK_FEATURE_HEIGHT=9,LABEL_SPACING=2,CONNECTOR_COLOR="#ccc";var LinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.draw_background_connector=true;this.draw_individual_connectors=false};extend(LinkedFeaturePainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var mode=this.mode,height;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="no_detail"){height=NO_DETAIL_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT}}}return height},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],feature_strand=feature[4],f_start=Math.floor(Math.max(0,(feature_start-tile_low-0.5)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low-0.5)*w_scale))),draw_start=f_start,draw_end=f_end,y_center=(mode==="Dense"?0:(0+slot))*y_scale+this.get_top_padding(width),thickness,y_start,thick_start=null,thick_end=null,block_color=(!feature_strand||feature_strand==="+"||feature_strand==="."?this.prefs.block_color:this.prefs.reverse_strand_color);label_color=this.prefs.label_color;ctx.globalAlpha=this.alpha_scaler.gen_val(feature);if(mode==="Dense"){slot=1}if(mode==="no_detail"){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_center+5,f_end-f_start,NO_DETAIL_FEATURE_HEIGHT)}else{var feature_ts=feature[5],feature_te=feature[6],feature_blocks=feature[7],full_height=true;if(feature_ts&&feature_te){thick_start=Math.floor(Math.max(0,(feature_ts-tile_low)*w_scale));thick_end=Math.ceil(Math.min(width,Math.max(0,(feature_te-tile_low)*w_scale)))}var thin_height,thick_height;if(mode==="Squish"){thin_height=1;thick_height=SQUISH_FEATURE_HEIGHT;full_height=false}else{if(mode==="Dense"){thin_height=5;thick_height=DENSE_FEATURE_HEIGHT}else{thin_height=5;thick_height=PACK_FEATURE_HEIGHT}}if(!feature_blocks){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_center+1,f_end-f_start,thick_height);if(feature_strand&&full_height){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}ctx.fillRect(f_start,y_center+1,f_end-f_start,thick_height)}}else{var cur_y_center,cur_height;if(mode==="Squish"||mode==="Dense"){cur_y_center=y_center+Math.floor(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}else{if(feature_strand){cur_y_center=y_center;cur_height=thick_height}else{cur_y_center+=(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}}if(this.draw_background_connector){if(mode==="Squish"||mode==="Dense"){ctx.fillStyle=CONNECTOR_COLOR}else{if(feature_strand){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand")}}}else{ctx.fillStyle=CONNECTOR_COLOR}}ctx.fillRect(f_start,cur_y_center,f_end-f_start,cur_height)}var start_and_height;for(var k=0,k_len=feature_blocks.length;k<k_len;k++){var block=feature_blocks[k],block_start=Math.floor(Math.max(0,(block[0]-tile_low-0.5)*w_scale)),block_end=Math.ceil(Math.min(width,Math.max((block[1]-tile_low-0.5)*w_scale))),last_block_start,last_block_end;if(block_start>block_end){continue}ctx.fillStyle=block_color;ctx.fillRect(block_start,y_center+(thick_height-thin_height)/2+1,block_end-block_start,thin_height);if(thick_start!==undefined&&feature_te>feature_ts&&!(block_start>thick_end||block_end<thick_start)){var block_thick_start=Math.max(block_start,thick_start),block_thick_end=Math.min(block_end,thick_end);ctx.fillRect(block_thick_start,y_center+1,block_thick_end-block_thick_start,thick_height);if(feature_blocks.length===1&&mode==="Pack"){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}if(block_thick_start+14<block_thick_end){block_thick_start+=2;block_thick_end-=2}ctx.fillRect(block_thick_start,y_center+1,block_thick_end-block_thick_start,thick_height)}}if(this.draw_individual_connectors&&last_block_start){this.draw_connector(ctx,last_block_start,last_block_end,block_start,block_end,y_center)}last_block_start=block_start;last_block_end=block_end}if(mode==="Pack"){ctx.globalAlpha=1;ctx.fillStyle="white";var hscale_factor=this.height_scaler.gen_val(feature),new_height=Math.ceil(thick_height*hscale_factor),ws_height=Math.round((thick_height-new_height)/2);if(hscale_factor!==1){ctx.fillRect(f_start,cur_y_center+1,f_end-f_start,ws_height);ctx.fillRect(f_start,cur_y_center+thick_height-ws_height+1,f_end-f_start,ws_height)}}}ctx.globalAlpha=1;if(feature_name&&mode==="Pack"&&feature_start>tile_low){ctx.fillStyle=label_color;if(tile_low===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_center+8);draw_end+=ctx.measureText(feature_name).width+LABEL_SPACING}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_center+8);draw_start-=ctx.measureText(feature_name).width+LABEL_SPACING}}}ctx.globalAlpha=1;return[draw_start,draw_end]}});var ReadPainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler,ref_seq,base_color_fn){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.ref_seq=(ref_seq?ref_seq.data:null);this.base_color_fn=base_color_fn};extend(ReadPainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var height,mode=this.mode;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT;if(this.prefs.show_insertions){height*=2}}}return height},draw_read:function(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,cigar,strand,read_seq){ctx.textAlign="center";var tile_region=[tile_low,tile_high],base_offset=0,seq_offset=0,gap=Math.round(w_scale/2),char_width_px=ctx.canvas.manager.char_width_px,block_color=(strand==="+"?this.prefs.block_color:this.prefs.reverse_strand_color),pack_mode=(mode==="Pack");var draw_last=[];if(!cigar){cigar=[[0,read_seq.length]]}for(var cig_id=0,len=cigar.length;cig_id<len;cig_id++){var cig=cigar[cig_id],cig_op="MIDNSHP=X"[cig[0]],cig_len=cig[1];if(cig_op==="H"||cig_op==="S"){base_offset-=cig_len}var seq_start=feature_start+base_offset,s_start=Math.floor(Math.max(0,(seq_start-tile_low-0.5)*w_scale)),s_end=Math.floor(Math.max(0,(seq_start+cig_len-tile_low-0.5)*w_scale));if(s_start===s_end){s_end+=1}switch(cig_op){case"H":break;case"S":case"M":case"=":if(is_overlap([seq_start,seq_start+cig_len],tile_region)){ctx.fillStyle=block_color;ctx.fillRect(s_start,y_center+(pack_mode?1:4),s_end-s_start,(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT));var seq=read_seq.slice(seq_offset,seq_offset+cig_len),ref_char,read_char,x_pos;for(var c=0,str_len=seq.length;c<str_len;c++){if(seq_start+c>=tile_low&&seq_start+c<=tile_high){ref_char=(this.ref_seq?this.ref_seq[seq_start-tile_low+c]:null);read_char=seq[c];x_pos=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));if((ref_char&&(!this.prefs.show_differences||(read_char.toLowerCase!=="n"&&(ref_char.toLowerCase()!==read_char.toLowerCase()))))||(!ref_char&&!this.prefs.show_differences)){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillStyle=this.base_color_fn(seq[c]);if(pack_mode&&w_scale>char_width_px){ctx.fillText(seq[c],c_start,y_center+9)}else{if(w_scale>0.05){ctx.fillRect(c_start,y_center+(pack_mode?1:4),Math.max(1,Math.round(w_scale)),(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT))}}}}}}seq_offset+=cig_len;base_offset+=cig_len;break;case"N":ctx.fillStyle=CONNECTOR_COLOR;ctx.fillRect(s_start,y_center+5,s_end-s_start,1);base_offset+=cig_len;break;case"D":ctx.fillStyle="red";ctx.fillRect(s_start,y_center+4,s_end-s_start,3);base_offset+=cig_len;break;case"P":break;case"I":var insert_x_coord=s_start-gap;if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var seq=ref_seq.slice(seq_offset,seq_offset+cig_len);if(this.prefs.show_insertions){var x_center=s_start-(s_end-s_start)/2;if((mode==="Pack"||this.mode==="Auto")&&ref_seq!==undefined&&w_scale>char_width_px){ctx.fillStyle="yellow";ctx.fillRect(x_center-gap,y_center-9,s_end-s_start,9);draw_last[draw_last.length]={type:"triangle",data:[insert_x_coord,y_center+4,5]};ctx.fillStyle=CONNECTOR_COLOR;switch(compute_overlap([seq_start,seq_start+cig_len],tile_region)){case (OVERLAP_START):seq=seq.slice(tile_low-seq_start);break;case (OVERLAP_END):seq=seq.slice(0,seq_start-tile_high);break;case (CONTAINED_BY):break;case (CONTAINS):seq=seq.slice(tile_low-seq_start,seq_start-tile_high);break}for(var c=0,str_len=seq.length;c<str_len;c++){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillText(seq[c],c_start-(s_end-s_start)/2,y_center)}}else{ctx.fillStyle="yellow";ctx.fillRect(x_center,y_center+(this.mode!=="Dense"?2:5),s_end-s_start,(mode!=="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}else{if((mode==="Pack"||this.mode==="Auto")&&ref_seq!==undefined&&w_scale>char_width_px){draw_last.push({type:"text",data:[seq.length,insert_x_coord,y_center+9]})}else{}}}seq_offset+=cig_len;break;case"X":seq_offset+=cig_len;break}}ctx.fillStyle="yellow";var item,type,data;for(var i=0;i<draw_last.length;i++){item=draw_last[i];type=item.type;data=item.data;if(type==="text"){ctx.save();ctx.font="bold "+ctx.font;ctx.fillText(data[0],data[1],data[2]);ctx.restore()}else{if(type==="triangle"){drawDownwardEquilateralTriangle(ctx,data[0],data[1],data[2])}}}},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],f_start=Math.floor(Math.max(0,(feature_start-tile_low-0.5)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low-0.5)*w_scale))),y_center=(mode==="Dense"?0:(0+slot))*y_scale,label_color=this.prefs.label_color;if(feature[5] instanceof Array){var b1_start=Math.floor(Math.max(0,(feature[4][0]-tile_low)*w_scale)),b1_end=Math.ceil(Math.min(width,Math.max(0,(feature[4][1]-tile_low)*w_scale))),b2_start=Math.floor(Math.max(0,(feature[5][0]-tile_low)*w_scale)),b2_end=Math.ceil(Math.min(width,Math.max(0,(feature[5][1]-tile_low)*w_scale))),connector=true;if(feature[4][1]>=tile_low&&feature[4][0]<=tile_high&&feature[4][2]){this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature[4][0],feature[4][2],feature[4][3],feature[4][4])}else{connector=false}if(feature[5][1]>=tile_low&&feature[5][0]<=tile_high&&feature[5][2]){this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature[5][0],feature[5][2],feature[5][3],feature[5][4])}else{connector=false}if(connector&&b2_start>b1_end){ctx.fillStyle=CONNECTOR_COLOR;dashedLine(ctx,b1_end,y_center+5,b2_start,y_center+5)}}else{this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,feature[4],feature[5],feature[6])}if(mode==="Pack"&&feature_start>tile_low&&feature_name!=="."){ctx.fillStyle=this.prefs.label_color;var tile_index=1;if(tile_index===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_center+8)}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_center+8)}}return[0,0]}});var ArcLinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){LinkedFeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.longest_feature_length=this.calculate_longest_feature_length();this.draw_background_connector=false;this.draw_individual_connectors=true};extend(ArcLinkedFeaturePainter.prototype,FeaturePainter.prototype,LinkedFeaturePainter.prototype,{calculate_longest_feature_length:function(){var longest_feature_length=0;for(var i=0,len=this.data.length;i<len;i++){var feature=this.data[i],feature_start=feature[1],feature_end=feature[2];longest_feature_length=Math.max(longest_feature_length,feature_end-feature_start)}return longest_feature_length},get_top_padding:function(width){var view_range=this.view_end-this.view_start,w_scale=width/view_range;return Math.min(128,Math.ceil((this.longest_feature_length/2)*w_scale))},draw_connector:function(ctx,block1_start,block1_end,block2_start,block2_end,y_center){var x_center=(block1_end+block2_start)/2,radius=block2_start-x_center;var angle1=Math.PI,angle2=0;if(radius>0){ctx.beginPath();ctx.arc(x_center,y_center,block2_start-x_center,Math.PI,0);ctx.stroke()}}});var Color=function(rgb,a){if(Array.isArray(rgb)){this.rgb=rgb}else{if(rgb.length==6){this.rgb=rgb.match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{if(rgb.length==7){this.rgb=rgb.substring(1,7).match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{this.rgb=rgb.split("").map(function(c){return parseInt(c+c,16)})}}}this.alpha=typeof(a)==="number"?a:1};Color.prototype={eval:function(){return this},toCSS:function(){if(this.alpha<1){return"rgba("+this.rgb.map(function(c){return Math.round(c)}).concat(this.alpha).join(", ")+")"}else{return"#"+this.rgb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")}},toHSL:function(){var r=this.rgb[0]/255,g=this.rgb[1]/255,b=this.rgb[2]/255,a=this.alpha;var max=Math.max(r,g,b),min=Math.min(r,g,b);var h,s,l=(max+min)/2,d=max-min;if(max===min){h=s=0}else{s=l>0.5?d/(2-max-min):d/(max+min);switch(max){case r:h=(g-b)/d+(g<b?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4;break}h/=6}return{h:h*360,s:s,l:l,a:a}},toARGB:function(){var argb=[Math.round(this.alpha*255)].concat(this.rgb);return"#"+argb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")},mix:function(color2,weight){color1=this;var p=weight;var w=p*2-1;var a=color1.toHSL().a-color2.toHSL().a;var w1=(((w*a==-1)?w:(w+a)/(1+w*a))+1)/2;var w2=1-w1;var rgb=[color1.rgb[0]*w1+color2.rgb[0]*w2,color1.rgb[1]*w1+color2.rgb[1]*w2,color1.rgb[2]*w1+color2.rgb[2]*w2];var alpha=color1.alpha*p+color2.alpha*(1-p);return new Color(rgb,alpha)}};var LinearRamp=function(start_color,end_color,start_value,end_value){this.start_color=new Color(start_color);this.end_color=new Color(end_color);this.start_value=start_value;this.end_value=end_value;this.value_range=end_value-start_value};LinearRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);value=(value-this.start_value)/this.value_range;return this.start_color.mix(this.end_color,1-value).toCSS()};var SplitRamp=function(start_color,middle_color,end_color,start_value,end_value){this.positive_ramp=new LinearRamp(middle_color,end_color,0,end_value);this.negative_ramp=new LinearRamp(middle_color,start_color,0,-start_value);this.start_value=start_value;this.end_value=end_value};SplitRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);if(value>=0){return this.positive_ramp.map_value(value)}else{return this.negative_ramp.map_value(-value)}};var DiagonalHeatmapPainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][5])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][5])}this.prefs.max_value=max_value}};DiagonalHeatmapPainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Heatmap",pos_color:"#FF8C00",neg_color:"#4169E1"};DiagonalHeatmapPainter.prototype.draw=function(ctx,width,height,w_scale){var min_value=this.prefs.min_value,max_value=this.prefs.max_value,value_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data,invsqrt2=1/Math.sqrt(2);var ramp=(new SplitRamp(this.prefs.neg_color,"#FFFFFF",this.prefs.pos_color,min_value,max_value));var d,s1,e1,s2,e2,value;var scale=function(p){return(p-view_start)*w_scale};ctx.save();ctx.rotate(-45*Math.PI/180);ctx.scale(invsqrt2,invsqrt2);for(var i=0,len=data.length;i<len;i++){d=data[i];s1=scale(d[1]);e1=scale(d[2]);s2=scale(d[4]);e2=scale(d[5]);value=d[6];ctx.fillStyle=(ramp.map_value(value));ctx.fillRect(s1,s2,(e1-s1),(e2-s2))}ctx.restore()};return{Scaler:Scaler,SummaryTreePainter:SummaryTreePainter,LinePainter:LinePainter,LinkedFeaturePainter:LinkedFeaturePainter,ReadPainter:ReadPainter,ArcLinkedFeaturePainter:ArcLinkedFeaturePainter,DiagonalHeatmapPainter:DiagonalHeatmapPainter}});
\ No newline at end of file
+define(["libs/underscore"],function(_){var extend=_.extend;var BEFORE=1001,CONTAINS=1002,OVERLAP_START=1003,OVERLAP_END=1004,CONTAINED_BY=1005,AFTER=1006;var compute_overlap=function(first_region,second_region){var first_start=first_region[0],first_end=first_region[1],second_start=second_region[0],second_end=second_region[1],overlap;if(first_start<second_start){if(first_end<=second_start){overlap=BEFORE}else{if(first_end<=second_end){overlap=OVERLAP_START}else{overlap=CONTAINS}}}else{if(first_start>second_end){overlap=AFTER}else{if(first_end<=second_end){overlap=CONTAINED_BY}else{overlap=OVERLAP_END}}}return overlap};var is_overlap=function(first_region,second_region){var overlap=compute_overlap(first_region,second_region);return(overlap!==BEFORE&&overlap!==AFTER)};var dashedLine=function(ctx,x1,y1,x2,y2,dashLen){if(dashLen===undefined){dashLen=4}var dX=x2-x1;var dY=y2-y1;var dashes=Math.floor(Math.sqrt(dX*dX+dY*dY)/dashLen);var dashX=dX/dashes;var dashY=dY/dashes;var q;for(q=0;q<dashes;q++,x1+=dashX,y1+=dashY){if(q%2!==0){continue}ctx.fillRect(x1,y1,dashLen,1)}};var drawDownwardEquilateralTriangle=function(ctx,down_vertex_x,down_vertex_y,side_len){var x1=down_vertex_x-side_len/2,x2=down_vertex_x+side_len/2,y=down_vertex_y-Math.sqrt(side_len*3/2);ctx.beginPath();ctx.moveTo(x1,y);ctx.lineTo(x2,y);ctx.lineTo(down_vertex_x,down_vertex_y);ctx.lineTo(x1,y);ctx.strokeStyle=this.fillStyle;ctx.fill();ctx.stroke();ctx.closePath()};var Scaler=function(default_val){this.default_val=(default_val?default_val:1)};Scaler.prototype.gen_val=function(input){return this.default_val};var Painter=function(data,view_start,view_end,prefs,mode){this.data=data;this.view_start=view_start;this.view_end=view_end;this.prefs=extend({},this.default_prefs,prefs);this.mode=mode};Painter.prototype.default_prefs={};Painter.prototype.draw=function(ctx,width,height,w_scale){};var SummaryTreePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode)};SummaryTreePainter.prototype.default_prefs={show_counts:false};SummaryTreePainter.prototype.draw=function(ctx,width,height,w_scale){var view_start=this.view_start,points=this.data.data,max=(this.prefs.histogram_max?this.prefs.histogram_max:this.data.max),base_y=height;delta_x_px=Math.ceil(this.data.delta*w_scale);ctx.save();for(var i=0,len=points.length;i<len;i++){var x=Math.floor((points[i][0]-view_start)*w_scale);var y=points[i][1];if(!y){continue}var y_px=y/max*height;if(y!==0&&y_px<1){y_px=1}ctx.fillStyle=this.prefs.block_color;ctx.fillRect(x,base_y-y_px,delta_x_px,y_px);var text_padding_req_x=4;if(this.prefs.show_counts&&(ctx.measureText(y).width+text_padding_req_x)<delta_x_px){ctx.fillStyle=this.prefs.label_color;ctx.textAlign="center";ctx.fillText(y,x+(delta_x_px/2),10)}}ctx.restore()};var LinePainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][1])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][1])}this.prefs.max_value=max_value}};LinePainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Histogram",color:"#000",overflow_color:"#F66"};LinePainter.prototype.draw=function(ctx,width,height,w_scale){var in_path=false,min_value=this.prefs.min_value,max_value=this.prefs.max_value,vertical_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data;ctx.save();var y_zero=Math.round(height+min_value/vertical_range*height);if(mode!=="Intensity"){ctx.fillStyle="#aaa";ctx.fillRect(0,y_zero,width,1)}ctx.beginPath();var x_scaled,y,delta_x_px;if(data.length>1){delta_x_px=Math.ceil((data[1][0]-data[0][0])*w_scale)}else{delta_x_px=10}var pref_color=parseInt(this.prefs.color.slice(1),16),pref_r=(pref_color&16711680)>>16,pref_g=(pref_color&65280)>>8,pref_b=pref_color&255;for(var i=0,len=data.length;i<len;i++){ctx.fillStyle=ctx.strokeStyle=this.prefs.color;x_scaled=Math.round((data[i][0]-view_start-0.5)*w_scale);y=data[i][1];var top_overflow=false,bot_overflow=false;if(y===null){if(in_path&&mode==="Filled"){ctx.lineTo(x_scaled,height_px)}in_path=false;continue}if(y<min_value){bot_overflow=true;y=min_value}else{if(y>max_value){top_overflow=true;y=max_value}}if(mode==="Histogram"){y=Math.round(y/vertical_range*height_px);ctx.fillRect(x_scaled,y_zero,delta_x_px,-y)}else{if(mode==="Intensity"){var saturation=(y-min_value)/vertical_range,new_r=Math.round(pref_r+(255-pref_r)*(1-saturation)),new_g=Math.round(pref_g+(255-pref_g)*(1-saturation)),new_b=Math.round(pref_b+(255-pref_b)*(1-saturation));ctx.fillStyle="rgb("+new_r+","+new_g+","+new_b+")";ctx.fillRect(x_scaled,0,delta_x_px,height_px)}else{y=Math.round(height_px-(y-min_value)/vertical_range*height_px);if(in_path){ctx.lineTo(x_scaled,y)}else{in_path=true;if(mode==="Filled"){ctx.moveTo(x_scaled,height_px);ctx.lineTo(x_scaled,y)}else{ctx.moveTo(x_scaled,y)}}}}ctx.fillStyle=this.prefs.overflow_color;if(top_overflow||bot_overflow){var overflow_x;if(mode==="Histogram"||mode==="Intensity"){overflow_x=delta_x_px}else{x_scaled-=2;overflow_x=4}if(top_overflow){ctx.fillRect(x_scaled,0,overflow_x,3)}if(bot_overflow){ctx.fillRect(x_scaled,height_px-3,overflow_x,3)}}ctx.fillStyle=this.prefs.color}if(mode==="Filled"){if(in_path){ctx.lineTo(x_scaled,y_zero);ctx.lineTo(0,y_zero)}ctx.fill()}else{ctx.stroke()}ctx.restore()};var FeaturePositionMapper=function(slot_height){this.feature_positions={};this.slot_height=slot_height;this.translation=0;this.y_translation=0};FeaturePositionMapper.prototype.map_feature_data=function(feature_data,slot,x_start,x_end){if(!this.feature_positions[slot]){this.feature_positions[slot]=[]}this.feature_positions[slot].push({data:feature_data,x_start:x_start,x_end:x_end})};FeaturePositionMapper.prototype.get_feature_data=function(x,y){var slot=Math.floor((y-this.y_translation)/this.slot_height),feature_dict;if(!this.feature_positions[slot]){return null}x+=this.translation;for(var i=0;i<this.feature_positions[slot].length;i++){feature_dict=this.feature_positions[slot][i];if(x>=feature_dict.x_start&&x<=feature_dict.x_end){return feature_dict.data}}};var FeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){Painter.call(this,data,view_start,view_end,prefs,mode);this.alpha_scaler=(alpha_scaler?alpha_scaler:new Scaler());this.height_scaler=(height_scaler?height_scaler:new Scaler())};FeaturePainter.prototype.default_prefs={block_color:"#FFF",connector_color:"#FFF"};extend(FeaturePainter.prototype,{get_required_height:function(rows_required,width){var required_height=this.get_row_height(),y_scale=required_height,mode=this.mode;if(mode==="no_detail"||mode==="Squish"||mode==="Pack"){required_height=rows_required*y_scale}return required_height+this.get_top_padding(width)+this.get_bottom_padding(width)},get_top_padding:function(width){return 0},get_bottom_padding:function(width){return Math.max(Math.round(this.get_row_height()/2),5)},draw:function(ctx,width,height,w_scale,slots){var data=this.data,view_start=this.view_start,view_end=this.view_end;ctx.save();ctx.fillStyle=this.prefs.block_color;ctx.textAlign="right";var y_scale=this.get_row_height(),feature_mapper=new FeaturePositionMapper(y_scale),x_draw_coords;for(var i=0,len=data.length;i<len;i++){var feature=data[i],feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],slot=(slots&&slots[feature_uid]!==undefined?slots[feature_uid]:null);if((feature_start<view_end&&feature_end>view_start)&&(this.mode==="Dense"||slot!==null)){x_draw_coords=this.draw_element(ctx,this.mode,feature,slot,view_start,view_end,w_scale,y_scale,width);feature_mapper.map_feature_data(feature,slot,x_draw_coords[0],x_draw_coords[1])}}ctx.restore();feature_mapper.y_translation=this.get_top_padding(width);return feature_mapper},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){console.log("WARNING: Unimplemented function.");return[0,0]}});var DENSE_TRACK_HEIGHT=10,NO_DETAIL_TRACK_HEIGHT=3,SQUISH_TRACK_HEIGHT=5,PACK_TRACK_HEIGHT=10,NO_DETAIL_FEATURE_HEIGHT=1,DENSE_FEATURE_HEIGHT=9,SQUISH_FEATURE_HEIGHT=3,PACK_FEATURE_HEIGHT=9,LABEL_SPACING=2,CONNECTOR_COLOR="#ccc";var LinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.draw_background_connector=true;this.draw_individual_connectors=false};extend(LinkedFeaturePainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var mode=this.mode,height;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="no_detail"){height=NO_DETAIL_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT}}}return height},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],feature_strand=feature[4],f_start=Math.floor(Math.max(0,(feature_start-tile_low-0.5)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low-0.5)*w_scale))),draw_start=f_start,draw_end=f_end,y_center=(mode==="Dense"?0:(0+slot))*y_scale+this.get_top_padding(width),thickness,y_start,thick_start=null,thick_end=null,block_color=(!feature_strand||feature_strand==="+"||feature_strand==="."?this.prefs.block_color:this.prefs.reverse_strand_color);label_color=this.prefs.label_color;ctx.globalAlpha=this.alpha_scaler.gen_val(feature);if(mode==="Dense"){slot=1}if(mode==="no_detail"){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_center+5,f_end-f_start,NO_DETAIL_FEATURE_HEIGHT)}else{var feature_ts=feature[5],feature_te=feature[6],feature_blocks=feature[7],full_height=true;if(feature_ts&&feature_te){thick_start=Math.floor(Math.max(0,(feature_ts-tile_low)*w_scale));thick_end=Math.ceil(Math.min(width,Math.max(0,(feature_te-tile_low)*w_scale)))}var thin_height,thick_height;if(mode==="Squish"){thin_height=1;thick_height=SQUISH_FEATURE_HEIGHT;full_height=false}else{if(mode==="Dense"){thin_height=5;thick_height=DENSE_FEATURE_HEIGHT}else{thin_height=5;thick_height=PACK_FEATURE_HEIGHT}}if(!feature_blocks){ctx.fillStyle=block_color;ctx.fillRect(f_start,y_center+1,f_end-f_start,thick_height);if(feature_strand&&full_height){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}ctx.fillRect(f_start,y_center+1,f_end-f_start,thick_height)}}else{var cur_y_center,cur_height;if(mode==="Squish"||mode==="Dense"){cur_y_center=y_center+Math.floor(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}else{if(feature_strand){cur_y_center=y_center;cur_height=thick_height}else{cur_y_center+=(SQUISH_FEATURE_HEIGHT/2)+1;cur_height=1}}if(this.draw_background_connector){if(mode==="Squish"||mode==="Dense"){ctx.fillStyle=CONNECTOR_COLOR}else{if(feature_strand){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand")}}}else{ctx.fillStyle=CONNECTOR_COLOR}}ctx.fillRect(f_start,cur_y_center,f_end-f_start,cur_height)}var start_and_height;for(var k=0,k_len=feature_blocks.length;k<k_len;k++){var block=feature_blocks[k],block_start=Math.floor(Math.max(0,(block[0]-tile_low-0.5)*w_scale)),block_end=Math.ceil(Math.min(width,Math.max((block[1]-tile_low-0.5)*w_scale))),last_block_start,last_block_end;if(block_start>block_end){continue}ctx.fillStyle=block_color;ctx.fillRect(block_start,y_center+(thick_height-thin_height)/2+1,block_end-block_start,thin_height);if(thick_start!==undefined&&feature_te>feature_ts&&!(block_start>thick_end||block_end<thick_start)){var block_thick_start=Math.max(block_start,thick_start),block_thick_end=Math.min(block_end,thick_end);ctx.fillRect(block_thick_start,y_center+1,block_thick_end-block_thick_start,thick_height);if(feature_blocks.length===1&&mode==="Pack"){if(feature_strand==="+"){ctx.fillStyle=ctx.canvas.manager.get_pattern("right_strand_inv")}else{if(feature_strand==="-"){ctx.fillStyle=ctx.canvas.manager.get_pattern("left_strand_inv")}}if(block_thick_start+14<block_thick_end){block_thick_start+=2;block_thick_end-=2}ctx.fillRect(block_thick_start,y_center+1,block_thick_end-block_thick_start,thick_height)}}if(this.draw_individual_connectors&&last_block_start){this.draw_connector(ctx,last_block_start,last_block_end,block_start,block_end,y_center)}last_block_start=block_start;last_block_end=block_end}if(mode==="Pack"){ctx.globalAlpha=1;ctx.fillStyle="white";var hscale_factor=this.height_scaler.gen_val(feature),new_height=Math.ceil(thick_height*hscale_factor),ws_height=Math.round((thick_height-new_height)/2);if(hscale_factor!==1){ctx.fillRect(f_start,cur_y_center+1,f_end-f_start,ws_height);ctx.fillRect(f_start,cur_y_center+thick_height-ws_height+1,f_end-f_start,ws_height)}}}ctx.globalAlpha=1;if(feature_name&&mode==="Pack"&&feature_start>tile_low){ctx.fillStyle=label_color;if(tile_low===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_center+8);draw_end+=ctx.measureText(feature_name).width+LABEL_SPACING}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_center+8);draw_start-=ctx.measureText(feature_name).width+LABEL_SPACING}}}ctx.globalAlpha=1;return[draw_start,draw_end]}});var ReadPainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler,ref_seq,base_color_fn){FeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.ref_seq=(ref_seq?ref_seq.data:null);this.base_color_fn=base_color_fn};extend(ReadPainter.prototype,FeaturePainter.prototype,{get_row_height:function(){var height,mode=this.mode;if(mode==="Dense"){height=DENSE_TRACK_HEIGHT}else{if(mode==="Squish"){height=SQUISH_TRACK_HEIGHT}else{height=PACK_TRACK_HEIGHT;if(this.prefs.show_insertions){height*=2}}}return height},draw_read:function(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,cigar,strand,read_seq){ctx.textAlign="center";var tile_region=[tile_low,tile_high],base_offset=0,seq_offset=0,gap=Math.round(w_scale/2),char_width_px=ctx.canvas.manager.char_width_px,block_color=(strand==="+"?this.prefs.block_color:this.prefs.reverse_strand_color),pack_mode=(mode==="Pack");var draw_last=[];if(!cigar){cigar=[[0,read_seq.length]]}for(var cig_id=0,len=cigar.length;cig_id<len;cig_id++){var cig=cigar[cig_id],cig_op="MIDNSHP=X"[cig[0]],cig_len=cig[1];if(cig_op==="H"||cig_op==="S"){base_offset-=cig_len}var seq_start=feature_start+base_offset,s_start=Math.floor(Math.max(-0.5*w_scale,(seq_start-tile_low-0.5)*w_scale)),s_end=Math.floor(Math.max(0,(seq_start+cig_len-tile_low-0.5)*w_scale));if(s_start===s_end){s_end+=1}switch(cig_op){case"H":break;case"S":case"M":case"=":if(is_overlap([seq_start,seq_start+cig_len],tile_region)){ctx.fillStyle=block_color;ctx.fillRect(s_start,y_center+(pack_mode?1:4),s_end-s_start,(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT));var seq=read_seq.slice(seq_offset,seq_offset+cig_len),ref_char,read_char,x_pos;for(var c=0,str_len=seq.length;c<str_len;c++){if(seq_start+c>=tile_low&&seq_start+c<=tile_high){ref_char=(this.ref_seq?this.ref_seq[seq_start-tile_low+c]:null);read_char=seq[c];x_pos=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));if((ref_char&&(!this.prefs.show_differences||(read_char.toLowerCase!=="n"&&(ref_char.toLowerCase()!==read_char.toLowerCase()))))||(!ref_char&&!this.prefs.show_differences)){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillStyle=this.base_color_fn(seq[c]);if(pack_mode&&w_scale>char_width_px){ctx.fillText(seq[c],c_start,y_center+9)}else{if(w_scale>0.05){ctx.fillRect(c_start,y_center+(pack_mode?1:4),Math.max(1,Math.round(w_scale)),(pack_mode?PACK_FEATURE_HEIGHT:SQUISH_FEATURE_HEIGHT))}}}}}}seq_offset+=cig_len;base_offset+=cig_len;break;case"N":ctx.fillStyle=CONNECTOR_COLOR;ctx.fillRect(s_start,y_center+5,s_end-s_start,1);base_offset+=cig_len;break;case"D":ctx.fillStyle="red";ctx.fillRect(s_start,y_center+4,s_end-s_start,3);base_offset+=cig_len;break;case"P":break;case"I":var insert_x_coord=s_start-gap;if(is_overlap([seq_start,seq_start+cig_len],tile_region)){var seq=read_seq.slice(seq_offset,seq_offset+cig_len);if(this.prefs.show_insertions){var x_center=s_start-(s_end-s_start)/2;if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){ctx.fillStyle="yellow";ctx.fillRect(x_center-gap,y_center-9,s_end-s_start,9);draw_last[draw_last.length]={type:"triangle",data:[insert_x_coord,y_center+4,5]};ctx.fillStyle=CONNECTOR_COLOR;switch(compute_overlap([seq_start,seq_start+cig_len],tile_region)){case (OVERLAP_START):seq=seq.slice(tile_low-seq_start);break;case (OVERLAP_END):seq=seq.slice(0,seq_start-tile_high);break;case (CONTAINED_BY):break;case (CONTAINS):seq=seq.slice(tile_low-seq_start,seq_start-tile_high);break}for(var c=0,str_len=seq.length;c<str_len;c++){var c_start=Math.floor(Math.max(0,(seq_start+c-tile_low)*w_scale));ctx.fillText(seq[c],c_start-(s_end-s_start)/2,y_center)}}else{ctx.fillStyle="yellow";ctx.fillRect(x_center,y_center+(this.mode!=="Dense"?2:5),s_end-s_start,(mode!=="Dense"?SQUISH_FEATURE_HEIGHT:DENSE_FEATURE_HEIGHT))}}else{if((mode==="Pack"||this.mode==="Auto")&&read_seq!==undefined&&w_scale>char_width_px){draw_last.push({type:"text",data:[seq.length,insert_x_coord,y_center+9]})}else{}}}seq_offset+=cig_len;break;case"X":seq_offset+=cig_len;break}}ctx.fillStyle="yellow";var item,type,data;for(var i=0;i<draw_last.length;i++){item=draw_last[i];type=item.type;data=item.data;if(type==="text"){ctx.save();ctx.font="bold "+ctx.font;ctx.fillText(data[0],data[1],data[2]);ctx.restore()}else{if(type==="triangle"){drawDownwardEquilateralTriangle(ctx,data[0],data[1],data[2])}}}},draw_element:function(ctx,mode,feature,slot,tile_low,tile_high,w_scale,y_scale,width){var feature_uid=feature[0],feature_start=feature[1],feature_end=feature[2],feature_name=feature[3],f_start=Math.floor(Math.max(-0.5*w_scale,(feature_start-tile_low-0.5)*w_scale)),f_end=Math.ceil(Math.min(width,Math.max(0,(feature_end-tile_low-0.5)*w_scale))),y_center=(mode==="Dense"?0:(0+slot))*y_scale,label_color=this.prefs.label_color;if(feature[5] instanceof Array){var b1_start=Math.floor(Math.max(0,(feature[4][0]-tile_low)*w_scale)),b1_end=Math.ceil(Math.min(width,Math.max(0,(feature[4][1]-tile_low)*w_scale))),b2_start=Math.floor(Math.max(0,(feature[5][0]-tile_low)*w_scale)),b2_end=Math.ceil(Math.min(width,Math.max(0,(feature[5][1]-tile_low)*w_scale))),connector=true;if(feature[4][1]>=tile_low&&feature[4][0]<=tile_high&&feature[4][2]){this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature[4][0],feature[4][2],feature[4][3],feature[4][4])}else{connector=false}if(feature[5][1]>=tile_low&&feature[5][0]<=tile_high&&feature[5][2]){this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature[5][0],feature[5][2],feature[5][3],feature[5][4])}else{connector=false}if(connector&&b2_start>b1_end){ctx.fillStyle=CONNECTOR_COLOR;dashedLine(ctx,b1_end,y_center+5,b2_start,y_center+5)}}else{this.draw_read(ctx,mode,w_scale,y_center,tile_low,tile_high,feature_start,feature[4],feature[5],feature[6])}if(mode==="Pack"&&feature_start>=tile_low&&feature_name!=="."){ctx.fillStyle=this.prefs.label_color;if(tile_low===0&&f_start-ctx.measureText(feature_name).width<0){ctx.textAlign="left";ctx.fillText(feature_name,f_end+LABEL_SPACING,y_center+8)}else{ctx.textAlign="right";ctx.fillText(feature_name,f_start-LABEL_SPACING,y_center+8)}}return[0,0]}});var ArcLinkedFeaturePainter=function(data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler){LinkedFeaturePainter.call(this,data,view_start,view_end,prefs,mode,alpha_scaler,height_scaler);this.longest_feature_length=this.calculate_longest_feature_length();this.draw_background_connector=false;this.draw_individual_connectors=true};extend(ArcLinkedFeaturePainter.prototype,FeaturePainter.prototype,LinkedFeaturePainter.prototype,{calculate_longest_feature_length:function(){var longest_feature_length=0;for(var i=0,len=this.data.length;i<len;i++){var feature=this.data[i],feature_start=feature[1],feature_end=feature[2];longest_feature_length=Math.max(longest_feature_length,feature_end-feature_start)}return longest_feature_length},get_top_padding:function(width){var view_range=this.view_end-this.view_start,w_scale=width/view_range;return Math.min(128,Math.ceil((this.longest_feature_length/2)*w_scale))},draw_connector:function(ctx,block1_start,block1_end,block2_start,block2_end,y_center){var x_center=(block1_end+block2_start)/2,radius=block2_start-x_center;var angle1=Math.PI,angle2=0;if(radius>0){ctx.beginPath();ctx.arc(x_center,y_center,block2_start-x_center,Math.PI,0);ctx.stroke()}}});var Color=function(rgb,a){if(Array.isArray(rgb)){this.rgb=rgb}else{if(rgb.length==6){this.rgb=rgb.match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{if(rgb.length==7){this.rgb=rgb.substring(1,7).match(/.{2}/g).map(function(c){return parseInt(c,16)})}else{this.rgb=rgb.split("").map(function(c){return parseInt(c+c,16)})}}}this.alpha=typeof(a)==="number"?a:1};Color.prototype={eval:function(){return this},toCSS:function(){if(this.alpha<1){return"rgba("+this.rgb.map(function(c){return Math.round(c)}).concat(this.alpha).join(", ")+")"}else{return"#"+this.rgb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")}},toHSL:function(){var r=this.rgb[0]/255,g=this.rgb[1]/255,b=this.rgb[2]/255,a=this.alpha;var max=Math.max(r,g,b),min=Math.min(r,g,b);var h,s,l=(max+min)/2,d=max-min;if(max===min){h=s=0}else{s=l>0.5?d/(2-max-min):d/(max+min);switch(max){case r:h=(g-b)/d+(g<b?6:0);break;case g:h=(b-r)/d+2;break;case b:h=(r-g)/d+4;break}h/=6}return{h:h*360,s:s,l:l,a:a}},toARGB:function(){var argb=[Math.round(this.alpha*255)].concat(this.rgb);return"#"+argb.map(function(i){i=Math.round(i);i=(i>255?255:(i<0?0:i)).toString(16);return i.length===1?"0"+i:i}).join("")},mix:function(color2,weight){color1=this;var p=weight;var w=p*2-1;var a=color1.toHSL().a-color2.toHSL().a;var w1=(((w*a==-1)?w:(w+a)/(1+w*a))+1)/2;var w2=1-w1;var rgb=[color1.rgb[0]*w1+color2.rgb[0]*w2,color1.rgb[1]*w1+color2.rgb[1]*w2,color1.rgb[2]*w1+color2.rgb[2]*w2];var alpha=color1.alpha*p+color2.alpha*(1-p);return new Color(rgb,alpha)}};var LinearRamp=function(start_color,end_color,start_value,end_value){this.start_color=new Color(start_color);this.end_color=new Color(end_color);this.start_value=start_value;this.end_value=end_value;this.value_range=end_value-start_value};LinearRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);value=(value-this.start_value)/this.value_range;return this.start_color.mix(this.end_color,1-value).toCSS()};var SplitRamp=function(start_color,middle_color,end_color,start_value,end_value){this.positive_ramp=new LinearRamp(middle_color,end_color,0,end_value);this.negative_ramp=new LinearRamp(middle_color,start_color,0,-start_value);this.start_value=start_value;this.end_value=end_value};SplitRamp.prototype.map_value=function(value){value=Math.max(value,this.start_value);value=Math.min(value,this.end_value);if(value>=0){return this.positive_ramp.map_value(value)}else{return this.negative_ramp.map_value(-value)}};var DiagonalHeatmapPainter=function(data,view_start,view_end,prefs,mode){Painter.call(this,data,view_start,view_end,prefs,mode);var i,len;if(this.prefs.min_value===undefined){var min_value=Infinity;for(i=0,len=this.data.length;i<len;i++){min_value=Math.min(min_value,this.data[i][5])}this.prefs.min_value=min_value}if(this.prefs.max_value===undefined){var max_value=-Infinity;for(i=0,len=this.data.length;i<len;i++){max_value=Math.max(max_value,this.data[i][5])}this.prefs.max_value=max_value}};DiagonalHeatmapPainter.prototype.default_prefs={min_value:undefined,max_value:undefined,mode:"Heatmap",pos_color:"#FF8C00",neg_color:"#4169E1"};DiagonalHeatmapPainter.prototype.draw=function(ctx,width,height,w_scale){var min_value=this.prefs.min_value,max_value=this.prefs.max_value,value_range=max_value-min_value,height_px=height,view_start=this.view_start,mode=this.mode,data=this.data,invsqrt2=1/Math.sqrt(2);var ramp=(new SplitRamp(this.prefs.neg_color,"#FFFFFF",this.prefs.pos_color,min_value,max_value));var d,s1,e1,s2,e2,value;var scale=function(p){return(p-view_start)*w_scale};ctx.save();ctx.rotate(-45*Math.PI/180);ctx.scale(invsqrt2,invsqrt2);for(var i=0,len=data.length;i<len;i++){d=data[i];s1=scale(d[1]);e1=scale(d[2]);s2=scale(d[4]);e2=scale(d[5]);value=d[6];ctx.fillStyle=(ramp.map_value(value));ctx.fillRect(s1,s2,(e1-s1),(e2-s2))}ctx.restore()};return{Scaler:Scaler,SummaryTreePainter:SummaryTreePainter,LinePainter:LinePainter,LinkedFeaturePainter:LinkedFeaturePainter,ReadPainter:ReadPainter,ArcLinkedFeaturePainter:ArcLinkedFeaturePainter,DiagonalHeatmapPainter:DiagonalHeatmapPainter}});
\ No newline at end of file
diff -r 5f20704ea90836a5fa54f63c78ceaa536010c4e8 -r 7369eda82e2cf7e10338232569ed9185bc3b526b static/scripts/viz/trackster/painters.js
--- a/static/scripts/viz/trackster/painters.js
+++ b/static/scripts/viz/trackster/painters.js
@@ -6,6 +6,7 @@
* Compute the type of overlap between two regions. They are assumed to be on the same chrom/contig.
* The overlap is computed relative to the second region; hence, OVERLAP_START indicates that the first
* region overlaps the start (but not the end) of the second region.
+ * NOTE: Coordinates are assumed to be in BED format: half open (start is closed, end is open).
*/
var BEFORE = 1001, CONTAINS = 1002, OVERLAP_START = 1003, OVERLAP_END = 1004, CONTAINED_BY = 1005, AFTER = 1006;
var compute_overlap = function(first_region, second_region) {
@@ -14,7 +15,7 @@
second_start = second_region[0], second_end = second_region[1],
overlap;
if (first_start < second_start) {
- if (first_end < second_start) {
+ if (first_end <= second_start) {
overlap = BEFORE;
}
else if (first_end <= second_end) {
@@ -763,7 +764,7 @@
}
var seq_start = feature_start + base_offset,
// -0.5 to offset sequence between bases.
- s_start = Math.floor( Math.max(0, (seq_start - tile_low - 0.5) * w_scale) ),
+ s_start = Math.floor( Math.max(-0.5 * w_scale, (seq_start - tile_low - 0.5) * w_scale) ),
s_end = Math.floor( Math.max(0, (seq_start + cig_len - tile_low - 0.5) * w_scale) );
// Make sure that read is drawn even if it too small to be rendered officially; in this case,
@@ -858,7 +859,7 @@
var insert_x_coord = s_start - gap;
if (is_overlap([seq_start, seq_start + cig_len], tile_region)) {
- var seq = ref_seq.slice(seq_offset, seq_offset + cig_len);
+ var seq = read_seq.slice(seq_offset, seq_offset + cig_len);
// Insertion point is between the sequence start and the previous base: (-gap) moves
// back from sequence start to insertion point.
if (this.prefs.show_insertions) {
@@ -869,7 +870,7 @@
// Draw sequence.
// X center is offset + start - <half_sequence_length>
var x_center = s_start - (s_end - s_start)/2;
- if ( (mode === "Pack" || this.mode === "Auto") && ref_seq !== undefined && w_scale > char_width_px) {
+ if ( (mode === "Pack" || this.mode === "Auto") && read_seq !== undefined && w_scale > char_width_px) {
// Draw sequence container.
ctx.fillStyle = "yellow";
ctx.fillRect(x_center - gap, y_center - 9, s_end - s_start, 9);
@@ -905,7 +906,7 @@
}
}
else {
- if ( (mode === "Pack" || this.mode === "Auto") && ref_seq !== undefined && w_scale > char_width_px) {
+ if ( (mode === "Pack" || this.mode === "Auto") && read_seq !== undefined && w_scale > char_width_px) {
// Show insertions with a single number at the insertion point.
draw_last.push( { type: "text", data: [seq.length, insert_x_coord, y_center + 9] } );
}
@@ -955,7 +956,7 @@
feature_end = feature[2],
feature_name = feature[3],
// -0.5 to put element between bases.
- f_start = Math.floor( Math.max(0, (feature_start - tile_low - 0.5) * w_scale) ),
+ f_start = Math.floor( Math.max(-0.5 * w_scale, (feature_start - tile_low - 0.5) * w_scale) ),
f_end = Math.ceil( Math.min(width, Math.max(0, (feature_end - tile_low - 0.5) * w_scale)) ),
y_center = (mode === "Dense" ? 0 : (0 + slot)) * y_scale,
label_color = this.prefs.label_color;
@@ -997,12 +998,10 @@
// Read is single.
this.draw_read(ctx, mode, w_scale, y_center, tile_low, tile_high, feature_start, feature[4], feature[5], feature[6]);
}
- if (mode === "Pack" && feature_start > tile_low && feature_name !== ".") {
+ if (mode === "Pack" && feature_start >= tile_low && feature_name !== ".") {
// Draw label.
ctx.fillStyle = this.prefs.label_color;
- // FIXME: eliminate tile_index
- var tile_index = 1;
- if (tile_index === 0 && f_start - ctx.measureText(feature_name).width < 0) {
+ if (tile_low === 0 && f_start - ctx.measureText(feature_name).width < 0) {
ctx.textAlign = "left";
ctx.fillText(feature_name, f_end + LABEL_SPACING, y_center + 8);
} else {
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: Be conservative when displaying custom datatypes in the tool shed.
by commits-noreply@bitbucket.org 01 Mar '13
by commits-noreply@bitbucket.org 01 Mar '13
01 Mar '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/5f20704ea908/
changeset: 5f20704ea908
user: greg
date: 2013-03-01 22:13:29
summary: Be conservative when displaying custom datatypes in the tool shed.
affected #: 1 file
diff -r c7c8316a1d134a19e929a2257a701ec1ebc3a33a -r 5f20704ea90836a5fa54f63c78ceaa536010c4e8 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
@@ -967,9 +967,9 @@
num_datatype_dicts = len( datatype_dicts )
for index, datatype_dict in enumerate( datatype_dicts ):
# Example: {"display_in_upload": "true", "dtype": "galaxy.datatypes.blast:BlastXml", "extension": "blastxml", "mimetype": "application/xml"}
- extension = datatype_dict[ 'extension' ]
- dtype = datatype_dict[ 'dtype' ]
- mimetype = datatype_dict[ 'mimetype' ]
+ extension = datatype_dict.get( 'extension', '' )
+ dtype = datatype_dict.get( 'dtype', '' )
+ mimetype = datatype_dict.get( 'mimetype', '' )
display_in_upload = datatype_dict.get( 'display_in_upload', False )
datatype_str += '<b>%s</b> | %s | %s' % ( escape_html( extension ), escape_html( dtype ), escape_html( mimetype ) )
if index < num_datatype_dicts - 1:
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: Implement more granular grids for valid Galaxy utilities in the tool shed - custom datatypes, tools, tool dependencies and repository dependencies are now accessible.
by commits-noreply@bitbucket.org 01 Mar '13
by commits-noreply@bitbucket.org 01 Mar '13
01 Mar '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/c7c8316a1d13/
changeset: c7c8316a1d13
user: greg
date: 2013-03-01 22:08:25
summary: Implement more granular grids for valid Galaxy utilities in the tool shed - custom datatypes, tools, tool dependencies and repository dependencies are now accessible.
affected #: 2 files
diff -r 513adadb31a2a4b014b3f03c5af2817919ea1760 -r c7c8316a1d134a19e929a2257a701ec1ebc3a33a 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
@@ -646,13 +646,15 @@
class RepositoryNameColumn( grids.TextColumn ):
def get_value( self, trans, grid, repository_metadata ):
- return escape_html( repository_metadata.repository.name )
+ repository = repository_metadata.repository
+ return escape_html( repository.name )
class RepositoryOwnerColumn( grids.TextColumn ):
def get_value( self, trans, grid, repository_metadata ):
- return escape_html( repository_metadata.user.username )
+ repository = repository_metadata.repository
+ return escape_html( repository.user.username )
class ChangesetRevisionColumn( grids.TextColumn ):
@@ -763,18 +765,53 @@
class RepositoryDependenciesGrid( RepositoryMetadataGrid ):
-
- title = "Repository dependencies available in this Tool Shed"
+
+
+ class RequiredRepositoryColumn( grids.TextColumn ):
+
+ def get_value( self, trans, grid, repository_metadata ):
+ rd_str = ''
+ if repository_metadata:
+ metadata = repository_metadata.metadata
+ if metadata:
+ rd_dict = metadata.get( 'repository_dependencies', {} )
+ if rd_dict:
+ rd_tups = rd_dict[ 'repository_dependencies' ]
+ # "repository_dependencies": [["http://localhost:9009", "bwa059", "test", "a07baa797d53"]]
+ # Sort rd_tups by by required repository name.
+ sorted_rd_tups = sorted( rd_tups, key=lambda rd_tup: rd_tup[ 1 ] )
+ num_tups = len( sorted_rd_tups )
+ for index, rd_tup in enumerate( sorted_rd_tups ):
+ name = rd_tup[ 1 ]
+ owner = rd_tup[ 2 ]
+ required_repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
+ if required_repository:
+ required_repository_id = trans.security.encode_id( required_repository.id )
+ rd_str += '<a href="browse_repository_dependencies?operation=browse_repository&id=%s">' % required_repository_id
+ rd_str += '<b>name:</b> %s | <b>owner:</b> %s | <b>revision:</b> %s' % ( escape_html( rd_tup[ 1 ] ), escape_html( rd_tup[ 2 ] ), escape_html( rd_tup[ 3 ] ) )
+ if required_repository:
+ rd_str += '</a>'
+ if index < num_tups - 1:
+ rd_str += '<br/>'
+ return rd_str
+
+ title = "Repository dependency definitions in this tool shed"
columns = [
RepositoryMetadataGrid.RepositoryNameColumn( "Repository name",
- link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
- attach_popup=False ),
+ model_class=model.Repository,
+ link=( lambda item: dict( operation="browse_repository", id=item.repository.id ) ),
+ attach_popup=False,
+ key="Repository.name" ),
RepositoryMetadataGrid.RepositoryOwnerColumn( "Owner",
model_class=model.User,
attach_popup=False,
- key="User.username" )
+ key="User.username" ),
+ RepositoryMetadataGrid.ChangesetRevisionColumn( "Revision",
+ attach_popup=False ),
+ RequiredRepositoryColumn( "Repository dependency",
+ attach_popup=False )
]
- columns.append( grids.MulticolFilterColumn( "Search repository name, description",
+ columns.append( grids.MulticolFilterColumn( "Search repository name, owner",
cols_to_filter=[ columns[0], columns[1] ],
key="free-text-search",
visible=False,
@@ -790,9 +827,190 @@
.order_by( model.Repository.name )
+class ToolDependenciesGrid( RepositoryMetadataGrid ):
+
+
+ class ToolDependencyColumn( grids.TextColumn ):
+
+ def get_value( self, trans, grid, repository_metadata ):
+ td_str = ''
+ if repository_metadata:
+ metadata = repository_metadata.metadata
+ if metadata:
+ tds_dict = metadata.get( 'tool_dependencies', {} )
+ if tds_dict:
+ # Example: {"bwa/0.5.9": {"name": "bwa", "type": "package", "version": "0.5.9"}}
+ sorted_keys = sorted( [ k for k in tds_dict.keys() ] )
+ num_keys = len( sorted_keys )
+ # Handle environment settings first.
+ if 'set_environment' in sorted_keys:
+ # Example: "set_environment": [{"name": "JAVA_JAR_FILE", "type": "set_environment"}]
+ env_dicts = tds_dict[ 'set_environment' ]
+ num_env_dicts = len( env_dicts )
+ td_str += '<b>environment:</b> '
+ for index, env_dict in enumerate( env_dicts ):
+ td_str += '%s' % escape_html( env_dict[ 'name' ] )
+ if index < num_env_dicts - 1:
+ td_str += ', '
+ td_str += '<br/>'
+ for index, key in enumerate( sorted_keys ):
+ if key == 'set_environment':
+ continue
+ td_dict = tds_dict[ key ]
+ # Example: {"name": "bwa", "type": "package", "version": "0.5.9"}
+ name = td_dict[ 'name' ]
+ type = td_dict[ 'type' ]
+ version = td_dict[ 'version' ]
+ td_str += '<b>%s</b> version <b>%s</b>' % ( escape_html( name ), escape_html( version ) )
+ if index < num_keys - 1:
+ td_str += '<br/>'
+ return td_str
+
+ title = "Tool dependency definitions in this tool shed"
+ columns = [
+ RepositoryMetadataGrid.RepositoryNameColumn( "Repository name",
+ model_class=model.Repository,
+ link=( lambda item: dict( operation="browse_repository", id=item.repository.id ) ),
+ attach_popup=False,
+ key="Repository.name" ),
+ RepositoryMetadataGrid.RepositoryOwnerColumn( "Owner",
+ model_class=model.User,
+ attach_popup=False,
+ key="User.username" ),
+ RepositoryMetadataGrid.ChangesetRevisionColumn( "Revision",
+ attach_popup=False ),
+ ToolDependencyColumn( "Tool dependency",
+ attach_popup=False )
+ ]
+ columns.append( grids.MulticolFilterColumn( "Search repository name, owner",
+ cols_to_filter=[ columns[0], columns[1] ],
+ key="free-text-search",
+ visible=False,
+ filterable="standard" ) )
+
+ def build_initial_query( self, trans, **kwd ):
+ return trans.sa_session.query( model.RepositoryMetadata ) \
+ .join( model.Repository ) \
+ .filter( and_( model.RepositoryMetadata.table.c.includes_tool_dependencies == True,
+ model.Repository.table.c.deleted == False,
+ model.Repository.table.c.deprecated == False ) ) \
+ .join( model.User.table ) \
+ .order_by( model.Repository.name )
+
+
+class ToolsGrid( RepositoryMetadataGrid ):
+
+
+ class ToolsColumn( grids.TextColumn ):
+
+ def get_value( self, trans, grid, repository_metadata ):
+ tool_str = ''
+ if repository_metadata:
+ metadata = repository_metadata.metadata
+ if metadata:
+ tool_dicts = metadata.get( 'tools', [] )
+ if tool_dicts:
+ num_tool_dicts = len( tool_dicts )
+ for index, tool_dict in enumerate( tool_dicts ):
+ tool_id = tool_dict[ 'id' ]
+ name = tool_dict[ 'name' ]
+ version = tool_dict[ 'version' ]
+ tool_str += '<b>%s</b> | %s | %s' % ( escape_html( tool_id ), escape_html( name ), escape_html( version ) )
+ if index < num_tool_dicts - 1:
+ tool_str += '<br/>'
+ return tool_str
+
+ title = "Valid tools in this tool shed"
+ columns = [
+ RepositoryMetadataGrid.RepositoryNameColumn( "Repository name",
+ model_class=model.Repository,
+ link=( lambda item: dict( operation="view_or_manage_repository", id=item.repository.id ) ),
+ attach_popup=False,
+ key="Repository.name" ),
+ RepositoryMetadataGrid.RepositoryOwnerColumn( "Owner",
+ model_class=model.User,
+ attach_popup=False,
+ key="User.username" ),
+ RepositoryMetadataGrid.ChangesetRevisionColumn( "Revision",
+ attach_popup=False ),
+ ToolsColumn( "Tool id | name | version",
+ attach_popup=False )
+ ]
+ columns.append( grids.MulticolFilterColumn( "Search repository name, owner",
+ cols_to_filter=[ columns[0], columns[1] ],
+ key="free-text-search",
+ visible=False,
+ filterable="standard" ) )
+
+ def build_initial_query( self, trans, **kwd ):
+ return trans.sa_session.query( model.RepositoryMetadata ) \
+ .join( model.Repository ) \
+ .filter( and_( model.RepositoryMetadata.table.c.includes_tools == True,
+ model.Repository.table.c.deleted == False,
+ model.Repository.table.c.deprecated == False ) ) \
+ .join( model.User.table ) \
+ .order_by( model.Repository.name )
+
+
+class DatatypesGrid( RepositoryMetadataGrid ):
+
+
+ class DatatypesColumn( grids.TextColumn ):
+
+ def get_value( self, trans, grid, repository_metadata ):
+ datatype_str = ''
+ if repository_metadata:
+ metadata = repository_metadata.metadata
+ if metadata:
+ datatype_dicts = metadata.get( 'datatypes', [] )
+ if datatype_dicts:
+ num_datatype_dicts = len( datatype_dicts )
+ for index, datatype_dict in enumerate( datatype_dicts ):
+ # Example: {"display_in_upload": "true", "dtype": "galaxy.datatypes.blast:BlastXml", "extension": "blastxml", "mimetype": "application/xml"}
+ extension = datatype_dict[ 'extension' ]
+ dtype = datatype_dict[ 'dtype' ]
+ mimetype = datatype_dict[ 'mimetype' ]
+ display_in_upload = datatype_dict.get( 'display_in_upload', False )
+ datatype_str += '<b>%s</b> | %s | %s' % ( escape_html( extension ), escape_html( dtype ), escape_html( mimetype ) )
+ if index < num_datatype_dicts - 1:
+ datatype_str += '<br/>'
+ return datatype_str
+
+ title = "Custom datatypes in this tool shed"
+ columns = [
+ RepositoryMetadataGrid.RepositoryNameColumn( "Repository name",
+ model_class=model.Repository,
+ link=( lambda item: dict( operation="view_or_manage_repository", id=item.repository.id ) ),
+ attach_popup=False,
+ key="Repository.name" ),
+ RepositoryMetadataGrid.RepositoryOwnerColumn( "Owner",
+ model_class=model.User,
+ attach_popup=False,
+ key="User.username" ),
+ RepositoryMetadataGrid.ChangesetRevisionColumn( "Revision",
+ attach_popup=False ),
+ DatatypesColumn( "Datatype extension | Type | Mimetype",
+ attach_popup=False )
+ ]
+ columns.append( grids.MulticolFilterColumn( "Search repository name, owner",
+ cols_to_filter=[ columns[0], columns[1] ],
+ key="free-text-search",
+ visible=False,
+ filterable="standard" ) )
+
+ def build_initial_query( self, trans, **kwd ):
+ return trans.sa_session.query( model.RepositoryMetadata ) \
+ .join( model.Repository ) \
+ .filter( and_( model.RepositoryMetadata.table.c.includes_datatypes == True,
+ model.Repository.table.c.deleted == False,
+ model.Repository.table.c.deprecated == False ) ) \
+ .join( model.User.table ) \
+ .order_by( model.Repository.name )
+
class RepositoryController( BaseUIController, common_util.ItemRatings ):
category_grid = CategoryGrid()
+ datatypes_grid = DatatypesGrid()
deprecated_repositories_i_own_grid = DeprecatedRepositoriesIOwnGrid()
email_alerts_repository_grid = EmailAlertsRepositoryGrid()
install_matched_repository_grid = InstallMatchedRepositoryGrid()
@@ -800,9 +1018,12 @@
my_writable_repositories_grid = MyWritableRepositoriesGrid()
repositories_by_user_grid = RepositoriesByUserGrid()
repositories_i_own_grid = RepositoriesIOwnGrid()
+ repository_dependencies_grid = RepositoryDependenciesGrid()
repository_grid = RepositoryGrid()
# The repository_metadata_grid is not currently displayed, but is sub-classed by several grids.
repository_metadata_grid = RepositoryMetadataGrid()
+ tool_dependencies_grid = ToolDependenciesGrid()
+ tools_grid = ToolsGrid()
valid_category_grid = ValidCategoryGrid()
valid_repository_grid = ValidRepositoryGrid()
@@ -824,7 +1045,7 @@
pass
return self.browse_repositories( trans, **kwd )
if 'operation' in kwd:
- operation = kwd['operation'].lower()
+ operation = kwd[ 'operation' ].lower()
if operation in [ "repositories_by_category", "repositories_by_user" ]:
# Eliminate the current filters if any exist.
for k, v in kwd.items():
@@ -836,6 +1057,16 @@
return self.category_grid( trans, **kwd )
@web.expose
+ def browse_datatypes( self, trans, **kwd ):
+ if 'operation' in kwd:
+ operation = kwd[ 'operation' ].lower()
+ if operation == "view_or_manage_repository":
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action='view_or_manage_repository',
+ **kwd ) )
+ return self.datatypes_grid( trans, **kwd )
+
+ @web.expose
def browse_invalid_tools( self, trans, **kwd ):
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
@@ -881,7 +1112,7 @@
# We add params to the keyword dict in this method in order to rename the param with an "f-" prefix, simulating filtering by clicking a search
# link. We have to take this approach because the "-" character is illegal in HTTP requests.
if 'operation' in kwd:
- operation = kwd['operation'].lower()
+ operation = kwd[ 'operation' ].lower()
if operation == "view_or_manage_repository":
return trans.response.send_redirect( web.url_for( controller='repository',
action='view_or_manage_repository',
@@ -1000,6 +1231,40 @@
status=status )
@web.expose
+ def browse_repository_dependencies( self, trans, **kwd ):
+ if 'operation' in kwd:
+ operation = kwd[ 'operation' ].lower()
+ if operation == "browse_repository":
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action='browse_repository',
+ **kwd ) )
+ if operation == "view_or_manage_repository":
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action='view_or_manage_repository',
+ **kwd ) )
+ return self.repository_dependencies_grid( trans, **kwd )
+
+ @web.expose
+ def browse_tools( self, trans, **kwd ):
+ if 'operation' in kwd:
+ operation = kwd[ 'operation' ].lower()
+ if operation == "view_or_manage_repository":
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action='view_or_manage_repository',
+ **kwd ) )
+ return self.tools_grid( trans, **kwd )
+
+ @web.expose
+ def browse_tool_dependencies( self, trans, **kwd ):
+ if 'operation' in kwd:
+ operation = kwd[ 'operation' ].lower()
+ if operation == "browse_repository":
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action='browse_repository',
+ **kwd ) )
+ return self.tool_dependencies_grid( trans, **kwd )
+
+ @web.expose
def browse_valid_categories( self, trans, **kwd ):
# The request came from Galaxy, so restrict category links to display only valid repository changeset revisions.
galaxy_url = kwd.get( 'galaxy_url', None )
@@ -1022,7 +1287,7 @@
pass
return self.browse_valid_repositories( trans, **kwd )
if 'operation' in kwd:
- operation = kwd['operation'].lower()
+ operation = kwd[ 'operation' ].lower()
if operation in [ "valid_repositories_by_category", "valid_repositories_by_user" ]:
# Eliminate the current filters if any exist.
for k, v in kwd.items():
@@ -2420,7 +2685,7 @@
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
if 'operation' in kwd:
- operation = kwd['operation'].lower()
+ operation = kwd[ 'operation' ].lower()
if operation == "receive email alerts":
if trans.user:
if kwd[ 'id' ]:
diff -r 513adadb31a2a4b014b3f03c5af2817919ea1760 -r c7c8316a1d134a19e929a2257a701ec1ebc3a33a templates/webapps/tool_shed/index.mako
--- a/templates/webapps/tool_shed/index.mako
+++ b/templates/webapps/tool_shed/index.mako
@@ -67,6 +67,22 @@
<a target="galaxy_main" href="${h.url_for( controller='repository', action='find_workflows' )}">Search for workflows</a></div></div>
+ <div class="toolSectionPad"></div>
+ <div class="toolSectionTitle">
+ Valid Galaxy Utilities
+ </div>
+ <div class="toolTitle">
+ <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_tools' )}">Tools</a>
+ </div>
+ <div class="toolTitle">
+ <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_datatypes' )}">Custom datatypes</a>
+ </div>
+ <div class="toolTitle">
+ <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_repository_dependencies' )}">Repository dependency definitions</a>
+ </div>
+ <div class="toolTitle">
+ <a target="galaxy_main" href="${h.url_for( controller='repository', action='browse_tool_dependencies' )}">Tool dependency definitions</a>
+ </div>
%endif
<div class="toolSectionPad"></div><div class="toolSectionTitle">
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: inithello: Improved documentation for automated repository installation and testing. Handle cases where a repository is missing test data. Limit the list of repositories to test to those that have tools. Update the parse_tool_panel_config method to return a flag specifying whether test data was found for the specified tool panel entry.
by commits-noreply@bitbucket.org 01 Mar '13
by commits-noreply@bitbucket.org 01 Mar '13
01 Mar '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/513adadb31a2/
changeset: 513adadb31a2
user: inithello
date: 2013-03-01 21:13:20
summary: Improved documentation for automated repository installation and testing. Handle cases where a repository is missing test data. Limit the list of repositories to test to those that have tools. Update the parse_tool_panel_config method to return a flag specifying whether test data was found for the specified tool panel entry.
affected #: 3 files
diff -r 2454aa4b6e7c308a90bb6ad7f00c47f6177e992a -r 513adadb31a2a4b014b3f03c5af2817919ea1760 scripts/functional_tests.py
--- a/scripts/functional_tests.py
+++ b/scripts/functional_tests.py
@@ -321,10 +321,10 @@
if testing_migrated_tools or testing_installed_tools:
shed_tools_dict = {}
if testing_migrated_tools:
- shed_tools_dict = parse_tool_panel_config( migrated_tool_panel_config, shed_tools_dict )
+ has_test_data, shed_tools_dict = parse_tool_panel_config( migrated_tool_panel_config, shed_tools_dict )
elif testing_installed_tools:
for shed_tool_config in installed_tool_panel_configs:
- shed_tools_dict = parse_tool_panel_config( shed_tool_config, shed_tools_dict )
+ has_test_data, shed_tools_dict = parse_tool_panel_config( shed_tool_config, shed_tools_dict )
# Persist the shed_tools_dict to the galaxy_tool_shed_test_file.
shed_tools_file = open( galaxy_tool_shed_test_file, 'w' )
shed_tools_file.write( to_json_string( shed_tools_dict ) )
diff -r 2454aa4b6e7c308a90bb6ad7f00c47f6177e992a -r 513adadb31a2a4b014b3f03c5af2817919ea1760 test/base/util.py
--- a/test/base/util.py
+++ b/test/base/util.py
@@ -1,4 +1,6 @@
-import os, sys
+import os, sys, logging
+
+log = logging.getLogger(__name__)
cwd = os.getcwd()
if cwd not in sys.path:
@@ -27,6 +29,8 @@
# Locate the test-data directory.
installed_tool_path = os.path.join( installed_tool_path_items[ 0 ], 'repos', repository_owner, repository_name, changeset_revision )
for root, dirs, files in os.walk( os.path.join(tool_path, installed_tool_path )):
+ if '.hg' in dirs:
+ dirs.remove( '.hg' )
if 'test-data' in dirs:
return os.path.join( root, 'test-data' ), repository_name, changeset_revision
return None, repository_name, changeset_revision
@@ -40,6 +44,7 @@
last_tested_repository_name = None
last_tested_changeset_revision = None
tool_path = None
+ has_test_data = False
tree = parse_xml( config )
root = tree.getroot()
tool_path = root.get('tool_path')
@@ -53,6 +58,8 @@
last_tested_changeset_revision,
tool_path )
if galaxy_test_file_dir:
+ if not has_test_data:
+ has_test_data = True
if galaxy_test_file_dir != last_galaxy_test_file_dir:
if not os.path.isabs( galaxy_test_file_dir ):
galaxy_test_file_dir = os.path.join( os.getcwd(), galaxy_test_file_dir )
@@ -70,11 +77,13 @@
last_tested_changeset_revision,
tool_path )
if galaxy_test_file_dir:
+ if not has_test_data:
+ has_test_data = True
if galaxy_test_file_dir != last_galaxy_test_file_dir:
if not os.path.isabs( galaxy_test_file_dir ):
galaxy_test_file_dir = os.path.join( os.getcwd(), galaxy_test_file_dir )
guid = section_elem.get( 'guid' )
shed_tools_dict[ guid ] = galaxy_test_file_dir
last_galaxy_test_file_dir = galaxy_test_file_dir
- return shed_tools_dict
+ return has_test_data, shed_tools_dict
diff -r 2454aa4b6e7c308a90bb6ad7f00c47f6177e992a -r 513adadb31a2a4b014b3f03c5af2817919ea1760 test/install_and_test_tool_shed_repositories/functional_tests.py
--- a/test/install_and_test_tool_shed_repositories/functional_tests.py
+++ b/test/install_and_test_tool_shed_repositories/functional_tests.py
@@ -5,6 +5,7 @@
# will execute this script with the appropriate parameters.
import os, sys, shutil, tempfile, re, string, urllib, platform
+from time import strftime
# Assume we are run from the galaxy root directory, add lib to the python path
cwd = os.getcwd()
@@ -114,6 +115,27 @@
else:
galaxy_encode_secret = os.environ[ 'GALAXY_INSTALL_TEST_SECRET' ]
+def execute_uninstall_method( repository_dict ):
+ # Delete any configured tool functional tests from the test_toolbox.__dict__, otherwise nose will find them
+ # and try to re-run the tests after uninstalling the repository.
+ tests_to_delete = []
+ for key in test_toolbox.__dict__:
+ if key.startswith( 'TestForTool_' ):
+ log.info( 'Tool test found in test_toolbox, deleting: %s' % key )
+ tests_to_delete.append( key )
+ for key in tests_to_delete:
+ del test_toolbox.__dict__[ key ]
+ # Generate a test method to uninstall this repository through the embedded Galaxy application's web interface.
+ test_install_repositories.generate_uninstall_method( repository_dict )
+ # Set up nose to run the generated uninstall method as a functional test.
+ test_config = nose.config.Config( env=os.environ, plugins=nose.plugins.manager.DefaultPluginManager() )
+ test_config.configure( sys.argv )
+ # Run the uninstall method. This method uses the Galaxy web interface to uninstall the previously installed
+ # repository and delete it from disk.
+ result = run_tests( test_config )
+ success = result.wasSuccessful()
+ return success
+
def get_api_url( base, parts=[], params=None, key=None ):
if 'api' in parts and parts.index( 'api' ) != 0:
parts.pop( parts.index( 'api' ) )
@@ -187,7 +209,7 @@
return update( tool_shed_api_key, '%s' % ( url_join( galaxy_tool_shed_url, 'api', 'repository_revisions', metadata_id ) ), params, return_formatted=False )
def register_test_success( url, metadata_id ):
- params = dict( tools_functionally_correct='true', do_not_test='false' )
+ params = dict( tools_functionally_correct='true', do_not_test='true' )
return update( tool_shed_api_key, '%s' % ( url_join( galaxy_tool_shed_url, 'api', 'repository_revisions', metadata_id ) ), params, return_formatted=False )
def run_tests( test_config ):
@@ -209,6 +231,11 @@
galaxy_test_host = os.environ.get( 'GALAXY_INSTALL_TEST_HOST', default_galaxy_test_host )
galaxy_test_port = os.environ.get( 'GALAXY_INSTALL_TEST_PORT', str( default_galaxy_test_port_max ) )
+ # Initialize some variables for the summary that will be printed to stdout.
+ repositories_tested = 0
+ repositories_passed = 0
+ repositories_failed = 0
+
tool_path = os.environ.get( 'GALAXY_INSTALL_TEST_TOOL_PATH', 'tools' )
if 'HTTP_ACCEPT_LANGUAGE' not in os.environ:
os.environ[ 'HTTP_ACCEPT_LANGUAGE' ] = default_galaxy_locales
@@ -373,132 +400,189 @@
log.info( "Retrieving repositories to install from the URL:\n%s\n" % str( galaxy_tool_shed_url ) )
repositories_to_install = get_repositories_to_install( galaxy_tool_shed_url, source='url' )
log.info( "Retrieved %d repositories to install..." % len( repositories_to_install ) )
+ repositories_tested = len( repositories_to_install )
+ # This loop will iterate through the list of repositories returned by the above method, skipping any that are marked
+ # as deleted. For each repository, it will generate a test method that will use Twill to install that repository into the
+ # embedded Galaxy application that was started up, selecting to install repository and tool dependencies if they are
+ # defined. If the installation completes successfully, it will then generate a test case for each functional test
+ # defined for each tool in the repository, and execute the generated test cases. When this completes, it will record
+ # the result of the tests, and if any failed, the traceback and captured output of the tool that was run.
+ # After all tests have completed, the repository is uninstalled, so that the previous test cases don't interfere with
+ # the next repository's functional tests.
for repository_to_install_dict in repositories_to_install:
"""
Each repository_to_install_dict looks something like:
- {'repository_id': '175812cd7caaf439',
- 'url': '/api/repository_revisions/175812cd7caaf439',
- 'malicious': False,
- 'downloadable': True,
- 'changeset_revision': '2388033730f3',
- 'id': '175812cd7caaf439'}
+ {
+ "changeset_revision": "13fa22a258b5",
+ "downloadable": true,
+ "id": "529fd61ab1c6cc36",
+ "malicious": false,
+ "repository_id": "529fd61ab1c6cc36",
+ "url": "/api/repository_revisions/529fd61ab1c6cc36"
+ }
"""
repository_id = repository_to_install_dict.get( 'repository_id', None )
changeset_revision = repository_to_install_dict.get( 'changeset_revision', None )
metadata_revision_id = repository_to_install_dict.get( 'id', None )
+ # Add the URL for the tool shed we're installing from, so the automated installation methods go to the right place.
repository_to_install_dict[ 'tool_shed_url' ] = galaxy_tool_shed_url
+ # We need to get some details from the tool shed API, such as repository name and owner, to pass on to the
+ # module that will generate the install methods.
repository_info_dict = get_repository_info_from_api( galaxy_tool_shed_url, repository_to_install_dict )
- # If a repository is deleted or malicious, we don't need to test it.
- if repository_info_dict[ 'deleted' ] or repository_info_dict[ 'deprecated' ]:
- log.info( "Skipping revision %s of repository id %s since it is either deleted or deprecated..." % ( str( changeset_revision ), str( repository_id ) ) )
+ # We are testing deprecated repositories, because it is possible that a deprecated repository contains valid
+ # and functionally correct tools that someone has previously installed. Deleted repositories have never been installed,
+ # and therefore do not need to be checked. If they are undeleted, this script will then test them the next time it runs.
+ if repository_info_dict[ 'deleted' ]:
+ log.info( "Skipping revision %s of repository id %s since the repository is deleted..." % ( str( changeset_revision ), str( repository_id ) ) )
continue
log.info( "Installing and testing revision %s of repository id %s..." % ( str( changeset_revision ), str( repository_id ) ) )
+ # Add repository details to the basic repository dict.
repository_dict = dict( repository_info_dict.items() + repository_to_install_dict.items() )
"""
- Each repository_dict looks something like:
- {'repository_id': '175812cd7caaf439',
- 'url': '/api/repository_revisions/175812cd7caaf439',
- 'malicious': False,
- 'downloadable': True,
- 'changeset_revision': '2388033730f3',
- 'id': '175812cd7caaf439'}
+ After the addition of the repository details, each repository_dict should now contain something like:
+ {
+ "changeset_revision": "13fa22a258b5",
+ "contents_url": "/api/repositories/529fd61ab1c6cc36/contents",
+ "deleted": false,
+ "deprecated": false,
+ "description": "Convert column case.",
+ "downloadable": true,
+ "id": "529fd61ab1c6cc36",
+ "long_description": "This tool takes the specified columns and converts them to uppercase or lowercase.",
+ "malicious": false,
+ "name": "change_case",
+ "owner": "test",
+ "private": false,
+ "repository_id": "529fd61ab1c6cc36",
+ "times_downloaded": 0,
+ "tool_shed_url": "http://toolshed.local:10001",
+ "url": "/api/repository_revisions/529fd61ab1c6cc36",
+ "user_id": "529fd61ab1c6cc36"
+ }
"""
- # Generate the method that will install this repository into the running Galaxy instance.
+ # Use the repository information dict to generate an install method that will install the repository into the embedded
+ # Galaxy application, with tool dependencies and repository dependencies, if any.
test_install_repositories.generate_install_method( repository_dict )
os.environ[ 'GALAXY_INSTALL_TEST_HOST' ] = galaxy_test_host
# Configure nose to run the install method as a test.
test_config = nose.config.Config( env=os.environ, plugins=nose.plugins.manager.DefaultPluginManager() )
test_config.configure( sys.argv )
- # Run the configured install method as a test. This method uses the Galaxy web interface to install the specified
+ # Run the configured install method as a test. This method uses the embedded Galaxy application's web interface to install the specified
# repository, with tool and repository dependencies also selected for installation.
result = run_tests( test_config )
success = result.wasSuccessful()
- # If the installation succeeds, set up and run functional tests for this repository. This is equivalent to
+ # If the installation succeeds, configure and run functional tests for this repository. This is equivalent to
# sh run_functional_tests.sh -installed
if success:
log.debug( 'Installation of %s succeeded, running all defined functional tests.' % repository_dict[ 'name' ] )
- # Parse the tool panel config to get the test-data path for this repository.
- if not os.path.exists( galaxy_shed_tools_dict ):
- file( galaxy_shed_tools_dict, 'w' ).write( to_json_string( dict() ) )
- shed_tools_dict = parse_tool_panel_config( galaxy_shed_tool_conf_file, from_json_string( file( galaxy_shed_tools_dict, 'r' ).read() ) )
- # Write this to a file, so the functional test framework can find it.
- file( galaxy_shed_tools_dict, 'w' ).write( to_json_string( shed_tools_dict ) )
- # Set up the environment so that test.functional.test_toolbox can find the Galaxy server we configured in this framework.
- os.environ[ 'GALAXY_TOOL_SHED_TEST_FILE' ] = galaxy_shed_tools_dict
- os.environ[ 'GALAXY_TEST_HOST' ] = galaxy_test_host
- os.environ[ 'GALAXY_TEST_PORT' ] = galaxy_test_port
- # Set the module-level variable 'toolbox', so that test.functional.test_toolbox will generate the appropriate test methods.
- test_toolbox.toolbox = app.toolbox
- # Generate the test methods for this installed repository. We need to pass in True here, or it will look
- # in $GALAXY_HOME/test-data for test data, which may result in missing or invalid test files.
- test_toolbox.build_tests( testing_shed_tools=True )
- # Set up nose to run the generated functional tests.
- test_config = nose.config.Config( env=os.environ, plugins=nose.plugins.manager.DefaultPluginManager() )
- test_config.configure( sys.argv )
- # Run the configured tests.
- result = run_tests( test_config )
- success = result.wasSuccessful()
- repository_dict[ 'test_environment' ] = get_test_environment()
- repository_dict[ 'functional_tests_passed' ] = success
- test_errors = []
- if success:
- register_test_success( galaxy_tool_shed_url, metadata_revision_id )
- log.debug( 'Repository %s installed and passed functional tests.' % repository_dict[ 'name' ] )
+ # Generate the shed_tools_dict that specifies the location of test data contained within this repository. If the repository
+ # does not have a test-data directory, this will return has_test_data = False, and we will set the do_not_test flag to True,
+ # and the tools_functionally_correct flag to False, as well as updating tool_test_errors.
+ file( galaxy_shed_tools_dict, 'w' ).write( to_json_string( dict() ) )
+ has_test_data, shed_tools_dict = parse_tool_panel_config( galaxy_shed_tool_conf_file, from_json_string( file( galaxy_shed_tools_dict, 'r' ).read() ) )
+ if not has_test_data:
+ log.error( 'Test data is missing for this repository. Updating repository and skipping functional tests.' )
+ repository_status[ 'test_environment' ] = get_test_environment()
+ test_id = 'Find functional test data for %s' % repository_dict[ 'name' ]
+ test_errors = dict( test_id=test_id,
+ stdout='No test data found for changeset revision %s of repository %s owned by %s.' % \
+ ( repository_dict[ 'changeset_revision' ], repository_dict[ 'name' ], repository_dict[ 'owner' ] ) )
+ repository_status[ 'test_errors' ] = [ test_errors ]
+ # Record the status of this repository in the tool shed.
+ register_test_failure( galaxy_tool_shed_url, metadata_revision_id, repository_status )
+ # Run the cleanup method. This removes tool functional test methods from the test_toolbox module and uninstalls the
+ # repository using Twill.
+ execute_uninstall_method( repository_dict )
+ # Set the test_toolbox.toolbox module-level variable to the new app.toolbox.
+ test_toolbox.toolbox = app.toolbox
+ repositories_failed += 1
else:
- # If the functional tests fail, log the output and submit it to the tool shed whence the repository was installed.
- for failure in result.failures:
- test_status = dict( test=str( failure[0] ) )
- log_output = failure[1].replace( '\\n', '\n' )
- log_output = re.sub( r'control \d+:.+', r'', log_output )
- log_output = re.sub( r'\n+', r'\n', log_output )
- appending_to = 'output'
- tmp_output = {}
- output = {}
- for line in log_output.split( '\n' ):
- if line.startswith( 'Traceback' ):
- appending_to = 'traceback'
- elif '>> end captured' in line:
- continue
- elif 'request returned None from get_history' in line:
- continue
- elif '>> begin captured logging <<' in line:
- appending_to = 'logging'
- continue
- elif '>> begin captured stdout <<' in line:
- appending_to = 'stdout'
- continue
- elif '>> begin captured stderr <<' in line:
- appending_to = 'stderr'
- continue
- if appending_to not in tmp_output:
- tmp_output[ appending_to ] = []
- tmp_output[ appending_to ].append( line )
- for output_type in [ 'stderr', 'stdout', 'traceback' ]:
- if output_type in tmp_output:
- test_status[ output_type ] = '\n'.join( tmp_output[ output_type ] )
- test_errors.append( test_status )
- if test_errors:
- repository_status[ 'test_environment' ] = get_test_environment()
- repository_status[ 'test_errors' ] = test_errors
- register_test_failure( galaxy_tool_shed_url, metadata_revision_id, repository_status )
- log.debug( 'Repository %s installed, but did not pass functional tests.' % repository_dict[ 'name' ] )
- # Delete the completed tool functional tests from the test_toolbox.__dict__, otherwise nose will find them and try to re-run the
- # tests after uninstalling the repository.
- tests_to_delete = []
- for key in test_toolbox.__dict__:
- if key.startswith( 'TestForTool_' ):
- tests_to_delete.append( key )
- for key in tests_to_delete:
- del test_toolbox.__dict__[ key ]
- # Generate an uninstall method for this repository, so that the next repository has a clean environment for testing.
- test_install_repositories.generate_uninstall_method( repository_dict )
- # Set up nose to run the generated uninstall method as a functional test.
- test_config = nose.config.Config( env=os.environ, plugins=nose.plugins.manager.DefaultPluginManager() )
- test_config.configure( sys.argv )
- # Run the uninstall method. This method uses the Galaxy web interface to uninstall the previously installed
- # repository and delete it from disk.
- result = run_tests( test_config )
- success = result.wasSuccessful()
+ # If the repository does have a test-data directory, we write the generated shed_tools_dict to a file, so the functional
+ # test framework can find it.
+ file( galaxy_shed_tools_dict, 'w' ).write( to_json_string( shed_tools_dict ) )
+ log.info( 'Saved generated shed_tools_dict to %s\nContents: %s' % ( galaxy_shed_tools_dict, str( shed_tools_dict ) ) )
+ # Set the GALAXY_TOOL_SHED_TEST_FILE environment variable to the path of the shed_tools_dict file, so that test.base.twilltestcase.setUp
+ # will find and parse it properly.
+ os.environ[ 'GALAXY_TOOL_SHED_TEST_FILE' ] = galaxy_shed_tools_dict
+ os.environ[ 'GALAXY_TEST_HOST' ] = galaxy_test_host
+ os.environ[ 'GALAXY_TEST_PORT' ] = galaxy_test_port
+ # Set the module-level variable 'toolbox', so that test.functional.test_toolbox will generate the appropriate test methods.
+ test_toolbox.toolbox = app.toolbox
+ # Generate the test methods for this installed repository. We need to pass in True here, or it will look
+ # in $GALAXY_HOME/test-data for test data, which may result in missing or invalid test files.
+ test_toolbox.build_tests( testing_shed_tools=True )
+ # Set up nose to run the generated functional tests.
+ test_config = nose.config.Config( env=os.environ, plugins=nose.plugins.manager.DefaultPluginManager() )
+ test_config.configure( sys.argv )
+ # Run the configured tests.
+ result = run_tests( test_config )
+ success = result.wasSuccessful()
+ # Record some information about the environment in which this test was run, in case a failure is specific to a certain processor
+ # architecture or operating system.
+ repository_dict[ 'test_environment' ] = get_test_environment()
+ repository_dict[ 'functional_tests_passed' ] = success
+ test_errors = []
+ if success:
+ # This repository's tools passed all functional tests. Update the repository_metadata table in the tool shed's database
+ # to reflect that. Call the register_test_success method, which executes a PUT request to the repository_revisions API
+ # controller with the status of the test. This also sets the do_not_test and tools_functionally correct flags, and
+ # updates the time_last_tested field to today's date.
+ repositories_passed += 1
+ register_test_success( galaxy_tool_shed_url, metadata_revision_id )
+ log.debug( 'Revision %s of repository %s installed and passed functional tests.' % \
+ ( repository_dict[ 'changeset_revision' ], repository_dict[ 'name' ] ) )
+ else:
+ # If the functional tests fail, log the output and update the failed changeset revision's metadata record in the tool shed via the API.
+ for failure in result.failures:
+ # Record the twill test identifier, so the repository owner can discover which test is failing.
+ test_status = dict( test_id=str( failure[0] ) )
+ log_output = failure[1].replace( '\\n', '\n' )
+ # Remove debug output that the reviewer or owner doesn't need.
+ log_output = re.sub( r'control \d+:.+', r'', log_output )
+ log_output = re.sub( r'\n+', r'\n', log_output )
+ appending_to = 'output'
+ tmp_output = {}
+ output = {}
+ # Iterate through the functional test output and extract only the important data. Captured logging is not recorded.
+ for line in log_output.split( '\n' ):
+ if line.startswith( 'Traceback' ):
+ appending_to = 'traceback'
+ elif '>> end captured' in line or '>> end tool' in line:
+ continue
+ elif 'request returned None from get_history' in line:
+ continue
+ elif '>> begin captured logging <<' in line:
+ appending_to = 'logging'
+ continue
+ elif '>> begin captured stdout <<' in line:
+ appending_to = 'stdout'
+ continue
+ elif '>> begin captured stderr <<' in line or '>> begin tool stderr <<' in line:
+ appending_to = 'stderr'
+ continue
+ if appending_to not in tmp_output:
+ tmp_output[ appending_to ] = []
+ tmp_output[ appending_to ].append( line )
+ for output_type in [ 'stderr', 'stdout', 'traceback' ]:
+ if output_type in tmp_output:
+ test_status[ output_type ] = '\n'.join( tmp_output[ output_type ] )
+ test_errors.append( test_status )
+ if test_errors:
+ # Only update test_errors for this repository if it's not empty.
+ repository_status[ 'test_environment' ] = get_test_environment()
+ repository_status[ 'test_errors' ] = test_errors
+ # Call the register_test_failure method, which executes a PUT request to the repository_revisions API controller with the failure
+ # status of the test, and updates tool_test_errors with the relevant log data.
+ # This also sets the do_not_test and tools_functionally correct flags, and updates the time_last_tested field to today's date.
+ repositories_failed += 1
+ register_test_failure( galaxy_tool_shed_url, metadata_revision_id, repository_status )
+ log.debug( 'Revision %s of repository %s installed successfully, but did not pass functional tests.' % \
+ ( repository_dict[ 'changeset_revision' ], repository_dict[ 'name' ] ) )
+ # Run the cleanup method. This removes tool functional test methods from the test_toolbox module and uninstalls the
+ # repository using Twill.
+ execute_uninstall_method( repository_dict )
+ # Set the test_toolbox.toolbox module-level variable to the new app.toolbox.
+ test_toolbox.toolbox = app.toolbox
else:
log.debug( 'Repository %s failed to install correctly.' % repository_dict[ 'name' ] )
except:
@@ -528,10 +612,25 @@
pass
else:
log.debug( 'GALAXY_INSTALL_TEST_NO_CLEANUP set, not cleaning up.' )
+
+ now = strftime( "%Y-%m-%d %H:%M:%S" )
+ print "####################################################################################"
+ print "# %s - repository installation and testing script completed." % now
+ print "# Repository revisions tested: %d" % repositories_tested
+ if repositories_tested > 0:
+ print "# Repository revisions passed: %d" % repositories_passed
+ print "# Repository revisions failed: %d" % repositories_failed
+ print "####################################################################################"
+
if success:
return 0
else:
return 1
if __name__ == "__main__":
- sys.exit( main() )
+ now = strftime( "%Y-%m-%d %H:%M:%S" )
+ print "####################################################################################"
+ print "# %s - running repository installation and testing script." % now
+ print "####################################################################################"
+ return_code = main()
+ sys.exit( return_code )
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: fix server_env saved output dir name; clean up prev. debugging statements
by commits-noreply@bitbucket.org 01 Mar '13
by commits-noreply@bitbucket.org 01 Mar '13
01 Mar '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/2454aa4b6e7c/
changeset: 2454aa4b6e7c
user: carlfeberhard
date: 2013-03-01 18:49:08
summary: fix server_env saved output dir name; clean up prev. debugging statements
affected #: 3 files
diff -r 153f7f450f4b7537bc8866f09b5cc3ca57ad25ee -r 2454aa4b6e7c308a90bb6ad7f00c47f6177e992a lib/galaxy/app.py
--- a/lib/galaxy/app.py
+++ b/lib/galaxy/app.py
@@ -45,8 +45,6 @@
self.tool_shed_registry = tool_shed.tool_shed_registry.Registry( self.config.root, self.config.tool_sheds_config )
else:
self.tool_shed_registry = None
- log.debug( 'self.config.tool_sheds_config: %s, self.tool_shed_registry: %s',
- self.config.tool_sheds_config, self.tool_shed_registry )
# Initialize database / check for appropriate schema version. # If this
# is a new installation, we'll restrict the tool migration messaging.
from galaxy.model.migrate.check import create_or_verify_database
diff -r 153f7f450f4b7537bc8866f09b5cc3ca57ad25ee -r 2454aa4b6e7c308a90bb6ad7f00c47f6177e992a scripts/functional_tests.py
--- a/scripts/functional_tests.py
+++ b/scripts/functional_tests.py
@@ -42,7 +42,6 @@
import nose.loader
import nose.plugins.manager
-import pprint
log = logging.getLogger( "functional_tests.py" )
default_galaxy_test_host = "localhost"
@@ -227,7 +226,6 @@
kwargs[ 'object_store' ] = 'distributed'
kwargs[ 'distributed_object_store_config_file' ] = 'distributed_object_store_conf.xml.sample'
# Build the Universe Application
- print 'app.kwargs:\n%s' %( pprint.pformat( kwargs ) )
app = UniverseApplication( job_queue_workers = 5,
id_secret = 'changethisinproductiontoo',
template_path = "templates",
diff -r 153f7f450f4b7537bc8866f09b5cc3ca57ad25ee -r 2454aa4b6e7c308a90bb6ad7f00c47f6177e992a test/casperjs/server_env.py
--- a/test/casperjs/server_env.py
+++ b/test/casperjs/server_env.py
@@ -29,6 +29,9 @@
@classmethod
def instance( cls, config=None ):
+ """Returns the singleton of TestEnvironment, instantiating it first if it
+ does not yet exist.
+ """
# singleton pattern
if( ( not cls._instance )
or ( config ) ):
@@ -36,25 +39,26 @@
cls._instance = cls( config )
return cls._instance
- @classmethod
- def get_server_url( cls ):
- return cls.instance().url
-
def __init__( self, env_config_dict=None ):
self.config = env_config_dict or {}
- self.protocol = self._get_setting_from_config_or_env( 'protocol', self.ENV_PROTOCOL, self.DEFAULT_PROTOCOL )
- self.host = self._get_setting_from_config_or_env( 'host', self.ENV_HOST, self.DEFAULT_HOST )
- self.port = self._get_setting_from_config_or_env( 'port', self.ENV_PORT, self.DEFAULT_PORT )
+ self.protocol = self._get_setting_from_config_or_env(
+ 'protocol', self.ENV_PROTOCOL, self.DEFAULT_PROTOCOL )
+ self.host = self._get_setting_from_config_or_env(
+ 'host', self.ENV_HOST, self.DEFAULT_HOST )
+ self.port = self._get_setting_from_config_or_env(
+ 'port', self.ENV_PORT, self.DEFAULT_PORT )
- self.history_id = self._get_setting_from_config_or_env( 'history_id', self.ENV_HISTORY_ID, default=None )
- self.file_dir = self._get_setting_from_config_or_env( 'file_dir', self.ENV_FILE_DIR, default=None )
+ self.history_id = self._get_setting_from_config_or_env(
+ 'history_id', self.ENV_HISTORY_ID, default=None )
+ self.file_dir = self._get_setting_from_config_or_env(
+ 'file_dir', self.ENV_FILE_DIR, default=None )
self.tool_shed_test_file = self._get_setting_from_config_or_env(
'tool_shed_test_file', self.ENV_TOOL_SHED_TEST_FILE, default=None )
self.shed_tools_dict = self._get_shed_tools_dict()
- self.keepOutdir = self._get_setting_from_config_or_env(
+ self.saved_output_dir = self._get_setting_from_config_or_env(
'saved_output_dir', self.ENV_SAVED_FILES_DIR, default=None )
self._init_saved_files_dir()
@@ -62,6 +66,7 @@
"""Try to get a setting from (in order):
TestEnvironment.config, the os env, or some default (if not False).
"""
+ #TODO: if falsy value needed, use None - not ideal
config = self.config.get( config_name, None )
env = os.environ.get( env_name, None )
if( ( not ( config or env ) )
@@ -94,6 +99,8 @@
@property
def url( self ):
+ """Builds and returns the url of the test server.
+ """
url = '%s://%s' %( self.protocol, self.host )
if self.port and self.port != 80:
url += ':%s' %( str( self.port ) )
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 RepositoryMetadata attributes that enable improved query abilities for tool shed repository revisions that contain Galaxy utilities.
by commits-noreply@bitbucket.org 01 Mar '13
by commits-noreply@bitbucket.org 01 Mar '13
01 Mar '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/153f7f450f4b/
changeset: 153f7f450f4b
user: greg
date: 2013-03-01 17:13:15
summary: Add RepositoryMetadata attributes that enable improved query abilities for tool shed repository revisions that contain Galaxy utilities.
affected #: 6 files
diff -r 21c69586390abeefde4a52560321b826473ad041 -r 153f7f450f4b7537bc8866f09b5cc3ca57ad25ee 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
@@ -33,6 +33,7 @@
class NameColumn( grids.TextColumn ):
+
def get_value( self, trans, grid, category ):
return category.name
@@ -43,6 +44,7 @@
class RepositoriesColumn( grids.TextColumn ):
+
def get_value( self, trans, grid, category ):
if category.repositories:
viewable_repositories = 0
@@ -82,6 +84,7 @@
class RepositoriesColumn( grids.TextColumn ):
+
def get_value( self, trans, grid, category ):
if category.repositories:
viewable_repositories = 0
@@ -123,6 +126,7 @@
class NameColumn( grids.TextColumn ):
+
def get_value( self, trans, grid, repository ):
return escape_html( repository.name )
@@ -468,6 +472,7 @@
class CategoryColumn( grids.TextColumn ):
+
def get_value( self, trans, grid, repository ):
rval = '<ul>'
if repository.categories:
@@ -481,6 +486,7 @@
class RepositoryCategoryColumn( grids.GridColumn ):
+
def filter( self, trans, user, query, column_filter ):
"""Modify query to filter by category."""
if column_filter == "All":
@@ -501,6 +507,7 @@
elif len( select_field.options ) == 1:
return select_field.options[ 0 ][ 0 ]
return ''
+
title = "Valid repositories"
columns = [
RepositoryGrid.NameColumn( "Name",
@@ -633,19 +640,171 @@
attach_popup=False )
+class RepositoryMetadataGrid( grids.Grid ):
+
+
+ class RepositoryNameColumn( grids.TextColumn ):
+
+ def get_value( self, trans, grid, repository_metadata ):
+ return escape_html( repository_metadata.repository.name )
+
+
+ class RepositoryOwnerColumn( grids.TextColumn ):
+
+ def get_value( self, trans, grid, repository_metadata ):
+ return escape_html( repository_metadata.user.username )
+
+
+ class ChangesetRevisionColumn( grids.TextColumn ):
+
+ def get_value( self, trans, grid, repository_metadata ):
+ return escape_html( repository_metadata.changeset_revision )
+
+
+ class MaliciousColumn( grids.BooleanColumn ):
+ def get_value( self, trans, grid, repository_metadata ):
+ if repository_metadata.malicious:
+ return 'yes'
+ return ''
+
+
+ class DownloadableColumn( grids.BooleanColumn ):
+ def get_value( self, trans, grid, repository_metadata ):
+ if repository_metadata.downloadable:
+ return 'yes'
+ return ''
+
+
+ class ToolsFunctionallyCorrectColumn( grids.BooleanColumn ):
+ def get_value( self, trans, grid, repository_metadata ):
+ if repository_metadata.tools_functionally_correct:
+ return 'yes'
+ return ''
+
+
+ class DoNotTestColumn( grids.BooleanColumn ):
+ def get_value( self, trans, grid, repository_metadata ):
+ if repository_metadata.do_not_test:
+ return 'yes'
+ return ''
+
+
+ class TimeLastTestedColumn( grids.DateTimeColumn ):
+ def get_value( self, trans, grid, repository_metadata ):
+ return repository_metadata.time_last_tested
+
+
+ class HasRepositoryDependenciesColumn( grids.BooleanColumn ):
+ def get_value( self, trans, grid, repository_metadata ):
+ if repository_metadata.has_repository_dependencies:
+ return 'yes'
+ return ''
+
+
+ class IncludesDatatypesColumn( grids.BooleanColumn ):
+ def get_value( self, trans, grid, repository_metadata ):
+ if repository_metadata.includes_datatypes:
+ return 'yes'
+ return ''
+
+
+ class IncludesToolsColumn( grids.BooleanColumn ):
+ def get_value( self, trans, grid, repository_metadata ):
+ if repository_metadata.includes_tools:
+ return 'yes'
+ return ''
+
+
+ class IncludesToolDependenciesColumn( grids.BooleanColumn ):
+ def get_value( self, trans, grid, repository_metadata ):
+ if repository_metadata.includes_tool_dependencies:
+ return 'yes'
+ return ''
+
+
+ class IncludesWorkflowsColumn( grids.BooleanColumn ):
+ def get_value( self, trans, grid, repository_metadata ):
+ if repository_metadata.includes_workflows:
+ return 'yes'
+ return ''
+
+ title = "Repository metadata"
+ model_class = model.RepositoryMetadata
+ template='/webapps/tool_shed/repository/grid.mako'
+ default_sort_key = "Repository.name"
+ columns = [
+ RepositoryNameColumn( "Repository name",
+ link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
+ attach_popup=False ),
+ RepositoryOwnerColumn( "Owner",
+ model_class=model.User,
+ attach_popup=False,
+ key="User.username" )
+ ]
+ columns.append( grids.MulticolFilterColumn( "Search repository name, description",
+ cols_to_filter=[ columns[0], columns[1] ],
+ key="free-text-search",
+ visible=False,
+ filterable="standard" ) )
+ operations = []
+ standard_filters = []
+ default_filter = dict( malicious="False" )
+ num_rows_per_page = 50
+ preserve_state = False
+ use_paging = True
+
+ def build_initial_query( self, trans, **kwd ):
+ return trans.sa_session.query( model.RepositoryMetadata ) \
+ .join( model.Repository ) \
+ .filter( and_( model.Repository.table.c.deleted == False,
+ model.Repository.table.c.deprecated == False ) ) \
+ .join( model.User.table ) \
+ .order_by( model.Repository.name )
+
+
+class RepositoryDependenciesGrid( RepositoryMetadataGrid ):
+
+ title = "Repository dependencies available in this Tool Shed"
+ columns = [
+ RepositoryMetadataGrid.RepositoryNameColumn( "Repository name",
+ link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ),
+ attach_popup=False ),
+ RepositoryMetadataGrid.RepositoryOwnerColumn( "Owner",
+ model_class=model.User,
+ attach_popup=False,
+ key="User.username" )
+ ]
+ columns.append( grids.MulticolFilterColumn( "Search repository name, description",
+ cols_to_filter=[ columns[0], columns[1] ],
+ key="free-text-search",
+ visible=False,
+ filterable="standard" ) )
+
+ def build_initial_query( self, trans, **kwd ):
+ return trans.sa_session.query( model.RepositoryMetadata ) \
+ .join( model.Repository ) \
+ .filter( and_( model.RepositoryMetadata.table.c.has_repository_dependencies == True,
+ model.Repository.table.c.deleted == False,
+ model.Repository.table.c.deprecated == False ) ) \
+ .join( model.User.table ) \
+ .order_by( model.Repository.name )
+
+
class RepositoryController( BaseUIController, common_util.ItemRatings ):
+ category_grid = CategoryGrid()
+ deprecated_repositories_i_own_grid = DeprecatedRepositoriesIOwnGrid()
+ email_alerts_repository_grid = EmailAlertsRepositoryGrid()
install_matched_repository_grid = InstallMatchedRepositoryGrid()
matched_repository_grid = MatchedRepositoryGrid()
+ my_writable_repositories_grid = MyWritableRepositoriesGrid()
+ repositories_by_user_grid = RepositoriesByUserGrid()
+ repositories_i_own_grid = RepositoriesIOwnGrid()
+ repository_grid = RepositoryGrid()
+ # The repository_metadata_grid is not currently displayed, but is sub-classed by several grids.
+ repository_metadata_grid = RepositoryMetadataGrid()
+ valid_category_grid = ValidCategoryGrid()
valid_repository_grid = ValidRepositoryGrid()
- repository_grid = RepositoryGrid()
- email_alerts_repository_grid = EmailAlertsRepositoryGrid()
- category_grid = CategoryGrid()
- valid_category_grid = ValidCategoryGrid()
- my_writable_repositories_grid = MyWritableRepositoriesGrid()
- repositories_i_own_grid = RepositoriesIOwnGrid()
- deprecated_repositories_i_own_grid = DeprecatedRepositoriesIOwnGrid()
- repositories_by_user_grid = RepositoriesByUserGrid()
@web.expose
def browse_categories( self, trans, **kwd ):
@@ -3036,7 +3195,11 @@
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision )
if repository_metadata:
repository_metadata_id = trans.security.encode_id( repository_metadata.id )
- tool_test_errors = json.from_json_string( repository_metadata.tool_test_errors )
+ # TODO: Fix this when the install and test framework is completed.
+ # if repository_metadata.tool_test_errors:
+ # tool_test_errors = json.from_json_string( repository_metadata.tool_test_errors )
+ # else:
+ # tool_test_errors = None
metadata = repository_metadata.metadata
if metadata:
if 'tools' in metadata:
@@ -3070,7 +3233,7 @@
else:
repository_metadata_id = None
metadata = None
- tool_test_errors = None
+ #tool_test_errors = None
is_malicious = suc.changeset_is_malicious( trans, repository_id, repository.tip( trans.app ) )
changeset_revision_select_field = build_changeset_revision_select_field( trans,
repository,
@@ -3094,7 +3257,7 @@
tool=tool,
tool_metadata_dict=tool_metadata_dict,
tool_lineage=tool_lineage,
- tool_test_errors=tool_test_errors,
+ #tool_test_errors=tool_test_errors,
changeset_revision=changeset_revision,
revision_label=revision_label,
changeset_revision_select_field=changeset_revision_select_field,
diff -r 21c69586390abeefde4a52560321b826473ad041 -r 153f7f450f4b7537bc8866f09b5cc3ca57ad25ee lib/galaxy/webapps/tool_shed/model/__init__.py
--- a/lib/galaxy/webapps/tool_shed/model/__init__.py
+++ b/lib/galaxy/webapps/tool_shed/model/__init__.py
@@ -191,11 +191,14 @@
fp.close()
class RepositoryMetadata( object, APIItem ):
- api_collection_visible_keys = ( 'id', 'repository_id', 'changeset_revision', 'malicious', 'downloadable' )
+ api_collection_visible_keys = ( 'id', 'repository_id', 'changeset_revision', 'malicious', 'downloadable', 'has_repository_dependencies', 'includes_datatypes',
+ 'includes_tools', 'includes_tool_dependencies', 'includes_workflows' )
api_element_visible_keys = ( 'id', 'repository_id', 'changeset_revision', 'malicious', 'downloadable', 'tools_functionally_correct',
- 'do_not_test', 'time_last_tested', 'tool_test_errors' )
+ 'do_not_test', 'time_last_tested', 'tool_test_errors', 'has_repository_dependencies', 'includes_datatypes', 'includes_tools',
+ 'includes_tool_dependencies', 'includes_workflows' )
def __init__( self, id=None, repository_id=None, changeset_revision=None, metadata=None, tool_versions=None, malicious=False, downloadable=False,
- tools_functionally_correct=False, do_not_test=False, time_last_tested=None, tool_test_errors=None ):
+ tools_functionally_correct=False, do_not_test=False, time_last_tested=None, tool_test_errors=None, has_repository_dependencies=False,
+ includes_datatypes=False, includes_tools=False, includes_tool_dependencies=False, includes_workflows=False ):
self.id = id
self.repository_id = repository_id
self.changeset_revision = changeset_revision
@@ -207,6 +210,11 @@
self.do_not_test = do_not_test
self.time_last_tested = time_last_tested
self.tool_test_errors = tool_test_errors
+ self.has_repository_dependencies = has_repository_dependencies
+ self.includes_datatypes = includes_datatypes
+ self.includes_tools = includes_tools
+ self.includes_tool_dependencies = includes_tool_dependencies
+ self.includes_workflows = includes_workflows
def as_dict( self, value_mapper=None ):
return self.get_api_value( view='element', value_mapper=value_mapper )
def get_api_value( self, view='collection', value_mapper=None ):
@@ -227,8 +235,8 @@
return rval
class RepositoryReview( object, APIItem ):
- api_collection_visible_keys = ( 'id', 'repository_id', 'changeset_revision', 'user_id', 'rating' )
- api_element_visible_keys = ( 'id', 'repository_id', 'changeset_revision', 'user_id', 'rating' )
+ api_collection_visible_keys = ( 'id', 'repository_id', 'changeset_revision', 'user_id', 'rating', 'deleted' )
+ api_element_visible_keys = ( 'id', 'repository_id', 'changeset_revision', 'user_id', 'rating', 'deleted' )
approved_states = Bunch( NO='no', YES='yes' )
def __init__( self, repository_id=None, changeset_revision=None, user_id=None, rating=None, deleted=False ):
self.repository_id = repository_id
diff -r 21c69586390abeefde4a52560321b826473ad041 -r 153f7f450f4b7537bc8866f09b5cc3ca57ad25ee lib/galaxy/webapps/tool_shed/model/mapping.py
--- a/lib/galaxy/webapps/tool_shed/model/mapping.py
+++ b/lib/galaxy/webapps/tool_shed/model/mapping.py
@@ -134,7 +134,12 @@
Column( "tools_functionally_correct", Boolean, default=False, index=True ),
Column( "do_not_test", Boolean, default=False, index=True ),
Column( "time_last_tested", DateTime, default=None, nullable=True ),
- Column( "tool_test_errors", JSONType, nullable=True ) )
+ Column( "tool_test_errors", JSONType, nullable=True ),
+ Column( "has_repository_dependencies", Boolean, default=False, index=True ),
+ Column( "includes_datatypes", Boolean, default=False, index=True ),
+ Column( "includes_tools", Boolean, default=False, index=True ),
+ Column( "includes_tool_dependencies", Boolean, default=False, index=True ),
+ Column( "includes_workflows", Boolean, default=False, index=True ) )
RepositoryReview.table = Table( "repository_review", metadata,
Column( "id", Integer, primary_key=True ),
diff -r 21c69586390abeefde4a52560321b826473ad041 -r 153f7f450f4b7537bc8866f09b5cc3ca57ad25ee lib/galaxy/webapps/tool_shed/model/migrate/versions/0017_add_galaxy_utility_columns_to_repository_metadata_table.py
--- /dev/null
+++ b/lib/galaxy/webapps/tool_shed/model/migrate/versions/0017_add_galaxy_utility_columns_to_repository_metadata_table.py
@@ -0,0 +1,115 @@
+"""
+Migration script to add the includes_datatypes, has_repository_dependencies, includes_tools, includes_tool_dependencies and includes_workflows
+columns to the repository_metadata table.
+"""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+
+# Need our custom types, but don't import anything else from model
+from galaxy.model.custom_types import *
+
+import sys, logging
+log = logging.getLogger( __name__ )
+log.setLevel(logging.DEBUG)
+handler = logging.StreamHandler( sys.stdout )
+format = "%(name)s %(levelname)s %(asctime)s %(message)s"
+formatter = logging.Formatter( format )
+handler.setFormatter( formatter )
+log.addHandler( handler )
+
+metadata = MetaData( migrate_engine )
+db_session = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, autocommit=True ) )
+
+def upgrade():
+ print __doc__
+ metadata.reflect()
+ # Initialize.
+ if migrate_engine.name == 'mysql' or migrate_engine.name == 'sqlite':
+ default_false = "0"
+ elif migrate_engine.name == 'postgres':
+ default_false = "false"
+ # Create and initialize tools_functionally_correct, do_not_test, time_last_tested, and tool_test_errors columns in repository_metadata table.
+ RepositoryMetadata_table = Table( "repository_metadata", metadata, autoload=True )
+
+ # Create tools_functionally_correct column
+ c = Column( "includes_datatypes", Boolean, default=False, index=True )
+ try:
+ c.create( RepositoryMetadata_table )
+ assert c is RepositoryMetadata_table.c.includes_datatypes
+ db_session.execute( "UPDATE repository_metadata SET includes_datatypes=%s" % default_false )
+ except Exception, e:
+ print "Adding includes_datatypes column to the repository_metadata table failed: %s" % str( e )
+
+ # Create includes_datatypes column
+ c = Column( "has_repository_dependencies", Boolean, default=False, index=True )
+ try:
+ c.create( RepositoryMetadata_table )
+ assert c is RepositoryMetadata_table.c.has_repository_dependencies
+ db_session.execute( "UPDATE repository_metadata SET has_repository_dependencies=%s" % default_false )
+ except Exception, e:
+ print "Adding has_repository_dependencies column to the repository_metadata table failed: %s" % str( e )
+
+ # Create includes_tools column
+ c = Column( "includes_tools", Boolean, default=False, index=True )
+ try:
+ c.create( RepositoryMetadata_table )
+ assert c is RepositoryMetadata_table.c.includes_tools
+ db_session.execute( "UPDATE repository_metadata SET includes_tools=%s" % default_false )
+ except Exception, e:
+ print "Adding includes_tools column to the repository_metadata table failed: %s" % str( e )
+
+ # Create includes_tool_dependencies column
+ c = Column( "includes_tool_dependencies", Boolean, default=False, index=True )
+ try:
+ c.create( RepositoryMetadata_table )
+ assert c is RepositoryMetadata_table.c.includes_tool_dependencies
+ db_session.execute( "UPDATE repository_metadata SET includes_tool_dependencies=%s" % default_false )
+ except Exception, e:
+ print "Adding includes_tool_dependencies column to the repository_metadata table failed: %s" % str( e )
+
+ # Create includes_workflows column
+ c = Column( "includes_workflows", Boolean, default=False, index=True )
+ try:
+ c.create( RepositoryMetadata_table )
+ assert c is RepositoryMetadata_table.c.includes_workflows
+ db_session.execute( "UPDATE repository_metadata SET includes_workflows=%s" % default_false )
+ except Exception, e:
+ print "Adding includes_workflows column to the repository_metadata table failed: %s" % str( e )
+
+def downgrade():
+ metadata.reflect()
+ # Drop tool_test_errors, time_last_tested, do_not_test, and tools_functionally_correct columns from repository_metadata table.
+ RepositoryMetadata_table = Table( "repository_metadata", metadata, autoload=True )
+
+ # Drop the includes_workflows column.
+ try:
+ RepositoryMetadata_table.c.includes_workflows.drop()
+ except Exception, e:
+ print "Dropping column includes_workflows from the repository_metadata table failed: %s" % str( e )
+
+ # Drop the includes_tool_dependencies column.
+ try:
+ RepositoryMetadata_table.c.includes_tool_dependencies.drop()
+ except Exception, e:
+ print "Dropping column includes_tool_dependencies from the repository_metadata table failed: %s" % str( e )
+
+ # Drop the includes_tools column.
+ try:
+ RepositoryMetadata_table.c.includes_tools.drop()
+ except Exception, e:
+ print "Dropping column includes_tools from the repository_metadata table failed: %s" % str( e )
+
+ # Drop the has_repository_dependencies column.
+ try:
+ RepositoryMetadata_table.c.has_repository_dependencies.drop()
+ except Exception, e:
+ print "Dropping column has_repository_dependencies from the repository_metadata table failed: %s" % str( e )
+
+ # Drop the includes_datatypes column.
+ try:
+ RepositoryMetadata_table.c.includes_datatypes.drop()
+ except Exception, e:
+ print "Dropping column includes_datatypes from the repository_metadata table failed: %s" % str( e )
diff -r 21c69586390abeefde4a52560321b826473ad041 -r 153f7f450f4b7537bc8866f09b5cc3ca57ad25ee 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
@@ -900,16 +900,42 @@
shutil.copy( full_source_path, os.path.join( dest_path, copied_file ) )
def create_or_update_repository_metadata( trans, id, repository, changeset_revision, metadata_dict ):
"""Create or update a repository_metadatqa record in the tool shed."""
- downloadable = is_downloadable( metadata_dict )
+ has_repository_dependencies = False
+ includes_datatypes = False
+ includes_tools = False
+ includes_tool_dependencies = False
+ includes_workflows = False
+ if metadata_dict:
+ if 'repository_dependencies' in metadata_dict:
+ has_repository_dependencies = True
+ if 'datatypes' in metadata_dict:
+ includes_datatypes = True
+ if 'tools' in metadata_dict:
+ includes_tools = True
+ if 'tool_dependencies' in metadata_dict:
+ includes_tool_dependencies = True
+ if 'workflows' in metadata_dict:
+ includes_workflows = True
+ downloadable = has_repository_dependencies or includes_datatypes or includes_tools or includes_tool_dependencies or includes_workflows
repository_metadata = get_repository_metadata_by_changeset_revision( trans, id, changeset_revision )
if repository_metadata:
repository_metadata.metadata = metadata_dict
repository_metadata.downloadable = downloadable
+ repository_metadata.has_repository_dependencies = has_repository_dependencies
+ repository_metadata.includes_datatypes = includes_datatypes
+ repository_metadata.includes_tools = includes_tools
+ repository_metadata.includes_tool_dependencies = includes_tool_dependencies
+ repository_metadata.includes_workflows = includes_workflows
else:
repository_metadata = trans.model.RepositoryMetadata( repository_id=repository.id,
changeset_revision=changeset_revision,
metadata=metadata_dict,
- downloadable=downloadable )
+ downloadable=downloadable,
+ has_repository_dependencies=has_repository_dependencies,
+ includes_datatypes=includes_datatypes,
+ includes_tools=includes_tools,
+ includes_tool_dependencies=includes_tool_dependencies,
+ includes_workflows=includes_workflows )
# Always set the default values for the following columns. When resetting all metadata on a repository, this will reset the values.
repository_metadata.tools_functionally_correct = False
repository_metadata.do_not_test = False
diff -r 21c69586390abeefde4a52560321b826473ad041 -r 153f7f450f4b7537bc8866f09b5cc3ca57ad25ee templates/webapps/tool_shed/repository/view_tool_metadata.mako
--- a/templates/webapps/tool_shed/repository/view_tool_metadata.mako
+++ b/templates/webapps/tool_shed/repository/view_tool_metadata.mako
@@ -22,6 +22,8 @@
can_review_repository = has_metadata and not is_deprecated and trans.app.security_agent.user_can_review_repositories( trans.user )
can_upload = can_push
can_view_change_log = trans.webapp.name == 'tool_shed' and not is_new
+ # TODO: fix the following when the install and test buildbot is functional.
+ #can_view_tool_test_errors = tool_test_errors is not None
if can_push:
browse_label = 'Browse or delete repository tip files'
@@ -265,11 +267,26 @@
${tool.force_history_refresh | h}
<div style="clear: both"></div></div>
- <div class="form-row">
- <label>Parallelism:</label>
- ${tool.parallelism | h}
- <div style="clear: both"></div>
- </div>
+ <% parallelism_info = tool.parallelism %>
+ %if parallelism_info:
+ <div class="form-row">
+ <table width="100%">
+ <tr bgcolor="#D8D8D8" width="100%"><td><b>Parallelism</td></tr>
+ </table>
+ </div>
+ <div class="form-row">
+ <label>Method:</label>
+ ${parallelism_info.method | h}
+ <div style="clear: both"></div>
+ </div>
+ %for key, val in parallelism_info.attributes.items():
+ <div class="form-row">
+ <label>${key}:</label>
+ ${val | h}
+ <div style="clear: both"></div>
+ </div>
+ %endfor
+ %endif
%endif
<div class="form-row"><table width="100%">
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 the level 16 database migration script for the tool shed.
by commits-noreply@bitbucket.org 01 Mar '13
by commits-noreply@bitbucket.org 01 Mar '13
01 Mar '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/21c69586390a/
changeset: 21c69586390a
user: greg
date: 2013-03-01 16:52:13
summary: Fix the level 16 database migration script for the tool shed.
affected #: 1 file
diff -r 12dc58f5831ef32aff9c69761a251476f567ef69 -r 21c69586390abeefde4a52560321b826473ad041 lib/galaxy/webapps/tool_shed/model/migrate/versions/0016_add_do_not_test_tools_functionally_correct_errors_columns.py
--- a/lib/galaxy/webapps/tool_shed/model/migrate/versions/0016_add_do_not_test_tools_functionally_correct_errors_columns.py
+++ b/lib/galaxy/webapps/tool_shed/model/migrate/versions/0016_add_do_not_test_tools_functionally_correct_errors_columns.py
@@ -65,7 +65,6 @@
log.debug( "Adding time_last_tested column to the repository_metadata table failed: %s" % str( e ) )
c = Column( "tool_test_errors", JSONType, nullable=True )
try:
- pass
# Create tool_test_errors column
c.create( RepositoryMetadata_table )
assert c is RepositoryMetadata_table.c.tool_test_errors
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 starting up Galaxy after community webapp was renamed to be tool_shed.
by commits-noreply@bitbucket.org 01 Mar '13
by commits-noreply@bitbucket.org 01 Mar '13
01 Mar '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/12dc58f5831e/
changeset: 12dc58f5831e
user: greg
date: 2013-03-01 16:16:20
summary: Fix for starting up Galaxy after community webapp was renamed to be tool_shed.
affected #: 1 file
diff -r 5f774e034512d06c497febcf042d3dbc44d91cf8 -r 12dc58f5831ef32aff9c69761a251476f567ef69 lib/tool_shed/galaxy_install/__init__.py
--- a/lib/tool_shed/galaxy_install/__init__.py
+++ b/lib/tool_shed/galaxy_install/__init__.py
@@ -28,9 +28,9 @@
ElementInclude.include( root )
tool_path = root.get( 'tool_path', None )
if tool_path:
- tool_shed = tool_shed.util.shed_util_common.clean_tool_shed_url( tool_shed_repository.tool_shed )
+ ts = tool_shed.util.shed_util_common.clean_tool_shed_url( tool_shed_repository.tool_shed )
relative_path = os.path.join( tool_path,
- tool_shed,
+ ts,
'repos',
tool_shed_repository.owner,
tool_shed_repository.name,
@@ -45,13 +45,13 @@
.order_by( self.model.ToolShedRepository.table.c.id ):
relative_install_dir = self.get_repository_install_dir( tool_shed_repository )
if relative_install_dir:
- installed_repository_dict = galaxy.util.shed_util.load_installed_datatypes( self.app, tool_shed_repository, relative_install_dir )
+ installed_repository_dict = tool_shed.util.shed_util.load_installed_datatypes( self.app, 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 ):
for installed_repository_dict in self.installed_repository_dicts:
if installed_repository_dict[ 'converter_path' ]:
- galaxy.util.shed_util.load_installed_datatype_converters( self.app, installed_repository_dict, deactivate=deactivate )
+ tool_shed.util.shed_util.load_installed_datatype_converters( self.app, installed_repository_dict, deactivate=deactivate )
if installed_repository_dict[ 'display_path' ]:
- galaxy.util.shed_util.load_installed_display_applications( self.app, installed_repository_dict, deactivate=deactivate )
+ tool_shed.util.shed_util.load_installed_display_applications( self.app, installed_repository_dict, deactivate=deactivate )
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0

commit/galaxy-central: greg: Add the method for displaying tool functional test errors for a repository in the tool shed to the repository controller in preparation for the upcoming install and test framework.
by commits-noreply@bitbucket.org 01 Mar '13
by commits-noreply@bitbucket.org 01 Mar '13
01 Mar '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/5f774e034512/
changeset: 5f774e034512
user: greg
date: 2013-03-01 15:14:38
summary: Add the method for displaying tool functional test errors for a repository in the tool shed to the repository controller in preparation for the upcoming install and test framework.
affected #: 1 file
diff -r 15eafd606d97f9700b5ec9bfc92bb8c50badd365 -r 5f774e034512d06c497febcf042d3dbc44d91cf8 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
@@ -1137,6 +1137,9 @@
@web.expose
@web.require_login( "deprecate repository" )
def deprecate( self, trans, **kwd ):
+ """Mark a repository in the tool shed as deprecated or not deprecated."""
+ # Marking a repository in the tool shed as deprecated has no effect on any downloadable changeset revisions that may be associated with the
+ # repository. Revisions are not marked as not downlaodable because those that have installed the repository must be allowed to get updates.
params = util.Params( kwd )
message = util.restore_text( params.get( 'message', '' ) )
status = params.get( 'status', 'done' )
@@ -1195,6 +1198,43 @@
status='error' ) )
@web.expose
+ def display_tool_functional_test_errors( self, trans, repository_id, repository_metadata_id, **kwd ):
+ params = util.Params( kwd )
+ message = util.restore_text( params.get( 'message', '' ) )
+ status = params.get( 'status', 'done' )
+ repository = suc.get_repository_by_id( trans.app, repository_id )
+ if repository:
+ repository_metadata = suc.get_repository_metadata_by_id( trans, repository_metadata_id )
+ changeset_revision = repository_metadata.changeset_revision
+ if repository_metadata:
+ metadata = repository_metadata.metadata
+ if metadata:
+ return trans.fill_template( '/webapps/tool_shed/repository/display_tool_functional_test_errors.mako',
+ repository=repository,
+ repository_metadata=repository_metadata,
+ message=message,
+ status=status )
+ else:
+ message = 'Missing metadata for revision <b>%s</b> of repository <b>%s</b> owned by <b>%s</b>.' % \
+ ( str( changeset_revision ), str( repository.name ), str( repository.user.username ) )
+ else:
+ message = 'Invalid repository_metadata_id <b>%s</b> received for displaying functional test errors for repository <b>%s</b>.' % \
+ ( str( repository_metadata_id ), str( repository.name ) )
+ else:
+ message = 'Invalid repository_id received for displaying functional test errors.<b>%s</b>.' % str( repository_id )
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action='browse_repositories',
+ message=message,
+ status='error' ) )
+ return trans.response.send_redirect( web.url_for( controller='repository',
+ action='browse_repository',
+ operation='view_or_manage_repository',
+ id=repository_id,
+ changeset_revision=changeset_revision,
+ message=message,
+ status='error' ) )
+
+ @web.expose
def download( self, trans, repository_id, changeset_revision, file_type, **kwd ):
# Download an archive of the repository files compressed as zip, gz or bz2.
params = util.Params( kwd )
@@ -2995,6 +3035,8 @@
revision_label = suc.get_revision_label( trans, repository, changeset_revision )
repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision )
if repository_metadata:
+ repository_metadata_id = trans.security.encode_id( repository_metadata.id )
+ tool_test_errors = json.from_json_string( repository_metadata.tool_test_errors )
metadata = repository_metadata.metadata
if metadata:
if 'tools' in metadata:
@@ -3026,7 +3068,9 @@
if guid:
tool_lineage = self.get_versions_of_tool( trans, repository, repository_metadata, guid )
else:
+ repository_metadata_id = None
metadata = None
+ tool_test_errors = None
is_malicious = suc.changeset_is_malicious( trans, repository_id, repository.tip( trans.app ) )
changeset_revision_select_field = build_changeset_revision_select_field( trans,
repository,
@@ -3045,10 +3089,12 @@
review_id = None
return trans.fill_template( "/webapps/tool_shed/repository/view_tool_metadata.mako",
repository=repository,
+ repository_metadata_id=repository_metadata_id,
metadata=metadata,
tool=tool,
tool_metadata_dict=tool_metadata_dict,
tool_lineage=tool_lineage,
+ tool_test_errors=tool_test_errors,
changeset_revision=changeset_revision,
revision_label=revision_label,
changeset_revision_select_field=changeset_revision_select_field,
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