6868INSTALL_TOOL_DEPENDENCIES = False
6969INSTALL_REPOSITORY_DEPENDENCIES = True
7070INSTALL_RESOLVER_DEPENDENCIES = True
71+ EXIT_CODE_INSTALL_ERRORS = 1
72+ EXIT_CODE_TOOL_TEST_ERRORS = 2
7173
7274
7375def _ensure_log_configured (name ):
@@ -278,7 +280,7 @@ def _parser():
278280 # update_tools in the name space and shed-tool update will not return all the install
279281 # variables.
280282 parser .set_defaults (
281- update_tools = False ,
283+ action = "install" ,
282284 tool_list_file = None ,
283285 tool_yaml = None ,
284286 owner = None ,
@@ -300,22 +302,51 @@ def _parser():
300302 "Use shed-tools install --help for more information" ,
301303 parents = [common_arguments ],
302304 )
303- install_command_parser .add_argument (
304- "-t" , "--toolsfile" ,
305- dest = "tool_list_file" ,
306- help = "Tools file to use (see tool_list.yaml.sample)" ,)
307- install_command_parser .add_argument (
308- "-y" , "--yaml_tool" ,
309- dest = "tool_yaml" ,
310- help = "Install tool represented by yaml string" ,)
311- install_command_parser .add_argument (
312- "--name" ,
313- help = "The name of the tool to install (only applicable "
314- "if the tools file is not provided)." )
315- install_command_parser .add_argument (
316- "--owner" ,
317- help = "The owner of the tool to install (only applicable "
318- "if the tools file is not provided)." )
305+ update_command_parser = subparsers .add_parser (
306+ "update" ,
307+ help = "This updates all tools in Galaxy to the latest revision. "
308+ "Use shed-tools update --help for more information" ,
309+ parents = [common_arguments ])
310+
311+ test_command_parser = subparsers .add_parser (
312+ "test" ,
313+ help = "This tests the supplied list of tools in Galaxy. "
314+ "Use shed-tools test --help for more information" ,
315+ )
316+
317+ for command_parser in [install_command_parser , test_command_parser ]:
318+ command_parser .add_argument (
319+ "-t" , "--toolsfile" ,
320+ dest = "tool_list_file" ,
321+ help = "Tools file to use (see tool_list.yaml.sample)" ,)
322+ command_parser .add_argument (
323+ "-y" , "--yaml_tool" ,
324+ dest = "tool_yaml" ,
325+ help = "Install tool represented by yaml string" ,)
326+ command_parser .add_argument (
327+ "--name" ,
328+ help = "The name of the tool to install (only applicable "
329+ "if the tools file is not provided)." )
330+ command_parser .add_argument (
331+ "--owner" ,
332+ help = "The owner of the tool to install (only applicable "
333+ "if the tools file is not provided)." )
334+ command_parser .add_argument (
335+ "--revisions" ,
336+ default = None ,
337+ nargs = '*' ,
338+ dest = "revisions" ,
339+ help = "The revisions of the tool repository that will be installed. "
340+ "All revisions must be specified after this flag by a space."
341+ "Example: --revisions 0a5c7992b1ac f048033da666"
342+ "(Only applicable if the tools file is not provided)." )
343+ command_parser .add_argument (
344+ "--toolshed" ,
345+ dest = "tool_shed_url" ,
346+ help = "The Tool Shed URL where to install the tool from. "
347+ "This is applicable only if the tool info is "
348+ "provided as an option vs. in the tools file." )
349+
319350 install_command_parser .add_argument (
320351 "--section" ,
321352 dest = "tool_panel_section_id" ,
@@ -329,21 +360,6 @@ def _parser():
329360 help = "Galaxy tool panel section label where tool will be installed "
330361 "(if the section does not exist, it will be created; "
331362 "only applicable if the tools file is not provided)." )
332- install_command_parser .add_argument (
333- "--revisions" ,
334- default = None ,
335- nargs = '*' ,
336- dest = "revisions" ,
337- help = "The revisions of the tool repository that will be installed. "
338- "All revisions must be specified after this flag by a space."
339- "Example: --revisions 0a5c7992b1ac f048033da666"
340- "(Only applicable if the tools file is not provided)." )
341- install_command_parser .add_argument (
342- "--toolshed" ,
343- dest = "tool_shed_url" ,
344- help = "The Tool Shed URL where to install the tool from. "
345- "This is applicable only if the tool info is "
346- "provided as an option vs. in the tools file." )
347363 install_command_parser .add_argument (
348364 "--skip_install_tool_dependencies" ,
349365 action = "store_true" ,
@@ -364,34 +380,40 @@ def _parser():
364380 dest = "force_latest_revision" ,
365381 help = "Will override the revisions in the tools file and always install the latest revision." )
366382
367- update_command_parser = subparsers .add_parser (
368- "update" ,
369- help = "This updates all tools in Galaxy to the latest revision."
370- "Use shed-tools update --help for more information" ,
371- parents = [common_arguments ])
372-
373383 for command_parser in [update_command_parser , install_command_parser ]:
374384 command_parser .add_argument (
375385 "--test" ,
376386 action = "store_true" ,
377387 dest = "test" ,
378388 help = "Run tool tests on install tools, requires Galaxy 18.05 or newer."
379389 )
380- command_parser .add_argument (
381- "--test_json" ,
382- dest = "test_json" ,
383- help = "If --test is specified, record tool test output to specified file. "
384- "This file can be turned into nice reports with ``planemo test_reports <output.json>``."
385- )
386390 command_parser .add_argument (
387391 "--test_existing" ,
388392 action = "store_true" ,
389- help = "If --test is specified , also run tool tests on repositories already installed "
393+ help = "If testing tools during install , also run tool tests on repositories already installed "
390394 "(i.e. skipped repositories)."
391395 )
396+ command_parser .add_argument (
397+ "--test_json" ,
398+ dest = "test_json" ,
399+ help = "If testing tools, record tool test output to specified file. "
400+ "This file can be turned into reports with ``planemo test_reports <output.json>``."
401+ )
402+
403+ # Same test_json as above but language modified for test instead of install/update.
404+ test_command_parser .add_argument (
405+ "--test_json" ,
406+ dest = "test_json" ,
407+ help = "Record tool test output to specified file. "
408+ "This file can be turned into reports with ``planemo test_reports <output.json>``."
409+ )
392410
393411 update_command_parser .set_defaults (
394- update_tools = True ,
412+ action = "update" ,
413+ )
414+
415+ test_command_parser .set_defaults (
416+ action = "test"
395417 )
396418
397419 return parser
@@ -517,7 +539,7 @@ def get_install_repository_manager(options):
517539 'install_tool_dependencies' , INSTALL_TOOL_DEPENDENCIES )
518540 elif options .tool_yaml :
519541 repositories = [yaml .safe_load (options .tool_yaml )]
520- elif options .update_tools :
542+ elif options .action == "update" :
521543 get_repository_list = GiToToolYaml (
522544 gi = gi ,
523545 skip_tool_panel_section_name = False ,
@@ -546,7 +568,7 @@ def get_install_repository_manager(options):
546568
547569 install_resolver_dependencies = options .install_resolver_dependencies or install_resolver_dependencies
548570
549- force_latest_revision = options .force_latest_revision or options .update_tools
571+ force_latest_revision = options .force_latest_revision or options .action == "update"
550572
551573 return InstallToolManager (repositories = repositories ,
552574 gi = gi ,
@@ -587,10 +609,11 @@ def __init__(self,
587609 self .test = test
588610 self .test_existing = test_existing
589611 self .test_json = test_json
612+ self .tests_passed = []
590613 self .test_exceptions = []
591614
592615 def install_repositories (self ):
593- """
616+ """Attempt to ensure each repository in ``self.repositories`` is installed.
594617 """
595618 installation_start = dt .datetime .now ()
596619 installed_repositories_list = installed_repository_revisions (self .gi ) # installed tools list
@@ -696,52 +719,81 @@ def install_repositories(self):
696719 )
697720 log .info ("All repositories have been installed." )
698721 if self .test :
699- installed_tools = []
700- target_repos = self .installed_repositories
722+ target_repositories = self .installed_repositories
701723 if self .test_existing :
702- target_repos += self .skipped_repositories
703- for installed_repository in target_repos :
704- repo_tools = tools_for_repository (self .gi , installed_repository )
705- installed_tools .extend (repo_tools )
706-
707- test_results = []
708-
709- for tool in installed_tools :
710- galaxy_interactor_kwds = {
711- "galaxy_url" : re .sub ('/api' , '' , self .gi .url ),
712- "master_api_key" : self .gi .key ,
713- "api_key" : None , # TODO
714- "keep_outputs_dir" : '' ,
715- }
716- galaxy_interactor = GalaxyInteractorApi (** galaxy_interactor_kwds )
717- tool_id = tool ["id" ]
718- tool_version = tool ["version" ]
719- tool_test_dicts = galaxy_interactor .get_tool_tests (tool_id , tool_version = tool_version )
720- test_indices = list (range (len (tool_test_dicts )))
721- for test_index in test_indices :
722- def register (job_data ):
723- test_results .append ({
724- 'id' : tool_id + "-" + str (test_index ),
725- 'has_data' : True ,
726- 'data' : job_data ,
727- })
728-
729- try :
730- verify_tool (
731- tool_id , galaxy_interactor , test_index = test_index , tool_version = tool_version ,
732- register_job_data = register , quiet = True
733- )
734- except Exception as e :
735- self .test_exceptions .append (e )
724+ target_repositories += self .skipped_repositories
725+ self .test_repositories (target_repositories = target_repositories )
726+ log .info ("Total run time: {0}" .format (dt .datetime .now () - installation_start ))
736727
737- report_obj = {
738- 'version' : '0.1' ,
739- 'tests' : test_results ,
740- }
741- with open (self .test_json or "tool_test_output.json" , "w" ) as f :
742- json .dump (report_obj , f )
728+ def test_repositories (self , target_repositories = None ):
729+ """Run tool tests for each tool in supplied repositories list or ``self.repositories``.
730+ """
731+ tool_test_start = dt .datetime .now ()
732+ if target_repositories is None :
733+ # Consider a variant of this that doesn't even consume a tool list YAML? target
734+ # something like installed_repository_revisions(self.gi)
735+ target_repositories = self .repositories
736+ installed_tools = []
737+ for target_repository in target_repositories :
738+ repo_tools = tools_for_repository (self .gi , target_repository )
739+ installed_tools .extend (repo_tools )
740+
741+ all_test_results = []
742+
743+ for tool in installed_tools :
744+ tool_test_results = self ._test_tool (tool )
745+ all_test_results .extend (tool_test_results )
746+
747+ report_obj = {
748+ 'version' : '0.1' ,
749+ 'tests' : all_test_results ,
750+ }
751+ with open (self .test_json or "tool_test_output.json" , "w" ) as f :
752+ json .dump (report_obj , f )
753+ log .info ("Passed tool tests ({0}): {1}" .format (
754+ len (self .tests_passed ),
755+ [t for t in self .tests_passed ])
756+ )
757+ log .info ("Failed tool tests ({0}): {1}" .format (
758+ len (self .test_exceptions ),
759+ [t [0 ] for t in self .errored_repositories ])
760+ )
761+ log .info ("Total tool test time: {0}" .format (dt .datetime .now () - tool_test_start ))
762+
763+ def _test_tool (self , tool ):
764+ galaxy_interactor_kwds = {
765+ "galaxy_url" : re .sub ('/api' , '' , self .gi .url ),
766+ "master_api_key" : self .gi .key ,
767+ "api_key" : None , # TODO
768+ "keep_outputs_dir" : '' ,
769+ }
770+ galaxy_interactor = GalaxyInteractorApi (** galaxy_interactor_kwds )
771+ tool_id = tool ["id" ]
772+ tool_version = tool ["version" ]
773+ tool_test_dicts = galaxy_interactor .get_tool_tests (tool_id , tool_version = tool_version )
774+ test_indices = list (range (len (tool_test_dicts )))
775+ tool_test_results = []
776+
777+ for test_index in test_indices :
778+ test_id = tool_id + "-" + str (test_index )
779+
780+ def register (job_data ):
781+ tool_test_results .append ({
782+ 'id' : test_id ,
783+ 'has_data' : True ,
784+ 'data' : job_data ,
785+ })
786+
787+ try :
788+ verify_tool (
789+ tool_id , galaxy_interactor , test_index = test_index , tool_version = tool_version ,
790+ register_job_data = register , quiet = True
791+ )
792+ self .tests_passed .append (test_id )
793+ except Exception as e :
794+ self .test_exceptions .append ((test_id , e ))
743795
744- log . info ( "Total run time: {0}" . format ( dt . datetime . now () - installation_start ))
796+ return tool_test_results
745797
746798 def create_repository_install_payload (self , repository_info ):
747799 """
@@ -820,23 +872,28 @@ def main():
820872 disable_external_library_logging ()
821873 log = setup_global_logger (name = __name__ , log_file = '/tmp/galaxy_tool_install.log' )
822874 options = _parse_cli_options ()
875+ install_tool_manager = None
823876 if options .tool_list_file or options .tool_yaml or \
824877 options .name and options .owner and (options .tool_panel_section_id or options .tool_panel_section_label ):
825- if options .update_tools :
826- sys .exit ("-- update can not be used together with tools to be installed." )
878+ if options .action == "update" :
879+ sys .exit ("update command can not be used together with tools to be installed." )
827880 install_tool_manager = get_install_repository_manager (options )
828- install_tool_manager .install_repositories ()
829- if install_tool_manager .errored_repositories :
830- sys .exit (1 )
881+ if options .action == "test" :
882+ install_tool_manager .test_repositories ()
883+ else :
884+ install_tool_manager .install_repositories ()
831885 elif options .update_tools :
832886 install_tool_manager = get_install_repository_manager (options )
833887 install_tool_manager .install_repositories ()
834- if install_tool_manager .errored_repositories :
835- sys .exit (1 )
836888 else :
837889 sys .exit ("Must provide a tool list file, individual tools info , a list of data manager tasks or issue the update command. "
838890 "Look at usage." )
839891
892+ if install_tool_manager .errored_repositories :
893+ sys .exit (EXIT_CODE_INSTALL_ERRORS )
894+ elif install_tool_manager .test_exceptions :
895+ sys .exit (EXIT_CODE_TOOL_TEST_ERRORS )
896+
840897
841898if __name__ == "__main__" :
842899 main ()
0 commit comments