changeset 5:e2c8c2fa192d draft

Uploaded
author fubar
date Tue, 27 Apr 2021 23:33:49 +0000
parents 2a46da701dde
children efefe43f23c8
files toolfactory/.github/workflows/commit.yml toolfactory/.gitignore toolfactory/.shed.yml toolfactory/README.md toolfactory/ToolFactory.py toolfactory/ToolFactory.xml toolfactory/ToolFactory_tester.py toolfactory/images/TFasIDE.png toolfactory/images/dynamicScriptTool.png toolfactory/images/hello_toolfactory_form.png toolfactory/images/lintplanemo-2021-01-08_18.02.45.mkv toolfactory/install_tf_demos.py toolfactory/maketf.sh toolfactory/test-data/test1_log.txt toolfactory/tfout/.shed.yml toolfactory/tfout/plotter.xml
diffstat 16 files changed, 33 insertions(+), 715 deletions(-) [+]
line wrap: on
line diff
--- a/toolfactory/.github/workflows/commit.yml	Mon Apr 26 05:25:26 2021 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-name: Galaxy Tool Linting and Tests for PR
-# run planemo on a git repository containing a single tool
-# as a github action.
-# ross lazarus august 2020
-on: [pull_request,push]
-env:
-  GALAXY_REPO: https://github.com/galaxyproject/galaxy
-  GALAXY_RELEASE: release_20.05
-jobs:
-  setup:
-    name: setup environment and python
-    runs-on: ubuntu-latest
-    strategy:
-      matrix:
-        python-version: [3.7]
-    steps:
-    - name: Print github context properties
-      run: |
-        echo 'event: ${{ github.event_name }}'
-        echo 'sha: ${{ github.sha }}'
-        echo 'ref: ${{ github.ref }}'
-        echo 'head_ref: ${{ github.head_ref }}'
-        echo 'base_ref: ${{ github.base_ref }}'
-        echo 'event.before: ${{ github.event.before }}'
-        echo 'event.after: ${{ github.event.after }}'
-    - uses: actions/setup-python@v1
-      with:
-        python-version: ${{ matrix.python-version }}
-    - uses: actions/checkout@v2
-      with:
-    # planemo does not seem to want to install the requirement galaxyxml
-    # into the venv it manages at tool testing so do it the old skool way
-        repository: 'galaxyproject/galaxy'
-        path: 'galaxy'
-    - name: make venv ready for this galaxy and planemo
-      run:  |
-        python3 -m venv $GITHUB_WORKSPACE/galaxy/.venv
-        . $GITHUB_WORKSPACE/galaxy/.venv/bin/activate
-        pip install --upgrade pip
-        pip install wheel
-        pip install -r $GITHUB_WORKSPACE/galaxy/requirements.txt
-    - name: Upgrade pip
-      run: pip install --upgrade pip
-    # Install the `wheel` package so that when installing other packages which
-    # are not available as wheels, pip will build a wheel for them, which can be cached.
-    - name: Install wheel
-      run: pip install wheel
-    - name: Install Planemo and flake8
-      run: pip install planemo flake8 flake8-import-order
-    # galaxyxml temporarily removed until PR accepted
-    - uses: actions/checkout@v2
-      with:
-        fetch-depth: 1
-    - name: flake8 *.py
-      run: flake8 --ignore=E501,E203,W503,C901
-    - name: Planemo lint
-      run: planemo lint .
-    - name: Planemo test tool
-      run: planemo test --galaxy_root $GITHUB_WORKSPACE/galaxy --test_output tool_test_output.html --skip_venv --test_output_json tool_test_output.json --galaxy_python_version ${{ matrix.python-version }}  .
-    - name: Copy artifacts into place
-      run: |
-        mkdir upload
-        mv tool_test_output.json tool_test_output.html upload/
-    - uses: actions/upload-artifact@v2.0.1
-      with:
-        name: 'All tool test results'
-        path: upload
--- a/toolfactory/.gitignore	Mon Apr 26 05:25:26 2021 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-# Byte-compiled / optimized / DLL files
-__pycache__/
-*.py[cod]
-*$py.class
-
-# C extensions
-*.so
-
-# Distribution / packaging
-.Python
-build/
-develop-eggs/
-dist/
-downloads/
-eggs/
-.eggs/
-lib/
-lib64/
-parts/
-sdist/
-var/
-wheels/
-pip-wheel-metadata/
-share/python-wheels/
-*.egg-info/
-.installed.cfg
-*.egg
-MANIFEST
-
-# PyInstaller
-#  Usually these files are written by a python script from a template
-#  before PyInstaller builds the exe, so as to inject date/other infos into it.
-*.manifest
-*.spec
-
-# Installer logs
-pip-log.txt
-pip-delete-this-directory.txt
-
-# Unit test / coverage reports
-htmlcov/
-.tox/
-.nox/
-.coverage
-.coverage.*
-.cache
-nosetests.xml
-coverage.xml
-*.cover
-*.py,cover
-.hypothesis/
-.pytest_cache/
-
-# Translations
-*.mo
-*.pot
-
-# Django stuff:
-*.log
-local_settings.py
-db.sqlite3
-db.sqlite3-journal
-
-# Flask stuff:
-instance/
-.webassets-cache
-
-# Scrapy stuff:
-.scrapy
-
-# Sphinx documentation
-docs/_build/
-
-# PyBuilder
-target/
-
-# Jupyter Notebook
-.ipynb_checkpoints
-
-# IPython
-profile_default/
-ipython_config.py
-
-# pyenv
-.python-version
-
-# pipenv
-#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
-#   However, in case of collaboration, if having platform-specific dependencies or dependencies
-#   having no cross-platform support, pipenv may install dependencies that don't work, or not
-#   install all needed dependencies.
-#Pipfile.lock
-
-# PEP 582; used by e.g. github.com/David-OConnor/pyflow
-__pypackages__/
-
-# Celery stuff
-celerybeat-schedule
-celerybeat.pid
-
-# SageMath parsed files
-*.sage.py
-
-# Environments
-.env
-.venv
-env/
-venv/
-ENV/
-env.bak/
-venv.bak/
-
-# Spyder project settings
-.spyderproject
-.spyproject
-
-# Rope project settings
-.ropeproject
-
-# mkdocs documentation
-/site
-
-# mypy
-.mypy_cache/
-.dmypy.json
-dmypy.json
-
-# Pyre type checker
-.pyre/
--- a/toolfactory/.shed.yml	Mon Apr 26 05:25:26 2021 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-name: toolfactory
-owner: fubar
-description: ToolFactory - tool to make Galaxy tools ready for the toolshed
-homepage_url: https://github.com/fubar2/toolfactory
-long_description: |
-    ToolFactory - turn executable packages and R/python/perl/bash scripts into ordinary Galaxy tools
-
-    Creating re-usable tools from scripts: The Galaxy Tool Factory Ross Lazarus; Antony Kaspi; Mark Ziemann; The Galaxy Team 
-    Bioinformatics 2012; doi: 10.1093/bioinformatics/bts573
-remote_repository_url: https://github.com/fubar2/toolfactory
-type: tool_dependency_definition
-categories:
-- Tool Generators
--- a/toolfactory/README.md	Mon Apr 26 05:25:26 2021 +0000
+++ b/toolfactory/README.md	Tue Apr 27 23:33:49 2021 +0000
@@ -1,7 +1,9 @@
-## Breaking news! Completely refactored
+## Breaking news! Docker container at https://github.com/fubar2/toolfactory-galaxy-docker recommended as at December 2020
 
 ### New demonstration of planemo tool_factory command ![Planemo ToolFactory demonstration](images/lintplanemo-2021-01-08_18.02.45.mkv?raw=false "Demonstration inside Planemo")
 
