galaxy-dev
Threads by month
- ----- 2025 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- 10008 discussions

18 Mar '10
details: http://www.bx.psu.edu/hg/galaxy/rev/90fa86a7b4e3
changeset: 3525:90fa86a7b4e3
user: Dan Blankenberg <dan(a)bx.psu.edu>
date: Fri Mar 12 12:17:36 2010 -0500
description:
Tweaks for flow control in Display applications:
Display Applications now use trans.response.send_redirect instead of javascript when redirecting users to prepared display applications.
Display Applications now use a <meta> refresh instead of a javascript based refresh when notifying users that the display application is being prepared.
diffstat:
lib/galaxy/web/controllers/dataset.py | 3 ++-
templates/dataset/display_application/display.mako | 9 ++-------
templates/dataset/display_application/launch_display.mako | 15 ---------------
3 files changed, 4 insertions(+), 23 deletions(-)
diffs (55 lines):
diff -r 5f967426f33f -r 90fa86a7b4e3 lib/galaxy/web/controllers/dataset.py
--- a/lib/galaxy/web/controllers/dataset.py Fri Mar 12 12:03:25 2010 -0500
+++ b/lib/galaxy/web/controllers/dataset.py Fri Mar 12 12:17:36 2010 -0500
@@ -557,7 +557,8 @@
trans.response.headers[ 'Content-Length' ] = content_length
return rval
elif app_action == None:
- return trans.fill_template_mako( "dataset/display_application/launch_display.mako", display_link = display_link )
+ #redirect user to url generated by display link
+ return trans.response.send_redirect( display_link.display_url() )
else:
msg.append( ( 'Invalid action provided: %s' % app_action, 'error' ) )
else:
diff -r 5f967426f33f -r 90fa86a7b4e3 templates/dataset/display_application/display.mako
--- a/templates/dataset/display_application/display.mako Fri Mar 12 12:03:25 2010 -0500
+++ b/templates/dataset/display_application/display.mako Fri Mar 12 12:17:36 2010 -0500
@@ -1,17 +1,12 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
<%def name="title()">Display Application: ${display_link.link.display_application.name} ${display_link.link.name}</%def>
-<% refresh_rate = 10 %>
-%if refresh:
-<script type="text/javascript">
- setTimeout( "location.reload(true);", ${ refresh_rate * 1000 } );
-</script>
-%endif
%for message, message_type in msg:
${render_msg( message, message_type )}
%endfor
%if refresh:
+<%def name="metas()"><meta http-equiv="refresh" content="10" /></%def>
<p>
-This page will <a href="javascript:location.reload(true);">refresh</a> after ${refresh_rate} seconds.
+This page will <a href="javascript:location.reload(true);">refresh</a> after 10 seconds.
</p>
%endif
diff -r 5f967426f33f -r 90fa86a7b4e3 templates/dataset/display_application/launch_display.mako
--- a/templates/dataset/display_application/launch_display.mako Fri Mar 12 12:03:25 2010 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-<%inherit file="/base.mako"/>
-<%def name="title()">Launching Display Application: ${display_link.link.display_application.name} ${display_link.link.name}</%def>
-
-<script type="text/javascript">
- location.href = '${display_link.display_url()}';
-</script>
-<p>
-All data has been prepared for the external display application: ${display_link.link.display_application.name} ${display_link.link.name}.
-</p>
-<p>
-You are now being automatically forwarded to the external application.
-</p>
-<p>
-Click <a href="${display_link.display_url()}">here</a> if this redirect has failed.
-</p>
1
0

18 Mar '10
details: http://www.bx.psu.edu/hg/galaxy/rev/5f967426f33f
changeset: 3524:5f967426f33f
user: Dan Blankenberg <dan(a)bx.psu.edu>
date: Fri Mar 12 12:03:25 2010 -0500
description:
Add 'metas()' %def to base.mako, to allow subclassing templates to declare additional <meta/> tags.
diffstat:
templates/base.mako | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diffs (17 lines):
diff -r c3eccab29814 -r 5f967426f33f templates/base.mako
--- a/templates/base.mako Fri Mar 12 09:37:22 2010 -0500
+++ b/templates/base.mako Fri Mar 12 12:03:25 2010 -0500
@@ -5,6 +5,7 @@
<head>
<title>${self.title()}</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+${self.metas()}
${self.stylesheets()}
${self.javascripts()}
</head>
@@ -30,3 +31,5 @@
${h.js( "jquery", "galaxy.base" )}
</%def>
+## Additional metas can be defined by templates inheriting from this one.
+<%def name="metas()"></%def>
1
0

