From 6f53287193b12b01fbe270648f3a3d917f9405bd Mon Sep 17 00:00:00 2001 From: Dan Blanchard Date: Mon, 16 Jun 2014 13:27:38 +0000 Subject: [PATCH 01/69] Update DRMAA Python version in eggs.ini to 0.7.6. This version has better string handling and supports Python 3. --- eggs.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eggs.ini b/eggs.ini index 5884a50ec80..409cf5a4951 100644 --- a/eggs.ini +++ b/eggs.ini @@ -38,7 +38,7 @@ bioblend = 0.4.2 boto = 2.27.0 decorator = 3.1.2 docutils = 0.7 -drmaa = 0.6 +drmaa = 0.7.6 elementtree = 1.2.6_20050316 Fabric = 1.7.0 GeneTrack = 2.0.0_beta_1 From 0fda9feb0f00779d31029063e54fc0cfc92eedaf Mon Sep 17 00:00:00 2001 From: Jeremy Goecks Date: Mon, 23 Jun 2014 15:46:45 -0400 Subject: [PATCH 02/69] Trackster: resize viewport when showing reference track to avoid inadvertently hiding scroll bar. --- static/scripts/viz/trackster/tracks.js | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/static/scripts/viz/trackster/tracks.js b/static/scripts/viz/trackster/tracks.js index 660c586ebac..4892613a0a0 100644 --- a/static/scripts/viz/trackster/tracks.js +++ b/static/scripts/viz/trackster/tracks.js @@ -1579,8 +1579,14 @@ extend( TracksterView.prototype, DrawableCollection.prototype, { this.request_redraw(); }, - resize_window: function() { + /** Resize viewport. Use this method if header/footer content has changed in size. */ + resize_viewport: function() { this.viewport_container.height( this.container.height() - this.top_container.height() - this.bottom_container.height() ); + }, + + /** Called when window is resized. */ + resize_window: function() { + this.resize_viewport(); this.request_redraw(); }, @@ -2940,6 +2946,12 @@ extend(TiledTrack.prototype, Drawable.prototype, Track.prototype, { * drawn/fetched and shown. */ postdraw_actions: function(tiles, width, w_scale, clear_after) { + // If reference track is visible, adjust viewport to be smaller so that bottom content + // is visible. + if (this.view.reference_track.tiles_div.is(':visible')) { + this.view.resize_viewport(); + } + var line_track_tiles = _.filter(tiles, function(tile) { return (tile instanceof LineTrackTile); }); @@ -3618,15 +3630,15 @@ extend(ReferenceTrack.prototype, Drawable.prototype, TiledTrack.prototype, { can_draw: Drawable.prototype.can_draw, /** - * Retrieves data and draws tile if reference data can be displayed. + * Draws and shows tile if reference data can be displayed; otherwise track is hidden. */ draw_helper: function(region, w_scale, options) { if (w_scale > this.view.canvas_manager.char_width_px) { - this.tiles_div.show(); + this.tiles_div.show(); return TiledTrack.prototype.draw_helper.call(this, region, w_scale, options); } else { - this.tiles_div.hide(); + this.tiles_div.hide(); return null; } }, From 39406fd0ef893179a28bc562c6c8d037b535cb7e Mon Sep 17 00:00:00 2001 From: Jeremy Goecks Date: Mon, 23 Jun 2014 16:11:46 -0400 Subject: [PATCH 03/69] Trackster: remove mousewheel scrolling amplifier and clarify comment. --- static/scripts/viz/trackster/tracks.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/static/scripts/viz/trackster/tracks.js b/static/scripts/viz/trackster/tracks.js index 4892613a0a0..cb7aa708b73 100644 --- a/static/scripts/viz/trackster/tracks.js +++ b/static/scripts/viz/trackster/tracks.js @@ -1070,11 +1070,10 @@ var TracksterView = Backbone.View.extend({ var delta_chrom = Math.round(delta / view.viewport_container.width() * (view.high - view.low)); view.move_delta(delta_chrom); // Also capture mouse wheel for left/right scrolling - }).bind( 'mousewheel', function( e, d, dx, dy ) { - // Only act on x axis scrolling if we see if, y will be i - // handled by the browser when the event bubbles up - if ( dx ) { - dx *= 50; + }).bind( 'mousewheel', function( e, d, dx, dy ) { + // Only handle x axis scrolling; y axis scrolling is + // handled by the browser when the event bubbles up. + if (dx) { var delta_chrom = Math.round( - dx / view.viewport_container.width() * (view.high - view.low) ); view.move_delta( delta_chrom ); } From 3d9da261d1dcbad2414d1edc2f25fbdab0cb1bc3 Mon Sep 17 00:00:00 2001 From: John Chilton Date: Mon, 23 Jun 2014 16:32:24 -0500 Subject: [PATCH 04/69] Allow tool conf 'tool_path' resolution relative to conf file. Relative 'tool_path' directories are resolved relative to GALAXY_ROOT (or really working directory). This is probably the expected behavior - but I think it is advantageous to be able to find tools relative to the tool_conf file also. This can now be done using string.Template resolution of ${tool_conf_dir}. --- lib/galaxy/tools/__init__.py | 15 +++++++++++++-- test/functional/tools/samples_tool_conf.xml | 2 +- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/galaxy/tools/__init__.py b/lib/galaxy/tools/__init__.py index 131294e6a63..10a9b2b217d 100755 --- a/lib/galaxy/tools/__init__.py +++ b/lib/galaxy/tools/__init__.py @@ -11,6 +11,7 @@ import pipes import re import shutil import sys +import string import tempfile import threading import traceback @@ -214,8 +215,7 @@ class ToolBox( object, Dictifiable ): config_elems = [] else: parsing_shed_tool_conf = False - # Default to backward compatible config setting. - tool_path = self.tool_root_dir + tool_path = self.__resolve_tool_path(tool_path, config_filename) # Only load the panel_dict under certain conditions. load_panel_dict = not self.integrated_tool_panel_config_has_contents for _, elem in enumerate( root ): @@ -243,6 +243,17 @@ class ToolBox( object, Dictifiable ): return shed_config_dict return default + def __resolve_tool_path(self, tool_path, config_filename): + if not tool_path: + # Default to backward compatible config setting. + tool_path = self.tool_root_dir + else: + # Allow use of __tool_conf_dir__ in toolbox config files. + tool_conf_dir = os.path.dirname(config_filename) + tool_path_vars = {"tool_conf_dir": tool_conf_dir} + tool_path = string.Template(tool_path).safe_substitute(tool_path_vars) + return tool_path + def __add_tool_to_tool_panel( self, tool, panel_component, section=False ): # See if a version of this tool is already loaded into the tool panel. The value of panel_component # will be a ToolSection (if the value of section=True) or self.tool_panel (if section=False). diff --git a/test/functional/tools/samples_tool_conf.xml b/test/functional/tools/samples_tool_conf.xml index 52f3e54bbba..918e7c5a5e9 100644 --- a/test/functional/tools/samples_tool_conf.xml +++ b/test/functional/tools/samples_tool_conf.xml @@ -1,5 +1,5 @@ - + From f6152c6b78ff4cd317ea68250d2e551dc4aa9b53 Mon Sep 17 00:00:00 2001 From: John Chilton Date: Wed, 25 Jun 2014 08:01:52 -0500 Subject: [PATCH 05/69] Add documentation about local runner destination option embed_metadata_in_job. --- job_conf.xml.sample_advanced | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/job_conf.xml.sample_advanced b/job_conf.xml.sample_advanced index ad14177b546..ffbb03cdb8c 100644 --- a/job_conf.xml.sample_advanced +++ b/job_conf.xml.sample_advanced @@ -102,6 +102,12 @@ + True + + + server + data_source.py $output $__app__.config.output_size_limit + + go to Flymine server $GALAXY_URL + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/data_source/flymine_test.xml b/tools/data_source/flymine_test.xml new file mode 100644 index 00000000000..f66259c694c --- /dev/null +++ b/tools/data_source/flymine_test.xml @@ -0,0 +1,31 @@ + + + + server + data_source.py $output $__app__.config.output_size_limit + + go to Flymine server $GALAXY_URL + + + + + + + + + + + + + + + + + + + + diff --git a/tools/data_source/metabolicmine.xml b/tools/data_source/metabolicmine.xml new file mode 100644 index 00000000000..206bb4aa33b --- /dev/null +++ b/tools/data_source/metabolicmine.xml @@ -0,0 +1,13 @@ + + + server + data_source.py $output $__app__.config.output_size_limit + + go to metabolicMine server $GALAXY_URL + + + + + + + diff --git a/tools/data_source/modmine.xml b/tools/data_source/modmine.xml new file mode 100644 index 00000000000..0d5b043dad1 --- /dev/null +++ b/tools/data_source/modmine.xml @@ -0,0 +1,19 @@ + + + + server + data_source.py $output $__app__.config.output_size_limit + + go to modENCODE modMine server $GALAXY_URL + + + + + + + + diff --git a/tools/data_source/mousemine.xml b/tools/data_source/mousemine.xml new file mode 100644 index 00000000000..e372d0d10f9 --- /dev/null +++ b/tools/data_source/mousemine.xml @@ -0,0 +1,35 @@ + + + + server + data_source.py $output $__app__.config.output_size_limit + + go to MouseMine server $GALAXY_URL + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/data_source/ratmine.xml b/tools/data_source/ratmine.xml new file mode 100644 index 00000000000..7ef3c69ef5d --- /dev/null +++ b/tools/data_source/ratmine.xml @@ -0,0 +1,34 @@ + + + + server + data_source.py $output $__app__.config.output_size_limit + + go to Ratmine server $GALAXY_URL + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/data_source/yeastmine.xml b/tools/data_source/yeastmine.xml new file mode 100644 index 00000000000..9c82ca39364 --- /dev/null +++ b/tools/data_source/yeastmine.xml @@ -0,0 +1,20 @@ + + + server + data_source.py $output $__app__.config.output_size_limit + + go to yeastMine server $GALAXY_URL + + + + + + + + + + + + + + From 6a7f871a236a867c9b5749469b79b101a331fa60 Mon Sep 17 00:00:00 2001 From: Daniel Blankenberg Date: Fri, 27 Jun 2014 14:44:55 -0400 Subject: [PATCH 18/69] Re-add InterMine tools removed in 401ee23dcf2f70d4be0e975bb3e00a43ae1dfdd0. --- tool_conf.xml.main | 5 +++++ tool_conf.xml.sample | 7 ++++++ tools/data_source/flymine.xml | 35 +++++++++++++++++++++++++++++ tools/data_source/flymine_test.xml | 31 +++++++++++++++++++++++++ tools/data_source/metabolicmine.xml | 13 +++++++++++ tools/data_source/modmine.xml | 19 ++++++++++++++++ tools/data_source/mousemine.xml | 35 +++++++++++++++++++++++++++++ tools/data_source/ratmine.xml | 34 ++++++++++++++++++++++++++++ tools/data_source/yeastmine.xml | 20 +++++++++++++++++ 9 files changed, 199 insertions(+) create mode 100644 tools/data_source/flymine.xml create mode 100644 tools/data_source/flymine_test.xml create mode 100644 tools/data_source/metabolicmine.xml create mode 100644 tools/data_source/modmine.xml create mode 100644 tools/data_source/mousemine.xml create mode 100644 tools/data_source/ratmine.xml create mode 100644 tools/data_source/yeastmine.xml diff --git a/tool_conf.xml.main b/tool_conf.xml.main index 485b9b16576..5c66e2c0ffa 100644 --- a/tool_conf.xml.main +++ b/tool_conf.xml.main @@ -7,7 +7,12 @@ + + + + + diff --git a/tool_conf.xml.sample b/tool_conf.xml.sample index 447b73b7268..76f4187f613 100644 --- a/tool_conf.xml.sample +++ b/tool_conf.xml.sample @@ -12,6 +12,13 @@ + + + + + + + diff --git a/tools/data_source/flymine.xml b/tools/data_source/flymine.xml new file mode 100644 index 00000000000..cb9253ab157 --- /dev/null +++ b/tools/data_source/flymine.xml @@ -0,0 +1,35 @@ + + + + server + data_source.py $output $__app__.config.output_size_limit + + go to Flymine server $GALAXY_URL + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/data_source/flymine_test.xml b/tools/data_source/flymine_test.xml new file mode 100644 index 00000000000..f66259c694c --- /dev/null +++ b/tools/data_source/flymine_test.xml @@ -0,0 +1,31 @@ + + + + server + data_source.py $output $__app__.config.output_size_limit + + go to Flymine server $GALAXY_URL + + + + + + + + + + + + + + + + + + + + diff --git a/tools/data_source/metabolicmine.xml b/tools/data_source/metabolicmine.xml new file mode 100644 index 00000000000..206bb4aa33b --- /dev/null +++ b/tools/data_source/metabolicmine.xml @@ -0,0 +1,13 @@ + + + server + data_source.py $output $__app__.config.output_size_limit + + go to metabolicMine server $GALAXY_URL + + + + + + + diff --git a/tools/data_source/modmine.xml b/tools/data_source/modmine.xml new file mode 100644 index 00000000000..0d5b043dad1 --- /dev/null +++ b/tools/data_source/modmine.xml @@ -0,0 +1,19 @@ + + + + server + data_source.py $output $__app__.config.output_size_limit + + go to modENCODE modMine server $GALAXY_URL + + + + + + + + diff --git a/tools/data_source/mousemine.xml b/tools/data_source/mousemine.xml new file mode 100644 index 00000000000..e372d0d10f9 --- /dev/null +++ b/tools/data_source/mousemine.xml @@ -0,0 +1,35 @@ + + + + server + data_source.py $output $__app__.config.output_size_limit + + go to MouseMine server $GALAXY_URL + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/data_source/ratmine.xml b/tools/data_source/ratmine.xml new file mode 100644 index 00000000000..7ef3c69ef5d --- /dev/null +++ b/tools/data_source/ratmine.xml @@ -0,0 +1,34 @@ + + + + server + data_source.py $output $__app__.config.output_size_limit + + go to Ratmine server $GALAXY_URL + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/data_source/yeastmine.xml b/tools/data_source/yeastmine.xml new file mode 100644 index 00000000000..9c82ca39364 --- /dev/null +++ b/tools/data_source/yeastmine.xml @@ -0,0 +1,20 @@ + + + server + data_source.py $output $__app__.config.output_size_limit + + go to yeastMine server $GALAXY_URL + + + + + + + + + + + + + + From b9389cc76d872b3c0c8092f950f84d88b56af5c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gr=C3=BCning?= Date: Fri, 27 Jun 2014 22:21:37 +0000 Subject: [PATCH 19/69] Add empty_field validator to gtf2bedgraph.xml --- tools/filters/gtf2bedgraph.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/filters/gtf2bedgraph.xml b/tools/filters/gtf2bedgraph.xml index 1ff85b8254d..a6da4016f8b 100644 --- a/tools/filters/gtf2bedgraph.xml +++ b/tools/filters/gtf2bedgraph.xml @@ -3,7 +3,9 @@ gtf_to_bedgraph_converter.py $input $out_file1 $attribute_name - + + + From 5578ae2186315876991c3790eebc2a00dd22eaf1 Mon Sep 17 00:00:00 2001 From: Christopher Bare Date: Sat, 28 Jun 2014 15:55:15 -0400 Subject: [PATCH 20/69] use galaxy.util.json rather than json from the python libraries --- lib/galaxy/util/__init__.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/galaxy/util/__init__.py b/lib/galaxy/util/__init__.py index d62f5cd8643..9d2c6f2926b 100644 --- a/lib/galaxy/util/__init__.py +++ b/lib/galaxy/util/__init__.py @@ -10,7 +10,6 @@ import binascii import collections import errno import grp -import json import logging import os import pickle @@ -24,6 +23,9 @@ import sys import tempfile import threading +# note: this imports galaxy.util.json +import json + from email.MIMEText import MIMEText from os.path import relpath @@ -312,8 +314,8 @@ def shrink_string_by_size( value, size, join_by="..", left_larger=True, beginnin def pretty_print_json(json_data, is_json_string=False): if is_json_string: - json_data = json.loads(json_data) - return json.dumps(json_data, sort_keys=True, indent=4 * ' ') + json_data = json.from_json_string(json_data) + return json.to_json_string(json_data, sort_keys=True, indent=4) # characters that are valid valid_chars = set(string.letters + string.digits + " -=_.()/+*^,:?!") From d2f3ee46f4bd6250584f9ec70e7d279d9770fe9f Mon Sep 17 00:00:00 2001 From: Ilya Sytchev Date: Sat, 28 Jun 2014 17:57:06 -0400 Subject: [PATCH 21/69] Enable stopping jobs when history is deleted via the API. --- lib/galaxy/webapps/galaxy/api/histories.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/galaxy/webapps/galaxy/api/histories.py b/lib/galaxy/webapps/galaxy/api/histories.py index cd4600b7adb..e2bbdbc6bb6 100644 --- a/lib/galaxy/webapps/galaxy/api/histories.py +++ b/lib/galaxy/webapps/galaxy/api/histories.py @@ -235,6 +235,10 @@ class HistoriesController( BaseAPIController, UsesHistoryMixin, UsesTagsMixin, for hda in history.datasets: if hda.purged: continue + if hda.creating_job_associations: + job = hda.creating_job_associations[0].job + job.mark_deleted( self.app.config.track_jobs_in_database ) + self.app.job_manager.job_stop_queue.put( job.id ) hda.purged = True trans.sa_session.add( hda ) trans.sa_session.flush() From 03bd87adbf78e0ecc6ea2aabbeb4e0fe7044620a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gr=C3=BCning?= Date: Sun, 29 Jun 2014 14:25:44 +0000 Subject: [PATCH 22/69] Fix some spelling mistake and hopefully all of the install_*_environments. --- lib/tool_shed/galaxy_install/install_manager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/tool_shed/galaxy_install/install_manager.py b/lib/tool_shed/galaxy_install/install_manager.py index 751b9cded3c..a87045d532c 100644 --- a/lib/tool_shed/galaxy_install/install_manager.py +++ b/lib/tool_shed/galaxy_install/install_manager.py @@ -44,8 +44,8 @@ class InstallToolDependencyManager( object ): def __init__( self, app ): self.app = app - self.INSTALL_ACTIONS = [ 'download_binary', 'download_by_url', 'download_file', 'setup_perl_environmnet', - 'setup_r_environmnet', 'setup_ruby_environmnet', 'shell_command' ] + self.INSTALL_ACTIONS = [ 'download_binary', 'download_by_url', 'download_file', 'setup_perl_environment', + 'setup_r_environment', 'setup_ruby_environent', 'shell_command' ] def format_traceback( self ): ex_type, ex, tb = sys.exc_info() From 027552edd99c1aeadf0b8ab684d625e53f96dd3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gr=C3=BCning?= Date: Sun, 29 Jun 2014 14:28:13 +0000 Subject: [PATCH 23/69] Fix some spelling mistake and hopefully all of the install_*_environments. --- lib/tool_shed/galaxy_install/install_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tool_shed/galaxy_install/install_manager.py b/lib/tool_shed/galaxy_install/install_manager.py index a87045d532c..95e3bdd44cc 100644 --- a/lib/tool_shed/galaxy_install/install_manager.py +++ b/lib/tool_shed/galaxy_install/install_manager.py @@ -45,7 +45,7 @@ class InstallToolDependencyManager( object ): def __init__( self, app ): self.app = app self.INSTALL_ACTIONS = [ 'download_binary', 'download_by_url', 'download_file', 'setup_perl_environment', - 'setup_r_environment', 'setup_ruby_environent', 'shell_command' ] + 'setup_r_environment', 'setup_ruby_environment', 'shell_command' ] def format_traceback( self ): ex_type, ex, tb = sys.exc_info() From a2c50e02ec182ecb7948918b7143db17d97454df Mon Sep 17 00:00:00 2001 From: Bjoern Gruening Date: Sun, 29 Jun 2014 20:19:03 +0200 Subject: [PATCH 24/69] Add new install_python_environment installation tag to the Tool Shed. It can be used like the following example: https://pypi.python.org/packages/source/d/deepTools/deepTools-1.5.8.tar.gz kMer-0.2.0.tar.gz Currently, you can specify one URL to a tarball or a name to a locally shiped tarball. Important: The underlying easy_install will skip all dependencies. The Tool Author need to specify every dependency explicitly. Test repository can be found on the Test Tool Shed: https://testtoolshed.g2.bx.psu.edu/view/bgruening/test_repository_setup_python_environment https://testtoolshed.g2.bx.psu.edu/view/bgruening/test_repository_setup_python_environment_with_python3 --- .../galaxy_install/install_manager.py | 3 +- .../tool_dependencies/env_manager.py | 2 +- .../recipe/recipe_manager.py | 1 + .../tool_dependencies/recipe/step_handler.py | 134 ++++++++++++++++++ 4 files changed, 138 insertions(+), 2 deletions(-) diff --git a/lib/tool_shed/galaxy_install/install_manager.py b/lib/tool_shed/galaxy_install/install_manager.py index 95e3bdd44cc..e38a97007c0 100644 --- a/lib/tool_shed/galaxy_install/install_manager.py +++ b/lib/tool_shed/galaxy_install/install_manager.py @@ -44,7 +44,8 @@ class InstallToolDependencyManager( object ): def __init__( self, app ): self.app = app - self.INSTALL_ACTIONS = [ 'download_binary', 'download_by_url', 'download_file', 'setup_perl_environment', + self.INSTALL_ACTIONS = [ 'download_binary', 'download_by_url', 'download_file', + 'setup_perl_environment', 'setup_python_environment', 'setup_r_environment', 'setup_ruby_environment', 'shell_command' ] def format_traceback( self ): diff --git a/lib/tool_shed/galaxy_install/tool_dependencies/env_manager.py b/lib/tool_shed/galaxy_install/tool_dependencies/env_manager.py index 096cba8404b..c896a57a196 100644 --- a/lib/tool_shed/galaxy_install/tool_dependencies/env_manager.py +++ b/lib/tool_shed/galaxy_install/tool_dependencies/env_manager.py @@ -124,7 +124,7 @@ class EnvManager( object ): Parse an XML tag set to discover all child repository dependency tags and define the path to an env.sh file associated with the repository (this requires the repository dependency to be in an installed state). The received action_dict will be updated with these discovered paths and returned to the caller. This method handles tool dependency definition - tag sets , and . + tag sets , , and . """ # An example elem is: # diff --git a/lib/tool_shed/galaxy_install/tool_dependencies/recipe/recipe_manager.py b/lib/tool_shed/galaxy_install/tool_dependencies/recipe/recipe_manager.py index 46d691b4324..92216e91df5 100644 --- a/lib/tool_shed/galaxy_install/tool_dependencies/recipe/recipe_manager.py +++ b/lib/tool_shed/galaxy_install/tool_dependencies/recipe/recipe_manager.py @@ -54,6 +54,7 @@ class StepManager( object ): setup_perl_environment=step_handler.SetupPerlEnvironment( self.app ), setup_r_environment=step_handler.SetupREnvironment( self.app ), setup_ruby_environment=step_handler.SetupRubyEnvironment( self.app ), + setup_python_environment=step_handler.SetupPythonEnvironment( self.app ), setup_virtualenv=step_handler.SetupVirtualEnv( self.app ), shell_command=step_handler.ShellCommand( self.app ), template_command=step_handler.TemplateCommand( self.app ) ) diff --git a/lib/tool_shed/galaxy_install/tool_dependencies/recipe/step_handler.py b/lib/tool_shed/galaxy_install/tool_dependencies/recipe/step_handler.py index 0acfd365574..5ff98efc761 100644 --- a/lib/tool_shed/galaxy_install/tool_dependencies/recipe/step_handler.py +++ b/lib/tool_shed/galaxy_install/tool_dependencies/recipe/step_handler.py @@ -1390,6 +1390,140 @@ class SetupRubyEnvironment( Download, RecipeStep ): return action_dict +class SetupPythonEnvironment( Download, RecipeStep ): + + def __init__( self, app ): + self.app = app + self.type = 'setup_python_environment' + + def execute_step( self, tool_dependency, package_name, actions, action_dict, filtered_actions, env_file_builder, + install_environment, work_dir, current_dir=None, initial_download=False ): + """ + Initialize the environment for installing Python packages. The class is called during the initial + download stage when installing packages, so the value of initial_download will generally be True. + However, the parameter value allows this class to also be used in the second stage of the installation, + although it may never be necessary. If initial_download is True, the recipe steps will be filtered + and returned and the installation directory (i.e., dir) will be defined and returned. If we're not + in the initial download stage, these actions will not occur, and None values will be returned for them. + + Warning: easy_install is configured that it will not be install any dependency, the tool developer needs + to specify every dependency explicitly + """ + # + # + # + # + # + # pysam.tar.gz + # http://url-to-some-python-package.de/pysam.tar.gz + # + dir = None + if initial_download: + filtered_actions = actions[ 1: ] + env_shell_file_paths = action_dict.get( 'env_shell_file_paths', None ) + log.debug( '\n%s\n' % env_shell_file_paths ) + if env_shell_file_paths is None: + log.debug( 'Missing Python environment, make sure your specified Python installation exists.' ) + if initial_download: + return tool_dependency, filtered_actions, dir + return tool_dependency, None, None + else: + install_environment.add_env_shell_file_paths( env_shell_file_paths ) + log.debug( 'Handling setup_python_environment for tool dependency %s with install_environment.env_shell_file_paths:\n%s' % \ + ( str( tool_dependency.name ), str( install_environment.env_shell_file_paths ) ) ) + dir = os.path.curdir + current_dir = os.path.abspath( os.path.join( work_dir, dir ) ) + with lcd( current_dir ): + with settings( warn_only=True ): + python_package_tups = action_dict.get( 'python_package_tups', [] ) + for python_package_tup in python_package_tups: + package, package_version = python_package_tup + package_path = os.path.join( install_environment.tool_shed_repository_install_dir, package ) + if os.path.isfile( package_path ): + # we assume a local shipped python package + + cmd = r'''PATH=$PATH:$PYTHONHOME/bin; export PATH; + export PYTHONPATH=$PYTHONPATH:$INSTALL_DIR; + easy_install --no-deps --install-dir $INSTALL_DIR --script-dir $INSTALL_DIR/bin %s + ''' % ( package_path ) + elif package.find( '://' ) != -1: + # We assume a URL to a python package. + url = package + package_name = url.split( '/' )[ -1 ] + self.url_download( work_dir, package_name, url, extract=False ) + + cmd = r'''PATH=$PATH:$PYTHONHOME/bin; export PATH; + export PYTHONPATH=$PYTHONPATH:$INSTALL_DIR; + easy_install --no-deps --install-dir $INSTALL_DIR --script-dir $INSTALL_DIR/bin %s + ''' % ( package_name ) + else: + pass + # pypi can be implemented or for > python3.4 we can use the build-in system + cmd = install_environment.build_command( basic_util.evaluate_template( cmd, install_environment ) ) + return_code = install_environment.handle_command( tool_dependency=tool_dependency, + cmd=cmd, + return_output=False ) + if return_code: + if initial_download: + return tool_dependency, filtered_actions, dir + return tool_dependency, None, None + # Pull in python dependencies (runtime). + env_file_builder.handle_action_shell_file_paths( action_dict ) + env_file_builder.append_line( name="PYTHONPATH", + action="prepend_to", + value= os.path.join( install_environment.install_dir, 'lib', 'python') ) + env_file_builder.append_line( name="PATH", + action="prepend_to", + value=os.path.join( install_environment.install_dir, 'bin' ) ) + return_code = env_file_builder.return_code + if return_code: + if initial_download: + return tool_dependency, filtered_actions, dir + return tool_dependency, None, None + if initial_download: + return tool_dependency, filtered_actions, dir + return tool_dependency, None, None + + def prepare_step( self, tool_dependency, action_elem, action_dict, install_environment, is_binary_download ): + # setup a Python environment. + # + # + # + # + # + # pysam.tar.gz + # http://url-to-some-python-package.de/pysam.tar.gz + # + # Discover all child repository dependency tags and define the path to an env.sh file + # associated with each repository. This will potentially update the value of the + # 'env_shell_file_paths' entry in action_dict. + all_env_shell_file_paths = [] + env_manager = EnvManager( self.app ) + action_dict = env_manager.get_env_shell_file_paths_from_setup_environment_elem( all_env_shell_file_paths, + action_elem, + action_dict ) + python_package_tups = [] + for env_elem in action_elem: + if env_elem.tag == 'package': + #A valid package definitions can be: + # pysam.tar.gz -> locally shipped tarball + # ftp://ftp.gruening.de/pysam.tar.gz -> online tarball + python_token = env_elem.text.strip().split( '=' ) + if len( python_token ) == 2: + # version string + package_name = python_token[ 0 ] + package_version = python_token[ 1 ] + python_package_tups.append( ( package_name, package_version ) ) + else: + # package name for pypi.org without version number + package = env_elem.text.strip() + python_package_tups.append( ( package, None ) ) + if python_package_tups: + action_dict[ 'python_package_tups' ] = python_package_tups + return action_dict + + + class SetupVirtualEnv( Download, RecipeStep ): def __init__( self, app ): From 2fb72ed65b3915b88054ee257203b638193b4713 Mon Sep 17 00:00:00 2001 From: John Chilton Date: Sun, 29 Jun 2014 13:24:32 -0500 Subject: [PATCH 25/69] Spelling fix in method name. --- lib/galaxy/tools/__init__.py | 2 +- lib/galaxy/tools/parameters/output_collect.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/galaxy/tools/__init__.py b/lib/galaxy/tools/__init__.py index fe0cc040b1a..6090f849348 100755 --- a/lib/galaxy/tools/__init__.py +++ b/lib/galaxy/tools/__init__.py @@ -2874,7 +2874,7 @@ class Tool( object, Dictifiable ): Find any additional datasets generated by a tool and attach (for cases where number of outputs is not known in advance). """ - return output_collect.collect_primary_datatasets( self, output, job_working_directory ) + return output_collect.collect_primary_datasets( self, output, job_working_directory ) def to_dict( self, trans, link_details=False, io_details=False ): """ Returns dict of tool. """ diff --git a/lib/galaxy/tools/parameters/output_collect.py b/lib/galaxy/tools/parameters/output_collect.py index 5fb8a9eeb71..b3e11b96152 100644 --- a/lib/galaxy/tools/parameters/output_collect.py +++ b/lib/galaxy/tools/parameters/output_collect.py @@ -14,7 +14,7 @@ DATASET_ID_TOKEN = "DATASET_ID" DEFAULT_EXTRA_FILENAME_PATTERN = r"primary_DATASET_ID_(?P[^_]+)_(?P[^_]+)_(?P[^_]+)(_(?P[^_]+))?" -def collect_primary_datatasets( tool, output, job_working_directory ): +def collect_primary_datasets( tool, output, job_working_directory ): app = tool.app sa_session = tool.sa_session new_primary_datasets = {} From 9ac1b7dd45df0eb6e3bac49f89bbef35237fec63 Mon Sep 17 00:00:00 2001 From: John Chilton Date: Sun, 29 Jun 2014 13:24:32 -0500 Subject: [PATCH 26/69] Allow discovered datasets to use input data format in 'ext' definition. --- lib/galaxy/jobs/__init__.py | 9 ++++++++- lib/galaxy/tools/__init__.py | 4 ++-- lib/galaxy/tools/parameters/output_collect.py | 4 +++- test/functional/tools/multi_output_configured.xml | 12 ++++++++++-- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/lib/galaxy/jobs/__init__.py b/lib/galaxy/jobs/__init__.py index e9d06a87242..e9fb332a8c7 100644 --- a/lib/galaxy/jobs/__init__.py +++ b/lib/galaxy/jobs/__init__.py @@ -1065,6 +1065,13 @@ class JobWrapper( object ): out_data = dict( [ ( da.name, da.dataset ) for da in job.output_datasets ] ) inp_data.update( [ ( da.name, da.dataset ) for da in job.input_library_datasets ] ) out_data.update( [ ( da.name, da.dataset ) for da in job.output_library_datasets ] ) + input_ext = 'data' + for _, data in inp_data.items(): + # For loop odd, but sort simulating behavior in galaxy.tools.actions + if not data: + continue + input_ext = data.ext + param_dict = dict( [ ( p.name, p.value ) for p in job.parameters ] ) # why not re-use self.param_dict here? ##dunno...probably should, this causes tools.parameters.basic.UnvalidatedValue to be used in following methods instead of validated and transformed values during i.e. running workflows param_dict = self.tool.params_from_strings( param_dict, self.app ) # Check for and move associated_files @@ -1075,7 +1082,7 @@ class JobWrapper( object ): # Create generated output children and primary datasets and add to param_dict collected_datasets = { 'children': self.tool.collect_child_datasets(out_data, self.working_directory), - 'primary': self.tool.collect_primary_datasets(out_data, self.working_directory) + 'primary': self.tool.collect_primary_datasets(out_data, self.working_directory, input_ext) } param_dict.update({'__collected_datasets__': collected_datasets}) # Certain tools require tasks to be completed after job execution diff --git a/lib/galaxy/tools/__init__.py b/lib/galaxy/tools/__init__.py index 6090f849348..d7f9aecff6f 100755 --- a/lib/galaxy/tools/__init__.py +++ b/lib/galaxy/tools/__init__.py @@ -2869,12 +2869,12 @@ class Tool( object, Dictifiable ): self.sa_session.flush() return children - def collect_primary_datasets( self, output, job_working_directory ): + def collect_primary_datasets( self, output, job_working_directory, input_ext ): """ Find any additional datasets generated by a tool and attach (for cases where number of outputs is not known in advance). """ - return output_collect.collect_primary_datasets( self, output, job_working_directory ) + return output_collect.collect_primary_datasets( self, output, job_working_directory, input_ext ) def to_dict( self, trans, link_details=False, io_details=False ): """ Returns dict of tool. """ diff --git a/lib/galaxy/tools/parameters/output_collect.py b/lib/galaxy/tools/parameters/output_collect.py index b3e11b96152..fe2a6273e50 100644 --- a/lib/galaxy/tools/parameters/output_collect.py +++ b/lib/galaxy/tools/parameters/output_collect.py @@ -14,7 +14,7 @@ DATASET_ID_TOKEN = "DATASET_ID" DEFAULT_EXTRA_FILENAME_PATTERN = r"primary_DATASET_ID_(?P[^_]+)_(?P[^_]+)_(?P[^_]+)(_(?P[^_]+))?" -def collect_primary_datasets( tool, output, job_working_directory ): +def collect_primary_datasets( tool, output, job_working_directory, input_ext ): app = tool.app sa_session = tool.sa_session new_primary_datasets = {} @@ -66,6 +66,8 @@ def collect_primary_datasets( tool, output, job_working_directory ): designation = fields_match.designation visible = fields_match.visible ext = fields_match.ext + if ext == "input": + ext = input_ext dbkey = fields_match.dbkey # Create new primary dataset primary_data = app.model.HistoryDatasetAssociation( extension=ext, diff --git a/test/functional/tools/multi_output_configured.xml b/test/functional/tools/multi_output_configured.xml index 7b28a3fe1d1..3e8d6de0b76 100644 --- a/test/functional/tools/multi_output_configured.xml +++ b/test/functional/tools/multi_output_configured.xml @@ -8,19 +8,24 @@ echo "1" > subdir2/CUSTOM_1.txt; echo "2" > subdir2/CUSTOM_2.tabular; echo "3" > subdir2/CUSTOM_3.txt; + mkdir subdir3; + echo "Foo" > subdir3/Foo; - + + + - + + @@ -37,6 +42,9 @@ + + + From 3982a6ae54c999aebe4abc67db490e4ab4179b0c Mon Sep 17 00:00:00 2001 From: John Chilton Date: Sun, 29 Jun 2014 13:31:33 -0500 Subject: [PATCH 27/69] Spelling fix in method name. --- lib/galaxy/tools/__init__.py | 2 +- lib/galaxy/tools/parameters/output_collect.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/galaxy/tools/__init__.py b/lib/galaxy/tools/__init__.py index 10a9b2b217d..2610c39c27d 100755 --- a/lib/galaxy/tools/__init__.py +++ b/lib/galaxy/tools/__init__.py @@ -2931,7 +2931,7 @@ class Tool( object, Dictifiable ): Find any additional datasets generated by a tool and attach (for cases where number of outputs is not known in advance). """ - return output_collect.collect_primary_datatasets( self, output, job_working_directory ) + return output_collect.collect_primary_datasets( self, output, job_working_directory ) def to_dict( self, trans, link_details=False, io_details=False ): """ Returns dict of tool. """ diff --git a/lib/galaxy/tools/parameters/output_collect.py b/lib/galaxy/tools/parameters/output_collect.py index 5fb8a9eeb71..b3e11b96152 100644 --- a/lib/galaxy/tools/parameters/output_collect.py +++ b/lib/galaxy/tools/parameters/output_collect.py @@ -14,7 +14,7 @@ DATASET_ID_TOKEN = "DATASET_ID" DEFAULT_EXTRA_FILENAME_PATTERN = r"primary_DATASET_ID_(?P[^_]+)_(?P[^_]+)_(?P[^_]+)(_(?P[^_]+))?" -def collect_primary_datatasets( tool, output, job_working_directory ): +def collect_primary_datasets( tool, output, job_working_directory ): app = tool.app sa_session = tool.sa_session new_primary_datasets = {} From 3020dcd037a1d6cce74199fc3dc4f8b7e3cbed66 Mon Sep 17 00:00:00 2001 From: John Chilton Date: Sun, 29 Jun 2014 13:31:33 -0500 Subject: [PATCH 28/69] Allow discovered datasets to use input data format in 'ext' definition. --- lib/galaxy/jobs/__init__.py | 9 ++++++++- lib/galaxy/tools/__init__.py | 4 ++-- lib/galaxy/tools/parameters/output_collect.py | 4 +++- test/functional/tools/multi_output_configured.xml | 12 ++++++++++-- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/lib/galaxy/jobs/__init__.py b/lib/galaxy/jobs/__init__.py index b1f8e444e74..d654ba8bbe0 100644 --- a/lib/galaxy/jobs/__init__.py +++ b/lib/galaxy/jobs/__init__.py @@ -1181,6 +1181,13 @@ class JobWrapper( object ): out_data = dict( [ ( da.name, da.dataset ) for da in job.output_datasets ] ) inp_data.update( [ ( da.name, da.dataset ) for da in job.input_library_datasets ] ) out_data.update( [ ( da.name, da.dataset ) for da in job.output_library_datasets ] ) + input_ext = 'data' + for _, data in inp_data.items(): + # For loop odd, but sort simulating behavior in galaxy.tools.actions + if not data: + continue + input_ext = data.ext + param_dict = dict( [ ( p.name, p.value ) for p in job.parameters ] ) # why not re-use self.param_dict here? ##dunno...probably should, this causes tools.parameters.basic.UnvalidatedValue to be used in following methods instead of validated and transformed values during i.e. running workflows param_dict = self.tool.params_from_strings( param_dict, self.app ) # Check for and move associated_files @@ -1191,7 +1198,7 @@ class JobWrapper( object ): # Create generated output children and primary datasets and add to param_dict collected_datasets = { 'children': self.tool.collect_child_datasets(out_data, self.working_directory), - 'primary': self.tool.collect_primary_datasets(out_data, self.working_directory) + 'primary': self.tool.collect_primary_datasets(out_data, self.working_directory, input_ext) } param_dict.update({'__collected_datasets__': collected_datasets}) # Certain tools require tasks to be completed after job execution diff --git a/lib/galaxy/tools/__init__.py b/lib/galaxy/tools/__init__.py index 2610c39c27d..275f40a12a3 100755 --- a/lib/galaxy/tools/__init__.py +++ b/lib/galaxy/tools/__init__.py @@ -2926,12 +2926,12 @@ class Tool( object, Dictifiable ): self.sa_session.flush() return children - def collect_primary_datasets( self, output, job_working_directory ): + def collect_primary_datasets( self, output, job_working_directory, input_ext ): """ Find any additional datasets generated by a tool and attach (for cases where number of outputs is not known in advance). """ - return output_collect.collect_primary_datasets( self, output, job_working_directory ) + return output_collect.collect_primary_datasets( self, output, job_working_directory, input_ext ) def to_dict( self, trans, link_details=False, io_details=False ): """ Returns dict of tool. """ diff --git a/lib/galaxy/tools/parameters/output_collect.py b/lib/galaxy/tools/parameters/output_collect.py index b3e11b96152..fe2a6273e50 100644 --- a/lib/galaxy/tools/parameters/output_collect.py +++ b/lib/galaxy/tools/parameters/output_collect.py @@ -14,7 +14,7 @@ DATASET_ID_TOKEN = "DATASET_ID" DEFAULT_EXTRA_FILENAME_PATTERN = r"primary_DATASET_ID_(?P[^_]+)_(?P[^_]+)_(?P[^_]+)(_(?P[^_]+))?" -def collect_primary_datasets( tool, output, job_working_directory ): +def collect_primary_datasets( tool, output, job_working_directory, input_ext ): app = tool.app sa_session = tool.sa_session new_primary_datasets = {} @@ -66,6 +66,8 @@ def collect_primary_datasets( tool, output, job_working_directory ): designation = fields_match.designation visible = fields_match.visible ext = fields_match.ext + if ext == "input": + ext = input_ext dbkey = fields_match.dbkey # Create new primary dataset primary_data = app.model.HistoryDatasetAssociation( extension=ext, diff --git a/test/functional/tools/multi_output_configured.xml b/test/functional/tools/multi_output_configured.xml index 7b28a3fe1d1..3e8d6de0b76 100644 --- a/test/functional/tools/multi_output_configured.xml +++ b/test/functional/tools/multi_output_configured.xml @@ -8,19 +8,24 @@ echo "1" > subdir2/CUSTOM_1.txt; echo "2" > subdir2/CUSTOM_2.tabular; echo "3" > subdir2/CUSTOM_3.txt; + mkdir subdir3; + echo "Foo" > subdir3/Foo; - + + + - + + @@ -37,6 +42,9 @@ + + + From efe577dfb54782f5e789ce178cd56265594f538a Mon Sep 17 00:00:00 2001 From: Bjoern Gruening Date: Sun, 29 Jun 2014 21:35:02 +0200 Subject: [PATCH 29/69] With that PR the Tool Shed will be able to get checksums from the Tool Developer. These checksums will be verified after download and in case of an mismatch an error is thrown. Currently, md5 and sha256 checksums are supported. Example: https://pypi.python.org/packages/source/k/khmer/khmer-1.0.tar.gz#md5=b60639a8b2939836f66495b9a88df757 --- .../tool_dependencies/recipe/step_handler.py | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/lib/tool_shed/galaxy_install/tool_dependencies/recipe/step_handler.py b/lib/tool_shed/galaxy_install/tool_dependencies/recipe/step_handler.py index 5ff98efc761..7fc95fb1bc3 100644 --- a/lib/tool_shed/galaxy_install/tool_dependencies/recipe/step_handler.py +++ b/lib/tool_shed/galaxy_install/tool_dependencies/recipe/step_handler.py @@ -8,6 +8,7 @@ import tarfile import time import urllib2 import zipfile +import hashlib from galaxy.util import asbool from galaxy.util.template import fill_template @@ -139,10 +140,29 @@ class CompressedFile( object ): class Download( object ): def url_download( self, install_dir, downloaded_file_name, download_url, extract=True ): + """ + The given download_url can have an extension like #md5# or #sha256#. + This indicates a checksum which will be chekced after download. + If the checksum does not match an exception is thrown. + + https://pypi.python.org/packages/source/k/khmer/khmer-1.0.tar.gz#md5#b60639a8b2939836f66495b9a88df757 + """ + file_path = os.path.join( install_dir, downloaded_file_name ) src = None dst = None + checksum = None + sha256 = False + md5 = False # Set a timer so we don't sit here forever. + + if '#md5#' in download_url: + md5 = True + dowonload_url, checksum = download_url.split('#md5#') + elif '#sha256#' in download_url: + sha256 = True + download_url, checksum = download_url.split('#sha256#') + start_time = time.time() try: src = urllib2.urlopen( download_url ) @@ -166,6 +186,18 @@ class Download( object ): src.close() if dst: dst.close() + + try: + if sha256: + downloaded_checksum = hashlib.sha256(open(file_path, 'rb').read()).hexdigest() + elif md5: + downloaded_checksum = hashlib.md5(open(file_path, 'rb').read()).hexdigest() + + if checksum and downloaded_checksum != checksum: + raise Exception( 'Given checksum does not match with the one from the downloaded file (%s).' % (downloaded_checksum) ) + except Exception, e: + raise + if extract: if tarfile.is_tarfile( file_path ) or ( zipfile.is_zipfile( file_path ) and not file_path.endswith( '.jar' ) ): archive = CompressedFile( file_path ) @@ -174,6 +206,7 @@ class Download( object ): extraction_path = os.path.abspath( install_dir ) else: extraction_path = os.path.abspath( install_dir ) + return extraction_path @@ -1421,7 +1454,6 @@ class SetupPythonEnvironment( Download, RecipeStep ): if initial_download: filtered_actions = actions[ 1: ] env_shell_file_paths = action_dict.get( 'env_shell_file_paths', None ) - log.debug( '\n%s\n' % env_shell_file_paths ) if env_shell_file_paths is None: log.debug( 'Missing Python environment, make sure your specified Python installation exists.' ) if initial_download: From 4a4a09a4888e52432c15024b090bd5f8d5348f8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gr=C3=BCning?= Date: Sun, 29 Jun 2014 20:34:56 +0000 Subject: [PATCH 30/69] spelling fix --- .../galaxy_install/tool_dependencies/recipe/step_handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tool_shed/galaxy_install/tool_dependencies/recipe/step_handler.py b/lib/tool_shed/galaxy_install/tool_dependencies/recipe/step_handler.py index 7fc95fb1bc3..df62967a329 100644 --- a/lib/tool_shed/galaxy_install/tool_dependencies/recipe/step_handler.py +++ b/lib/tool_shed/galaxy_install/tool_dependencies/recipe/step_handler.py @@ -158,7 +158,7 @@ class Download( object ): if '#md5#' in download_url: md5 = True - dowonload_url, checksum = download_url.split('#md5#') + download_url, checksum = download_url.split('#md5#') elif '#sha256#' in download_url: sha256 = True download_url, checksum = download_url.split('#sha256#') From 6a276db5ff2ed8f22f951519ddce6c529ad81e3d Mon Sep 17 00:00:00 2001 From: Aysam Guerler Date: Sun, 29 Jun 2014 20:04:28 -0400 Subject: [PATCH 31/69] Fix popovers --- static/scripts/mvc/ui/ui-popover.js | 2 +- static/scripts/packed/mvc/ui/ui-popover.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/static/scripts/mvc/ui/ui-popover.js b/static/scripts/mvc/ui/ui-popover.js index 0bfb6b091de..c1909ab024a 100644 --- a/static/scripts/mvc/ui/ui-popover.js +++ b/static/scripts/mvc/ui/ui-popover.js @@ -140,7 +140,7 @@ var View = Backbone.View.extend({ // template _template: function(options) { - var tmpl = '
' + + var tmpl = '
' + '
' + '
' + '
' + diff --git a/static/scripts/packed/mvc/ui/ui-popover.js b/static/scripts/packed/mvc/ui/ui-popover.js index b06b276a346..ce25e27ba53 100644 --- a/static/scripts/packed/mvc/ui/ui-popover.js +++ b/static/scripts/packed/mvc/ui/ui-popover.js @@ -1 +1 @@ -define(["utils/utils"],function(a){var b=Backbone.View.extend({optionsDefault:{with_close:true,container:"body",title:null,placement:"top"},visible:false,initialize:function(d){var c=this;this.options=_.defaults(d,this.optionsDefault);this.setElement(this._template(this.options));this.options.container.parent().append(this.$el);if(this.options.with_close){this.$el.find("#close").on("click",function(){c.hide()})}this.uuid=a.uuid();var c=this;$("body").on("mousedown."+this.uuid,function(f){c._hide(f)})},title:function(c){if(c!==undefined){this.$el.find(".popover-title-label").html(c)}},show:function(){this.$el.show();this.visible=true;var c=this._get_placement(this.options.placement);this.$el.css(c)},_get_placement:function(h){var d=this._get_width(this.$el);var j=this.$el.height();var k=this.options.container;var c=this._get_width(k);var f=this._get_height(k);var g=k.position();var i=0;var e=0;if(h=="top"||h=="bottom"){e=g.left-d+(c+d)/2;if(h=="top"){i=g.top-j-5}else{i=g.top+f+5}}return{top:i,left:e}},_get_width:function(c){return c.width()+parseInt(c.css("padding-left"))+parseInt(c.css("padding-right"))},_get_height:function(c){return c.height()+parseInt(c.css("padding-top"))+parseInt(c.css("padding-bottom"))},hide:function(){this.$el.hide();this.visible=false},append:function(c){this.$el.find(".popover-content").append(c)},empty:function(c){this.$el.find(".popover-content").empty()},remove:function(){$("body").off("mousedown."+this.uuid);this.$el.remove()},_hide:function(c){if(!$(this.options.container).is(c.target)&&!$(this.el).is(c.target)&&$(this.el).has(c.target).length===0){this.hide()}},_template:function(d){var c='
'+d.title+"
";if(d.with_close){c+='
'}c+='
';return c}});return{View:b}}); \ No newline at end of file +define(["utils/utils"],function(a){var b=Backbone.View.extend({optionsDefault:{with_close:true,container:"body",title:null,placement:"top"},visible:false,initialize:function(d){var c=this;this.options=_.defaults(d,this.optionsDefault);this.setElement(this._template(this.options));this.options.container.parent().append(this.$el);if(this.options.with_close){this.$el.find("#close").on("click",function(){c.hide()})}this.uuid=a.uuid();var c=this;$("body").on("mousedown."+this.uuid,function(f){c._hide(f)})},title:function(c){if(c!==undefined){this.$el.find(".popover-title-label").html(c)}},show:function(){this.$el.show();this.visible=true;var c=this._get_placement(this.options.placement);this.$el.css(c)},_get_placement:function(h){var d=this._get_width(this.$el);var j=this.$el.height();var k=this.options.container;var c=this._get_width(k);var f=this._get_height(k);var g=k.position();var i=0;var e=0;if(h=="top"||h=="bottom"){e=g.left-d+(c+d)/2;if(h=="top"){i=g.top-j-5}else{i=g.top+f+5}}return{top:i,left:e}},_get_width:function(c){return c.width()+parseInt(c.css("padding-left"))+parseInt(c.css("padding-right"))},_get_height:function(c){return c.height()+parseInt(c.css("padding-top"))+parseInt(c.css("padding-bottom"))},hide:function(){this.$el.hide();this.visible=false},append:function(c){this.$el.find(".popover-content").append(c)},empty:function(c){this.$el.find(".popover-content").empty()},remove:function(){$("body").off("mousedown."+this.uuid);this.$el.remove()},_hide:function(c){if(!$(this.options.container).is(c.target)&&!$(this.el).is(c.target)&&$(this.el).has(c.target).length===0){this.hide()}},_template:function(d){var c='
'+d.title+"
";if(d.with_close){c+='
'}c+='
';return c}});return{View:b}}); \ No newline at end of file From eca5804f1f024882cdb3c7eb2503a0c738d5e38a Mon Sep 17 00:00:00 2001 From: Christopher Bare Date: Sun, 29 Jun 2014 22:47:47 -0400 Subject: [PATCH 32/69] changed import to explicitly import galaxy.util.json based on code review --- lib/galaxy/util/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/galaxy/util/__init__.py b/lib/galaxy/util/__init__.py index 9d2c6f2926b..93b2d60ac14 100644 --- a/lib/galaxy/util/__init__.py +++ b/lib/galaxy/util/__init__.py @@ -23,8 +23,7 @@ import sys import tempfile import threading -# note: this imports galaxy.util.json -import json +from galaxy.util import json from email.MIMEText import MIMEText From 9ba766eb260dc50c199017f4a708e79987fe48d6 Mon Sep 17 00:00:00 2001 From: John Chilton Date: Tue, 1 Jul 2014 07:07:09 -0500 Subject: [PATCH 33/69] Bugfix: Value error when specifying empty docker_volume param. Thanks Andrew Stewart! --- lib/galaxy/tools/deps/containers.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/galaxy/tools/deps/containers.py b/lib/galaxy/tools/deps/containers.py index 0707c0ddea3..cf6e828f513 100644 --- a/lib/galaxy/tools/deps/containers.py +++ b/lib/galaxy/tools/deps/containers.py @@ -204,6 +204,9 @@ class DockerContainer(Container): ) def __expand_str(self, value): + if not value: + return value + template = string.Template(value) variables = dict() From 8f52bfffa24b3ff4db5daebcc864a919086a58d8 Mon Sep 17 00:00:00 2001 From: John Chilton Date: Tue, 1 Jul 2014 07:07:09 -0500 Subject: [PATCH 34/69] Allow Docker destinations to use --volumes-from option. Enables certain kind of Docker-to-Docker job executions. Thanks to Andrew Stewart. --- job_conf.xml.sample_advanced | 5 +++++ lib/galaxy/tools/deps/containers.py | 2 ++ lib/galaxy/tools/deps/docker_util.py | 4 ++++ 3 files changed, 11 insertions(+) diff --git a/job_conf.xml.sample_advanced b/job_conf.xml.sample_advanced index ffbb03cdb8c..e390afbfe26 100644 --- a/job_conf.xml.sample_advanced +++ b/job_conf.xml.sample_advanced @@ -154,6 +154,11 @@ are available to all jobs and $job_directory is also available for Pulsar jobs. --> + + diff --git a/lib/galaxy/tools/deps/containers.py b/lib/galaxy/tools/deps/containers.py index cf6e828f513..d5a823342e4 100644 --- a/lib/galaxy/tools/deps/containers.py +++ b/lib/galaxy/tools/deps/containers.py @@ -190,10 +190,12 @@ class DockerContainer(Container): volumes_raw = self.__expand_str(self.destination_info.get("docker_volumes", "$defaults")) # TODO: Remove redundant volumes... volumes = docker_util.DockerVolume.volumes_from_str(volumes_raw) + volumes_from = self.destination_info.get("docker_volumes_from", docker_util.DEFAULT_VOLUMES_FROM) return docker_util.build_docker_run_command( command, self.container_id, volumes=volumes, + volumes_from=volumes_from, env_directives=env_directives, working_directory=working_directory, docker_cmd=prop("cmd", docker_util.DEFAULT_DOCKER_COMMAND), diff --git a/lib/galaxy/tools/deps/docker_util.py b/lib/galaxy/tools/deps/docker_util.py index 8117ab13322..487bdc8fbb5 100644 --- a/lib/galaxy/tools/deps/docker_util.py +++ b/lib/galaxy/tools/deps/docker_util.py @@ -7,6 +7,7 @@ DEFAULT_VOLUME_MOUNT_TYPE = "rw" DEFAULT_WORKING_DIRECTORY = None DEFAULT_NET = None DEFAULT_MEMORY = None +DEFAULT_VOLUMES_FROM = None class DockerVolume(object): @@ -55,6 +56,7 @@ def build_docker_run_command( tag=None, docker_cmd=DEFAULT_DOCKER_COMMAND, volumes=[], + volumes_from=DEFAULT_VOLUMES_FROM, memory=DEFAULT_MEMORY, env_directives=[], working_directory=DEFAULT_WORKING_DIRECTORY, @@ -75,6 +77,8 @@ def build_docker_run_command( command_parts.extend(["-e", env_directive]) for volume in volumes: command_parts.extend(["-v", str(volume)]) + if volumes_from: + command_parts.extend(["--volumes-from", str(volumes_from)]) if memory: command_parts.extend(["-m", memory]) if name: From 46d9937ff5427bd8181f676bf798770bdb6ef49e Mon Sep 17 00:00:00 2001 From: Jeremy Goecks Date: Tue, 1 Jul 2014 18:27:15 -0400 Subject: [PATCH 35/69] Fixes for Trackster and Circster, mostly around preference selection and usage. --- static/scripts/utils/config.js | 8 ++++---- static/scripts/viz/circster.js | 9 +++++++-- static/scripts/viz/trackster/tracks.js | 3 ++- static/scripts/viz/visualization.js | 2 +- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/static/scripts/utils/config.js b/static/scripts/utils/config.js index e1f1614ad59..db3c4052ede 100644 --- a/static/scripts/utils/config.js +++ b/static/scripts/utils/config.js @@ -32,7 +32,7 @@ var ConfigSetting = Backbone.Model.extend({ * Cast and set value. This should be instead of * setting.set('value', new_value) */ - set_value: function(value) { + set_value: function(value, options) { var type = this.get('type'); if (type === 'float') { @@ -43,7 +43,7 @@ var ConfigSetting = Backbone.Model.extend({ } // TODO: handle casting from string to bool? - this.set('value', value); + this.set({value: value}, options); } }, { // This is a master list of default settings for known settings. @@ -101,10 +101,10 @@ var ConfigSettingCollection = Backbone.Collection.extend({ /** * Set value for a setting. */ - set_value: function(key, value) { + set_value: function(key, value, options) { var s = this.get(key); if (s) { - return s.set_value(value); + return s.set_value(value, options); } return undefined; diff --git a/static/scripts/viz/circster.js b/static/scripts/viz/circster.js index 32362d48fd5..233fee879bd 100644 --- a/static/scripts/viz/circster.js +++ b/static/scripts/viz/circster.js @@ -620,8 +620,13 @@ var CircsterTrackView = Backbone.View.extend({ $.when(track.get('data_manager').get_genome_wide_data(this.genome)).then(function(genome_wide_data) { // Set bounds. self.data_bounds = self.get_data_bounds(genome_wide_data); - track.get('config').set_value('min_value', self.data_bounds[0]); - track.get('config').set_value('max_value', self.data_bounds[1]); + + // Set min, max value in config so that they can be adjusted. Make this silent + // because these attributes are watched for changes and the viz is updated + // accordingly (set up in initialize). Because we are setting up, we don't want + // the watch to trigger events here. + track.get('config').set_value('min_value', self.data_bounds[0], {silent: true}); + track.get('config').set_value('max_value', self.data_bounds[1], {silent: true}); // Merge chroms layout with data. layout_and_data = _.zip(chrom_arcs, genome_wide_data), diff --git a/static/scripts/viz/trackster/tracks.js b/static/scripts/viz/trackster/tracks.js index cb7aa708b73..0fa48e6c52c 100644 --- a/static/scripts/viz/trackster/tracks.js +++ b/static/scripts/viz/trackster/tracks.js @@ -994,7 +994,8 @@ var TracksterView = Backbone.View.extend({ }; })); }); - } + }, + minLength: 2 }); }); if (this.vis_id !== undefined) { diff --git a/static/scripts/viz/visualization.js b/static/scripts/viz/visualization.js index 9b4ad111737..31d2e350602 100644 --- a/static/scripts/viz/visualization.js +++ b/static/scripts/viz/visualization.js @@ -894,7 +894,7 @@ var BackboneTrack = Backbone.Model.extend(CustomToJSON).extend({ // -- Set up config settings. -- var models = [ - { key: 'name', value: this.get('dataset').get('name') }, + { key: 'name', default_value: this.get('dataset').get('name') }, { key: 'color' }, { key: 'min_value', label: 'Min Value', type: 'float', default_value: 0 }, { key: 'max_value', label: 'Max Value', type: 'float', default_value: 1 } From 606dff10890c7e04dcdebba2e010936de6057f93 Mon Sep 17 00:00:00 2001 From: Jeremy Goecks Date: Tue, 1 Jul 2014 18:36:28 -0400 Subject: [PATCH 36/69] Trackster: disable mousewheel scrolling for now until a better usage model can be created. --- static/scripts/viz/trackster/tracks.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/static/scripts/viz/trackster/tracks.js b/static/scripts/viz/trackster/tracks.js index 0fa48e6c52c..24762116041 100644 --- a/static/scripts/viz/trackster/tracks.js +++ b/static/scripts/viz/trackster/tracks.js @@ -1070,6 +1070,11 @@ var TracksterView = Backbone.View.extend({ d.current_x = d.offsetX; var delta_chrom = Math.round(delta / view.viewport_container.width() * (view.high - view.low)); view.move_delta(delta_chrom); + }) + /* + FIXME: Do not do this for now because it's too jittery. Some kind of gravity approach is + needed here because moving left/right should be difficult. + // Also capture mouse wheel for left/right scrolling }).bind( 'mousewheel', function( e, d, dx, dy ) { // Only handle x axis scrolling; y axis scrolling is @@ -1079,6 +1084,7 @@ var TracksterView = Backbone.View.extend({ view.move_delta( delta_chrom ); } }); + */ // Dragging in the top label track allows selecting a region to zoom in on selected region. this.top_labeltrack.bind( "dragstart", function( e, d ) { From 595d737fa87ba9957e660e2b605e4503b9743c6d Mon Sep 17 00:00:00 2001 From: Greg Von Kuster Date: Tue, 1 Jul 2014 21:44:49 -0400 Subject: [PATCH 37/69] Add a very basic framework to the Tool Shed for creating a Galaxy flavor Docker Image that uses Bjoern Gruning's Galaxy Docker project. This is a proof-of-concept that should be enhanced if kept. --- lib/galaxy/webapps/tool_shed/config.py | 2 + .../tool_shed/controllers/repository.py | 57 +++++++++++++++++ lib/tool_shed/grids/repository_grids.py | 20 ++++++ lib/tool_shed/util/basic_util.py | 27 ++++++++ templates/webapps/tool_shed/index.mako | 10 +++ .../repository/docker_image_repositories.mako | 64 +++++++++++++++++++ tool_shed_wsgi.ini.sample | 3 + 7 files changed, 183 insertions(+) create mode 100644 templates/webapps/tool_shed/repository/docker_image_repositories.mako diff --git a/lib/galaxy/webapps/tool_shed/config.py b/lib/galaxy/webapps/tool_shed/config.py index f34a2e49d87..d43437d336a 100644 --- a/lib/galaxy/webapps/tool_shed/config.py +++ b/lib/galaxy/webapps/tool_shed/config.py @@ -65,6 +65,8 @@ class Configuration( object ): self.tool_dependency_dir = None self.use_tool_dependencies = False self.update_integrated_tool_panel = False + # Galaxy flavor Docker Image + self.enable_galaxy_flavor_docker_image = string_as_bool( kwargs.get( "enable_galaxy_flavor_docker_image", "False" ) ) self.use_remote_user = string_as_bool( kwargs.get( "use_remote_user", "False" ) ) self.user_activation_on = kwargs.get( 'user_activation_on', None ) self.activation_grace_period = kwargs.get( 'activation_grace_period', None ) diff --git a/lib/galaxy/webapps/tool_shed/controllers/repository.py b/lib/galaxy/webapps/tool_shed/controllers/repository.py index 912606a256e..f74a723da55 100644 --- a/lib/galaxy/webapps/tool_shed/controllers/repository.py +++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py @@ -55,6 +55,7 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ): datatypes_grid = repository_grids.DatatypesGrid() deprecated_repositories_i_own_grid = repository_grids.DeprecatedRepositoriesIOwnGrid() email_alerts_repository_grid = repository_grids.EmailAlertsRepositoryGrid() + docker_image_grid = repository_grids.DockerImageGrid() install_matched_repository_grid = repository_grids.InstallMatchedRepositoryGrid() matched_repository_grid = repository_grids.MatchedRepositoryGrid() my_writable_repositories_grid = repository_grids.MyWritableRepositoriesGrid() @@ -985,6 +986,62 @@ class RepositoryController( BaseUIController, ratings_util.ItemRatings ): # Do all we can to eliminate spam. return trans.show_error_message( "You must be logged in to contact the owner of a repository." ) + @web.expose + def create_galaxy_docker_image( self, trans, **kwd ): + message = kwd.get( 'message', '' ) + status = kwd.get( 'status', 'done' ) + repository_ids = util.listify( kwd.get( 'id', '' ) ) + if 'operation' in kwd: + if repository_ids: + operation = kwd[ 'operation' ].lower() + if operation == "include in docker image": + repository_tups = [] + for repository_id in repository_ids: + repository = suc.get_repository_by_id( trans.app, repository_id ) + repository_tups.append( ( str( repository.name ), + str( repository.user.username ), + str( repository.type ) ) ) + return trans.fill_template( "/webapps/tool_shed/repository/docker_image_repositories.mako", + id=','.join( repository_ids ), + repository_tups=repository_tups, + message=message, + status=status ) + else: + # This can only occur when there is a multi-select grid with check boxes and an operation, + # and the user clicked the operation button without checking any of the check boxes. + kwd[ 'message' ] = "No items were selected." + kwd[ 'status' ] = 'error' + elif kwd.get( 'create_docker_image_button', False ): + tmp_image_dir = tempfile.mkdtemp( prefix="tmp-toolshed-cdidir" ) + docker_file_name = 'Dockerfile' + docker_file_path = os.path.join( tmp_image_dir, docker_file_name ) + tool_shed_url = tool_shed_url = web.url_for( '/', qualified=True ) + repository_string = '' + for repository_id in repository_ids: + repository = suc.get_repository_by_id( trans.app, repository_id ) + template = basic_util.SELECTED_REPOSITORIES_TEMPLATE + repository_template = \ + string.Template( template ).safe_substitute( tool_shed_url=tool_shed_url, + repository_owner=str( repository.user.username ) , + repository_name=str( repository.name ) ) + repository_string = '%s\n%s' % ( repository_string, repository_template ) + template = basic_util.DOCKER_IMAGE_TEMPLATE + docker_image_template = \ + string.Template( template ).safe_substitute( selected_repositories=repository_string ) + docker_image_string = docker_image_template + trans.response.set_content_type( 'application/text/plain' ) + trans.response.headers[ "Content-Disposition" ] = 'attachment; filename="%s"' % docker_file_name + opened_file = open( docker_file_path, "w" ) + opened_file.write( docker_image_string ) + opened_file.close() + opened_file = open( docker_file_path, "r" ) + # Make sure the file is removed from disk after the contents have been downloaded. + os.unlink( docker_file_path ) + docker_file_path, docker_file_name = os.path.split( docker_file_path ) + basic_util.remove_dir( docker_file_path ) + return opened_file + return self.docker_image_grid( trans, **kwd ) + @web.expose def create_repository( self, trans, **kwd ): message = kwd.get( 'message', '' ) diff --git a/lib/tool_shed/grids/repository_grids.py b/lib/tool_shed/grids/repository_grids.py index 9a5296adadc..d057db038ff 100644 --- a/lib/tool_shed/grids/repository_grids.py +++ b/lib/tool_shed/grids/repository_grids.py @@ -329,6 +329,26 @@ class RepositoryGrid( grids.Grid ): .outerjoin( model.Category.table ) +class DockerImageGrid( RepositoryGrid ): + columns = [ + RepositoryGrid.NameColumn( "Name", + key="name", + link=( lambda item: dict( operation="view_or_manage_repository", id=item.id ) ), + attach_popup=False ), + RepositoryGrid.DescriptionColumn( "Synopsis", + key="description", + attach_popup=False ), + RepositoryGrid.UserColumn( "Owner", + model_class=model.User, + link=( lambda item: dict( operation="repositories_by_user", id=item.id ) ), + attach_popup=False, + key="User.username" ), + RepositoryGrid.EmailAlertsColumn( "Alert", attach_popup=False ), + ] + operations = [ grids.GridOperation( "Include in Docker image", allow_multiple=True ) ] + show_item_checkboxes = True + + class EmailAlertsRepositoryGrid( RepositoryGrid ): columns = [ RepositoryGrid.NameColumn( "Name", diff --git a/lib/tool_shed/util/basic_util.py b/lib/tool_shed/util/basic_util.py index 7d606081ecd..58dbb17e564 100644 --- a/lib/tool_shed/util/basic_util.py +++ b/lib/tool_shed/util/basic_util.py @@ -20,6 +20,33 @@ NO_OUTPUT_TIMEOUT = 1200.0 MAXDIFFSIZE = 8000 MAX_DISPLAY_SIZE = 32768 +DOCKER_IMAGE_TEMPLATE = ''' +# Galaxy Docker image + +FROM bgruening/galaxy-stable + +MAINTAINER Bjoern A. Gruning, bjoern.gruening@gmail.com + +RUN sed -i 's|brand.*|brand = deepTools|g' ~/galaxy-central/universe_wsgi.ini + +WORKDIR /galaxy-central + +${selected_repositories} + +# Mark one folder as imported from the host. +VOLUME ["/export/"] + +# Expose port 80 to the host +EXPOSE :80 + +# Autostart script that is invoked during container start +CMD ["/usr/bin/startup"] +''' + +SELECTED_REPOSITORIES_TEMPLATE = ''' +RUN service postgresql start && service apache2 start && ./run.sh --daemon && sleep 120 && python ./scripts/api/install_tool_shed_repositories.py --api admin -l http://localhost:8080 --url ${tool_shed_url} -o ${repository_owner} --name ${repository_name} --tool-deps --repository-deps --panel-section-name 'Docker' +''' + def evaluate_template( text, install_environment ): """ Substitute variables defined in XML blocks from dependencies file. The value of the received diff --git a/templates/webapps/tool_shed/index.mako b/templates/webapps/tool_shed/index.mako index 34f6331206a..5826c89acf1 100644 --- a/templates/webapps/tool_shed/index.mako +++ b/templates/webapps/tool_shed/index.mako @@ -155,6 +155,11 @@ + %if trans.app.config.enable_galaxy_flavor_docker_image: + + %endif %if can_review_repositories:
@@ -216,6 +221,11 @@ + %if trans.app.config.enable_galaxy_flavor_docker_image: + + %endif %endif %endif
diff --git a/templates/webapps/tool_shed/repository/docker_image_repositories.mako b/templates/webapps/tool_shed/repository/docker_image_repositories.mako new file mode 100644 index 00000000000..8606da6c185 --- /dev/null +++ b/templates/webapps/tool_shed/repository/docker_image_repositories.mako @@ -0,0 +1,64 @@ +<%namespace file="/message.mako" import="render_msg" /> + +<%! + def inherit(context): + if context.get('use_panels'): + return '/webapps/tool_shed/base_panels.mako' + else: + return '/base.mako' +%> + +<%inherit file="${inherit(context)}"/> + +<%def name="stylesheets()"> + ${parent.stylesheets()} + + +<%def name="javascripts()"> + ${parent.javascripts()} + + +%if message: + ${render_msg( message, status )} +%endif + +
+
+
+
+ Click the Create Docker Image button below to create a Docker Image that will install the following repositories. +
+
+
+
+
+
+
Repositories for inclusion in Docker Image
+
+
+ +
+
+ + + + + + + %for repository_tup in repository_tups: + <% name, owner, type = repository_tup %> + + + + + + %endfor +
NameOwnerType
${ name | h }${ owner | h }${ type | h }
+
+
+
+ +
+
+
+
diff --git a/tool_shed_wsgi.ini.sample b/tool_shed_wsgi.ini.sample index 2a22906b139..7db0c615ee4 100644 --- a/tool_shed_wsgi.ini.sample +++ b/tool_shed_wsgi.ini.sample @@ -90,6 +90,9 @@ sendmail_path = /usr/sbin/sendmail # Profiling middleware (cProfile based) ## use_profile = True +# Enable creation of Galaxy flavor Docker Image +#enable_galaxy_flavor_docker_image = False + # Use the new iframe / javascript based layout use_new_layout = true From bc520f0bf8a74e2a1bbaa5b5e1734b0e2c241128 Mon Sep 17 00:00:00 2001 From: Aysam Guerler Date: Wed, 2 Jul 2014 10:56:02 -0400 Subject: [PATCH 38/69] Charts: Add comments, minor code clean up --- .../visualizations/charts/static/app.js | 32 +++------ .../visualizations/charts/static/build-app.js | 2 +- .../static/charts/jqplot/common/wrapper.js | 7 +- .../static/charts/nvd3/common/wrapper.js | 8 ++- .../charts/static/charts/nvd3/pie/wrapper.js | 2 +- .../charts/static/charts/tools.js | 7 +- .../charts/static/library/datasets.js | 7 +- .../charts/static/library/deferred.js | 10 +-- .../charts/static/library/jobs.js | 7 +- .../charts/static/library/screenshot.js | 4 +- .../charts/static/library/storage.js | 10 +-- .../charts/static/library/ui-button-menu.js | 7 +- .../charts/static/library/ui-select.js | 7 +- .../charts/static/library/ui-table-form.js | 7 +- .../charts/static/library/ui-table.js | 7 +- .../charts/static/library/ui.js | 65 +++++++++---------- .../charts/static/models/chart.js | 5 +- .../charts/static/models/config.js | 3 +- .../charts/static/models/group.js | 6 +- .../charts/static/models/groups.js | 3 +- .../charts/static/views/editor.js | 7 +- .../charts/static/views/group.js | 11 ++-- .../charts/static/views/settings.js | 9 +-- .../charts/static/views/types.js | 8 ++- .../charts/static/views/viewer.js | 16 ++--- .../charts/static/views/viewport.js | 12 ++-- 26 files changed, 133 insertions(+), 136 deletions(-) diff --git a/config/plugins/visualizations/charts/static/app.js b/config/plugins/visualizations/charts/static/app.js index 96b289d3aaf..215e0c67840 100644 --- a/config/plugins/visualizations/charts/static/app.js +++ b/config/plugins/visualizations/charts/static/app.js @@ -1,26 +1,26 @@ // dependencies define(['mvc/ui/ui-modal', 'mvc/ui/ui-portlet', 'plugin/library/ui', 'utils/utils', - 'plugin/library/jobs', 'plugin/library/datasets', 'plugin/library/storage', + 'plugin/library/jobs', 'plugin/library/datasets', 'plugin/library/storage', 'plugin/library/deferred', 'plugin/views/viewer', 'plugin/views/editor', 'plugin/models/config', 'plugin/models/chart', 'plugin/charts/types'], - function( Modal, Portlet, Ui, Utils, Jobs, Datasets, Storage, + function( Modal, Portlet, Ui, Utils, Jobs, Datasets, Storage, Deferred, ViewerView, EditorView, Config, Chart, Types ) { -// widget -return Backbone.View.extend( -{ +/** + * Main application class. + */ +return Backbone.View.extend({ // initialize - initialize: function(options) - { + initialize: function(options){ // deactivate all debugs outputs //window.console.debug = function() {}; // link options this.options = options; - + // link galaxy modal or create one if (Galaxy && Galaxy.modal) { this.modal = Galaxy.modal; @@ -41,6 +41,7 @@ return Backbone.View.extend( this.jobs = new Jobs(this); this.datasets = new Datasets(this); this.storage = new Storage(this); + this.deferred = new Deferred(); // // views @@ -62,7 +63,7 @@ return Backbone.View.extend( // draw chart var self = this; - this.chart.deferred.execute(function() { + this.deferred.execute(function() { self.chart.trigger('redraw'); }); } @@ -100,19 +101,6 @@ return Backbone.View.extend( console.debug('FAILED App:chartPath() - Invalid format: ' + chart_type); } return undefined; - }, - - // execute command - execute: function(options) { - }, - - // unload - onunload: function() { - }, - - // log - log: function(location, message) { - console.log(location + ' ' + message); } }); diff --git a/config/plugins/visualizations/charts/static/build-app.js b/config/plugins/visualizations/charts/static/build-app.js index efedde934fb..2f4d65035f8 100644 --- a/config/plugins/visualizations/charts/static/build-app.js +++ b/config/plugins/visualizations/charts/static/build-app.js @@ -3,4 +3,4 @@ // (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc. // Underscore may be freely distributed under the MIT license. -define("mvc/ui/ui-modal",[],function(){var e=Backbone.View.extend({elMain:"body",optionsDefault:{title:"ui-modal",body:"",backdrop:!0,height:null,width:null,closing_events:!1,closing_callback:null},buttonList:{},initialize:function(e){e&&this._create(e)},show:function(e){this.initialize(e),this.options.height?(this.$body.css("height",this.options.height),this.$body.css("overflow","hidden")):this.$body.css("max-height",$(window).height()/2),this.options.width&&this.$dialog.css("width",this.options.width),this.visible?this.$el.show():this.$el.fadeIn("fast"),this.visible=!0},hide:function(){this.visible=!1,this.$el.fadeOut("fast"),this.options.closing_callback&&this.options.closing_callback()},enableButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).prop("disabled",!1)},disableButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).prop("disabled",!0)},showButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).show()},hideButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).hide()},getButton:function(e){var t=this.buttonList[e];return this.$buttons.find("#"+t)},scrollTop:function(){return this.$body.scrollTop()},_create:function(e){var t=this;this.options=_.defaults(e,this.optionsDefault),this.options.body=="progress"&&(this.options.body=$('
')),this.$el&&(this.$el.remove(),$(document).off("keyup.ui-modal")),this.setElement(this._template(this.options.title)),this.$dialog=this.$el.find(".modal-dialog"),this.$body=this.$el.find(".modal-body"),this.$footer=this.$el.find(".modal-footer"),this.$buttons=this.$el.find(".buttons"),this.$backdrop=this.$el.find(".modal-backdrop"),this.$body.html(this.options.body),this.options.backdrop||this.$backdrop.removeClass("in");if(this.options.buttons){this.buttonList={};var n=0;$.each(this.options.buttons,function(e,r){var i="button-"+n++;t.$buttons.append($('').text(e).click(r)).append(" "),t.buttonList[e]=i})}else this.$footer.hide();$(this.elMain).append($(this.el)),this.options.closing_events&&($(document).on("keyup.ui-modal",function(e){e.keyCode==27&&t.hide()}),this.$el.find(".modal-backdrop").on("click",function(){t.hide()}))},_template:function(e){return'