+## This is the original ToolFactory suitable for non-docker situations. Please use the docker container if you can because it's integrated with a Toolshed...
+
 # WARNING
 
 Install this tool to a throw-away private Galaxy or Docker container ONLY!
--- a/toolfactory/ToolFactory.py	Mon Apr 26 05:25:26 2021 +0000
+++ b/toolfactory/ToolFactory.py	Tue Apr 27 23:33:49 2021 +0000
@@ -70,146 +70,41 @@
             citation_tuples.append(("bibtex", citation[len("bibtex") :].strip()))
     return citation_tuples
 
-class ToolTester():
-    # requires highly insecure docker settings - like write to tool_conf.xml and to tools !
-    # if in a container possibly not so courageous.
-    # Fine on your own laptop but security red flag for most production instances
-    # uncompress passed tar, run planemo and rebuild a new tarball with tests
-
-    def __init__(self, report_dir, in_tool_archive, new_tool_archive, include_tests, galaxy_root):
-        self.new_tool_archive = new_tool_archive
-        self.include_tests = include_tests
-        self.galaxy_root = galaxy_root
-        self.repdir = report_dir
-        assert in_tool_archive and tarfile.is_tarfile(in_tool_archive)
-        # this is not going to go well with arbitrary names. TODO introspect tool xml!
-        tff = tarfile.open(in_tool_archive, "r:*")
-        flist = tff.getnames()
-        ourdir = os.path.commonpath(flist) # eg pyrevpos
-        self.tool_name = ourdir
-        ourxmls = [x for x in flist if x.lower().endswith('.xml') and os.path.split(x)[0] == ourdir]
-        # planemo_test/planemo_test.xml
-        assert len(ourxmls) > 0
-        self.ourxmls = ourxmls # [os.path.join(tool_path,x) for x in ourxmls]
-        res = tff.extractall()
-        tff.close()
-        self.update_tests(ourdir)
-        self.tooloutdir = ourdir
-        self.testdir = os.path.join(self.tooloutdir, "test-data")
-        if not os.path.exists(self.tooloutdir):
-            os.mkdir(self.tooloutdir)
-        if not os.path.exists(self.testdir):
-            os.mkdir(self.testdir)
-        if not os.path.exists(self.repdir):
-            os.mkdir(self.repdir)
-        if not os.path.exists(self.tooloutdir):
-            os.mkdir(self.tooloutdir)
-        if not os.path.exists(self.testdir):
-            os.mkdir(self.testdir)
-        if not os.path.exists(self.repdir):
-            os.mkdir(self.repdir)
-        self.moveRunOutputs()
-        self.makeToolTar()
-
-    def call_planemo(self,xmlpath,ourdir):
-        penv = os.environ
-        penv['HOME'] = os.path.join(self.galaxy_root,'planemo')
-        #penv["GALAXY_VIRTUAL_ENV"] = os.path.join(penv['HOME'],'.planemo','gx_venv_3.9')
-        penv["PIP_CACHE_DIR"] = os.path.join(self.galaxy_root,'pipcache')
-        toolfile = os.path.split(xmlpath)[1]
-        tool_name = self.tool_name
-        tool_test_output = os.path.join(self.repdir, f"{tool_name}_planemo_test_report.html")
-        cll = ["planemo",
-            "test",
-            #"--job_config_file",
-            # os.path.join(self.galaxy_root,"config","job_conf.xml"),
-            #"--galaxy_python_version",
-            #"3.9",
-            "--test_output",
-            os.path.abspath(tool_test_output),
-            "--galaxy_root",
-            self.galaxy_root,
-            "--update_test_data",
-            os.path.abspath(xmlpath),
-        ]
-        print("Call planemo cl =", cll)
-        p = subprocess.run(
-            cll,
-            capture_output=True,
-            encoding='utf8',
-            env = penv,
-            shell=False,
-        )
-        return p
-
-    def makeToolTar(self):
-        """move outputs into test-data and prepare the tarball"""
-        excludeme = "_planemo_test_report.html"
-
-        def exclude_function(tarinfo):
-            filename = tarinfo.name
-            return None if filename.endswith(excludeme) else tarinfo
-
-        newtar = 'new_%s_toolshed.gz' % self.tool_name
-        ttf = tarfile.open(newtar, "w:gz")
-        ttf.add(name=self.tooloutdir,
-            arcname=self.tool_name,
-            filter=exclude_function)
-        ttf.close()
-        shutil.copyfile(newtar, self.new_tool_archive)
-
-    def move_One(self,scandir):
-        with os.scandir('.') as outs:
-            for entry in outs:
-                newname = entry.name
-                if not entry.is_file() or entry.name.endswith('_sample'):
-                    continue
-                if not (entry.name.endswith('.html') or entry.name.endswith('.gz') or entry.name.endswith(".tgz")):
-                    fname, ext = os.path.splitext(entry.name)
-                    if len(ext) > 1:
-                        newname = f"{fname}_{ext[1:]}.txt"
-                    else:
-                        newname = f"{fname}.txt"
-                dest = os.path.join(self.repdir, newname)
-                src = entry.name
-                shutil.copyfile(src, dest)
-
-    def moveRunOutputs(self):
-        """need to move planemo or run outputs into toolfactory collection"""
-        self.move_One(self.tooloutdir)
-        self.move_One('.')
-        if self.include_tests:
-            self.move_One(self.testdir)
-
-    def update_tests(self,ourdir):
-        for xmlf in self.ourxmls:
-            capture = self.call_planemo(xmlf,ourdir)
-            logf = open(f"%s_run_report" % (self.tool_name),'w')
-            logf.write("stdout:")
-            logf.write(capture.stdout)
-            logf.write("stderr:")
-            logf.write(capture.stderr)
-
-
 class ToolConfUpdater():
     # update config/tool_conf.xml with a new tool unpacked in /tools
     # requires highly insecure docker settings - like write to tool_conf.xml and to tools !
     # if in a container possibly not so courageous.
     # Fine on your own laptop but security red flag for most production instances
 