18 Mar '10
details: http://www.bx.psu.edu/hg/galaxy/rev/c3eccab29814
changeset: 3523:c3eccab29814
user: jeremy goecks <jeremy.goecks(a)emory.edu>
date: Fri Mar 12 09:37:22 2010 -0500
description:
Make visualizations sharable, publishable, taggable, and annotate-able. Plumbing code is in place, but UI code needs work; in particular, viewing a shared/published visualization is empty and annotations are available only via edit attributes.
Some code tidying: refactoring, removing unused code.
diffstat:
lib/galaxy/model/__init__.py | 16 +-
lib/galaxy/model/mapping.py | 73 +-
lib/galaxy/model/migrate/versions/0043_visualization_sharing_tagging_annotating.py | 220 ++++++
lib/galaxy/tags/tag_handler.py | 1 +
lib/galaxy/web/base/controller.py | 39 +-
lib/galaxy/web/buildapp.py | 1 +
lib/galaxy/web/controllers/history.py | 56 +-
lib/galaxy/web/controllers/page.py | 21 +-
lib/galaxy/web/controllers/tracks.py | 4 +-
lib/galaxy/web/controllers/visualization.py | 322 +++++++++-
lib/galaxy/web/controllers/workflow.py | 6 +-
templates/base_panels.mako | 2 +-
templates/display_common.mako | 7 +-
templates/page/create.mako | 3 +-
templates/panels.mako | 2 -
templates/visualization/create.mako | 14 +
templates/visualization/display.mako | 19 +
templates/visualization/list.mako | 52 +
templates/visualization/list_published.mako | 36 +
19 files changed, 773 insertions(+), 121 deletions(-)
diffs (1317 lines):
diff -r 582fd1777763 -r c3eccab29814 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py Thu Mar 11 15:54:13 2010 -0500
+++ b/lib/galaxy/model/__init__.py Fri Mar 12 09:37:22 2010 -0500
@@ -1527,6 +1527,11 @@
self.title = None
self.config = None
+class VisualizationUserShareAssociation( object ):
+ def __init__( self ):
+ self.visualization = None
+ self.user = None
+
class Tag ( object ):
def __init__( self, id=None, type=None, parent_id=None, name=None ):
self.id = id
@@ -1558,16 +1563,16 @@
class PageTagAssociation ( ItemTagAssociation ):
pass
-
-class WorkflowTagAssociation ( ItemTagAssociation ):
- pass
-
+
class WorkflowStepTagAssociation ( ItemTagAssociation ):
pass
class StoredWorkflowTagAssociation ( ItemTagAssociation ):
pass
+class VisualizationTagAssociation ( ItemTagAssociation ):
+ pass
+
class HistoryAnnotationAssociation( object ):
pass
@@ -1583,6 +1588,9 @@
class PageAnnotationAssociation( object ):
pass
+class VisualizationAnnotationAssociation( object ):
+ pass
+
class UserPreference ( object ):
def __init__( self, name=None, value=None ):
self.name = name
diff -r 582fd1777763 -r c3eccab29814 lib/galaxy/model/mapping.py
--- a/lib/galaxy/model/mapping.py Thu Mar 11 15:54:13 2010 -0500
+++ b/lib/galaxy/model/mapping.py Fri Mar 12 09:37:22 2010 -0500
@@ -80,7 +80,7 @@
Column( "genome_build", TrimmedString( 40 ) ),
Column( "importable", Boolean, default=False ),
Column( "slug", TEXT, index=True ),
- Column( "published", Boolean, index=True ) )
+ Column( "published", Boolean, index=True, default=False ) )
HistoryUserShareAssociation.table = Table( "history_user_share_association", metadata,
Column( "id", Integer, primary_key=True ),
@@ -521,7 +521,7 @@
Column( "deleted", Boolean, default=False ),
Column( "importable", Boolean, default=False ),
Column( "slug", TEXT, index=True ),
- Column( "published", Boolean, index=True )
+ Column( "published", Boolean, index=True, default=False )
)
Workflow.table = Table( "workflow", metadata,
@@ -721,7 +721,11 @@
Column( "latest_revision_id", Integer,
ForeignKey( "visualization_revision.id", use_alter=True, name='visualization_latest_revision_id_fk' ), index=True ),
Column( "title", TEXT ),
- Column( "type", TEXT )
+ Column( "type", TEXT ),
+ Column( "deleted", Boolean, default=False, index=True ),
+ Column( "importable", Boolean, default=False, index=True ),
+ Column( "slug", TEXT, index=True ),
+ Column( "published", Boolean, default=False, index=True )
)
VisualizationRevision.table = Table( "visualization_revision", metadata,
@@ -733,6 +737,12 @@
Column( "config", JSONType )
)
+VisualizationUserShareAssociation.table = Table( "visualization_user_share_association", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "visualization_id", Integer, ForeignKey( "visualization.id" ), index=True ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True )
+ )
+
# Tagging tables.
Tag.table = Table( "tag", metadata,
@@ -768,16 +778,7 @@
Column( "user_tname", TrimmedString(255), index=True),
Column( "value", TrimmedString(255), index=True),
Column( "user_value", TrimmedString(255), index=True) )
-
-WorkflowTagAssociation.table = Table( "workflow_tag_association", metadata,
- Column( "id", Integer, primary_key=True ),
- Column( "workflow_id", Integer, ForeignKey( "workflow.id" ), index=True ),
- Column( "tag_id", Integer, ForeignKey( "tag.id" ), index=True ),
- Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
- Column( "user_tname", Unicode(255), index=True),
- Column( "value", Unicode(255), index=True),
- Column( "user_value", Unicode(255), index=True) )
-
+
StoredWorkflowTagAssociation.table = Table( "stored_workflow_tag_association", metadata,
Column( "id", Integer, primary_key=True ),
Column( "stored_workflow_id", Integer, ForeignKey( "stored_workflow.id" ), index=True ),
@@ -805,6 +806,15 @@
Column( "value", Unicode(255), index=True),
Column( "user_value", Unicode(255), index=True) )
+VisualizationTagAssociation.table = Table( "visualization_tag_association", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "visualization_id", Integer, ForeignKey( "visualization.id" ), index=True ),
+ Column( "tag_id", Integer, ForeignKey( "tag.id" ), index=True ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
+ Column( "user_tname", TrimmedString(255), index=True),
+ Column( "value", TrimmedString(255), index=True),
+ Column( "user_value", TrimmedString(255), index=True) )
+
# Annotation tables.
HistoryAnnotationAssociation.table = Table( "history_annotation_association", metadata,
@@ -836,6 +846,12 @@
Column( "page_id", Integer, ForeignKey( "page.id" ), index=True ),
Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
Column( "annotation", TEXT, index=True) )
+
+VisualizationAnnotationAssociation.table = Table( "visualization_annotation_association", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "visualization_id", Integer, ForeignKey( "visualization.id" ), index=True ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
+ Column( "annotation", TEXT, index=True) )
# User tables.
@@ -1271,8 +1287,7 @@
properties=dict( steps=relation( WorkflowStep, backref='workflow',
order_by=asc(WorkflowStep.table.c.order_index),
cascade="all, delete-orphan",
- lazy=False ),
- tags=relation(WorkflowTagAssociation, order_by=WorkflowTagAssociation.table.c.id, backref="workflows")
+ lazy=False )
) )
assign_mapper( context, WorkflowStep, WorkflowStep.table,
@@ -1359,8 +1374,20 @@
primaryjoin=( Visualization.table.c.id == VisualizationRevision.table.c.visualization_id ) ),
latest_revision=relation( VisualizationRevision, post_update=True,
primaryjoin=( Visualization.table.c.latest_revision_id == VisualizationRevision.table.c.id ),
- lazy=False )
+ lazy=False ),
+ tags=relation( VisualizationTagAssociation, order_by=VisualizationTagAssociation.table.c.id, backref="visualizations" ),
+ annotations=relation( VisualizationAnnotationAssociation, order_by=VisualizationAnnotationAssociation.table.c.id, backref="visualizations" )
) )
+
+# Set up proxy so that
+# Visualization.users_shared_with_dot_users
+# returns a list of User objects for users that a visualization is shared with.
+Visualization.users_shared_with_dot_users = association_proxy( 'users_shared_with', 'user' )
+
+assign_mapper( context, VisualizationUserShareAssociation, VisualizationUserShareAssociation.table,
+ properties=dict( user=relation( User, backref='visualizations_shared_by_others' ),
+ visualization=relation( Visualization, backref='users_shared_with' )
+ ) )
assign_mapper( context, Tag, Tag.table,
properties=dict( children=relation(Tag, backref=backref( 'parent', remote_side=[Tag.table.c.id] ) )
@@ -1381,19 +1408,19 @@
assign_mapper( context, PageTagAssociation, PageTagAssociation.table,
properties=dict( tag=relation(Tag, backref="tagged_pages"), user=relation( User ) )
)
-
-assign_mapper( context, WorkflowTagAssociation, WorkflowTagAssociation.table,
- properties=dict( tag=relation(Tag, backref="tagged_workflows"), user=relation( User ) )
- )
assign_mapper( context, StoredWorkflowTagAssociation, StoredWorkflowTagAssociation.table,
- properties=dict( tag=relation(Tag, backref="tagged_stored_workflows"), user=relation( User ) )
+ properties=dict( tag=relation(Tag, backref="tagged_workflows"), user=relation( User ) )
)
assign_mapper( context, WorkflowStepTagAssociation, WorkflowStepTagAssociation.table,
properties=dict( tag=relation(Tag, backref="tagged_workflow_steps"), user=relation( User ) )
)
+assign_mapper( context, VisualizationTagAssociation, VisualizationTagAssociation.table,
+ properties=dict( tag=relation(Tag, backref="tagged_visualizations"), user=relation( User ) )
+ )
+
assign_mapper( context, HistoryAnnotationAssociation, HistoryAnnotationAssociation.table,
properties=dict( history=relation( History ), user=relation( User ) )
)
@@ -1414,6 +1441,10 @@
properties=dict( page=relation( Page ), user=relation( User ) )
)
+assign_mapper( context, VisualizationAnnotationAssociation, VisualizationAnnotationAssociation.table,
+ properties=dict( visualization=relation( Visualization ), user=relation( User ) )
+ )
+
assign_mapper( context, UserPreference, UserPreference.table,
properties = {}
)
diff -r 582fd1777763 -r c3eccab29814 lib/galaxy/model/migrate/versions/0043_visualization_sharing_tagging_annotating.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/galaxy/model/migrate/versions/0043_visualization_sharing_tagging_annotating.py Fri Mar 12 09:37:22 2010 -0500
@@ -0,0 +1,220 @@
+"""
+Migration script to create tables and columns for sharing visualizations.
+"""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+
+import logging
+log = logging.getLogger( __name__ )
+
+metadata = MetaData( migrate_engine )
+db_session = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, autocommit=True ) )
+
+# Sharing visualizations.
+
+VisualizationUserShareAssociation_table = Table( "visualization_user_share_association", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "visualization_id", Integer, ForeignKey( "visualization.id" ), index=True ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True )
+ )
+
+# Tagging visualizations.
+
+VisualizationTagAssociation_table = Table( "visualization_tag_association", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "visualization_id", Integer, ForeignKey( "visualization.id" ), index=True ),
+ Column( "tag_id", Integer, ForeignKey( "tag.id" ), index=True ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
+ Column( "user_tname", Unicode(255), index=True),
+ Column( "value", Unicode(255), index=True),
+ Column( "user_value", Unicode(255), index=True) )
+
+# Annotating visualizations.
+
+VisualizationAnnotationAssociation_table = Table( "visualization_annotation_association", metadata,
+ Column( "id", Integer, primary_key=True ),
+ Column( "visualization_id", Integer, ForeignKey( "visualization.id" ), index=True ),
+ Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
+ Column( "annotation", TEXT, index=False ) )
+
+Visualiation_table = Table( "visualization", metadata, autoload=True )
+
+def upgrade():
+ print __doc__
+ metadata.reflect()
+
+ # Create visualization_user_share_association table.
+ try:
+ VisualizationUserShareAssociation_table.create()
+ except Exception, e:
+ print "Creating visualization_user_share_association table failed: %s" % str( e )
+ log.debug( "Creating visualization_user_share_association table failed: %s" % str( e ) )
+
+ # Get default boolean value 'false' so that columns can be initialized.
+ if migrate_engine.name == 'mysql':
+ default_false = "0"
+ elif migrate_engine.name == 'sqlite':
+ default_false = "'false'"
+ elif migrate_engine.name == 'postgres':
+ default_false = "false"
+
+ # Add columns & create indices for supporting sharing to visualization table.
+ deleted_column = Column( "deleted", Boolean, default=False, index=True )
+ importable_column = Column( "importable", Boolean, default=False, index=True )
+ slug_column = Column( "slug", TEXT, index=True )
+ published_column = Column( "published", Boolean, index=True )
+
+ try:
+ # Add column.
+ deleted_column.create( Visualiation_table )
+ assert deleted_column is Visualiation_table.c.deleted
+
+ # Fill column with default value.
+ cmd = "UPDATE visualization SET deleted = %s" % default_false
+ db_session.execute( cmd )
+ except Exception, e:
+ print "Adding deleted column to visualization table failed: %s" % str( e )
+ log.debug( "Adding deleted column to visualization table failed: %s" % str( e ) )
+
+ try:
+ i = Index( "ix_visualization_deleted", Visualiation_table.c.deleted )
+ i.create()
+ except Exception, e:
+ print "Adding index 'ix_visualization_deleted' failed: %s" % str( e )
+ log.debug( "Adding index 'ix_visualization_deleted' failed: %s" % str( e ) )
+
+ try:
+ # Add column.
+ importable_column.create( Visualiation_table )
+ assert importable_column is Visualiation_table.c.importable
+
+ # Fill column with default value.
+ cmd = "UPDATE visualization SET importable = %s" % default_false
+ db_session.execute( cmd )
+ except Exception, e:
+ print "Adding importable column to visualization table failed: %s" % str( e )
+ log.debug( "Adding importable column to visualization table failed: %s" % str( e ) )
+
+ i = Index( "ix_visualization_importable", Visualiation_table.c.importable )
+ try:
+ i.create()
+ except Exception, e:
+ print "Adding index 'ix_visualization_importable' failed: %s" % str( e )
+ log.debug( "Adding index 'ix_visualization_importable' failed: %s" % str( e ) )
+
+ try:
+ slug_column.create( Visualiation_table )
+ assert slug_column is Visualiation_table.c.slug
+ except Exception, e:
+ print "Adding slug column to visualization table failed: %s" % str( e )
+ log.debug( "Adding slug column to visualization table failed: %s" % str( e ) )
+
+ try:
+ if migrate_engine.name == 'mysql':
+ # Have to create index manually.
+ cmd = "CREATE INDEX ix_visualization_slug ON visualization ( slug ( 100 ) )"
+ db_session.execute( cmd )
+ else:
+ i = Index( "ix_visualization_slug", Visualiation_table.c.slug )
+ i.create()
+ except Exception, e:
+ print "Adding index 'ix_visualization_slug' failed: %s" % str( e )
+ log.debug( "Adding index 'ix_visualization_slug' failed: %s" % str( e ) )
+
+ try:
+ # Add column.
+ published_column.create( Visualiation_table )
+ assert published_column is Visualiation_table.c.published
+
+ # Fill column with default value.
+ cmd = "UPDATE visualization SET published = %s" % default_false
+ db_session.execute( cmd )
+ except Exception, e:
+ print "Adding published column to visualization table failed: %s" % str( e )
+ log.debug( "Adding published column to visualization table failed: %s" % str( e ) )
+
+ i = Index( "ix_visualization_published", Visualiation_table.c.published )
+ try:
+ i.create()
+ except Exception, e:
+ print "Adding index 'ix_visualization_published' failed: %s" % str( e )
+ log.debug( "Adding index 'ix_visualization_published' failed: %s" % str( e ) )
+
+ # Create visualization_tag_association table.
+ try:
+ VisualizationTagAssociation_table.create()
+ except Exception, e:
+ print str(e)
+ log.debug( "Creating visualization_tag_association table failed: %s" % str( e ) )
+
+ # Create visualization_annotation_association table.
+ try:
+ VisualizationAnnotationAssociation_table.create()
+ except Exception, e:
+ print str(e)
+ log.debug( "Creating visualization_annotation_association table failed: %s" % str( e ) )
+
+ # Need to create index for visualization annotation manually to deal with errors.
+ try:
+ if migrate_engine.name == 'mysql':
+ # Have to create index manually.
+ cmd = "CREATE INDEX ix_visualization_annotation_association_annotation ON visualization_annotation_association ( annotation ( 100 ) )"
+ db_session.execute( cmd )
+ else:
+ i = Index( "ix_visualization_annotation_association_annotation", VisualizationAnnotationAssociation_table.c.annotation )
+ i.create()
+ except Exception, e:
+ print "Adding index 'ix_visualization_annotation_association_annotation' failed: %s" % str( e )
+ log.debug( "Adding index 'ix_visualization_annotation_association_annotation' failed: %s" % str( e ) )
+
+def downgrade():
+ metadata.reflect()
+
+ # Drop visualization_user_share_association table.
+ try:
+ VisualizationUserShareAssociation_table.drop()
+ except Exception, e:
+ print str(e)
+ log.debug( "Dropping visualization_user_share_association table failed: %s" % str( e ) )
+
+ # Drop columns for supporting sharing from visualization table.
+ try:
+ Visualiation_table.c.deleted.drop()
+ except Exception, e:
+ print "Dropping deleted column from visualization table failed: %s" % str( e )
+ log.debug( "Dropping deleted column from visualization table failed: %s" % str( e ) )
+
+ try:
+ Visualiation_table.c.importable.drop()
+ except Exception, e:
+ print "Dropping importable column from visualization table failed: %s" % str( e )
+ log.debug( "Dropping importable column from visualization table failed: %s" % str( e ) )
+
+ try:
+ Visualiation_table.c.slug.drop()
+ except Exception, e:
+ print "Dropping slug column from visualization table failed: %s" % str( e )
+ log.debug( "Dropping slug column from visualization table failed: %s" % str( e ) )
+
+ try:
+ Visualiation_table.c.published.drop()
+ except Exception, e:
+ print "Dropping published column from visualization table failed: %s" % str( e )
+ log.debug( "Dropping published column from visualization table failed: %s" % str( e ) )
+
+ # Drop visualization_tag_association table.
+ try:
+ VisualizationTagAssociation_table.drop()
+ except Exception, e:
+ print str(e)
+ log.debug( "Dropping visualization_tag_association table failed: %s" % str( e ) )
+
+ # Drop visualization_annotation_association table.
+ try:
+ VisualizationAnnotationAssociation_table.drop()
+ except Exception, e:
+ print str(e)
+ log.debug( "Dropping visualization_annotation_association table failed: %s" % str( e ) )
\ No newline at end of file
diff -r 582fd1777763 -r c3eccab29814 lib/galaxy/tags/tag_handler.py
--- a/lib/galaxy/tags/tag_handler.py Thu Mar 11 15:54:13 2010 -0500
+++ b/lib/galaxy/tags/tag_handler.py Fri Mar 12 09:37:22 2010 -0500
@@ -34,6 +34,7 @@
ItemTagAssocInfo( model.HistoryDatasetAssociation, model.HistoryDatasetAssociationTagAssociation, model.HistoryDatasetAssociationTagAssociation.table.c.history_dataset_association_id )
item_tag_assoc_info["Page"] = ItemTagAssocInfo( model.Page, model.PageTagAssociation, model.PageTagAssociation.table.c.page_id )
item_tag_assoc_info["StoredWorkflow"] = ItemTagAssocInfo( model.StoredWorkflow, model.StoredWorkflowTagAssociation, model.StoredWorkflowTagAssociation.table.c.stored_workflow_id )
+ item_tag_assoc_info["Visualization"] = ItemTagAssocInfo( model.Visualization, model.VisualizationTagAssociation, model.VisualizationTagAssociation.table.c.visualization_id )
def get_tag_assoc_class(self, item_class):
""" Returns tag association class for item class. """
diff -r 582fd1777763 -r c3eccab29814 lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py Thu Mar 11 15:54:13 2010 -0500
+++ b/lib/galaxy/web/base/controller.py Fri Mar 12 09:37:22 2010 -0500
@@ -16,6 +16,9 @@
# States for passing messages
SUCCESS, INFO, WARNING, ERROR = "done", "info", "warning", "error"
+
+# RE that tests for valid slug.
+VALID_SLUG_RE = re.compile( "^[a-z0-9\-]+$" )
class BaseController( object ):
"""
@@ -40,6 +43,8 @@
item_class = model.Page
elif class_name == 'StoredWorkflow':
item_class = model.StoredWorkflow
+ elif class_name == 'Visualization':
+ item_class = model.Visualization
else:
item_class = None
return item_class
@@ -76,6 +81,8 @@
annotation_assoc = annotation_assoc.filter_by( workflow_step=item )
elif item.__class__ == model.Page:
annotation_assoc = annotation_assoc.filter_by( page=item )
+ elif item.__class__ == model.Visualization:
+ annotation_assoc = annotation_assoc.filter_by( visualization=item )
return annotation_assoc.first()
def add_item_annotation( self, trans, item, annotation ):
@@ -153,6 +160,19 @@
truncated = False
return truncated, dataset_data
+class UsesVisualization( SharableItemSecurity ):
+ """ Mixin for controllers that use Visualization objects. """
+
+ def get_visualization( self, trans, id, check_ownership=True, check_accessible=False ):
+ """ Get a Visualization from the database by id, verifying ownership. """
+ # Load workflow from database
+ id = trans.security.decode_id( id )
+ visualization = trans.sa_session.query( model.Visualization ).get( id )
+ if not visualization:
+ error( "Visualization not found" )
+ else:
+ return self.security_check( trans.get_user(), stored, check_ownership, check_accessible )
+
class UsesStoredWorkflow( SharableItemSecurity ):
""" Mixin for controllers that use StoredWorkflow objects. """
@@ -240,6 +260,12 @@
pass
@web.expose
+ @web.require_login( "share Galaxy items" )
+ def share( self, trans, id=None, email="", **kwd ):
+ """ Handle sharing an item with a particular user. """
+ pass
+
+ @web.expose
def display_by_username_and_slug( self, trans, username, slug ):
""" Display item by username and slug. """
pass
@@ -262,13 +288,18 @@
def _make_item_accessible( self, sa_session, item ):
""" Makes item accessible--viewable and importable--and sets item's slug. Does not flush/commit changes, however. Item must have name, user, importable, and slug attributes. """
item.importable = True
- self.set_item_slug( sa_session, item )
+ self.create_item_slug( sa_session, item )
- def set_item_slug( self, sa_session, item ):
- """ Set item slug. Slug is unique among user's importable items for item's class. Returns true if item's slug was set; false otherwise. """
+ def create_item_slug( self, sa_session, item ):
+ """ Create item slug. Slug is unique among user's importable items for item's class. Returns true if item's slug was set; false otherwise. """
if item.slug is None or item.slug == "":
+ # Item can have either a name or a title.
+ if hasattr( item, 'name' ):
+ item_name = item.name
+ elif hasattr( item, 'title' ):
+ item_name = item.title
# Replace whitespace with '-'
- slug_base = re.sub( "\s+", "-", item.name.lower() )
+ slug_base = re.sub( "\s+", "-", item_name.lower() )
# Remove all non-alphanumeric characters.
slug_base = re.sub( "[^a-zA-Z0-9\-]", "", slug_base )
# Remove trailing '-'.
diff -r 582fd1777763 -r c3eccab29814 lib/galaxy/web/buildapp.py
--- a/lib/galaxy/web/buildapp.py Thu Mar 11 15:54:13 2010 -0500
+++ b/lib/galaxy/web/buildapp.py Fri Mar 12 09:37:22 2010 -0500
@@ -79,6 +79,7 @@
webapp.add_route( '/u/:username/p/:slug', controller='page', action='display_by_username_and_slug' )
webapp.add_route( '/u/:username/h/:slug', controller='history', action='display_by_username_and_slug' )
webapp.add_route( '/u/:username/w/:slug', controller='workflow', action='display_by_username_and_slug' )
+ webapp.add_route( '/u/:username/v/:slug', controller='visualization', action='display_by_username_and_slug' )
webapp.finalize_config()
# Wrap the webapp in some useful middleware
if kwargs.get( 'middleware', True ):
diff -r 582fd1777763 -r c3eccab29814 lib/galaxy/web/controllers/history.py
--- a/lib/galaxy/web/controllers/history.py Thu Mar 11 15:54:13 2010 -0500
+++ b/lib/galaxy/web/controllers/history.py Fri Mar 12 09:37:22 2010 -0500
@@ -440,7 +440,7 @@
""" Returns history's name and link. """
history = self.get_history( trans, id, False )
- if self.set_item_slug( trans.sa_session, history ):
+ if self.create_item_slug( trans.sa_session, history ):
trans.sa_session.flush()
return_dict = { "name" : history.name, "link" : url_for( action="display_by_username_and_slug", username=history.user.username, slug=history.slug ) }
return return_dict
@@ -652,58 +652,6 @@
session.flush()
return trans.fill_template( "/sharing_base.mako", item=history )
-
- ## TODO: remove this method when history sharing has been verified to work correctly with new sharing() method.
- @web.expose
- @web.require_login( "share histories with other users" )
- def sharing_old( self, trans, histories=[], id=None, **kwd ):
- """Performs sharing of histories among users."""
- # histories looks like: [ historyX, historyY ]
- params = util.Params( kwd )
- msg = util.restore_text ( params.get( 'msg', '' ) )
- if id:
- ids = util.listify( id )
- if ids:
- histories = [ self.get_history( trans, history_id ) for history_id in ids ]
- for history in histories:
- trans.sa_session.add( history )
- if params.get( 'enable_import_via_link', False ):
- self._make_item_accessible( trans.sa_session, history )
- trans.sa_session.flush()
- elif params.get( 'disable_import_via_link', False ):
- history.importable = False
- trans.sa_session.flush()
- elif params.get( 'unshare_user', False ):
- user = trans.sa_session.query( trans.app.model.User ).get( trans.security.decode_id( kwd[ 'unshare_user' ] ) )
- if not user:
- msg = 'History (%s) does not seem to be shared with user (%s)' % ( history.name, user.email )
- return trans.fill_template( 'history/sharing.mako', histories=histories, msg=msg, messagetype='error' )
- husas = trans.sa_session.query( trans.app.model.HistoryUserShareAssociation ).filter_by( user=user, history=history ).all()
- if husas:
- for husa in husas:
- trans.sa_session.delete( husa )
- trans.sa_session.flush()
- histories = []
- # Get all histories that have been shared with others
- husas = trans.sa_session.query( trans.app.model.HistoryUserShareAssociation ) \
- .join( "history" ) \
- .filter( and_( trans.app.model.History.user == trans.user,
- trans.app.model.History.deleted == False ) ) \
- .order_by( trans.app.model.History.table.c.name )
- for husa in husas:
- history = husa.history
- if history not in histories:
- histories.append( history )
- # Get all histories that are importable
- importables = trans.sa_session.query( trans.app.model.History ) \
- .filter_by( user=trans.user, importable=True, deleted=False ) \
- .order_by( trans.app.model.History.table.c.name )
- for importable in importables:
- if importable not in histories:
- histories.append( importable )
- # Sort the list of histories by history.name
- histories.sort( key=operator.attrgetter( 'name') )
- return trans.fill_template( 'history/sharing.mako', histories=histories, msg=msg, messagetype='done' )
@web.expose
@web.require_login( "share histories with other users" )
@@ -975,7 +923,7 @@
share.history = history
share.user = send_to_user
trans.sa_session.add( share )
- self.set_item_slug( trans.sa_session, history )
+ self.create_item_slug( trans.sa_session, history )
trans.sa_session.flush()
if history not in shared_histories:
shared_histories.append( history )
diff -r 582fd1777763 -r c3eccab29814 lib/galaxy/web/controllers/page.py
--- a/lib/galaxy/web/controllers/page.py Thu Mar 11 15:54:13 2010 -0500
+++ b/lib/galaxy/web/controllers/page.py Fri Mar 12 09:37:22 2010 -0500
@@ -4,10 +4,6 @@
from galaxy.util.odict import odict
from galaxy.util.json import from_json_string
-import re
-
-VALID_SLUG_RE = re.compile( "^[a-z0-9\-]+$" )
-
def format_bool( b ):
if b:
return "yes"
@@ -45,8 +41,8 @@
]
operations = [
grids.DisplayByUsernameAndSlugGridOperation( "View", allow_multiple=False ),
+ grids.GridOperation( "Edit content", allow_multiple=False, url_args=dict( action='edit_content') ),
grids.GridOperation( "Edit attributes", allow_multiple=False, url_args=dict( action='edit') ),
- grids.GridOperation( "Edit content", allow_multiple=False, url_args=dict( action='edit_content') ),
grids.GridOperation( "Share or Publish", allow_multiple=False, condition=( lambda item: not item.deleted ), async_compatible=False ),
grids.GridOperation( "Delete", confirm="Are you sure you want to delete this page?" ),
]
@@ -62,7 +58,7 @@
default_sort_key = "-update_time"
default_filter = dict( title="All", username="All" )
columns = [
- grids.PublicURLColumn( "Title", key="title", model_class=model.Page, filterable="advanced"),
+ grids.PublicURLColumn( "Title", key="title", model_class=model.Page, filterable="advanced" ),
grids.OwnerAnnotationColumn( "Annotation", key="annotation", model_class=model.Page, model_annotation_association_class=model.PageAnnotationAssociation, filterable="advanced" ),
grids.OwnerColumn( "Owner", key="username", model_class=model.User, filterable="advanced", sortable=False ),
grids.CommunityTagsColumn( "Community Tags", "tags", model.Page, model.PageTagAssociation, filterable="advanced", grid_name="PageAllPublishedGrid" ),
@@ -356,10 +352,10 @@
template="page/create.mako" )
@web.expose
- @web.require_login( "create pages" )
+ @web.require_login( "edit pages" )
def edit( self, trans, id, page_title="", page_slug="", page_annotation="" ):
"""
- Create a new page
+ Edit a page's attributes.
"""
encoded_id = id
id = trans.security.decode_id( id )
@@ -456,6 +452,7 @@
@web.expose
@web.require_login( "use Galaxy pages" )
def share( self, trans, id, email="" ):
+ """ Handle sharing with an individual user. """
msg = mtype = None
page = trans.sa_session.query( model.Page ).get( trans.security.decode_id( id ) )
if email:
@@ -468,18 +465,18 @@
msg = ( "User '%s' does not exist" % email )
elif other == trans.get_user():
mtype = "error"
- msg = ( "You cannot share a workflow with yourself" )
+ msg = ( "You cannot share a page with yourself" )
elif trans.sa_session.query( model.PageUserShareAssociation ) \
.filter_by( user=other, page=page ).count() > 0:
mtype = "error"
- msg = ( "Workflow already shared with '%s'" % email )
+ msg = ( "Page already shared with '%s'" % email )
else:
share = model.PageUserShareAssociation()
share.page = page
share.user = other
session = trans.sa_session
session.add( share )
- self.set_item_slug( session, page )
+ self.create_item_slug( session, page )
session.flush()
trans.set_message( "Page '%s' shared with user '%s'" % ( page.title, other.email ) )
return trans.response.send_redirect( url_for( controller='page', action='sharing', id=id ) )
@@ -609,7 +606,7 @@
""" Returns page's name and link. """
page = self.get_page( trans, id )
- if self.set_item_slug( trans.sa_session, page ):
+ if self.create_item_slug( trans.sa_session, page ):
trans.sa_session.flush()
return_dict = { "name" : page.title, "link" : url_for( action="display_by_username_and_slug", username=page.user.username, slug=page.slug ) }
return return_dict
diff -r 582fd1777763 -r c3eccab29814 lib/galaxy/web/controllers/tracks.py
--- a/lib/galaxy/web/controllers/tracks.py Thu Mar 11 15:54:13 2010 -0500
+++ b/lib/galaxy/web/controllers/tracks.py Fri Mar 12 09:37:22 2010 -0500
@@ -262,7 +262,9 @@
@web.json
def save( self, trans, **kwargs ):
session = trans.sa_session
- vis_id = kwargs['vis_id'].strip('"')
+ vis_id = "undefined"
+ if 'vis_id' in kwargs:
+ vis_id = kwargs['vis_id'].strip('"')
dbkey = kwargs['dbkey']
if vis_id == "undefined": # new vis
diff -r 582fd1777763 -r c3eccab29814 lib/galaxy/web/controllers/visualization.py
--- a/lib/galaxy/web/controllers/visualization.py Thu Mar 11 15:54:13 2010 -0500
+++ b/lib/galaxy/web/controllers/visualization.py Fri Mar 12 09:37:22 2010 -0500
@@ -1,35 +1,325 @@
from galaxy.web.base.controller import *
-from galaxy.web.framework.helpers import time_ago, grids
+from galaxy.web.framework.helpers import time_ago, grids, iff
from galaxy.util.sanitize_html import sanitize_html
class VisualizationListGrid( grids.Grid ):
# Grid definition
- title = "Visualizations"
+ title = "Saved Visualizations"
model_class = model.Visualization
default_sort_key = "-update_time"
+ default_filter = dict( title="All", deleted="False", tags="All", sharing="All" )
columns = [
- grids.GridColumn( "Title", key="title", attach_popup=True,
+ grids.TextColumn( "Title", key="title", model_class=model.Visualization, attach_popup=True,
link=( lambda item: dict( controller="tracks", action="browser", id=item.id ) ) ),
- grids.GridColumn( "Type", key="type" ),
+ grids.TextColumn( "Type", key="type", model_class=model.Visualization ),
+ grids.IndividualTagsColumn( "Tags", "tags", model.Visualization, model.VisualizationTagAssociation, filterable="advanced", grid_name="VisualizationListGrid" ),
+ grids.SharingStatusColumn( "Sharing", key="sharing", model_class=model.Visualization, filterable="advanced", sortable=False ),
grids.GridColumn( "Created", key="create_time", format=time_ago ),
grids.GridColumn( "Last Updated", key="update_time", format=time_ago ),
- ]
- ## global_actions = [
- ## grids.GridAction( "Add new page", dict( action='create' ) )
- ## ]
+ ]
+ columns.append(
+ grids.MulticolFilterColumn(
+ "Search",
+ cols_to_filter=[ columns[0], columns[2] ],
+ key="free-text-search", visible=False, filterable="standard" )
+ )
operations = [
- grids.GridOperation( "View", allow_multiple=False, url_args=dict( controller="tracks", action='browser' ) ),
+ grids.GridOperation( "Edit content", allow_multiple=False, url_args=dict( controller='tracks', action='browser' ) ),
+ grids.GridOperation( "Edit attributes", allow_multiple=False, url_args=dict( action='edit') ),
+ grids.GridOperation( "Share or Publish", allow_multiple=False, condition=( lambda item: not item.deleted ), async_compatible=False ),
+ grids.GridOperation( "Delete", condition=( lambda item: not item.deleted ), async_compatible=True, confirm="Are you sure you want to delete this visualization?" ),
]
def apply_default_filter( self, trans, query, **kwargs ):
- return query.filter_by( user=trans.user )
+ return query.filter_by( user=trans.user, deleted=False )
+
+class VisualizationAllPublishedGrid( grids.Grid ):
+ # Grid definition
+ use_panels = True
+ use_async = True
+ title = "Published Visualizations"
+ model_class = model.Visualization
+ default_sort_key = "-update_time"
+ default_filter = dict( title="All", username="All" )
+ columns = [
+ grids.PublicURLColumn( "Title", key="title", model_class=model.Visualization, filterable="advanced" ),
+ grids.OwnerAnnotationColumn( "Annotation", key="annotation", model_class=model.Visualization, model_annotation_association_class=model.VisualizationAnnotationAssociation, filterable="advanced" ),
+ grids.OwnerColumn( "Owner", key="username", model_class=model.User, filterable="advanced", sortable=False ),
+ grids.CommunityTagsColumn( "Community Tags", "tags", model.Visualization, model.VisualizationTagAssociation, filterable="advanced", grid_name="VisualizationAllPublishedGrid" ),
+ grids.GridColumn( "Last Updated", key="update_time", format=time_ago )
+ ]
+ columns.append(
+ grids.MulticolFilterColumn(
+ "Search",
+ cols_to_filter=[ columns[0], columns[1], columns[2], columns[3] ],
+ key="free-text-search", visible=False, filterable="standard" )
+ )
+ def build_initial_query( self, session ):
+ # Join so that searching history.user makes sense.
+ return session.query( self.model_class ).join( model.User.table )
+ def apply_default_filter( self, trans, query, **kwargs ):
+ return query.filter( self.model_class.deleted==False ).filter( self.model_class.published==True )
-class VisualizationController( BaseController ):
- list_grid = VisualizationListGrid()
+
+class VisualizationController( BaseController, Sharable, UsesAnnotations, UsesVisualization ):
+ _user_list_grid = VisualizationListGrid()
+ _published_list_grid = VisualizationAllPublishedGrid()
+
@web.expose
- @web.require_login()
- def index( self, trans, *args, **kwargs ):
- return trans.fill_template( "panels.mako", grid=self.list_grid( trans, *args, **kwargs ), active_view='visualization', main_url=url_for( action='list' ) )
+ def list_published( self, trans, *args, **kwargs ):
+ grid = self._published_list_grid( trans, **kwargs )
+ if 'async' in kwargs:
+ return grid
+ else:
+ # Render grid wrapped in panels
+ return trans.fill_template( "visualization/list_published.mako", grid=grid )
+
+ @web.expose
+ @web.require_login("use Galaxy visualizations")
+ def list( self, trans, *args, **kwargs ):
+ # Handle operation
+ if 'operation' in kwargs and 'id' in kwargs:
+ session = trans.sa_session
+ operation = kwargs['operation'].lower()
+ ids = util.listify( kwargs['id'] )
+ for id in ids:
+ item = session.query( model.Visualization ).get( trans.security.decode_id( id ) )
+ if operation == "delete":
+ item.deleted = True
+ if operation == "share or publish":
+ return self.sharing( trans, **kwargs )
+ session.flush()
+
+ # Build list of visualizations shared with user.
+ shared_by_others = trans.sa_session \
+ .query( model.VisualizationUserShareAssociation ) \
+ .filter_by( user=trans.get_user() ) \
+ .join( model.Visualization.table ) \
+ .filter( model.Visualization.deleted == False ) \
+ .order_by( desc( model.Visualization.update_time ) ) \
+ .all()
+
+ return trans.fill_template( "visualization/list.mako", grid=self._user_list_grid( trans, *args, **kwargs ), shared_by_others=shared_by_others )
+
+ @web.expose
+ @web.require_login( "modify Galaxy visualizations" )
+ def set_slug_async( self, trans, id, new_slug ):
+ """ Set item slug asynchronously. """
+ visualization = self.get_visualization( trans, id )
+ if visualization:
+ visualization.slug = new_slug
+ trans.sa_session.flush()
+ return visualization.slug
+
+ @web.expose
+ @web.require_login( "share Galaxy visualizations" )
+ def sharing( self, trans, id, **kwargs ):
+ """ Handle visualization sharing. """
+
+ # Get session and visualization.
+ session = trans.sa_session
+ visualization = trans.sa_session.query( model.Visualization ).get( trans.security.decode_id( id ) )
+
+ # Do operation on visualization.
+ if 'make_accessible_via_link' in kwargs:
+ self._make_item_accessible( trans.sa_session, visualization )
+ elif 'make_accessible_and_publish' in kwargs:
+ self._make_item_accessible( trans.sa_session, visualization )
+ visualization.published = True
+ elif 'publish' in kwargs:
+ visualization.published = True
+ elif 'disable_link_access' in kwargs:
+ visualization.importable = False
+ elif 'unpublish' in kwargs:
+ visualization.published = False
+ elif 'disable_link_access_and_unpublish' in kwargs:
+ visualization.importable = visualization.published = False
+ elif 'unshare_user' in kwargs:
+ user = session.query( model.User ).get( trans.security.decode_id( kwargs['unshare_user' ] ) )
+ if not user:
+ error( "User not found for provided id" )
+ association = session.query( model.VisualizationUserShareAssociation ) \
+ .filter_by( user=user, visualization=visualization ).one()
+ session.delete( association )
+
+ session.flush()
+
+ return trans.fill_template( "/sharing_base.mako", item=visualization )
+
+ @web.expose
+ @web.require_login( "share Galaxy visualizations" )
+ def share( self, trans, id=None, email="", **kwd ):
+ """ Handle sharing a visualization with a particular user. """
+ msg = mtype = None
+ visualization = trans.sa_session.query( model.Visualization ).get( trans.security.decode_id( id ) )
+ if email:
+ other = trans.sa_session.query( model.User ) \
+ .filter( and_( model.User.table.c.email==email,
+ model.User.table.c.deleted==False ) ) \
+ .first()
+ if not other:
+ mtype = "error"
+ msg = ( "User '%s' does not exist" % email )
+ elif other == trans.get_user():
+ mtype = "error"
+ msg = ( "You cannot share a visualization with yourself" )
+ elif trans.sa_session.query( model.VisualizationUserShareAssociation ) \
+ .filter_by( user=other, visualization=visualization ).count() > 0:
+ mtype = "error"
+ msg = ( "Visualization already shared with '%s'" % email )
+ else:
+ share = model.VisualizationUserShareAssociation()
+ share.visualization = visualization
+ share.user = other
+ session = trans.sa_session
+ session.add( share )
+ self.create_item_slug( session, visualization )
+ session.flush()
+ trans.set_message( "Visualization '%s' shared with user '%s'" % ( visualization.title, other.email ) )
+ return trans.response.send_redirect( url_for( action='sharing', id=id ) )
+ return trans.fill_template( "/share_base.mako",
+ message = msg,
+ messagetype = mtype,
+ item=visualization,
+ email=email )
+
+
+ @web.expose
+ def display_by_username_and_slug( self, trans, username, slug ):
+ """ Display visualization based on a username and slug. """
+
+ # Get visualization.
+ session = trans.sa_session
+ user = session.query( model.User ).filter_by( username=username ).first()
+ visualization = trans.sa_session.query( model.Visualization ).filter_by( user=user, slug=slug, deleted=False ).first()
+ if visualization is None:
+ raise web.httpexceptions.HTTPNotFound()
+ # Security check raises error if user cannot access visualization.
+ self.security_check( trans.get_user(), visualization, False, True)
+ return trans.fill_template_mako( "visualization/display.mako", item=visualization, item_data=None, content_only=True )
+
+ @web.expose
+ @web.json
+ @web.require_login( "get item name and link" )
+ def get_name_and_link_async( self, trans, id=None ):
+ """ Returns visualization's name and link. """
+ visualization = self.get_visualization( trans, id )
+
+ if self.create_item_slug( trans.sa_session, visualization ):
+ trans.sa_session.flush()
+ return_dict = { "name" : visualization.title, "link" : url_for( action="display_by_username_and_slug", username=visualization.user.username, slug=visualization.slug ) }
+ return return_dict
+
+ @web.expose
+ @web.require_login("get item content asynchronously")
+ def get_item_content_async( self, trans, id ):
+ """ Returns item content in HTML format. """
+ pass
+
+ @web.expose
+ @web.require_login( "create visualizations" )
+ def create( self, trans, visualization_title="", visualization_slug="", visualization_annotation="" ):
+ """
+ Create a new visualization
+ """
+ user = trans.get_user()
+ visualization_title_err = visualization_slug_err = visualization_annotation_err = ""
+ if trans.request.method == "POST":
+ if not visualization_title:
+ visualization_title_err = "visualization name is required"
+ elif not visualization_slug:
+ visualization_slug_err = "visualization id is required"
+ elif not VALID_SLUG_RE.match( visualization_slug ):
+ visualization_slug_err = "visualization identifier must consist of only lowercase letters, numbers, and the '-' character"
+ elif trans.sa_session.query( model.Visualization ).filter_by( user=user, slug=visualization_slug, deleted=False ).first():
+ visualization_slug_err = "visualization id must be unique"
+ else:
+ # Create the new stored visualization
+ visualization = model.Visualization()
+ visualization.title = visualization_title
+ visualization.slug = visualization_slug
+ visualization_annotation = sanitize_html( visualization_annotation, 'utf-8', 'text/html' )
+ self.add_item_annotation( trans, visualization, visualization_annotation )
+ visualization.user = user
+ # And the first (empty) visualization revision
+ visualization_revision = model.VisualizationRevision()
+ visualization_revision.title = visualization_title
+ visualization_revision.visualization = visualization
+ visualization.latest_revision = visualization_revision
+ visualization_revision.content = ""
+ # Persist
+ session = trans.sa_session
+ session.add( visualization )
+ session.flush()
+ # Display the management visualization
+ ## trans.set_message( "Visualization '%s' created" % visualization.title )
+ return trans.response.send_redirect( web.url_for( action='list' ) )
+ return trans.show_form(
+ web.FormBuilder( web.url_for(), "Create new visualization", submit_text="Submit" )
+ .add_text( "visualization_title", "Visualization title", value=visualization_title, error=visualization_title_err )
+ .add_text( "visualization_slug", "Visualization identifier", value=visualization_slug, error=visualization_slug_err,
+ help="""A unique identifier that will be used for
+ public links to this visualization. A default is generated
+ from the visualization title, but can be edited. This field
+ must contain only lowercase letters, numbers, and
+ the '-' character.""" )
+ .add_text( "visualization_annotation", "Visualization annotation", value=visualization_annotation, error=visualization_annotation_err,
+ help="A description of the visualization; annotation is shown alongside published visualizations."),
+ template="visualization/create.mako" )
+
+ @web.expose
+ @web.require_login( "edit visualizations" )
+ def edit( self, trans, id, visualization_title="", visualization_slug="", visualization_annotation="" ):
+ """
+ Edit a visualization's attributes.
+ """
+ encoded_id = id
+ id = trans.security.decode_id( id )
+ session = trans.sa_session
+ visualization = session.query( model.Visualization ).get( id )
+ user = trans.user
+ assert visualization.user == user
+ visualization_title_err = visualization_slug_err = visualization_annotation_err = ""
+ if trans.request.method == "POST":
+ if not visualization_title:
+ visualization_title_err = "Visualization name is required"
+ elif not visualization_slug:
+ visualization_slug_err = "Visualization id is required"
+ elif not VALID_SLUG_RE.match( visualization_slug ):
+ visualization_slug_err = "Visualization identifier must consist of only lowercase letters, numbers, and the '-' character"
+ elif visualization_slug != visualization.slug and trans.sa_session.query( model.Visualization ).filter_by( user=user, slug=visualization_slug, deleted=False ).first():
+ visualization_slug_err = "Visualization id must be unique"
+ elif not visualization_annotation:
+ visualization_annotation_err = "Visualization annotation is required"
+ else:
+ visualization.title = visualization_title
+ visualization.slug = visualization_slug
+ visualization_annotation = sanitize_html( visualization_annotation, 'utf-8', 'text/html' )
+ self.add_item_annotation( trans, visualization, visualization_annotation )
+ session.flush()
+ # Redirect to visualization list.
+ return trans.response.send_redirect( web.url_for( action='list' ) )
+ else:
+ visualization_title = visualization.title
+ # Create slug if it's not already set.
+ if visualization.slug is None:
+ self.create_item_slug( trans.sa_session, visualization )
+ visualization_slug = visualization.slug
+ visualization_annotation = self.get_item_annotation_str( trans.sa_session, trans.get_user(), visualization )
+ if not visualization_annotation:
+ visualization_annotation = ""
+ return trans.show_form(
+ web.FormBuilder( web.url_for( id=encoded_id ), "Edit visualization attributes", submit_text="Submit" )
+ .add_text( "visualization_title", "Visualization title", value=visualization_title, error=visualization_title_err )
+ .add_text( "visualization_slug", "Visualization identifier", value=visualization_slug, error=visualization_slug_err,
+ help="""A unique identifier that will be used for
+ public links to this visualization. A default is generated
+ from the visualization title, but can be edited. This field
+ must contain only lowercase letters, numbers, and
+ the '-' character.""" )
+ .add_text( "visualization_annotation", "Visualization annotation", value=visualization_annotation, error=visualization_annotation_err,
+ help="A description of the visualization; annotation is shown alongside published visualizations."),
+ template="visualization/create.mako" )
# @web.expose
# @web.require_login()
@@ -42,6 +332,6 @@
# # Build grid
# grid = self.list( trans, *args, **kwargs )
# # Render grid wrapped in panels
- # return trans.fill_template( "page/index.mako", grid=grid )
+ # return trans.fill_template( "visualization/index.mako", grid=grid )
\ No newline at end of file
diff -r 582fd1777763 -r c3eccab29814 lib/galaxy/web/controllers/workflow.py
--- a/lib/galaxy/web/controllers/workflow.py Thu Mar 11 15:54:13 2010 -0500
+++ b/lib/galaxy/web/controllers/workflow.py Fri Mar 12 09:37:22 2010 -0500
@@ -123,7 +123,7 @@
# Legacy issue: all shared workflows must have slugs.
slug_set = False
for workflow_assoc in shared_by_others:
- slug_set = self.set_item_slug( trans.sa_session, workflow_assoc.stored_workflow )
+ slug_set = self.create_item_slug( trans.sa_session, workflow_assoc.stored_workflow )
if slug_set:
trans.sa_session.flush()
@@ -224,7 +224,7 @@
share.user = other
session = trans.sa_session
session.add( share )
- self.set_item_slug( session, stored )
+ self.create_item_slug( session, stored )
session.flush()
trans.set_message( "Workflow '%s' shared with user '%s'" % ( stored.name, other.email ) )
return trans.response.send_redirect( url_for( controller='workflow', action='sharing', id=id ) )
@@ -401,7 +401,7 @@
""" Returns workflow's name and link. """
stored = self.get_stored_workflow( trans, id )
- if self.set_item_slug( trans.sa_session, stored ):
+ if self.create_item_slug( trans.sa_session, stored ):
trans.sa_session.flush()
return_dict = { "name" : stored.name, "link" : url_for( action="display_by_username_and_slug", username=stored.user.username, slug=stored.slug ) }
return return_dict
diff -r 582fd1777763 -r c3eccab29814 templates/base_panels.mako
--- a/templates/base_panels.mako Thu Mar 11 15:54:13 2010 -0500
+++ b/templates/base_panels.mako Fri Mar 12 09:37:22 2010 -0500
@@ -207,7 +207,7 @@
<ul>
<li><a href="${h.url_for( controller='/tracks', action='index' )}">Build track browser</a></li>
<li><hr style="color: inherit; background-color: gray"/></li>
- <li><a href="${h.url_for( controller='/visualization', action='index' )}">Stored visualizations</a></li>
+ <li><a href="${h.url_for( controller='/visualization', action='list' )}">Stored visualizations</a></li>
</ul>
</div>
</td>
diff -r 582fd1777763 -r c3eccab29814 templates/display_common.mako
--- a/templates/display_common.mako Thu Mar 11 15:54:13 2010 -0500
+++ b/templates/display_common.mako Fri Mar 12 09:37:22 2010 -0500
@@ -18,8 +18,11 @@
<%def name="get_item_name( item )">
<%
+ # Start with exceptions, end with default.
if type( item ) is model.Page:
return item.title
+ elif type( item ) is model.Visualization:
+ return item.title
if hasattr( item, 'get_display_name'):
return item.get_display_name()
return item.name
@@ -29,7 +32,7 @@
## Get plural display name for a class.
<%def name="get_class_plural_display_name( a_class )">
<%
- ## Start with exceptions, end with default.
+ # Start with exceptions, end with default.
if a_class is model.History:
return "Histories"
elif a_class is model.FormDefinitionCurrent:
@@ -89,6 +92,8 @@
return "dataset"
elif isinstance( item, model.Page ):
return "page"
+ elif isinstance( item, model.Visualization ):
+ return "visualization"
%>
</%def>
diff -r 582fd1777763 -r c3eccab29814 templates/page/create.mako
--- a/templates/page/create.mako Thu Mar 11 15:54:13 2010 -0500
+++ b/templates/page/create.mako Fri Mar 12 09:37:22 2010 -0500
@@ -8,8 +8,7 @@
var page_slug = $("input[name=page_slug]");
page_name.keyup(function(){
page_slug.val( $(this).val().replace(/\s+/g,'-').replace(/[^a-zA-Z0-9\-]/g,'').toLowerCase() )
- });
-
+ });
})
</script>
</%def>
\ No newline at end of file
diff -r 582fd1777763 -r c3eccab29814 templates/panels.mako
--- a/templates/panels.mako Thu Mar 11 15:54:13 2010 -0500
+++ b/templates/panels.mako Fri Mar 12 09:37:22 2010 -0500
@@ -10,11 +10,9 @@
</%def>
<%def name="center_panel()">
-
<div style="overflow: auto; height: 100%;">
<div style="padding: 10px">
${grid}
</div>
</div>
-
</%def>
diff -r 582fd1777763 -r c3eccab29814 templates/visualization/create.mako
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/visualization/create.mako Fri Mar 12 09:37:22 2010 -0500
@@ -0,0 +1,14 @@
+<%inherit file="/form.mako"/>
+
+<%def name="javascripts()">
+${parent.javascripts()}
+<script type="text/javascript">
+$(function(){
+ var visualization_name = $("input[name=visualization_title]");
+ var visualization_slug = $("input[name=visualization_slug]");
+ visualization_name.keyup(function(){
+ visualization_slug.val( $(this).val().replace(/\s+/g,'-').replace(/[^a-zA-Z0-9\-]/g,'').toLowerCase() )
+ });
+})
+</script>
+</%def>
\ No newline at end of file
diff -r 582fd1777763 -r c3eccab29814 templates/visualization/display.mako
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/visualization/display.mako Fri Mar 12 09:37:22 2010 -0500
@@ -0,0 +1,19 @@
+<%inherit file="/display_base.mako"/>
+
+<%def name="javascripts()">
+ ${parent.javascripts()}
+ ## Need visualization JS.
+</%def>
+
+<%def name="stylesheets()">
+ ${parent.stylesheets()}
+ ## Need visualization CSS.
+</%def>
+
+<%def name="render_item_links( visualization )">
+ ## TODO
+</%def>
+
+<%def name="render_item( visualization, visualization_data )">
+ ## TODO
+</%def>
\ No newline at end of file
diff -r 582fd1777763 -r c3eccab29814 templates/visualization/list.mako
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/visualization/list.mako Fri Mar 12 09:37:22 2010 -0500
@@ -0,0 +1,52 @@
+<%inherit file="/base_panels.mako"/>
+
+<%def name="init()">
+<%
+ self.has_left_panel=False
+ self.has_right_panel=False
+ self.active_view="visualization"
+ self.message_box_visible=False
+%>
+</%def>
+
+<%def name="center_panel()">
+
+ <div style="overflow: auto; height: 100%;">
+ <div class="page-container" style="padding: 10px;">
+ ${grid}
+
+ <br><br>
+ <h2>Visualizations shared with you by others</h2>
+
+ %if shared_by_others:
+ <table class="colored" border="0" cellspacing="0" cellpadding="0" width="100%">
+ <tr class="header">
+ <th>Title</th>
+ <th>Owner</th>
+ <th></th>
+ </tr>
+ %for i, association in enumerate( shared_by_others ):
+ <% visualization = association.visualization %>
+ <tr>
+ <td>
+ <a class="menubutton" id="shared-${i}-popup" href="${h.url_for( action='display_by_username_and_slug', username=visualization.user.username, slug=visualization.slug)}">${visualization.title}</a>
+ </td>
+ <td>${visualization.user.username}</td>
+ <td>
+ <div popupmenu="shared-${i}-popup">
+ <a class="action-button" href="${h.url_for( action='display_by_username_and_slug', username=visualization.user.username, slug=visualization.slug)}" target="_top">View</a>
+ </div>
+ </td>
+ </tr>
+ %endfor
+ </table>
+ %else:
+
+ No visualizations have been shared with you.
+
+ %endif
+
+ </div>
+ </div>
+
+</%def>
diff -r 582fd1777763 -r c3eccab29814 templates/visualization/list_published.mako
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/visualization/list_published.mako Fri Mar 12 09:37:22 2010 -0500
@@ -0,0 +1,36 @@
+<%inherit file="/base_panels.mako"/>
+
+<%def name="init()">
+<%
+ self.has_left_panel=False
+ self.has_right_panel=False
+ self.active_view="page"
+ self.message_box_visible=False
+%>
+</%def>
+
+<%def name="title()">
+ Galaxy :: Published Visualizations
+</%def>
+
+<%def name="stylesheets()">
+ ${parent.stylesheets()}
+ <style>
+ .grid td {
+ min-width: 100px;
+ }
+ </style>
+</%def>
+
+<%def name="center_panel()">
+
+ ## <iframe name="galaxy_main" id="galaxy_main" frameborder="0" style="position: absolute; width: 100%; height: 100%;" src="${h.url_for( controller="page", action="list" )}"> </iframe>
+
+ <div style="overflow: auto; height: 100%;">
+ <div class="page-container" style="padding: 10px;">
+ ${unicode( grid, 'utf-8' )}
+ </div>
+ </div>
+
+
+</%def>
1
0

