diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..c30764f --- /dev/null +++ b/.coveragerc @@ -0,0 +1,5 @@ +[html] +directory = ./python-coverage + +[xml] +output = ./python-coverage/coverage.xml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..512f0b0 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,19 @@ +version: 2 +updates: +- package-ecosystem: docker + directory: "/" + schedule: + interval: monthly + time: '11:00' + open-pull-requests-limit: 10 +- package-ecosystem: pip + directory: "/" + schedule: + interval: monthly + time: '11:00' + open-pull-requests-limit: 10 +- package-ecosystem: "github-actions" + directory: ".github/workflows" + schedule: + interval: "monthly" + open-pull-requests-limit: 10 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..c90635b --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,47 @@ +name: "CodeQL" + +on: + push: + branches: + - develop + - main + - master + pull_request: + types: + - opened + - reopened + - synchronize + - closed + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [python] + + steps: + - name: Checkout + uses: actions/checkout@master + + - name: Initialize CodeQL + uses: github/codeql-action/init@main + with: + languages: ${{ matrix.language }} + queries: +security-and-quality + + - name: Autobuild + uses: github/codeql-action/autobuild@main + if: ${{ matrix.language == 'javascript' || matrix.language == 'python' }} + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@main + with: + category: "/language:${{ matrix.language }}" diff --git a/.github/workflows/kb_sdk_test.yaml b/.github/workflows/kb_sdk_test.yaml index a31e626..6c294ef 100644 --- a/.github/workflows/kb_sdk_test.yaml +++ b/.github/workflows/kb_sdk_test.yaml @@ -1,62 +1,49 @@ name: KBase SDK Tests on: - push: - branches: - - master - - main - pull_request: - branches: - - master - - main - - develop + pull_request: + branches: + - main + - develop jobs: - - sdk_tests: - runs-on: ubuntu-latest - steps: - - - name: Check out GitHub repo - if: "!contains(github.event.head_commit.message, 'skip ci')" - uses: actions/checkout@v2 - - - name: Check out Actions CI files - if: "!contains(github.event.head_commit.message, 'skip ci')" - uses: actions/checkout@v2 - with: - repository: 'kbaseapps/kb_sdk_actions' - path: 'kb_sdk_actions' - - - - name: Set up test environment - if: "!contains(github.event.head_commit.message, 'skip ci')" - shell: bash - env: - KBASE_TEST_TOKEN: ${{ secrets.KBASE_TEST_TOKEN }} - run: | - # Verify kb_sdk_actions clone worked - test -f "$HOME/kb_sdk_actions/bin/kb-sdk" && echo "CI files cloned" - # Pull kb-sdk & create startup script - docker pull kbase/kb-sdk - - sh $GITHUB_WORKSPACE/kb_sdk_actions/bin/make_testdir && echo "Created test_local" - test -f "test_local/test.cfg" && echo "Confirmed config exists" - - - name: Configure authentication - if: "!contains(github.event.head_commit.message, 'skip ci')" - shell: bash - env: - KBASE_TEST_TOKEN: ${{ secrets.KBASE_TEST_TOKEN }} - run: | - # Add token to config - sed -ie "s/^test_token=.*$/&$KBASE_TEST_TOKEN/g" ./test_local/test.cfg - - - name: Run tests - if: "!contains(github.event.head_commit.message, 'skip ci')" - shell: bash - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - run: | - sh $GITHUB_WORKSPACE/kb_sdk_actions/bin/kb-sdk test - bash <(curl -s https://codecov.io/bash) + sdk_tests: + runs-on: ubuntu-latest + steps: + - name: Check out GitHub repo + uses: actions/checkout@master + + - name: Set up test environment + shell: bash + run: | + # Cache the group for the docker file + if [ ! -e $HOME/.kbsdk.cache ] ; then + docker run -i -v /var/run/docker.sock:/var/run/docker.sock --entrypoint ls ghcr.io/kbase/kb_sdk_patch-develop:br-0.0.4-rc-1 -l /var/run/docker.sock|awk '{print $4}' > $HOME/.kbsdk.cache + fi + + + # ignore the exit code + docker run -i --rm -v $HOME:$HOME -u $(id -u) -w $(pwd) -v /var/run/docker.sock:/var/run/docker.sock -e DUSER=$USER -e DSHELL=$SHELL --group-add $(cat $HOME/.kbsdk.cache) ghcr.io/kbase/kb_sdk_patch-develop:br-0.0.4-rc-1 test || true + + - name: Confirm config exists and add token + shell: bash + env: + KBASE_TEST_TOKEN: ${{ secrets.KBASE_TEST_TOKEN }} + run: | + test -f "test_local/test.cfg" && echo "Confirmed config exists" + # Add token to config + sed -ie "s/^test_token=.*$/&$KBASE_TEST_TOKEN/g" ./test_local/test.cfg + + - name: Run tests + shell: bash + run: | + docker run -i --rm -v $HOME:$HOME -w $(pwd) -v /var/run/docker.sock:/var/run/docker.sock -e DSHELL=$SHELL --group-add $(cat $HOME/.kbsdk.cache) ghcr.io/kbase/kb_sdk_patch-develop:br-0.0.4-rc-1 test --verbose + + - name: Upload coverage to Codecov + id: send_to_codecov + uses: codecov/codecov-action@main + continue-on-error: true + with: + files: ./python-coverage/coverage.xml + fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/Dockerfile b/Dockerfile index 14978df..3b8b70d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,11 +17,10 @@ RUN update-ca-certificates # Install ETE3 -RUN apt-get update && \ - apt-get -y install xvfb +RUN apt-get -y install xvfb RUN pip install --upgrade pip # Note: You must use PyQt5==5.11.3 on debian -RUN pip install ete3==3.1.2 PyQt5==5.11.3 numpy==1.23.1 +RUN pip install ete3==3.1.2 PyQt5==5.11.3 numpy==1.23.1 pytest coverage pytest-cov # ----------------------------------------- @@ -37,16 +36,11 @@ RUN make all # RUN mkdir -p /kb/module/FastTree/bin WORKDIR /kb/module/FastTree/bin -RUN curl -o FastTree2.1.11_64 http://www.microbesonline.org/fasttree/FastTree && \ -#RUN \ -# git clone https://github.com/kbaseapps/kb_fasttree && \ -# cp kb_fasttree/src/FastTree2.1.11_64 . && \ - chmod 555 FastTree2.1.11_64 && \ - ln -s FastTree2.1.11_64 FastTree +RUN curl -o FastTree http://www.microbesonline.org/fasttree/FastTree && \ + chmod 555 FastTree WORKDIR /kb/module ENTRYPOINT [ "./scripts/entrypoint.sh" ] CMD [ ] - diff --git a/Makefile b/Makefile index ac281b1..ebe37db 100644 --- a/Makefile +++ b/Makefile @@ -10,15 +10,18 @@ LBIN_DIR = bin EXECUTABLE_SCRIPT_NAME = run_$(SERVICE_CAPS)_async_job.sh STARTUP_SCRIPT_NAME = start_server.sh TEST_SCRIPT_NAME = run_tests.sh +COMPILE_REPORT = ./compile_report.json .PHONY: test default: compile -all: compile build build-startup-script build-executable-script build-test-script +all: build compile compile: - kb-sdk compile $(SPEC_FILE) \ + rm $(COMPILE_REPORT) || true + KB_SDK_COMPILE_REPORT_FILE=$(COMPILE_REPORT) kb-sdk compile $(SPEC_FILE) \ + --verbose \ --out $(LIB_DIR) \ --plclname $(SERVICE_CAPS)::$(SERVICE_CAPS)Client \ --jsclname javascript/Client \ @@ -31,33 +34,6 @@ compile: build: chmod +x $(SCRIPTS_DIR)/entrypoint.sh -build-executable-script: - mkdir -p $(LBIN_DIR) - echo '#!/bin/bash' > $(LBIN_DIR)/$(EXECUTABLE_SCRIPT_NAME) - echo 'script_dir=$$(dirname "$$(readlink -f "$$0")")' >> $(LBIN_DIR)/$(EXECUTABLE_SCRIPT_NAME) - echo 'export PYTHONPATH=$$script_dir/../$(LIB_DIR):$$PATH:$$PYTHONPATH' >> $(LBIN_DIR)/$(EXECUTABLE_SCRIPT_NAME) - echo 'python -u $$script_dir/../$(LIB_DIR)/$(SERVICE_CAPS)/$(SERVICE_CAPS)Server.py $$1 $$2 $$3' >> $(LBIN_DIR)/$(EXECUTABLE_SCRIPT_NAME) - chmod +x $(LBIN_DIR)/$(EXECUTABLE_SCRIPT_NAME) - -build-startup-script: - mkdir -p $(LBIN_DIR) - echo '#!/bin/bash' > $(SCRIPTS_DIR)/$(STARTUP_SCRIPT_NAME) - echo 'script_dir=$$(dirname "$$(readlink -f "$$0")")' >> $(SCRIPTS_DIR)/$(STARTUP_SCRIPT_NAME) - echo 'export KB_DEPLOYMENT_CONFIG=$$script_dir/../deploy.cfg' >> $(SCRIPTS_DIR)/$(STARTUP_SCRIPT_NAME) - echo 'export PYTHONPATH=$$script_dir/../$(LIB_DIR):$$PATH:$$PYTHONPATH' >> $(SCRIPTS_DIR)/$(STARTUP_SCRIPT_NAME) - echo 'uwsgi --master --processes 5 --threads 5 --http :5000 --wsgi-file $$script_dir/../$(LIB_DIR)/$(SERVICE_CAPS)/$(SERVICE_CAPS)Server.py' >> $(SCRIPTS_DIR)/$(STARTUP_SCRIPT_NAME) - chmod +x $(SCRIPTS_DIR)/$(STARTUP_SCRIPT_NAME) - -build-test-script: - echo '#!/bin/bash' > $(TEST_DIR)/$(TEST_SCRIPT_NAME) - echo 'script_dir=$$(dirname "$$(readlink -f "$$0")")' >> $(TEST_DIR)/$(TEST_SCRIPT_NAME) - echo 'export KB_DEPLOYMENT_CONFIG=$$script_dir/../deploy.cfg' >> $(TEST_DIR)/$(TEST_SCRIPT_NAME) - echo 'export KB_AUTH_TOKEN=`cat /kb/module/work/token`' >> $(TEST_DIR)/$(TEST_SCRIPT_NAME) - echo 'export PYTHONPATH=$$script_dir/../$(LIB_DIR):$$PATH:$$PYTHONPATH' >> $(TEST_DIR)/$(TEST_SCRIPT_NAME) - echo 'cd $$script_dir/../$(TEST_DIR)' >> $(TEST_DIR)/$(TEST_SCRIPT_NAME) - echo 'python -m nose --with-coverage --cover-package=$(SERVICE_CAPS) --cover-html --cover-html-dir=/kb/module/work/test_coverage --nocapture --nologcapture .' >> $(TEST_DIR)/$(TEST_SCRIPT_NAME) - chmod +x $(TEST_DIR)/$(TEST_SCRIPT_NAME) - test: if [ ! -f /kb/module/work/token ]; then echo -e '\nOutside a docker container please run "kb-sdk test" rather than "make test"\n' && exit 1; fi xvfb-run bash $(TEST_DIR)/$(TEST_SCRIPT_NAME) diff --git a/compile_report.json b/compile_report.json new file mode 100644 index 0000000..435cecb --- /dev/null +++ b/compile_report.json @@ -0,0 +1 @@ +{"functions":{"run_FastTree":{"name":"run_FastTree","comment":"Method for Tree building of either DNA or PROTEIN sequences\n**\n** input_type: MSA\n** output_type: Tree","place":null,"input":[{"type":"kb_fasttree.FastTree_Params","comment":"FastTree Input Params"}],"output":[{"type":"kb_fasttree.FastTree_Output","comment":"FastTree Output"}]}},"module_name":"kb_fasttree","sdk_version":"1.2.6","sdk_git_commit":"cedcfc2326db32bbdb09eb6d031838a93853c530","impl_file_path":"lib/kb_fasttree/kb_fasttreeImpl.py","spec_files":[{"content":"/*\n** A KBase module: kb_fasttree\n**\n** This module runs FastTree to make Trees for either DNA or PROTEIN MSAs\n** \n*/\n\nmodule kb_fasttree {\n\n /* \n ** The workspace object refs are of form:\n **\n ** objects = ws.get_objects([{'ref': params['workspace_id']+'/'+params['obj_name']}])\n **\n ** \"ref\" means the entire name combining the workspace id and the object name\n ** \"id\" is a numerical identifier of the workspace or object, and should just be used for workspace\n ** \"name\" is a string identifier of a workspace or object. This is received from Narrative.\n */\n typedef string workspace_name;\n typedef string data_obj_name;\n typedef string data_obj_ref;\n\n\n /* FastTree Input Params\n */\n typedef structure {\n workspace_name workspace_name;\n\tstring desc;\n\tdata_obj_ref input_ref;\n data_obj_name output_name;\n\tint species_tree_flag; /* boolean */\n\tdata_obj_ref intree_ref;\n\tint fastest; /* boolean */\n\tint pseudo; /* boolean */\n\tint gtr; /* boolean */\n\tint wag; /* boolean */\n\tint noml; /* boolean */\n\tint nome; /* boolean */\n int cat; /* actually is an int */\n\tint nocat; /* boolean */\n int gamma; /* boolean */\n } FastTree_Params;\n\n\n /* FastTree Output\n */\n typedef structure {\n\tdata_obj_name report_name;\n\tdata_obj_ref report_ref;\n data_obj_ref output_ref;\n } FastTree_Output;\n\t\n\n /* Method for Tree building of either DNA or PROTEIN sequences\n **\n ** input_type: MSA\n ** output_type: Tree\n */\n funcdef run_FastTree (FastTree_Params params) returns (FastTree_Output) authentication required;\n};\n","file_name":"kb_fasttree.spec","is_main":1}],"function_places":{}} \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..684b9ee --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,123 @@ +[tool.ruff] +line-length = 100 + +extend-exclude = [ + "lib/installed_clients/*" +] + +# Assume Python 3.12. +target-version = "py312" + +[tool.ruff.lint] +select = [ + # core + "F", # Pyflakes + "E", # pycodestyle errors + "W", # pycodestyle warnings + "C90", # mccabe + + "I", # isort + "N", # pep8-naming + "D", # pydocstyle + "UP", # pyupgrade + # extensions + "YTT", # flake8-2020 + "ANN", # flake8-annotations + "ASYNC", # flake8-async + "S", # flake8-bandit + "BLE", # flake8-blind-except + "FBT", # flake8-boolean-trap + "B", # flake8-bugbear + "A", # flake8-builtins + # "COM", # flake8-commas + "CPY", # flake8-copyright + "C4", # flake8-comprehensions + "DTZ", # flake8-datetimez + "T10", # flake8-debugger + # "DJ", # flake8-django + "EM", # flake8-errmsg + "EXE", # flake8-executable + "FA", # flake8-future-annotations + "ISC", # flake8-implicit-str-concat + "ICN", # flake8-import-conventions + "G", # flake8-logging-format + "INP", # flake8-no-pep420 + "PIE", # flake8-pie + "T20", # flake8-print + "PYI", # flake8-pyi + "PT", # flake8-pytest-style + "Q", # flake8-quotes + "RSE", # flake8-raise + "RET", # flake8-return + "SLF", # flake8-self + # "SLOT", # flake8-slots + "SIM", # flake8-simplify + "TID", # flake8-tidy-imports + "TCH", # flake8-type-checking + "INT", # flake8-gettext + "ARG", # flake8-unused-arguments + "PTH", # flake8-use-pathlib + "TD", # flake8-todos + "FIX", # flake8-fixme + "ERA", # eradicate + # "PD", # pandas-vet + "PGH", # pygrep-hooks + "PL", # Pylint + "TRY", # tryceratops + "FLY", # flynt + # "NPY", # NumPy-specific rules + "AIR", # Airflow + "PERF", # Perflint + "FURB", # refurb + "LOG", # flake8-logging + "RUF", # Ruff-specific rules +] + +# E203: whitespace before ‘,’, ‘;’, or ‘:’ +# E501: line length +# ISC001: conflicts with Ruff's formatter +# W503: line break after binary operator +ignore = [ + "E203", + "E501", + "ISC001", + "S101", +] + +# Allow autofix for all enabled rules (when `--fix`) is provided. +fixable = ["ALL"] +unfixable = [] + +# Exclude a variety of commonly ignored directories. +exclude = [ + "__pypackages__", + "_build", + ".bzr", + ".direnv", + ".eggs", + ".git-rewrite", + ".git", + ".github", + ".hg", + ".mypy_cache", + ".nox", + ".pants.d", + ".pytype", + ".ruff_cache", + ".svn", + ".tox", + ".venv", + "*.pyc", + "buck-out", + "build", + "deps", + "dist", + "node_modules", + "other_schema", + "python-coverage", + "sample_data", + "venv", +] +per-file-ignores = {} + +[tool.ruff.lint.pydocstyle] +convention = "google" diff --git a/test/kb_fasttree_server_test.py b/test/kb_fasttree_server_test.py index 5ddaa33..88c3f35 100644 --- a/test/kb_fasttree_server_test.py +++ b/test/kb_fasttree_server_test.py @@ -1,50 +1,61 @@ -import unittest -import os +"""Tests for the kb_fasttree implementation.""" + import json import time -import uuid - -from os import environ +import unittest from configparser import ConfigParser # py3 -from pprint import pprint +from os import environ +from pathlib import Path from installed_clients.WorkspaceClient import Workspace as workspaceService from kb_fasttree.kb_fasttreeImpl import kb_fasttree +# Set a variable to refer to the test directory +TEST_BASE_DIR = Path(__file__).resolve().parent + +MSA_JSON_FILE = TEST_BASE_DIR / "data" / "DsrA.MSA.json" -class kb_fasttreeTest(unittest.TestCase): +class kb_fasttreeTest(unittest.TestCase): @classmethod def setUpClass(cls): - token = environ.get('KB_AUTH_TOKEN', None) - cls.ctx = {'token': token, 'provenance': [{'service': 'kb_fasttree', - 'method': 'please_never_use_it_in_production', 'method_params': []}], - 'authenticated': 1} - config_file = environ.get('KB_DEPLOYMENT_CONFIG', None) + token = environ.get("KB_AUTH_TOKEN", None) + cls.ctx = { + "token": token, + "provenance": [ + { + "service": "kb_fasttree", + "method": "please_never_use_it_in_production", + "method_params": [], + } + ], + "authenticated": 1, + } + config_file = environ.get("KB_DEPLOYMENT_CONFIG", None) cls.cfg = {} config = ConfigParser() config.read(config_file) - for nameval in config.items('kb_fasttree'): + for nameval in config.items("kb_fasttree"): cls.cfg[nameval[0]] = nameval[1] - cls.wsURL = cls.cfg['workspace-url'] + cls.wsURL = cls.cfg["workspace-url"] cls.wsClient = workspaceService(cls.wsURL, token=token) cls.serviceImpl = kb_fasttree(cls.cfg) @classmethod def tearDownClass(cls): - if hasattr(cls, 'wsName'): - cls.wsClient.delete_workspace({'workspace': cls.wsName}) - print('Test workspace was deleted') + if hasattr(cls, "wsName"): + cls.wsClient.delete_workspace({"workspace": cls.wsName}) + print("Test workspace was deleted") def getWsClient(self): return self.__class__.wsClient def getWsName(self): - if hasattr(self.__class__, 'wsName'): + if hasattr(self.__class__, "wsName"): return self.__class__.wsName suffix = int(time.time() * 1000) wsName = "test_kb_fasttree_" + str(suffix) - ret = self.getWsClient().create_workspace({'workspace': wsName}) + ret = self.getWsClient().create_workspace({"workspace": wsName}) self.__class__.wsName = wsName return wsName @@ -54,17 +65,15 @@ def getImpl(self): def getContext(self): return self.__class__.ctx - ############## # UNIT TESTS # ############## - #### basic fasttree test ## # HIDE @unittest.skip("skipped test_kb_fasttree_run_FastTree_01()") # uncomment to skip def test_kb_fasttree_run_FastTree_01(self): - # Prepare test objects in workspace if needed using + # Prepare test objects in workspace if needed using # self.getWsClient().save_objects({'workspace': self.getWsName(), 'objects': []}) # # Run your method by @@ -73,57 +82,72 @@ def test_kb_fasttree_run_FastTree_01(self): # Check returned data with # self.assertEqual(ret[...], ...) or other unittest methods - obj_basename = 'fasttree' - obj_out_name = obj_basename+'.'+"test_fasttree.Tree" - obj_out_type = 'KBaseTrees.Tree' + obj_basename = "fasttree" + obj_out_name = obj_basename + "." + "test_fasttree.Tree" + obj_out_type = "KBaseTrees.Tree" # MSA - MSA_json_file = os.path.join('data', 'DsrA.MSA.json') - with open (MSA_json_file, 'r') as MSA_json_fh: - MSA_obj = json.load(MSA_json_fh) + with MSA_JSON_FILE.open() as msa_json_fh: + msa_obj = json.load(msa_json_fh) provenance = [{}] - MSA_info = self.getWsClient().save_objects({ - 'workspace': self.getWsName(), - 'objects': [ - { - 'type': 'KBaseTrees.MSA', - 'data': MSA_obj, - 'name': 'test_MSA', - 'meta': {}, - 'provenance': provenance - } - ]})[0] - - [OBJID_I, NAME_I, TYPE_I, SAVE_DATE_I, VERSION_I, SAVED_BY_I, WSID_I, WORKSPACE_I, CHSUM_I, SIZE_I, META_I] = range(11) # object_info tuple - MSA_ref = str(MSA_info[WSID_I])+'/'+str(MSA_info[OBJID_I])+'/'+str(MSA_info[VERSION_I]) - - parameters = { 'workspace_name': self.getWsName(), - 'desc': 'test_FastTree', - 'input_ref': MSA_ref, - 'output_name': obj_out_name, - 'species_tree_flag': "0", - 'intree_ref': "", - 'fastest': "0", - 'pseudo': "0", - 'gtr': "0", - 'wag': "0", - 'noml': "0", - 'nome': "0", - 'cat': "20", - 'nocat': "0", - 'gamma': "0" - } + msa_info = self.getWsClient().save_objects( + { + "workspace": self.getWsName(), + "objects": [ + { + "type": "KBaseTrees.MSA", + "data": msa_obj, + "name": "test_MSA", + "meta": {}, + "provenance": provenance, + } + ], + } + )[0] + + [ + OBJID_I, + NAME_I, + TYPE_I, + SAVE_DATE_I, + VERSION_I, + SAVED_BY_I, + WSID_I, + WORKSPACE_I, + CHSUM_I, + SIZE_I, + META_I, + ] = range(11) # object_info tuple + msa_ref = f"{msa_info[WSID_I]}/{msa_info[OBJID_I]}/{msa_info[VERSION_I]}" + + parameters = { + "workspace_name": self.getWsName(), + "desc": "test_FastTree", + "input_ref": msa_ref, + "output_name": obj_out_name, + "species_tree_flag": "0", + "intree_ref": "", + "fastest": "0", + "pseudo": "0", + "gtr": "0", + "wag": "0", + "noml": "0", + "nome": "0", + "cat": "20", + "nocat": "0", + "gamma": "0", + } ret = self.getImpl().run_FastTree(self.getContext(), parameters)[0] - self.assertIsNotNone(ret['report_ref']) + self.assertIsNotNone(ret["report_ref"]) # check created obj - #report_obj = self.getWsClient().get_objects2({'objects':[{'ref':ret['report_ref']}]})[0]['data'] - report_obj = self.getWsClient().get_objects([{'ref':ret['report_ref']}])[0]['data'] - self.assertIsNotNone(report_obj['objects_created'][0]['ref']) + report_obj = self.getWsClient().get_objects([{"ref": ret["report_ref"]}])[0]["data"] + self.assertIsNotNone(report_obj["objects_created"][0]["ref"]) - created_obj_0_info = self.getWsClient().get_object_info_new({'objects':[{'ref':report_obj['objects_created'][0]['ref']}]})[0] + created_obj_0_info = self.getWsClient().get_object_info_new( + {"objects": [{"ref": report_obj["objects_created"][0]["ref"]}]} + )[0] self.assertEqual(created_obj_0_info[NAME_I], obj_out_name) - self.assertEqual(created_obj_0_info[TYPE_I].split('-')[0], obj_out_type) - pass + self.assertEqual(created_obj_0_info[TYPE_I].split("-")[0], obj_out_type) diff --git a/test/run_tests.sh b/test/run_tests.sh index 8d93b67..80dc50d 100755 --- a/test/run_tests.sh +++ b/test/run_tests.sh @@ -3,5 +3,14 @@ script_dir=$(dirname "$(readlink -f "$0")") export KB_DEPLOYMENT_CONFIG=$script_dir/../deploy.cfg export KB_AUTH_TOKEN=`cat /kb/module/work/token` export PYTHONPATH=$script_dir/../lib:$PATH:$PYTHONPATH -cd $script_dir/../test -python -u -m unittest discover -p "*_test.py" + +# run without collecting coverage data +# pytest -vv test + +# collect coverage data +pytest \ + --cov=lib/ \ + --cov-config=.coveragerc \ + --cov-report=html \ + --cov-report=xml \ + test diff --git a/ui/narrative/methods/run_FastTree/spec.json b/ui/narrative/methods/run_FastTree/spec.json index f9aa92b..74f5c5e 100644 --- a/ui/narrative/methods/run_FastTree/spec.json +++ b/ui/narrative/methods/run_FastTree/spec.json @@ -2,36 +2,45 @@ "ver": "1.1.0", "authors": [ "dylan", - "psdehal" + "psdehal" ], "contact": "http://www.kbase.us/support/", "visible": true, - "categories": ["active","comparative_genomics"], + "categories": [ + "active", + "comparative_genomics" + ], "widgets": { "input": null, "output": "no-display" }, - "parameters": [ + "parameters": [ { "id": "desc", "optional": false, "advanced": false, "allow_multiple": false, - "default_values": [ "" ], + "default_values": [ + "" + ], "field_type": "text", - "text_options": { - "is_output_name": false - } + "text_options": { + "is_output_name": false + } }, { "id": "input_ref", "optional": true, "advanced": false, "allow_multiple": false, - "default_values": [ "" ], + "default_values": [ + "" + ], "field_type": "text", "text_options": { - "valid_ws_types": [ "KBaseTrees.MSA" ] + "valid_ws_types": [ + "KBaseTrees.MSA" + ] } }, { @@ -39,11 +48,15 @@ "optional": false, "advanced": false, "allow_multiple": false, - "default_values": [ "" ], + "default_values": [ + "" + ], "field_type": "text", "text_options": { - "valid_ws_types": [ "KBaseTrees.Tree" ], - "is_output_name": true + "valid_ws_types": [ + "KBaseTrees.Tree" + ], + "is_output_name": true } }, { @@ -51,11 +64,13 @@ "optional": true, "advanced": false, "allow_multiple": false, - "default_values": [ "" ], + "default_values": [ + "" + ], "field_type": "checkbox", "checkbox_options": { - "checked_value": "1", - "unchecked_value": "0" + "checked_value": "1", + "unchecked_value": "0" } }, { @@ -63,10 +78,14 @@ "optional": true, "advanced": true, "allow_multiple": false, - "default_values": [ "" ], + "default_values": [ + "" + ], "field_type": "text", "text_options": { - "valid_ws_types": [ "KBaseTrees.Tree" ] + "valid_ws_types": [ + "KBaseTrees.Tree" + ] } }, { @@ -74,11 +93,13 @@ "optional": true, "advanced": true, "allow_multiple": false, - "default_values": [ "" ], + "default_values": [ + "" + ], "field_type": "checkbox", "checkbox_options": { - "checked_value": "1", - "unchecked_value": "0" + "checked_value": "1", + "unchecked_value": "0" } }, { @@ -86,11 +107,13 @@ "optional": true, "advanced": true, "allow_multiple": false, - "default_values": [ "" ], + "default_values": [ + "" + ], "field_type": "checkbox", "checkbox_options": { - "checked_value": "1", - "unchecked_value": "0" + "checked_value": "1", + "unchecked_value": "0" } }, { @@ -98,11 +121,13 @@ "optional": true, "advanced": true, "allow_multiple": false, - "default_values": [ "" ], + "default_values": [ + "" + ], "field_type": "checkbox", "checkbox_options": { - "checked_value": "1", - "unchecked_value": "0" + "checked_value": "1", + "unchecked_value": "0" } }, { @@ -110,11 +135,13 @@ "optional": true, "advanced": true, "allow_multiple": false, - "default_values": [ "" ], + "default_values": [ + "" + ], "field_type": "checkbox", "checkbox_options": { - "checked_value": "1", - "unchecked_value": "0" + "checked_value": "1", + "unchecked_value": "0" } }, { @@ -122,11 +149,13 @@ "optional": true, "advanced": true, "allow_multiple": false, - "default_values": [ "" ], + "default_values": [ + "" + ], "field_type": "checkbox", "checkbox_options": { - "checked_value": "1", - "unchecked_value": "0" + "checked_value": "1", + "unchecked_value": "0" } }, { @@ -134,11 +163,13 @@ "optional": true, "advanced": true, "allow_multiple": false, - "default_values": [ "" ], + "default_values": [ + "" + ], "field_type": "checkbox", "checkbox_options": { - "checked_value": "1", - "unchecked_value": "0" + "checked_value": "1", + "unchecked_value": "0" } }, { @@ -146,11 +177,13 @@ "optional": true, "advanced": true, "allow_multiple": false, - "default_values": [ "20" ], + "default_values": [ + "20" + ], "field_type": "text", "text_options": { "validate_as": "int", - "min_integer" : 1 + "min_integer": 1 } }, { @@ -158,11 +191,13 @@ "optional": true, "advanced": true, "allow_multiple": false, - "default_values": [ "" ], + "default_values": [ + "" + ], "field_type": "checkbox", "checkbox_options": { - "checked_value": "1", - "unchecked_value": "0" + "checked_value": "1", + "unchecked_value": "0" } }, { @@ -170,14 +205,15 @@ "optional": true, "advanced": true, "allow_multiple": false, - "default_values": [ "" ], + "default_values": [ + "" + ], "field_type": "checkbox", "checkbox_options": { - "checked_value": "1", - "unchecked_value": "0" + "checked_value": "1", + "unchecked_value": "0" } } - ], "behavior": { "service-mapping": { @@ -196,7 +232,7 @@ { "input_parameter": "input_ref", "target_property": "input_ref", - "target_type_transform": "resolved-ref" + "target_type_transform": "resolved-ref" }, { "input_parameter": "output_name", @@ -209,7 +245,7 @@ { "input_parameter": "intree_ref", "target_property": "intree_ref", - "target_type_transform": "resolved-ref" + "target_type_transform": "resolved-ref" }, { "input_parameter": "fastest", @@ -254,15 +290,24 @@ "target_property": "workspace_name" }, { - "service_method_output_path": [0, "report_name"], + "service_method_output_path": [ + 0, + "report_name" + ], "target_property": "report_name" }, { - "service_method_output_path": [0, "report_ref"], + "service_method_output_path": [ + 0, + "report_ref" + ], "target_property": "report_ref" }, { - "service_method_output_path": [0, "output_ref"], + "service_method_output_path": [ + 0, + "output_ref" + ], "target_property": "output_ref" } ]