-    def __init__(self, args, tool_conf_path, new_tool_archive_path, new_tool_name, tool_dir):
+  def __init__(self, args, tool_conf_path, new_tool_archive_path, new_tool_name, tool_dir):
         self.args = args
-        self.tool_conf_path = tool_conf_path
+        self.tool_conf_path = os.path.join(args.galaxy_root,tool_conf_path)
+        self.tool_dir = os.path.join(args.galaxy_root, tool_dir)
         self.our_name = 'ToolFactory'
         tff = tarfile.open(new_tool_archive_path, "r:*")
         flist = tff.getnames()
         ourdir = os.path.commonpath(flist) # eg pyrevpos
         self.tool_id = ourdir # they are the same for TF tools
         ourxml = [x for x in flist if x.lower().endswith('.xml')]
-        res = tff.extractall(tool_dir)
+        res = tff.extractall()
         tff.close()
+        self.run_rsync(ourdir, self.tool_dir)
         self.update_toolconf(ourdir,ourxml)
 
+    def run_rsync(self, srcf, dstf):
+        src = os.path.abspath(srcf)
+        dst = os.path.abspath(dstf)
+        if os.path.isdir(src):
+            cll = ['rsync', '-vr', src, dst]
+        else:
+            cll = ['rsync', '-v', src, dst]
+        p = subprocess.run(
+            cll,
+            capture_output=False,
+            encoding='utf8',
+            shell=False,
+        )
+
     def install_deps(self):
         gi = galaxy.GalaxyInstance(url=self.args.galaxy_url, key=self.args.galaxy_api_key)
         x = gi.tools.install_dependencies(self.tool_id)