18 Mar '10
details: http://www.bx.psu.edu/hg/galaxy/rev/582fd1777763
changeset: 3522:582fd1777763
user: Kelly Vincent <kpvincent(a)bx.psu.edu>
date: Thu Mar 11 15:54:13 2010 -0500
description:
Modified BWA output files so last two tests will pass
diffstat:
test-data/bwa_wrapper_out2.sam | 2 +-
test-data/bwa_wrapper_out3.sam | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diffs (14 lines):
diff -r f13d85256124 -r 582fd1777763 test-data/bwa_wrapper_out2.sam
--- a/test-data/bwa_wrapper_out2.sam Thu Mar 11 14:35:36 2010 -0500
+++ b/test-data/bwa_wrapper_out2.sam Thu Mar 11 15:54:13 2010 -0500
@@ -1,1 +1,1 @@
-081017-and-081020:1:1:1715:1759 16 phiX 322 25 36M * 0 0 GATATTTTAAAGGAGCGTGGATTACTATCTGAGTCC B&&I13A$G$*%$IIIIIII9(.+5$IIIIIII#II XT:A:U NM:i:2 X0:i:1 XM:i:2 XO:i:0 XG:i:0 MD:Z:2C8A24
+081017-and-081020:1:1:1715:1759 16 phiX 322 25 36M * 0 0 GATATTTTAAAGGAGCGTGGATTACTATCTGAGTCC B&&I13A$G$*%$IIIIIII9(.+5$IIIIIII#II XT:A:U NM:i:2 X0:i:1 X1:i:0 XM:i:2 XO:i:0 XG:i:0 MD:Z:2C8A24
diff -r f13d85256124 -r 582fd1777763 test-data/bwa_wrapper_out3.sam
--- a/test-data/bwa_wrapper_out3.sam Thu Mar 11 14:35:36 2010 -0500
+++ b/test-data/bwa_wrapper_out3.sam Thu Mar 11 15:54:13 2010 -0500
@@ -1,2 +1,2 @@
-081017-and-081020:1:1:1715:1759 113 PHIX174 322 25 18M = 340 18 GATATTTTAAAGGAGCGT B&&I13A$G$*%$IIIII XT:A:U NM:i:2 SM:i:25 AM:i:25 X0:i:1 XM:i:2 XO:i:0 XG:i:0 MD:Z:2C8A6
-081017-and-081020:1:1:1715:1759 177 PHIX174 340 37 18M = 322 -18 GGATTACTATCTGAGTCC II9(.+5$IIIIIII#II XT:A:U NM:i:0 SM:i:37 AM:i:25 X0:i:1 XM:i:0 XO:i:0 XG:i:0 MD:Z:18
+081017-and-081020:1:1:1715:1759 113 PHIX174 322 25 18M = 340 18 GATATTTTAAAGGAGCGT B&&I13A$G$*%$IIIII XT:A:U NM:i:2 SM:i:25 AM:i:25 X0:i:1 X1:i:0 XM:i:2 XO:i:0 XG:i:0 MD:Z:2C8A6
+081017-and-081020:1:1:1715:1759 177 PHIX174 340 37 18M = 322 -18 GGATTACTATCTGAGTCC II9(.+5$IIIIIII#II XT:A:U NM:i:0 SM:i:37 AM:i:25 X0:i:1 X1:i:0 XM:i:0 XO:i:0 XG:i:0 MD:Z:18
1
0

18 Mar '10
details: http://www.bx.psu.edu/hg/galaxy/rev/f13d85256124
changeset: 3521:f13d85256124
user: Dan Blankenberg <dan(a)bx.psu.edu>
date: Thu Mar 11 14:35:36 2010 -0500
description:
Display Application framework enhancements.
Add the ability for display applications to be populated dynamically based upon the content of (e.g. tabular) files.
Display application links can be filtered by various attributes, including e.g. dataset dbkey matching from field in a file or an attribute matching a Galaxy application configuration setting.
Param and Data URL values can now be generated dynamically, allowing e.g unique base filenames to be created and used.
See updated xml configurations in /display_applications/ for examples of syntax.
diffstat:
datatypes_conf.xml.sample | 9 +-
display_applications/ucsc/bam.xml | 34 +++++-
display_applications/ucsc/interval_as_bed.xml | 63 +++++++++++-
lib/galaxy/datatypes/data.py | 9 +
lib/galaxy/datatypes/display_applications/application.py | 78 ++++++++++++++-
lib/galaxy/datatypes/display_applications/parameters.py | 13 +-
lib/galaxy/datatypes/registry.py | 34 ++++--
lib/galaxy/model/__init__.py | 3 +
templates/root/history_common.mako | 2 +-
tool-data/shared/bx/bx_build_sites.txt | 2 +-
10 files changed, 205 insertions(+), 42 deletions(-)
diffs (468 lines):
diff -r 262b16c8e277 -r f13d85256124 datatypes_conf.xml.sample
--- a/datatypes_conf.xml.sample Thu Mar 11 13:51:53 2010 -0500
+++ b/datatypes_conf.xml.sample Thu Mar 11 14:35:36 2010 -0500
@@ -15,10 +15,7 @@
<!-- <display file="ucsc/interval_as_bed.xml" /> -->
<display file="genetrack.xml" />
</datatype>
- <datatype extension="bedstrict" type="galaxy.datatypes.interval:BedStrict">
- <display file="ucsc/interval_as_bed.xml" />
- <display file="genetrack.xml" />
- </datatype>
+ <datatype extension="bedstrict" type="galaxy.datatypes.interval:BedStrict" />
<datatype extension="binseq.zip" type="galaxy.datatypes.binary:Binseq" mimetype="application/zip" display_in_upload="true"/>
<datatype extension="len" type="galaxy.datatypes.chrominfo:ChromInfo" display_in_upload="true">
<!-- no converters yet -->
@@ -51,8 +48,8 @@
<converter file="interval_to_bed_converter.xml" target_datatype="bed"/>
<converter file="interval_to_bedstrict_converter.xml" target_datatype="bedstrict"/>
<indexer file="interval_awk.xml" />
- <!-- <display file="ucsc/interval_as_bed.xml" /> -->
- <display file="genetrack.xml" />
+ <!-- <display file="ucsc/interval_as_bed.xml" inherit="True" /> -->
+ <display file="genetrack.xml" inherit="True"/>
</datatype>
<datatype extension="jpg" type="galaxy.datatypes.images:Image" mimetype="image/jpeg"/>
<datatype extension="laj" type="galaxy.datatypes.images:Laj"/>
diff -r 262b16c8e277 -r f13d85256124 display_applications/ucsc/bam.xml
--- a/display_applications/ucsc/bam.xml Thu Mar 11 13:51:53 2010 -0500
+++ b/display_applications/ucsc/bam.xml Thu Mar 11 14:35:36 2010 -0500
@@ -1,8 +1,32 @@
<display id="ucsc_bam" version="1.0.0" name="display at UCSC">
- <link id="main" name="main">
- <url>http://genome.ucsc.edu/cgi-bin/hgTracks?db=${qp($bam_file.dbkey)}&hgt.c…</url>
- <param type="data" name="bam_file" url="galaxy.bam" strip_https="True" />
- <param type="data" name="bai_file" url="galaxy.bam.bai" metadata="bam_index" strip_https="True" /><!-- UCSC expects index file to exist as bam_file_name.bai -->
+ <!-- Load links from file: one line to one link -->
+ <dynamic_links from_file="tool-data/shared/ucsc/ucsc_build_sites.txt" skip_startswith="#" id="0" name="0">
+ <!-- Define parameters by column from file, allow splitting on builds -->
+ <dynamic_param name="site_id" value="0"/>
+ <dynamic_param name="ucsc_link" value="1"/>
+ <dynamic_param name="builds" value="2" split="True" separator="," />
+ <!-- Filter out some of the links based upon matching site_id to a Galaxy application configuration parameter and by dataset dbkey -->
+ <filter>${site_id in $APP.config.ucsc_display_sites}</filter>
+ <filter>${dataset.dbkey in $builds}</filter>
+ <!-- We define url and params as normal, but values defined in dynamic_param are available by specified name -->
+ <url>${ucsc_link}db=${qp($bam_file.dbkey)}&hgt.customText=${qp($track.url)}</url>
+ <param type="data" name="bam_file" url="galaxy_${DATASET_HASH}.bam" strip_https="True" />
+ <param type="data" name="bai_file" url="galaxy_${DATASET_HASH}.bam.bai" metadata="bam_index" strip_https="True" /><!-- UCSC expects index file to exist as bam_file_name.bai -->
<param type="template" name="track" viewable="True" strip_https="True">track type=bam name="${bam_file.name}" bigDataUrl=${bam_file.url} db=${bam_file.dbkey}</param>
- </link>
+ </dynamic_links>
+ <!-- Load links from file: one line to one link -->
+ <dynamic_links from_file="tool-data/shared/bx/bx_build_sites.txt" skip_startswith="#" id="3" name="3">
+ <!-- Define parameters by column from file, allow splitting on builds -->
+ <dynamic_param name="site_id" value="0"/>
+ <dynamic_param name="ucsc_link" value="1"/>
+ <dynamic_param name="builds" value="2" split="True" separator="," />
+ <!-- Filter out some of the links based upon matching site_id to a Galaxy application configuration parameter and by dataset dbkey -->
+ <filter>${site_id in $APP.config.bx_display_sites}</filter>
+ <filter>${dataset.dbkey in $builds}</filter>
+ <!-- We define url and params as normal, but values defined in dynamic_param are available by specified name -->
+ <url>${ucsc_link}db=${qp($bam_file.dbkey)}&hgt.customText=${qp($track.url)}</url>
+ <param type="data" name="bam_file" url="galaxy_${DATASET_HASH}.bam" strip_https="True" />
+ <param type="data" name="bai_file" url="galaxy_${DATASET_HASH}.bam.bai" metadata="bam_index" strip_https="True" /><!-- UCSC expects index file to exist as bam_file_name.bai -->
+ <param type="template" name="track" viewable="True" strip_https="True">track type=bam name="${bam_file.name}" bigDataUrl=${bam_file.url} db=${bam_file.dbkey}</param>
+ </dynamic_links>
</display>
diff -r 262b16c8e277 -r f13d85256124 display_applications/ucsc/interval_as_bed.xml
--- a/display_applications/ucsc/interval_as_bed.xml Thu Mar 11 13:51:53 2010 -0500
+++ b/display_applications/ucsc/interval_as_bed.xml Thu Mar 11 14:35:36 2010 -0500
@@ -1,7 +1,16 @@
-<display id="ucsc_interval_as_bed" version="1.0.0" name="display at UCSC">
- <link id="main" name="main">
- <url>http://genome.ucsc.edu/cgi-bin/hgTracks?db=${qp($bed_file.dbkey)}&posit…</url>
- <param type="data" name="bed_file" url="galaxy.bed" format="bedstrict"/> <!-- Galaxy allows BED files to contain non-standard fields beyond the first 3 columns, UCSC does not: force use of converter which will make strict BED6+ file -->
+<display id="ucsc_interval_as_bed" version="1.0.0" name="display at UCSC" inherit="True">
+ <!-- Load links from file: one line to one link -->
+ <dynamic_links from_file="tool-data/shared/ucsc/ucsc_build_sites.txt" skip_startswith="#" id="0" name="0">
+ <!-- Define parameters by column from file, allow splitting on builds -->
+ <dynamic_param name="site_id" value="0"/>
+ <dynamic_param name="ucsc_link" value="1"/>
+ <dynamic_param name="builds" value="2" split="True" separator="," />
+ <!-- Filter out some of the links based upon matching site_id to a Galaxy application configuration parameter and by dataset dbkey -->
+ <filter>${site_id in $APP.config.ucsc_display_sites}</filter>
+ <filter>${dataset.dbkey in $builds}</filter>
+ <!-- We define url and params as normal, but values defined in dynamic_param are available by specified name -->
+ <url>${ucsc_link}db=${qp($bed_file.dbkey)}&position=${position.qp}&hgt.customText=${bed_file.qp}</url>
+ <param type="data" name="bed_file" url="galaxy_${DATASET_HASH}.bed" format="bedstrict"/> <!-- Galaxy allows BED files to contain non-standard fields beyond the first 3 columns, UCSC does not: force use of converter which will make strict BED6+ file -->
<param type="template" name="position" strip="True" >
#set line_count = 0
#set chrom = None
@@ -33,5 +42,49 @@
:-
#end if
</param>
- </link>
+ </dynamic_links>
+ <!-- Load links from file: one line to one link -->
+ <dynamic_links from_file="tool-data/shared/bx/bx_build_sites.txt" skip_startswith="#" id="3" name="3">
+ <!-- Define parameters by column from file, allow splitting on builds -->
+ <dynamic_param name="site_id" value="0"/>
+ <dynamic_param name="ucsc_link" value="1"/>
+ <dynamic_param name="builds" value="2" split="True" separator="," />
+ <!-- Filter out some of the links based upon matching site_id to a Galaxy application configuration parameter and by dataset dbkey -->
+ <filter>${site_id in $APP.config.bx_display_sites}</filter>
+ <filter>${dataset.dbkey in $builds}</filter>
+ <!-- We define url and params as normal, but values defined in dynamic_param are available by specified name -->
+ <url>${ucsc_link}db=${qp($bed_file.dbkey)}&position=${position.qp}&hgt.customText=${bed_file.qp}</url>
+ <param type="data" name="bed_file" url="galaxy_${DATASET_HASH}.bed" format="bedstrict"/> <!-- Galaxy allows BED files to contain non-standard fields beyond the first 3 columns, UCSC does not: force use of converter which will make strict BED6+ file -->
+ <param type="template" name="position" strip="True" >
+#set line_count = 0
+#set chrom = None
+#set start = float( 'inf' )
+#set end = 0
+#for $line in open( $bed_file.file_name ):
+ #if $line_count > 10: ##10 max lines to check for view port
+ #break
+ #end if
+ #if not $line.startswith( "#" ):
+ #set $fields = $line.split( "\t" )
+ #try:
+ #if len( $fields ) >= max( $bed_file.metadata.startCol, $bed_file.metadata.endCol, $bed_file.metadata.chromCol ):
+ #if $chrom is None or $fields[ $bed_file.metadata.chromCol - 1 ] == $chrom:
+ #set chrom = $fields[ $bed_file.metadata.chromCol - 1 ]
+ #set start = min( $start, int( $fields[ $bed_file.metadata.startCol - 1 ] ) )
+ #set end = max( $end, int( $fields[ $bed_file.metadata.endCol - 1 ] ) )
+ #end if
+ #end if
+ #except:
+ #pass
+ #end try
+ #end if
+ #set line_count += 1
+#end for
+#if $chrom is not None:
+${chrom}:${start}-${end + 1}
+#else:
+:-
+#end if
+ </param>
+ </dynamic_links>
</display>
diff -r 262b16c8e277 -r f13d85256124 lib/galaxy/datatypes/data.py
--- a/lib/galaxy/datatypes/data.py Thu Mar 11 13:51:53 2010 -0500
+++ b/lib/galaxy/datatypes/data.py Thu Mar 11 14:35:36 2010 -0500
@@ -205,6 +205,15 @@
"""New style display applications"""
assert display_application.id not in self.display_applications, 'Attempted to add a display application twice'
self.display_applications[ display_application.id ] = display_application
+ def get_display_application( self, key, default = None ):
+ return self.display_applications.get( key, default )
+ def get_display_applications_by_dataset( self, dataset, trans ):
+ rval = odict()
+ for key, value in self.display_applications.iteritems():
+ value = value.filter_by_dataset( dataset, trans )
+ if value.links:
+ rval[key] = value
+ return rval
def get_display_types(self):
"""Returns display types available"""
return self.supported_display_apps.keys()
diff -r 262b16c8e277 -r f13d85256124 lib/galaxy/datatypes/display_applications/application.py
--- a/lib/galaxy/datatypes/display_applications/application.py Thu Mar 11 13:51:53 2010 -0500
+++ b/lib/galaxy/datatypes/display_applications/application.py Thu Mar 11 14:35:36 2010 -0500
@@ -1,24 +1,27 @@
#Contains objects for using external display applications
-from galaxy.util import parse_xml
+from galaxy.util import parse_xml, string_as_bool
from galaxy.util.odict import odict
from galaxy.util.template import fill_template
from galaxy.web import url_for
from parameters import DisplayApplicationParameter, DEFAULT_DATASET_NAME
from urllib import quote_plus
from util import encode_dataset_user
+from copy import deepcopy
#Any basic functions that we want to provide as a basic part of parameter dict should be added to this dict
BASE_PARAMS = { 'qp': quote_plus, 'url_for':url_for } #url_for has route memory...
class DisplayApplicationLink( object ):
@classmethod
- def from_elem( cls, elem, display_application ):
+ def from_elem( cls, elem, display_application, other_values = None ):
rval = DisplayApplicationLink( display_application )
rval.id = elem.get( 'id', None )
assert rval.id, 'Link elements require a id.'
rval.name = elem.get( 'name', rval.id )
rval.url = elem.find( 'url' )
assert rval.url is not None, 'A url element must be provided for link elements.'
+ rval.other_values = other_values
+ rval.filters = elem.findall( 'filter' )
for param_elem in elem.findall( 'param' ):
param = DisplayApplicationParameter.from_elem( param_elem, rval )
assert param, 'Unable to load parameter from element: %s' % param_elem
@@ -36,13 +39,19 @@
dataset_hash, user_hash = encode_dataset_user( trans, data, None )
return url_for( controller = '/dataset', action = "display_application", dataset_id = dataset_hash, user_id = user_hash, app_name = self.display_application.id, link_name = self.id, app_action = None )
def get_inital_values( self, data, trans ):
- rval = odict( { 'BASE_URL': trans.request.base, 'APP': trans.app } ) #trans automatically appears as a response, need to add properties of trans that we want here
+ if self.other_values:
+ rval = odict( self.other_values )
+ else:
+ rval = odict()
+ rval.update( { 'BASE_URL': trans.request.base, 'APP': trans.app } ) #trans automatically appears as a response, need to add properties of trans that we want here
for key, value in BASE_PARAMS.iteritems(): #add helper functions/variables
rval[ key ] = value
rval[ DEFAULT_DATASET_NAME ] = data #always have the display dataset name available
return rval
def build_parameter_dict( self, data, dataset_hash, user_hash, trans ):
other_values = self.get_inital_values( data, trans )
+ other_values[ 'DATASET_HASH' ] = dataset_hash
+ other_values[ 'USER_HASH' ] = user_hash
for name, param in self.parameters.iteritems():
assert name not in other_values, "The display parameter '%s' has been defined more than once." % name
if param.ready( other_values ):
@@ -51,6 +60,51 @@
other_values[ name ] = None
return False, other_values #need to stop here, next params may need this value
return True, other_values #we built other_values, lets provide it as well, or else we will likely regenerate it in the next step
+ def filter_by_dataset( self, data, trans ):
+ context = self.get_inital_values( data, trans )
+ for filter_elem in self.filters:
+ if fill_template( filter_elem.text, context = context ) != filter_elem.get( 'value', 'True' ):
+ return False
+ return True
+
+class DynamicDisplayApplicationBuilder( object ):
+ @classmethod
+ def __init__( self, elem, display_application ):
+ rval = []
+ filename = elem.get( 'from_file', None )
+ assert filename is not None, 'Filename and id attributes required for dynamic_links'
+ skip_startswith = elem.get( 'skip_startswith', None )
+ separator = elem.get( 'separator', '\t' )
+ id_col = int( elem.get( 'id', None ) )
+ name_col = int( elem.get( 'name', id_col ) )
+ dynamic_params = {}
+ max_col = max( id_col, name_col )
+ for dynamic_param in elem.findall( 'dynamic_param' ):
+ name = dynamic_param.get( 'name' )
+ value = int( dynamic_param.get( 'value' ) )
+ split = string_as_bool( dynamic_param.get( 'split', False ) )
+ param_separator = dynamic_param.get( 'separator', ',' )
+ max_col = max( max_col, value )
+ dynamic_params[name] = { 'column': value, 'split': split, 'separator': param_separator }
+ for line in open( filename ):
+ if not skip_startswith or not line.startswith( skip_startswith ):
+ line = line.rstrip( '\n\r' )
+ fields = line.split( separator )
+ if len( fields ) >= max_col:
+ new_elem = deepcopy( elem )
+ new_elem.set( 'id', fields[id_col] )
+ new_elem.set( 'name', fields[name_col] )
+ dynamic_values = {}
+ for key, attributes in dynamic_params.iteritems():
+ value = fields[ attributes[ 'column' ] ]
+ if attributes['split']:
+ value = value.split( attributes['separator'] )
+ dynamic_values[key] = value
+ #now populate
+ rval.append( DisplayApplicationLink.from_elem( new_elem, display_application, other_values = dynamic_values ) )
+ self.links = rval
+ def __iter__( self ):
+ return iter( self.links )
class PopulatedDisplayApplicationLink( object ):
def __init__( self, display_application_link, data, dataset_hash, user_hash, trans ):
@@ -84,9 +138,11 @@
def display_url( self ):
assert self.display_ready(), 'Display is not yet ready, cannot generate display link'
return fill_template( self.link.url.text, context = self.parameters )
- def get_param_name_by_url( self, name ):
- assert name in self.link.url_param_name_map, "Unknown URL parameter name provided: %s" % name
- return self.link.url_param_name_map[ name ]
+ def get_param_name_by_url( self, url ):
+ for name, parameter in self.link.parameters.iteritems():
+ if parameter.build_url( self.parameters ) == url:
+ return name
+ raise ValueError( "Unknown URL parameter name provided: %s" % url )
class DisplayApplication( object ):
@classmethod
@@ -103,6 +159,9 @@
link = DisplayApplicationLink.from_elem( link_elem, rval )
if link:
rval.links[ link.id ] = link
+ for dynamic_links in elem.findall( 'dynamic_links' ):
+ for link in DynamicDisplayApplicationBuilder( dynamic_links, rval ):
+ rval.links[ link.id ] = link
return rval
def __init__( self, display_id, name, datatypes_registry, version = None ):
self.id = display_id
@@ -115,4 +174,9 @@
def get_link( self, link_name, data, dataset_hash, user_hash, trans ):
#returns a link object with data knowledge to generate links
return PopulatedDisplayApplicationLink( self.links[ link_name ], data, dataset_hash, user_hash, trans )
-
+ def filter_by_dataset( self, data, trans ):
+ filtered = DisplayApplication( self.id, self.name, self.datatypes_registry, version = self.version )
+ for link_name, link_value in self.links.iteritems():
+ if link_value.filter_by_dataset( data, trans ):
+ filtered.links[link_name] = link_value
+ return filtered
diff -r 262b16c8e277 -r f13d85256124 lib/galaxy/datatypes/display_applications/parameters.py
--- a/lib/galaxy/datatypes/display_applications/parameters.py Thu Mar 11 13:51:53 2010 -0500
+++ b/lib/galaxy/datatypes/display_applications/parameters.py Thu Mar 11 14:35:36 2010 -0500
@@ -35,6 +35,8 @@
return True
def is_preparing( self, other_values ):
return False
+ def build_url( self, other_values ):
+ return fill_template( self.url, context = other_values )
class DisplayApplicationDataParameter( DisplayApplicationParameter ):
""" Parameter that returns a file_name containing the requested content """
@@ -141,15 +143,16 @@
self.trans = trans
self._dataset_hash = dataset_hash
self._user_hash = user_hash
+ self._url = self.parameter.build_url( self.other_values )
def __str__( self ):
return str( self.value )
def mime_type( self ):
if self.parameter.mime_type is not None:
return self.parameter.mime_type
if self.parameter.guess_mime_type:
- mime, encoding = mimetypes.guess_type( self.parameter.url )
+ mime, encoding = mimetypes.guess_type( self._url )
if not mime:
- mime = self.trans.app.datatypes_registry.get_mimetype_by_extension( ".".split( self.parameter.url )[ -1 ], None )
+ mime = self.trans.app.datatypes_registry.get_mimetype_by_extension( ".".split( self._url )[ -1 ], None )
if mime:
return mime
return 'text/plain'
@@ -158,7 +161,7 @@
base_url = self.trans.request.base
if self.parameter.strip_https and base_url[ : 5].lower() == 'https':
base_url = "http%s" % base_url[ 5: ]
- return "%s%s" % ( base_url, url_for( controller = '/dataset', action = "display_application", dataset_id = self._dataset_hash, user_id = self._user_hash, app_name = self.parameter.link.display_application.id, link_name = self.parameter.link.id, app_action = self.action_name, action_param = self.parameter.url ) )
+ return "%s%s" % ( base_url, url_for( controller = '/dataset', action = "display_application", dataset_id = self._dataset_hash, user_id = self._user_hash, app_name = self.parameter.link.display_application.id, link_name = self.parameter.link.id, app_action = self.action_name, action_param = self._url ) )
@property
def action_name( self ):
return self.ACTION_NAME
@@ -178,9 +181,9 @@
if self.parameter.mime_type is not None:
return self.parameter.mime_type
if self.parameter.guess_mime_type:
- mime, encoding = mimetypes.guess_type( self.parameter.url )
+ mime, encoding = mimetypes.guess_type( self._url )
if not mime:
- mime = self.trans.app.datatypes_registry.get_mimetype_by_extension( ".".split( self.parameter.url )[ -1 ], None )
+ mime = self.trans.app.datatypes_registry.get_mimetype_by_extension( ".".split( self._url )[ -1 ], None )
if mime:
return mime
return self.other_values[ DEFAULT_DATASET_NAME ].get_mime()
diff -r 262b16c8e277 -r f13d85256124 lib/galaxy/datatypes/registry.py
--- a/lib/galaxy/datatypes/registry.py Thu Mar 11 13:51:53 2010 -0500
+++ b/lib/galaxy/datatypes/registry.py Thu Mar 11 14:35:36 2010 -0500
@@ -25,6 +25,7 @@
self.sniff_order = []
self.upload_file_formats = []
self.display_applications = odict() #map a display application id to a display application
+ inherit_display_application_by_class = []
if root_dir and config:
# Parse datatypes_conf.xml
tree = galaxy.util.parse_xml( config )
@@ -42,11 +43,11 @@
for elem in registration.findall( 'datatype' ):
try:
extension = elem.get( 'extension', None )
- type = elem.get( 'type', None )
+ dtype = elem.get( 'type', None )
mimetype = elem.get( 'mimetype', None )
display_in_upload = elem.get( 'display_in_upload', False )
- if extension and type:
- fields = type.split( ':' )
+ if extension and dtype:
+ fields = dtype.split( ':' )
datatype_module = fields[0]
datatype_class = fields[1]
fields = datatype_module.split( '.' )
@@ -85,27 +86,36 @@
for display_app in elem.findall( 'display' ):
display_file = display_app.get( 'file', None )
assert display_file is not None, "A file must be specified for a datatype display tag."
+ inherit = galaxy.util.string_as_bool( display_app.get( 'inherit', 'False' ) )
display_app = DisplayApplication.from_file( os.path.join( self.display_applications_path, display_file ), self )
if display_app:
if display_app.id in self.display_applications:
#if we already loaded this display application, we'll use the first one again
display_app = self.display_applications[ display_app.id ]
- self.log.debug( "Loaded display application '%s' for datatype '%s'" % ( display_app.id, extension ) )
+ self.log.debug( "Loaded display application '%s' for datatype '%s', inherit=%s" % ( display_app.id, extension, inherit ) )
self.display_applications[ display_app.id ] = display_app #Display app by id
self.datatypes_by_extension[ extension ].add_display_application( display_app )
-
+ if inherit and ( self.datatypes_by_extension[extension], display_app ) not in inherit_display_application_by_class:
+ #subclass inheritance will need to wait until all datatypes have been loaded
+ inherit_display_application_by_class.append( ( self.datatypes_by_extension[extension], display_app ) )
except Exception, e:
self.log.warning( 'Error loading datatype "%s", problem: %s' % ( extension, str( e ) ) )
+ # Handle display_application subclass inheritance here:
+ for ext, d_type1 in self.datatypes_by_extension.iteritems():
+ for d_type2, display_app in inherit_display_application_by_class:
+ current_app = d_type1.get_display_application( display_app.id, None )
+ if current_app is None and isinstance( d_type1, type( d_type2 ) ):
+ d_type1.add_display_application( display_app )
# Load datatype sniffers from the config
sniff_order = []
sniffers = root.find( 'sniffers' )
for elem in sniffers.findall( 'sniffer' ):
- type = elem.get( 'type', None )
- if type:
- sniff_order.append( type )
- for type in sniff_order:
+ dtype = elem.get( 'type', None )
+ if dtype:
+ sniff_order.append( dtype )
+ for dtype in sniff_order:
try:
- fields = type.split( ":" )
+ fields = dtype.split( ":" )
datatype_module = fields[0]
datatype_class = fields[1]
fields = datatype_module.split( "." )
@@ -120,9 +130,9 @@
break
if not included:
self.sniff_order.append( aclass )
- self.log.debug( 'Loaded sniffer for datatype: %s' % type )
+ self.log.debug( 'Loaded sniffer for datatype: %s' % dtype )
except Exception, exc:
- self.log.warning( 'Error appending datatype %s to sniff_order, problem: %s' % ( type, str( exc ) ) )
+ self.log.warning( 'Error appending datatype %s to sniff_order, problem: %s' % ( dtype, str( exc ) ) )
#default values
if len(self.datatypes_by_extension) < 1:
self.datatypes_by_extension = {
diff -r 262b16c8e277 -r f13d85256124 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py Thu Mar 11 13:51:53 2010 -0500
+++ b/lib/galaxy/model/__init__.py Thu Mar 11 14:35:36 2010 -0500
@@ -637,6 +637,9 @@
return ( None, None )
return get_source( self )
+ def get_display_applications( self, trans ):
+ return self.datatype.get_display_applications_by_dataset( self, trans )
+
class HistoryDatasetAssociation( DatasetInstance ):
def __init__( self,
hid = None,
diff -r 262b16c8e277 -r f13d85256124 templates/root/history_common.mako
--- a/templates/root/history_common.mako Thu Mar 11 13:51:53 2010 -0500
+++ b/templates/root/history_common.mako Thu Mar 11 14:35:36 2010 -0500
@@ -102,7 +102,7 @@
%endif
%endfor
%endif
- %for display_app in data.datatype.display_applications.itervalues():
+ %for display_app in data.get_display_applications( trans ).itervalues():
| ${display_app.name}
%for link_app in display_app.links.itervalues():
<a target="${link_app.url.get( 'target_frame', '_blank' )}" href="${link_app.get_display_url( data, trans )}">${_(link_app.name)}</a>
diff -r 262b16c8e277 -r f13d85256124 tool-data/shared/bx/bx_build_sites.txt
--- a/tool-data/shared/bx/bx_build_sites.txt Thu Mar 11 13:51:53 2010 -0500
+++ b/tool-data/shared/bx/bx_build_sites.txt Thu Mar 11 14:35:36 2010 -0500
@@ -1,1 +1,1 @@
-main http://main.genome-browser.bx.psu.edu/cgi-bin/hgTracks? hg18,hg19,mm8,mm9
+main http://main.genome-browser.bx.psu.edu/cgi-bin/hgTracks? hg18,hg19,mm8,mm9 bx-main
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/262b16c8e277
changeset: 3520:262b16c8e277
user: fubar: ross Lazarus at gmail period com
date: Thu Mar 11 13:51:53 2010 -0500
description:
remove bogus string.translate
diffstat:
lib/galaxy/web/controllers/library_common.py | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
diffs (12 lines):
diff -r 39e4b119bdf4 -r 262b16c8e277 lib/galaxy/web/controllers/library_common.py
--- a/lib/galaxy/web/controllers/library_common.py Thu Mar 11 13:41:40 2010 -0500
+++ b/lib/galaxy/web/controllers/library_common.py Thu Mar 11 13:51:53 2010 -0500
@@ -1357,8 +1357,6 @@
path = os.path.join( parent_folder.name, path )
parent_folder = parent_folder.parent
path += ldda.name
- if path > '':
- path = path.translate(trantab)
while path in seen:
path += '_'
seen.append( path )
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/39e4b119bdf4
changeset: 3519:39e4b119bdf4
user: fubar: ross Lazarus at gmail period com
date: Thu Mar 11 13:41:40 2010 -0500
description:
merge with 3518:0c9e154e9176
diffstat:
lib/galaxy/datatypes/sniff.py | 39 ++++++++++++++++++++++++---------------
tools/data_source/upload.py | 24 +++++++++++++++++++-----
2 files changed, 43 insertions(+), 20 deletions(-)
diffs (140 lines):
diff -r e98117dd6054 -r 39e4b119bdf4 lib/galaxy/datatypes/sniff.py
--- a/lib/galaxy/datatypes/sniff.py Thu Mar 11 13:37:49 2010 -0500
+++ b/lib/galaxy/datatypes/sniff.py Thu Mar 11 13:41:40 2010 -0500
@@ -70,7 +70,7 @@
f.close()
return False
-def convert_newlines( fname ):
+def convert_newlines( fname, in_place=True ):
"""
Converts in place a file from universal line endings
to Posix line endings.
@@ -78,7 +78,7 @@
>>> fname = get_test_fname('temp.txt')
>>> file(fname, 'wt').write("1 2\\r3 4")
>>> convert_newlines(fname)
- 2
+ (2, None)
>>> file(fname).read()
'1 2\\n3 4\\n'
"""
@@ -87,18 +87,21 @@
for i, line in enumerate( file( fname, "U" ) ):
fp.write( "%s\n" % line.rstrip( "\r\n" ) )
fp.close()
- shutil.move( temp_name, fname )
- # Return number of lines in file.
- return i + 1
+ if in_place:
+ shutil.move( temp_name, fname )
+ # Return number of lines in file.
+ return ( i + 1, None )
+ else:
+ return ( i + 1, temp_name )
-def sep2tabs(fname, patt="\\s+"):
+def sep2tabs( fname, in_place=True, patt="\\s+" ):
"""
Transforms in place a 'sep' separated file to a tab separated one
>>> fname = get_test_fname('temp.txt')
>>> file(fname, 'wt').write("1 2\\n3 4\\n")
>>> sep2tabs(fname)
- 2
+ (2, None)
>>> file(fname).read()
'1\\t2\\n3\\t4\\n'
"""
@@ -110,11 +113,14 @@
elems = regexp.split( line )
fp.write( "%s\n" % '\t'.join( elems ) )
fp.close()
- shutil.move( temp_name, fname )
- # Return number of lines in file.
- return i + 1
+ if in_place:
+ shutil.move( temp_name, fname )
+ # Return number of lines in file.
+ return ( i + 1, None )
+ else:
+ return ( i + 1, temp_name )
-def convert_newlines_sep2tabs( fname, patt="\\s+" ):
+def convert_newlines_sep2tabs( fname, in_place=True, patt="\\s+" ):
"""
Combines above methods: convert_newlines() and sep2tabs()
so that files do not need to be read twice
@@ -122,7 +128,7 @@
>>> fname = get_test_fname('temp.txt')
>>> file(fname, 'wt').write("1 2\\r3 4")
>>> convert_newlines_sep2tabs(fname)
- 2
+ (2, None)
>>> file(fname).read()
'1\\t2\\n3\\t4\\n'
"""
@@ -134,9 +140,12 @@
elems = regexp.split( line )
fp.write( "%s\n" % '\t'.join( elems ) )
fp.close()
- shutil.move( temp_name, fname )
- # Return number of lines in file.
- return i + 1
+ if in_place:
+ shutil.move( temp_name, fname )
+ # Return number of lines in file.
+ return ( i + 1, None )
+ else:
+ return ( i + 1, temp_name )
def get_headers( fname, sep, count=60, is_multi_byte=False ):
"""
diff -r e98117dd6054 -r 39e4b119bdf4 tools/data_source/upload.py
--- a/tools/data_source/upload.py Thu Mar 11 13:37:49 2010 -0500
+++ b/tools/data_source/upload.py Thu Mar 11 13:41:40 2010 -0500
@@ -138,6 +138,7 @@
def add_file( dataset, json_file, output_path ):
data_type = None
line_count = None
+ converted_path = None
if dataset.type == 'url':
try:
@@ -239,10 +240,15 @@
file_err( 'The uploaded file contains inappropriate content', dataset, json_file )
return
if data_type != 'binary' and data_type != 'zip':
- if dataset.space_to_tab:
- line_count = sniff.convert_newlines_sep2tabs( dataset.path )
- else:
- line_count = sniff.convert_newlines( dataset.path )
+ # don't convert newlines on data we're only going to symlink
+ if not dataset.get( 'link_data_only', False ):
+ in_place = True
+ if dataset.type in ( 'server_dir', 'path_paste' ):
+ in_place = False
+ if dataset.space_to_tab:
+ line_count, converted_path = sniff.convert_newlines_sep2tabs( dataset.path, in_place=in_place )
+ else:
+ line_count, converted_path = sniff.convert_newlines( dataset.path, in_place=in_place )
if dataset.file_type == 'auto':
ext = sniff.guess_ext( dataset.path )
else:
@@ -257,7 +263,15 @@
if dataset.get( 'link_data_only', False ):
pass # data will remain in place
elif dataset.type in ( 'server_dir', 'path_paste' ):
- shutil.copy( dataset.path, output_path )
+ if converted_path is not None:
+ shutil.copy( converted_path, output_path )
+ try:
+ os.remove( converted_path )
+ except:
+ pass
+ else:
+ # this should not happen, but it's here just in case
+ shutil.copy( dataset.path, output_path )
else:
shutil.move( dataset.path, output_path )
# Write the job info
1
0

18 Mar '10
details: http://www.bx.psu.edu/hg/galaxy/rev/e98117dd6054
changeset: 3518:e98117dd6054
user: fubar: ross Lazarus at gmail period com
date: Thu Mar 11 13:37:49 2010 -0500
description:
fix for string.translate on empty path in creating an archive of library composite datatypes
diffstat:
lib/galaxy/web/controllers/library_common.py | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diffs (23 lines):
diff -r 2e97ae04856d -r e98117dd6054 lib/galaxy/web/controllers/library_common.py
--- a/lib/galaxy/web/controllers/library_common.py Thu Mar 11 11:17:11 2010 -0500
+++ b/lib/galaxy/web/controllers/library_common.py Thu Mar 11 13:37:49 2010 -0500
@@ -1357,7 +1357,8 @@
path = os.path.join( parent_folder.name, path )
parent_folder = parent_folder.parent
path += ldda.name
- path = path.translate(trantab)
+ if path > '':
+ path = path.translate(trantab)
while path in seen:
path += '_'
seen.append( path )
@@ -1377,7 +1378,8 @@
flist = glob.glob(os.path.join(ldda.dataset.extra_files_path,'*.*')) # glob returns full paths
for fpath in flist:
efp,fname = os.path.split(fpath)
- fname = fname.translate(trantab)
+ if fname > '':
+ fname = fname.translate(trantab)
try:
archive.add( fpath,fname )
except IOError:
1
0

18 Mar '10
details: http://www.bx.psu.edu/hg/galaxy/rev/0c9e154e9176
changeset: 3517:0c9e154e9176
user: Nate Coraor <nate(a)bx.psu.edu>
date: Thu Mar 11 11:56:20 2010 -0500
description:
Modify the newline conversion methods in sniff so converting in place is optional. This is necessary to fix a bug that occurs if using the 'server_dir' or 'path_paste' library upload methods: previously, they would modify the file to be imported in-place if permissions allowed (probably not what the admin wanted) or fail if permissions did not allow. New functionality is to return the converted tempfile if 'server_dir' or 'path_paste' methods are used. Also, no newline conversion will be done if the administrator uses the symlink checkbox.
diffstat:
lib/galaxy/datatypes/sniff.py | 39 ++++++++++++++++++++++++---------------
tools/data_source/upload.py | 24 +++++++++++++++++++-----
2 files changed, 43 insertions(+), 20 deletions(-)
diffs (140 lines):
diff -r 2e97ae04856d -r 0c9e154e9176 lib/galaxy/datatypes/sniff.py
--- a/lib/galaxy/datatypes/sniff.py Thu Mar 11 11:17:11 2010 -0500
+++ b/lib/galaxy/datatypes/sniff.py Thu Mar 11 11:56:20 2010 -0500
@@ -70,7 +70,7 @@
f.close()
return False
-def convert_newlines( fname ):
+def convert_newlines( fname, in_place=True ):
"""
Converts in place a file from universal line endings
to Posix line endings.
@@ -78,7 +78,7 @@
>>> fname = get_test_fname('temp.txt')
>>> file(fname, 'wt').write("1 2\\r3 4")
>>> convert_newlines(fname)
- 2
+ (2, None)
>>> file(fname).read()
'1 2\\n3 4\\n'
"""
@@ -87,18 +87,21 @@
for i, line in enumerate( file( fname, "U" ) ):
fp.write( "%s\n" % line.rstrip( "\r\n" ) )
fp.close()
- shutil.move( temp_name, fname )
- # Return number of lines in file.
- return i + 1
+ if in_place:
+ shutil.move( temp_name, fname )
+ # Return number of lines in file.
+ return ( i + 1, None )
+ else:
+ return ( i + 1, temp_name )
-def sep2tabs(fname, patt="\\s+"):
+def sep2tabs( fname, in_place=True, patt="\\s+" ):
"""
Transforms in place a 'sep' separated file to a tab separated one
>>> fname = get_test_fname('temp.txt')
>>> file(fname, 'wt').write("1 2\\n3 4\\n")
>>> sep2tabs(fname)
- 2
+ (2, None)
>>> file(fname).read()
'1\\t2\\n3\\t4\\n'
"""
@@ -110,11 +113,14 @@
elems = regexp.split( line )
fp.write( "%s\n" % '\t'.join( elems ) )
fp.close()
- shutil.move( temp_name, fname )
- # Return number of lines in file.
- return i + 1
+ if in_place:
+ shutil.move( temp_name, fname )
+ # Return number of lines in file.
+ return ( i + 1, None )
+ else:
+ return ( i + 1, temp_name )
-def convert_newlines_sep2tabs( fname, patt="\\s+" ):
+def convert_newlines_sep2tabs( fname, in_place=True, patt="\\s+" ):
"""
Combines above methods: convert_newlines() and sep2tabs()
so that files do not need to be read twice
@@ -122,7 +128,7 @@
>>> fname = get_test_fname('temp.txt')
>>> file(fname, 'wt').write("1 2\\r3 4")
>>> convert_newlines_sep2tabs(fname)
- 2
+ (2, None)
>>> file(fname).read()
'1\\t2\\n3\\t4\\n'
"""
@@ -134,9 +140,12 @@
elems = regexp.split( line )
fp.write( "%s\n" % '\t'.join( elems ) )
fp.close()
- shutil.move( temp_name, fname )
- # Return number of lines in file.
- return i + 1
+ if in_place:
+ shutil.move( temp_name, fname )
+ # Return number of lines in file.
+ return ( i + 1, None )
+ else:
+ return ( i + 1, temp_name )
def get_headers( fname, sep, count=60, is_multi_byte=False ):
"""
diff -r 2e97ae04856d -r 0c9e154e9176 tools/data_source/upload.py
--- a/tools/data_source/upload.py Thu Mar 11 11:17:11 2010 -0500
+++ b/tools/data_source/upload.py Thu Mar 11 11:56:20 2010 -0500
@@ -138,6 +138,7 @@
def add_file( dataset, json_file, output_path ):
data_type = None
line_count = None
+ converted_path = None
if dataset.type == 'url':
try:
@@ -239,10 +240,15 @@
file_err( 'The uploaded file contains inappropriate content', dataset, json_file )
return
if data_type != 'binary' and data_type != 'zip':
- if dataset.space_to_tab:
- line_count = sniff.convert_newlines_sep2tabs( dataset.path )
- else:
- line_count = sniff.convert_newlines( dataset.path )
+ # don't convert newlines on data we're only going to symlink
+ if not dataset.get( 'link_data_only', False ):
+ in_place = True
+ if dataset.type in ( 'server_dir', 'path_paste' ):
+ in_place = False
+ if dataset.space_to_tab:
+ line_count, converted_path = sniff.convert_newlines_sep2tabs( dataset.path, in_place=in_place )
+ else:
+ line_count, converted_path = sniff.convert_newlines( dataset.path, in_place=in_place )
if dataset.file_type == 'auto':
ext = sniff.guess_ext( dataset.path )
else:
@@ -257,7 +263,15 @@
if dataset.get( 'link_data_only', False ):
pass # data will remain in place
elif dataset.type in ( 'server_dir', 'path_paste' ):
- shutil.copy( dataset.path, output_path )
+ if converted_path is not None:
+ shutil.copy( converted_path, output_path )
+ try:
+ os.remove( converted_path )
+ except:
+ pass
+ else:
+ # this should not happen, but it's here just in case
+ shutil.copy( dataset.path, output_path )
else:
shutil.move( dataset.path, output_path )
# Write the job info
1
0
details: http://www.bx.psu.edu/hg/galaxy/rev/2e97ae04856d
changeset: 3516:2e97ae04856d
user: Dan Blankenberg <dan(a)bx.psu.edu>
date: Thu Mar 11 11:17:11 2010 -0500
description:
Fix for implicit datatype conversion.
diffstat:
lib/galaxy/datatypes/data.py | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diffs (12 lines):
diff -r 6fa986527398 -r 2e97ae04856d lib/galaxy/datatypes/data.py
--- a/lib/galaxy/datatypes/data.py Wed Mar 10 23:59:25 2010 -0500
+++ b/lib/galaxy/datatypes/data.py Thu Mar 11 11:17:11 2010 -0500
@@ -257,7 +257,7 @@
break
params[input_name] = original_dataset
#Run converter, job is dispatched through Queue
- converted_dataset = converter.execute( trans, incoming = params, set_output_hid = visible )
+ converted_dataset = converter.execute( trans, incoming = params, set_output_hid = visible )[1]
if len(params) > 0:
trans.log_event( "Converter params: %s" % (str(params)), tool_id=converter.id )
if not visible:
1
0