comparison toolfactory/rgToolFactory2.py @ 113:6873c211b250 draft

Uploaded
author fubar
date Tue, 01 Dec 2020 09:03:34 +0000
parents 5509dc4c1cf2
children e0cf315853cf
comparison
equal deleted inserted replaced
112:5509dc4c1cf2 113:6873c211b250
192 self.repdir = "./TF_run_report_tempdir" 192 self.repdir = "./TF_run_report_tempdir"
193 self.testdir = os.path.join(self.tooloutdir, "test-data") 193 self.testdir = os.path.join(self.tooloutdir, "test-data")
194 if not os.path.exists(self.tooloutdir): 194 if not os.path.exists(self.tooloutdir):
195 os.mkdir(self.tooloutdir) 195 os.mkdir(self.tooloutdir)
196 if not os.path.exists(self.testdir): 196 if not os.path.exists(self.testdir):
197 os.mkdir(self.testdir) # make tests directory 197 os.mkdir(self.testdir)
198 if not os.path.exists(self.repdir): 198 if not os.path.exists(self.repdir):
199 os.mkdir(self.repdir) 199 os.mkdir(self.repdir)
200 self.tinputs = gxtp.Inputs() 200 self.tinputs = gxtp.Inputs()
201 self.toutputs = gxtp.Outputs() 201 self.toutputs = gxtp.Outputs()
202 self.testparam = [] 202 self.testparam = []
222 aCL(self.executeme) 222 aCL(self.executeme)
223 aCL(self.sfile) 223 aCL(self.sfile)
224 aXCL(self.executeme) 224 aXCL(self.executeme)
225 aXCL("$runme") 225 aXCL("$runme")
226 else: 226 else:
227 aCL(self.executeme) # this little CL will just run 227 aCL(self.executeme)
228 aXCL(self.executeme) 228 aXCL(self.executeme)
229 self.elog = os.path.join(self.repdir, "%s_error_log.txt" % self.tool_name) 229 self.elog = os.path.join(self.repdir, "%s_error_log.txt" % self.tool_name)
230 self.tlog = os.path.join(self.repdir, "%s_runner_log.txt" % self.tool_name) 230 self.tlog = os.path.join(self.repdir, "%s_runner_log.txt" % self.tool_name)
231 231
232 if self.args.parampass == "0": 232 if self.args.parampass == "0":
255 xclsuffix.append(xappendme) 255 xclsuffix.append(xappendme)
256 for i, p in enumerate(self.outfiles): 256 for i, p in enumerate(self.outfiles):
257 if p[OOCLPOS] == "STDOUT": 257 if p[OOCLPOS] == "STDOUT":
258 self.lastclredirect = [">", p[ONAMEPOS]] 258 self.lastclredirect = [">", p[ONAMEPOS]]
259 self.lastxclredirect = [">", "$%s" % p[OCLPOS]] 259 self.lastxclredirect = [">", "$%s" % p[OCLPOS]]
260 else: # for (o_v, k, v, koverride) in self.xclsuffix: 260 else:
261 clsuffix.append([p[ONAMEPOS], p[ONAMEPOS], p[ONAMEPOS], ""]) 261 clsuffix.append([p[ONAMEPOS], p[ONAMEPOS], p[ONAMEPOS], ""])
262 xclsuffix.append([p[ONAMEPOS], p[ONAMEPOS], "$%s" % p[ONAMEPOS], ""]) 262 xclsuffix.append([p[ONAMEPOS], p[ONAMEPOS], "$%s" % p[ONAMEPOS], ""])
263 for p in self.addpar: 263 for p in self.addpar:
264 clsuffix.append([p[AOCLPOS], p[ACLPOS], p[AVALPOS], p[AOVERPOS]]) 264 clsuffix.append([p[AOCLPOS], p[ACLPOS], p[AVALPOS], p[AOVERPOS]])
265 xclsuffix.append( 265 xclsuffix.append(
311 infp[ICLPOS] = scl 311 infp[ICLPOS] = scl
312 self.infiles[i] = infp 312 self.infiles[i] = infp
313 for i, p in enumerate( 313 for i, p in enumerate(
314 self.outfiles 314 self.outfiles
315 ): 315 ):
316 if self.args.parampass == "positional" and p[OCLPOS] != "STDOUT": 316 if self.args.parampass == "positional" and p[OCLPOS].upper() != "STDOUT":
317 assert p[ 317 assert p[
318 OCLPOS 318 OCLPOS
319 ].isdigit(), "Positional parameters must be ordinal integers - got %s for %s" % ( 319 ].isdigit(), "Positional parameters must be ordinal integers - got %s for %s" % (
320 p[OCLPOS], 320 p[OCLPOS],
321 p[ONAMEPOS], 321 p[ONAMEPOS],
322 ) 322 )
323 p.append(p[OCLPOS]) # keep copy 323 p.append(p[OCLPOS]) # keep copy
324 if p[OOCLPOS].isdigit() or p[OOCLPOS] == "STDOUT": 324 if p[OOCLPOS].isdigit() or p[OOCLPOS].upper() == "STDOUT":
325 scl = p[ONAMEPOS] 325 scl = p[ONAMEPOS]
326 p[OCLPOS] = scl 326 p[OCLPOS] = scl
327 self.outfiles[i] = p 327 self.outfiles[i] = p
328 for i, p in enumerate(self.addpar): 328 for i, p in enumerate(self.addpar):
329 if self.args.parampass == "positional": 329 if self.args.parampass == "positional":
367 for (o_v, k, v, koverride) in self.xclsuffix: 367 for (o_v, k, v, koverride) in self.xclsuffix:
368 aXCL(v) 368 aXCL(v)
369 if self.lastxclredirect: 369 if self.lastxclredirect:
370 aXCL(self.lastxclredirect[0]) 370 aXCL(self.lastxclredirect[0])
371 aXCL(self.lastxclredirect[1]) 371 aXCL(self.lastxclredirect[1])
372 if os.path.exists(self.tlog):
373 tout = open(self.tlog, "a")
374 else:
375 tout = open(self.tlog, "w")
376 tout.write(f" #### clpositional: self.clsuffix = {self.clsuffix} and self.xclsuffix = {self.xclsuffix}")
377 tout.close()
378 372
379 373
380 def clargparse(self): 374 def clargparse(self):
381 """argparse style""" 375 """argparse style"""
382 aCL = self.cl.append 376 aCL = self.cl.append
399 k = "-%s" % k 393 k = "-%s" % k
400 else: 394 else:
401 k = "--%s" % k 395 k = "--%s" % k
402 aCL(k) 396 aCL(k)
403 aCL(v) 397 aCL(v)
404 if os.path.exists(self.tlog):
405 tout = open(self.tlog, "a")
406 else:
407 tout = open(self.tlog, "w")
408 tout.write(f" #### clargparse: self.clsuffix = {self.clsuffix} and self.xclsuffix = {self.xclsuffix}")
409 tout.close()
410 398
411 399
412 def getNdash(self, newname): 400 def getNdash(self, newname):
413 if self.is_positional: 401 if self.is_positional:
414 ndash = 0 402 ndash = 0
425 test = test.strip() 413 test = test.strip()
426 ndash = self.getNdash(newcl) 414 ndash = self.getNdash(newcl)
427 aparm = gxtp.OutputData(name=newname, format=newfmt, num_dashes=ndash, label=newcl) 415 aparm = gxtp.OutputData(name=newname, format=newfmt, num_dashes=ndash, label=newcl)
428 aparm.positional = self.is_positional 416 aparm.positional = self.is_positional
429 if self.is_positional: 417 if self.is_positional:
430 if oldcl == "STDOUT": 418 if oldcl.upper() == "STDOUT":
431 aparm.positional = 9999999 419 aparm.positional = 9999999
432 aparm.command_line_override = "> $%s" % newname 420 aparm.command_line_override = "> $%s" % newname
433 else: 421 else:
434 aparm.positional = int(oldcl) 422 aparm.positional = int(oldcl)
435 aparm.command_line_override = "$%s" % newname 423 aparm.command_line_override = "$%s" % newname
601 ) 589 )
602 self.newtool.version_command = None # do not want 590 self.newtool.version_command = None # do not want
603 requirements = gxtp.Requirements() 591 requirements = gxtp.Requirements()
604 if self.args.packages: 592 if self.args.packages:
605 for d in self.args.packages.split(","): 593 for d in self.args.packages.split(","):
594 ver = ''
595 d = d.replace('==',':')
596 d = d.replace('=',':')
606 if ":" in d: 597 if ":" in d:
607 packg, ver = d.split(":") 598 packg, ver = d.split(":")
608 else: 599 else:
609 packg = d 600 packg = d
610 ver = ""
611 requirements.append( 601 requirements.append(
612 gxtp.Requirement("package", packg.strip(), ver.strip()) 602 gxtp.Requirement("package", packg.strip(), ver.strip())
613 ) 603 )
614 self.newtool.requirements = requirements 604 self.newtool.requirements = requirements
615 if self.args.parampass == "0": 605 if self.args.parampass == "0":
749 def prun(container, tout, cl, user="biodocker"): 739 def prun(container, tout, cl, user="biodocker"):
750 rlog = container.exec_run(cl, user=user) 740 rlog = container.exec_run(cl, user=user)
751 slogl = str(rlog).split("\\n") 741 slogl = str(rlog).split("\\n")
752 slog = "\n".join(slogl) 742 slog = "\n".join(slogl)
753 tout.write(f"## got rlog {slog} from {cl}\n") 743 tout.write(f"## got rlog {slog} from {cl}\n")
744
754 if os.path.exists(self.tlog): 745 if os.path.exists(self.tlog):
755 tout = open(self.tlog, "a") 746 tout = open(self.tlog, "a")
756 else: 747 else:
757 tout = open(self.tlog, "w") 748 tout = open(self.tlog, "w")
758 planemoimage = "quay.io/fubar2/planemo-biocontainer" 749 planemoimage = "quay.io/fubar2/planemo-biocontainer"
763 client = docker.from_env() 754 client = docker.from_env()
764 tvol = client.volumes.create() 755 tvol = client.volumes.create()
765 tvolname = tvol.name 756 tvolname = tvol.name
766 destdir = "/toolfactory/ptest" 757 destdir = "/toolfactory/ptest"
767 imrep = os.path.join(destdir, repname) 758 imrep = os.path.join(destdir, repname)
768 # need to keep the container running so sleep a while - we stop and destroy it when we are done 759 # need to keep the container running so keep it open with tail -f.
760 # will stop and destroy it when we are done
769 container = client.containers.run( 761 container = client.containers.run(
770 planemoimage, 762 planemoimage,
771 "sleep 30m", 763 "tail -f /galaxy-central/CITATION",
772 detach=True, 764 detach=True,
773 user="biodocker", 765 user="biodocker",
774 volumes={f"{tvolname}": {"bind": "/toolfactory", "mode": "rw"}}, 766 volumes={f"{tvolname}": {"bind": "/toolfactory", "mode": "rw"}},
775 ) 767 )
776 cl = f"mkdir -p {destdir}" 768 cl = f"mkdir -p {destdir}"
777 prun(container, tout, cl, user="root") 769 prun(container, tout, cl, user="root")
770 # that's how hard it is to get root on a biodocker container :(
778 cl = f"rm -rf {destdir}/*" 771 cl = f"rm -rf {destdir}/*"
779 prun(container, tout, cl, user="root") 772 prun(container, tout, cl, user="root")
780 ptestpath = os.path.join(destdir, "tfout", xreal) 773 ptestpath = os.path.join(destdir, "tfout", xreal)
781 self.copy_to_container(self.tooloutdir, destdir, container) 774 self.copy_to_container(self.tooloutdir, destdir, container)
782 cl = "chown -R biodocker /toolfactory" 775 cl = "chown -R biodocker /toolfactory"
783 prun(container, tout, cl, user="root") 776 prun(container, tout, cl, user="root")
784 rlog = container.exec_run(f"ls -la {destdir}") 777 rlog = container.exec_run(f"ls -la {destdir}")
785 ptestcl = f"planemo test --update_test_data --no_cleanup --test_data {destdir}/tfout/test-data --galaxy_root /home/biodocker/galaxy-central {ptestpath}" 778 ptestcl = f"planemo test --update_test_data --no_cleanup --test_data {destdir}/tfout/test-data --galaxy_root /home/biodocker/galaxy-central {ptestpath}"
786 try: 779 try:
787 rlog = container.exec_run(ptestcl) 780 rlog = container.exec_run(ptestcl)
781 # fails because test outputs missing but updates the test-data directory
788 except: 782 except:
789 e = sys.exc_info()[0] 783 e = sys.exc_info()[0]
790 tout.write(f"#### error: {e} from {ptestcl}\n") 784 tout.write(f"#### error: {e} from {ptestcl}\n")
791 # fails - used to generate test outputs
792 cl = f"planemo test --test_output {imrep} --no_cleanup --test_data {destdir}/tfout/test-data --galaxy_root /home/biodocker/galaxy-central {ptestpath}" 785 cl = f"planemo test --test_output {imrep} --no_cleanup --test_data {destdir}/tfout/test-data --galaxy_root /home/biodocker/galaxy-central {ptestpath}"
793 try: 786 try:
794 prun(container, tout, cl) 787 prun(container, tout, cl)
795 except: 788 except:
796 pass 789 pass
806 tout.write(f"No output from run to shutil.copytree in {src}\n") 799 tout.write(f"No output from run to shutil.copytree in {src}\n")
807 tout.close() 800 tout.close()
808 container.stop() 801 container.stop()
809 container.remove() 802 container.remove()
810 tvol.remove() 803 tvol.remove()
811 # shutil.rmtree(testouts) 804 # shutil.rmtree(testouts) leave for debugging
812 805
813 def shedLoad(self): 806 def shedLoad(self):
814 """ 807 """
815 {'deleted': False, 808 use bioblend to create new repository
816 'description': 'Tools for manipulating data', 809 or update existing
817 'id': '175812cd7caaf439',
818 'model_class': 'Category',
819 'name': 'Text Manipulation',
820 'url': '/api/categories/175812cd7caaf439'}]
821
822 810
823 """ 811 """
824 if os.path.exists(self.tlog): 812 if os.path.exists(self.tlog):
825 sto = open(self.tlog, "a") 813 sto = open(self.tlog, "a")
826 else: 814 else:
849 remote_repository_url=self.args.toolshed_url, 837 remote_repository_url=self.args.toolshed_url,
850 homepage_url=None, 838 homepage_url=None,
851 category_ids=catID, 839 category_ids=catID,
852 ) 840 )
853 tid = res.get("id", None) 841 tid = res.get("id", None)
854 sto.write(f"#####create_repository {self.args.tool_name} tid={tid} res={res}\n") 842 sto.write(f"#create_repository {self.args.tool_name} tid={tid} res={res}\n")
855 else: 843 else:
856 i = rnames.index(self.tool_name) 844 i = rnames.index(self.tool_name)
857 tid = rids[i] 845 tid = rids[i]
858 try: 846 try:
859 res = ts.repositories.update_repository( 847 res = ts.repositories.update_repository(
860 id=tid, tar_ball_path=self.newtarpath, commit_message=None 848 id=tid, tar_ball_path=self.newtarpath, commit_message=None
861 ) 849 )
862 sto.write(f"#####update res id {id} ={res}\n") 850 sto.write(f"#update res id {id} ={res}\n")
863 except ConnectionError: 851 except ConnectionError:
864 sto.write( 852 sto.write(
865 "Is the toolshed running and the API key correct? Bioblend shed upload failed\n" 853 "####### Is the toolshed running and the API key correct? Bioblend shed upload failed\n"
866 ) 854 )
867 sto.close() 855 sto.close()
868 856
869 def eph_galaxy_load(self): 857 def eph_galaxy_load(self):
870 """load the new tool from the local toolshed after planemo uploads it""" 858 """
859 use ephemeris to load the new tool from the local toolshed after planemo uploads it
860 """
871 if os.path.exists(self.tlog): 861 if os.path.exists(self.tlog):
872 tout = open(self.tlog, "a") 862 tout = open(self.tlog, "a")
873 else: 863 else:
874 tout = open(self.tlog, "w") 864 tout = open(self.tlog, "w")
875 cll = [ 865 cll = [
1032 a("--galaxy_api_key", default="fakekey") 1022 a("--galaxy_api_key", default="fakekey")
1033 a("--galaxy_root", default="/galaxy-central") 1023 a("--galaxy_root", default="/galaxy-central")
1034 a("--galaxy_venv", default="/galaxy_venv") 1024 a("--galaxy_venv", default="/galaxy_venv")
1035 args = parser.parse_args() 1025 args = parser.parse_args()
1036 assert not args.bad_user, ( 1026 assert not args.bad_user, (
1037 'UNAUTHORISED: %s is NOT authorized to use this tool until Galaxy admin adds %s to "admin_users" in the Galaxy configuration file' 1027 'UNAUTHORISED: %s is NOT authorized to use this tool until Galaxy admin adds %s to "admin_users" in the galaxy.yml Galaxy configuration file'
1038 % (args.bad_user, args.bad_user) 1028 % (args.bad_user, args.bad_user)
1039 ) 1029 )
1040 assert args.tool_name, "## Tool Factory expects a tool name - eg --tool_name=DESeq" 1030 assert args.tool_name, "## Tool Factory expects a tool name - eg --tool_name=DESeq"
1041 assert ( 1031 assert (
1042 args.sysexe or args.packages 1032 args.sysexe or args.packages