@@ -217,7 +112,9 @@
 
     def update_toolconf(self,ourdir,ourxml): # path is relative to tools
         updated = False
-        tree = ET.parse(self.tool_conf_path)
+        localconf = './local_tool_conf.xml'
+        self.run_rsync(self.tool_conf_path,localconf)
+        tree = ET.parse(localconf)
         root = tree.getroot()
         hasTF = False
         TFsection = None
@@ -235,7 +132,9 @@
                 updated = True
                 ET.SubElement(TFsection, 'tool', {'file':xml})
         ET.indent(tree)
-        tree.write(self.tool_conf_path, pretty_print=True)
+        newconf = f"{self.tool_id}_conf"
+        tree.write(newconf, pretty_print=True)
+        self.run_rsync(newconf,self.tool_conf_path)
         if False and self.args.packages and self.args.packages > '':
             self.install_deps()
 
@@ -1171,8 +1070,8 @@
     a("--include_tests", default=False, action="store_true")
     a("--install", default=False, action="store_true")
     a("--run_test", default=False, action="store_true")
-    a("--local_tools", default='tools') # relative to galaxy_root
-    a("--tool_conf_path", default='/galaxy_root/config/tool_conf.xml')
+    a("--local_tools", default='tools') # relative to $__root_dir__
+    a("--tool_conf_path", default='config/tool_conf.xml') # relative to $__root_dir__
     a("--galaxy_url", default="http://localhost:8080")
     a("--toolshed_url", default="http://localhost:9009")
     # make sure this is identical to tool_sheds_conf.xml
@@ -1203,8 +1102,8 @@
             tt = ToolTester(report_dir=r.repdir, in_tool_archive=r.newtarpath, new_tool_archive=r.args.new_tool, galaxy_root=args.galaxy_root, include_tests=False)
     if args.install:
         #try:
-        tcu = ToolConfUpdater(args=args, tool_dir=os.path.join(args.galaxy_root,args.local_tools),
-        new_tool_archive_path=r.newtarpath, tool_conf_path=os.path.join(args.galaxy_root,'config','tool_conf.xml'),
+        tcu = ToolConfUpdater(args=args, tool_dir=args.local_tools,
+        new_tool_archive_path=r.newtarpath, tool_conf_path=args.tool_conf_path,
         new_tool_name=r.tool_name)
         #except Exception:
         #   print("### Unable to install the new tool. Are you sure you have all the required special settings?")
--- a/toolfactory/ToolFactory.xml	Mon Apr 26 05:25:26 2021 +0000
+++ b/toolfactory/ToolFactory.xml	Tue Apr 27 23:33:49 2021 +0000
@@ -196,6 +196,7 @@
 <requirements>
      <requirement type="package" version="0.4.14">galaxyxml</requirement>
      <requirement type="package" version="0.15.0">bioblend</requirement>
+     <requirement type="package" version="3.2.3">rsync</requirement>
 </requirements>
 
 <command detect_errors="exit_code"><![CDATA[
--- a/toolfactory/ToolFactory_tester.py	Mon Apr 26 05:25:26 2021 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,202 +0,0 @@
-# see https://github.com/fubar2/toolfactory
-#
-# copyright ross lazarus (ross stop lazarus at gmail stop com) May 2012
-#
-# all rights reserved
-# Licensed under the LGPL
-# suggestions for improvement and bug fixes welcome at
-# https://github.com/fubar2/toolfactory
-#
-# July 2020: BCC was fun and I feel like rip van winkle after 5 years.
-# Decided to
-# 1. Fix the toolfactory so it works - done for simplest case
-# 2. Fix planemo so the toolfactory function works
-# 3. Rewrite bits using galaxyxml functions where that makes sense - done
-
-import argparse
-import copy
-import os
-import subprocess
-import shutil
-import sys
-import tarfile
-import tempfile
-import time
-
-myversion = "V2.2 April 2021"
-verbose = True
-debug = True
-toolFactoryURL = "https://github.com/fubar2/toolfactory"
-
-def timenow():
-    """return current time as a string"""
-    return time.strftime("%d/%m/%Y %H:%M:%S", time.localtime(time.time()))
-
-class ToolTester():
-    # requires highly insecure docker settings - like write to tool_conf.xml and to tools !
-    # if in a container possibly not so courageous.
-    # Fine on your own laptop but security red flag for most production instances
-    # uncompress passed tar, run planemo and rebuild a new tarball with tests
-
-    def __init__(self, args=None, in_tool_archive='/galaxy-central/tools/newtool/newtool_toolshed.gz', new_tool_archive=None):
-        self.args = args
-        self.new_tool_archive = new_tool_archive
-        assert tarfile.is_tarfile(in_tool_archive)
-        # this is not going to go well with arbitrary names. TODO introspect tool xml!
-        self.tooloutdir = "./tfout"
-        self.repdir = "./TF_run_report"
-        self.testdir = os.path.join(self.tooloutdir, "test-data")
-        if not os.path.exists(self.tooloutdir):
-            os.mkdir(self.tooloutdir)
-        if not os.path.exists(self.testdir):
-            os.mkdir(self.testdir)
-        if not os.path.exists(self.repdir):
-            os.mkdir(self.repdir)
-        tff = tarfile.open(in_tool_archive, "r:*")
-        flist = tff.getnames()
-        ourdir = os.path.commonpath(flist) # eg pyrevpos
-        self.tool_name = ourdir
-        ourxmls = [x for x in flist if x.lower().endswith('.xml') and os.path.split(x)[0] == ourdir]
-        assert len(ourxmls) > 0
-        self.ourxmls = ourxmls # [os.path.join(tool_path,x) for x in ourxmls]
-        res = tff.extractall()
-        tff.close()
-        self.update_tests(ourdir)
-        self.makeTool()
-        self.moveRunOutputs()
-        self.makeToolTar()
-
-    def call_planemo(self,xmlpath,ourdir):
-        penv = os.environ
-        penv['HOME'] = '/home/ross/galaxy-release_21.01'
-        toolfile = os.path.split(xmlpath)[1]
-        tool_name = self.tool_name
-        tool_test_output = f"{tool_name}_planemo_test_report.html"
-        cll = [
-            "planemo",
-            "test",
-            "--test_output",
-            os.path.abspath(tool_test_output),
-            "--galaxy_root",
-            self.args.galaxy_root,
-            "--update_test_data",
-            os.path.abspath(xmlpath),
-        ]
-        print(cll)
-        p = subprocess.run(
-            cll,
-            capture_output=True,
-            encoding='utf8',
-            env = penv,
-            shell=False,
-        )
-        return p
-
-    def makeTool(self):
-        """write xmls and input samples into place"""
-        for xreal in self.ourxmls:
-            x = os.path.split(xreal)[1]
-            xout = os.path.join(self.tooloutdir,x)
-            shutil.copyfile(xreal, xout)
-        # for p in self.infiles:
-            # pth = p["name"]
-            # dest = os.path.join(self.testdir, "%s_sample" % p["infilename"])
-            # shutil.copyfile(pth, dest)
-            # dest = os.path.join(self.repdir, "%s_sample" % p["infilename"])
-            # shutil.copyfile(pth, dest)
-
-    def makeToolTar(self):
-        """move outputs into test-data and prepare the tarball"""
-        excludeme = "_planemo_test_report.html"
-
-        def exclude_function(tarinfo):
-            filename = tarinfo.name
-            return None if filename.endswith(excludeme) else tarinfo
-
-        newtar = 'new_%s_toolshed.gz' % self.tool_name
-        ttf = tarfile.open(newtar, "w:gz")
-        ttf.add(name=self.tooloutdir,
-            arcname=self.tool_name,
-            filter=exclude_function)
-        ttf.close()
-        shutil.copyfile(newtar, self.new_tool_archive)
-
-    def moveRunOutputs(self):
-        """need to move planemo or run outputs into toolfactory collection"""
-        with os.scandir(self.tooloutdir) as outs:
-            for entry in outs:
-                if not entry.is_file():
-                    continue
-                if "." in entry.name:
-                    _, ext = os.path.splitext(entry.name)
-                    if ext in [".tgz", ".json"]:
-                        continue
-                    if ext in [".yml", ".xml", ".yaml"]:
-                        newname = f"{entry.name.replace('.','_')}.txt"
-                    else:
-                        newname = entry.name
-                else:
-                    newname = f"{entry.name}.txt"
-                dest = os.path.join(self.repdir, newname)
-                src = os.path.join(self.tooloutdir, entry.name)
-                shutil.copyfile(src, dest)
-        with os.scandir('.') as outs:
-            for entry in outs:
-                if not entry.is_file():
-                    continue
-                if "." in entry.name:
-                    _, ext = os.path.splitext(entry.name)
-                    if ext in [".yml", ".xml", ".yaml"]:
-                        newname = f"{entry.name.replace('.','_')}.txt"
-                    else:
-                        newname = entry.name
-                else:
-                    newname = f"{entry.name}.txt"
-                dest = os.path.join(self.repdir, newname)
-                src =entry.name
-                shutil.copyfile(src, dest)
-        if True or self.args.include_tests:
-            with os.scandir(self.testdir) as outs:
-                for entry in outs:
-                    if (not entry.is_file()) or entry.name.endswith(
-                        "_planemo_test_report.html"
-                    ):
-                        continue
-                    if "." in entry.name:
-                        _, ext = os.path.splitext(entry.name)
-                        if ext in [".tgz", ".json"]:
-                            continue
-                        if ext in [".yml", ".xml", ".yaml"]:
-                            newname = f"{entry.name.replace('.','_')}.txt"
-                        else:
-                            newname = entry.name
-                    else:
-                        newname = f"{entry.name}.txt"
-                    dest = os.path.join(self.repdir, newname)
-                    src = os.path.join(self.testdir, entry.name)
-                    shutil.copyfile(src, dest)
-
-
-    def update_tests(self,ourdir):
-        for xmlf in self.ourxmls:
-            capture = self.call_planemo(xmlf,ourdir)
-            #sys.stderr.write('%s, stdout=%s, stderr=%s' % (xmlf, capture.stdout, capture.stdout))
-            print('%s, stdout=%s, stderr=%s' % (capture.stdout, capture.stdout,xmlf))
-
-def main():
-    """
-    This is a Galaxy wrapper.
-    It expects to be called by a special purpose tool.xml
-
-    """
-    parser = argparse.ArgumentParser()
-    a = parser.add_argument
-    a("--in_tool_archive", default=None)
-    a("--new_tested_tool_archive", default=None)
-    a("--galaxy_root", default="/home/ross/galaxy-release_21.01/")
-    args = parser.parse_args()
-    print('Hello from',os.getcwd())
-    tt = ToolTester(args=args, in_tool_archive=args.in_tool_archive, new_tool_archive=args.new_tested_tool_archive)
-
-if __name__ == "__main__":
-    main()
Binary file toolfactory/images/TFasIDE.png has changed
Binary file toolfactory/images/dynamicScriptTool.png has changed
Binary file toolfactory/images/hello_toolfactory_form.png has changed
Binary file toolfactory/images/lintplanemo-2021-01-08_18.02.45.mkv has changed
--- a/toolfactory/install_tf_demos.py	Mon Apr 26 05:25:26 2021 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-import argparse
-import urllib.request
-
-from bioblend import galaxy
-
-WF = "https://drive.google.com/uc?export=download&id=13xE8o7tucHGNA0qYkEP98FfUGl2wdOU5"
-HIST = (
-    "https://drive.google.com/uc?export=download&id=1V0ZN9ZBuqcGJvt2AP7s3g0q11uYEhdDB"
-)
-WF_FILE = "tf_workflow.ga"
-HIST_FILE = "tf_history.tgz"
-
-
-def _parser():
-    parser = argparse.ArgumentParser()
-    parser.add_argument(
-        "-g", "--galaxy", help="URL of target galaxy", default="http://localhost:9090"
-    )
-    parser.add_argument("-a", "--key", help="Galaxy admin key", default=None)
-    return parser
-
-
-def main():
-    """
-    load the planemo tool_factory demonstration history and tool generating workflow
-    fails in planemo served galaxies because there seems to be no user in trans?
-    """
-    args = _parser().parse_args()
-    urllib.request.urlretrieve(WF, WF_FILE)
-    urllib.request.urlretrieve(HIST, HIST_FILE)
-    assert args.key, "Need an administrative key for the target Galaxy supplied please"
-    gi = galaxy.GalaxyInstance(
-        url=args.galaxy, key=args.key, email="planemo@galaxyproject.org"
-    )
-    x = gi.workflows.import_workflow_from_local_path(WF_FILE, publish=True)
-    print(f"installed {WF_FILE} Returned = {x}\n")
-    x = gi.histories.import_history(file_path=HIST_FILE)
-    print(f"installed {HIST_FILE} Returned = {x}\n")
-
-
-if __name__ == "__main__":
-    main()
--- a/toolfactory/maketf.sh	Mon Apr 26 05:25:26 2021 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-# if a new ubuntu image, will need a port mapped and add some basics first
-# apt update ; apt install -y python3-dev python3-venv python3-wheel nano curl wget git python3-setuptools
-TARGDIR="/galaxy-central"
-PDIR="/planemo"
-git clone --recursive https://github.com/fubar2/planemo.git $PDIR
-mkdir -p $TARGDIR
-curl -L -s https://github.com/galaxyproject/galaxy/archive/dev.tar.gz | tar xzf - --strip-components=1 -C $TARGDIR
-cd $PDIR
-mkdir mytools
-python3 -m venv .venv
-. .venv/bin/activate
-python3 setup.py build
-python3 setup.py install
-planemo conda_init --conda_prefix $PDIR/con
-/planemo/con/bin/conda init
-. ~/.bashrc
-/planemo/con/bin/conda activate base
-/planemo/con/bin/conda install -y -c bioconda -c conda-forge configparser galaxyxml
-# without this, planemo does not work in docker... No clue why but planemo goes all pear shaped
-# but pip reports that it's missing - installing it explicitly seems to do some kind of magic
-echo "Starting first run. This takes ages and includes building the Galaxy client. Be patient. Do something else for 20 minutes"
-. $PDIR/.venv/bin/activate
-planemo tool_factory --galaxy_root $TARGDIR --port 9090 --host 0.0.0.0 --conda_dependency_resolution --conda_auto_install 
-# planemo tool_factory --galaxy_root $TARGDIR --port 8080 --host 0.0.0.0 --conda_dependency_resolution --conda_auto_install 
-#planemo tool_factory --galaxy_root $TARGDIR --conda_prefix $PDIR/con --port 9090 --host 0.0.0.0
-# planemo serve --galaxy_root /galaxy-central/ --conda_prefix /planemo/con --port 8080 --host 0.0.0.0 --conda_dependency_resolution --conda_auto_install /planemo/.venv/lib/python3.8/site-packages/planemo-0.74.1-py3.8.egg/planemo_ext/tool_factory_2 
-# planemo serve --galaxy_root /galaxy-central/ --port 8080 --host 0.0.0.0 --conda_dependency_resolution --conda_auto_install /planemo/.venv/lib/python3.8/site-packages/planemo-0.74.1-py3.8.egg/planemo_ext/tool_factory_2 
-# planemo serve --galaxy_root $TARGDIR --port 8080 --host 0.0.0.0 --conda_dependency_resolution --conda_auto_install /usr/local/lib/python3.6/dist-packages/planemo-0.74.1-py3.6.egg/planemo_ext/tool_factory_2/
-
-# host is needed to get -p 9090:9090 to work in docker. Default 127.0.0.1 doesn't redirect :(ls -l /tmp
--- a/toolfactory/test-data/test1_log.txt	Mon Apr 26 05:25:26 2021 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-## Executing Toolfactory generated command line = python /tmp/pyrevposq5dmcdy1.python /tmp/tmpqrksf8sd/files/5/b/9/dataset_5b952a86-87df-44ad-a415-ea549f3f0cee.dat output2
--- a/toolfactory/tfout/.shed.yml	Mon Apr 26 05:25:26 2021 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-category: TF Generated Tools
-description: Makes random plots
-name: plotter
-owner: planemo
-synopsis: Makes random plots
-type: unrestricted
--- a/toolfactory/tfout/plotter.xml	Mon Apr 26 05:25:26 2021 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-<tool name="plotter" id="plotter" version="0.01">
-  <!--Source in git at: https://github.com/fubar2/toolfactory-->
-  <!--Created by planemo@galaxyproject.org at 31/03/2021 10:58:49 using the Galaxy Tool Factory.-->
-  <description>Makes random plots</description>
-  <requirements>
-    <requirement version="" type="package">r-base</requirement>
-  </requirements>
-  <stdio>
-    <exit_code range="1:" level="fatal"/>
-  </stdio>
-  <expand macro="stdio"/>
-  <version_command><![CDATA[echo "0.01"]]></version_command>
-  <command><![CDATA[Rscript
-$runme
-"$nplot"]]></command>
-  <configfiles>
-    <configfile name="runme"><![CDATA[
-\# demo
-args = commandArgs(trailingOnly=TRUE)
-if (length(args)==0) {
-   n_plots = 3
-} else {
-   n_plots = as.integer(args[1]) }
-dir.create('plots')
-for (i in 1:n_plots) {
-    foo = runif(100)
-    bar = rnorm(100)
-    bar = foo + 0.05*bar
-    pdf(paste('plots/yet',i,"anotherplot.pdf",sep='_'))
-    plot(foo,bar,main=paste("Foo by Bar plot \#",i),col="maroon", pch=3,cex=0.6)
-    dev.off()
-    foo = data.frame(a=runif(100),b=runif(100),c=runif(100),d=runif(100),e=runif(100),f=runif(100))
-    bar = as.matrix(foo)
-    pdf(paste('plots/yet',i,"anotherheatmap.pdf",sep='_'))
-    heatmap(bar,main='Random Heatmap')
-    dev.off()
-}
-
-]]></configfile>
-  </configfiles>
-  <inputs>
-    <param name="nplot" type="text" value="3" label="Number of random plots pairs to draw" help=""/>
-  </inputs>
-  <outputs>
-    <collection name="plots" type="list" label="Plots">
-      <discover_datasets pattern="__name_and_ext__" directory="plots" visible="false"/>
-    </collection>
-  </outputs>
-  <tests>
-    <test>
-      <param name="nplot" value="3"/>
-      <output_collection name="plots"/>
-    </test>
-  </tests>
-  <help><![CDATA[
-
-**What it Does**
-
-Makes plots into a collection demonstration
-
- 
-
-------
-
-
-Script::
-
-    # demo
-    args = commandArgs(trailingOnly=TRUE)
-    if (length(args)==0) {
-       n_plots = 3
-    } else {
-       n_plots = as.integer(args[1]) }
-    dir.create('plots')
-    for (i in 1:n_plots) {
-        foo = runif(100)
-        bar = rnorm(100)
-        bar = foo + 0.05*bar
-        pdf(paste('plots/yet',i,"anotherplot.pdf",sep='_'))
-        plot(foo,bar,main=paste("Foo by Bar plot #",i),col="maroon", pch=3,cex=0.6)
-        dev.off()
-        foo = data.frame(a=runif(100),b=runif(100),c=runif(100),d=runif(100),e=runif(100),f=runif(100))
-        bar = as.matrix(foo)
-        pdf(paste('plots/yet',i,"anotherheatmap.pdf",sep='_'))
-        heatmap(bar,main='Random Heatmap')
-        dev.off()
-    }
-
-]]></help>
-  <citations>
-    <citation type="doi">10.1093/bioinformatics/bts573</citation>
-  </citations>
-</tool>
-